2026-05-17 22:43:52 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
namespace App\Tests\Unit\Infrastructure\Channel\Ebay;
|
|
|
|
|
|
|
|
|
|
use App\Domain\Article\Article;
|
|
|
|
|
use App\Domain\Article\ArticleCondition;
|
|
|
|
|
use App\Domain\Article\ArticleType;
|
2026-05-19 07:13:51 +00:00
|
|
|
use App\Domain\Channel\ArticleTypePlatformConfig;
|
|
|
|
|
use App\Domain\Channel\Platform;
|
|
|
|
|
use App\Domain\Channel\Repository\ArticleTypePlatformConfigRepositoryInterface;
|
2026-05-17 22:43:52 +00:00
|
|
|
use App\Infrastructure\Channel\Ebay\EbayAdapter;
|
|
|
|
|
use App\Infrastructure\Channel\Ebay\EbayInventoryApiClient;
|
|
|
|
|
use PHPUnit\Framework\MockObject\MockObject;
|
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
|
|
|
|
|
|
final class EbayAdapterTest extends TestCase
|
|
|
|
|
{
|
|
|
|
|
private EbayInventoryApiClient&MockObject $apiClient;
|
2026-05-19 07:13:51 +00:00
|
|
|
private ArticleTypePlatformConfigRepositoryInterface&MockObject $configRepo;
|
2026-05-17 22:43:52 +00:00
|
|
|
private EbayAdapter $adapter;
|
|
|
|
|
private Article $article;
|
2026-05-19 07:13:51 +00:00
|
|
|
private ArticleTypePlatformConfig $platformConfig;
|
2026-05-17 22:43:52 +00:00
|
|
|
|
|
|
|
|
protected function setUp(): void
|
|
|
|
|
{
|
|
|
|
|
$this->apiClient = $this->createMock(EbayInventoryApiClient::class);
|
2026-05-19 07:13:51 +00:00
|
|
|
$this->configRepo = $this->createMock(ArticleTypePlatformConfigRepositoryInterface::class);
|
|
|
|
|
$this->adapter = new EbayAdapter($this->apiClient, $this->configRepo, 'EBAY_DE');
|
|
|
|
|
|
|
|
|
|
$articleType = new ArticleType('Notebook');
|
|
|
|
|
$platform = new Platform('ebay', 'eBay');
|
|
|
|
|
$this->platformConfig = new ArticleTypePlatformConfig($articleType, $platform, '177');
|
|
|
|
|
|
|
|
|
|
$this->article = new Article($articleType, 'NB-001', 'INV-001', 1, ArticleCondition::Good);
|
2026-05-17 22:43:52 +00:00
|
|
|
$this->article->setEbayTitle('Dell Latitude 5520');
|
|
|
|
|
$this->article->setListingPrice('299.00');
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-19 07:13:51 +00:00
|
|
|
public function testGetTypeReturnsEbay(): void
|
2026-05-17 22:43:52 +00:00
|
|
|
{
|
|
|
|
|
$this->assertSame('ebay', $this->adapter->getType());
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-19 07:13:51 +00:00
|
|
|
public function testPublishListingCallsUpsertCreateAndPublish(): void
|
2026-05-17 22:43:52 +00:00
|
|
|
{
|
2026-05-19 07:13:51 +00:00
|
|
|
$this->configRepo->method('findByArticleTypeAndPlatformType')->willReturn($this->platformConfig);
|
|
|
|
|
|
2026-05-17 22:43:52 +00:00
|
|
|
$this->apiClient->expects($this->once())->method('upsertInventoryItem');
|
|
|
|
|
$this->apiClient->expects($this->once())->method('createOffer')->willReturn('offer-123');
|
|
|
|
|
$this->apiClient->expects($this->once())->method('publishOffer')->with('offer-123')->willReturn('listing-456');
|
|
|
|
|
|
|
|
|
|
$listingId = $this->adapter->publishListing($this->article);
|
|
|
|
|
|
|
|
|
|
$this->assertSame('listing-456', $listingId);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-19 07:13:51 +00:00
|
|
|
public function testPublishListingThrowsWhenNoPlatformConfig(): void
|
|
|
|
|
{
|
|
|
|
|
$this->configRepo->method('findByArticleTypeAndPlatformType')->willReturn(null);
|
|
|
|
|
|
|
|
|
|
$this->expectException(\RuntimeException::class);
|
|
|
|
|
$this->expectExceptionMessage('No eBay platform config found for ArticleType');
|
|
|
|
|
|
|
|
|
|
$this->adapter->publishListing($this->article);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testPublishListingIncludesPoliciesWhenSet(): void
|
|
|
|
|
{
|
|
|
|
|
$this->platformConfig->setFulfillmentPolicyId('FP-123');
|
|
|
|
|
$this->platformConfig->setPaymentPolicyId('PP-456');
|
|
|
|
|
$this->platformConfig->setReturnPolicyId('RP-789');
|
|
|
|
|
$this->platformConfig->setMerchantLocationKey('WAREHOUSE-1');
|
|
|
|
|
$this->configRepo->method('findByArticleTypeAndPlatformType')->willReturn($this->platformConfig);
|
|
|
|
|
|
|
|
|
|
$this->apiClient->expects($this->once())->method('upsertInventoryItem');
|
|
|
|
|
$this->apiClient->expects($this->once())
|
|
|
|
|
->method('createOffer')
|
|
|
|
|
->with($this->callback(static function (array $body): bool {
|
|
|
|
|
return isset($body['listingPolicies']['fulfillmentPolicyId'])
|
|
|
|
|
&& 'FP-123' === $body['listingPolicies']['fulfillmentPolicyId']
|
|
|
|
|
&& 'PP-456' === $body['listingPolicies']['paymentPolicyId']
|
|
|
|
|
&& 'RP-789' === $body['listingPolicies']['returnPolicyId']
|
|
|
|
|
&& 'WAREHOUSE-1' === $body['merchantLocationKey'];
|
|
|
|
|
}))
|
|
|
|
|
->willReturn('offer-123');
|
|
|
|
|
$this->apiClient->method('publishOffer')->willReturn('listing-456');
|
|
|
|
|
|
|
|
|
|
$this->adapter->publishListing($this->article);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testPublishListingOmitsPoliciesWhenNotSet(): void
|
|
|
|
|
{
|
|
|
|
|
$this->configRepo->method('findByArticleTypeAndPlatformType')->willReturn($this->platformConfig);
|
|
|
|
|
|
|
|
|
|
$this->apiClient->expects($this->once())->method('upsertInventoryItem');
|
|
|
|
|
$this->apiClient->expects($this->once())
|
|
|
|
|
->method('createOffer')
|
|
|
|
|
->with($this->callback(static function (array $body): bool {
|
|
|
|
|
return !isset($body['listingPolicies']) && !isset($body['merchantLocationKey']);
|
|
|
|
|
}))
|
|
|
|
|
->willReturn('offer-123');
|
|
|
|
|
$this->apiClient->method('publishOffer')->willReturn('listing-456');
|
|
|
|
|
|
|
|
|
|
$this->adapter->publishListing($this->article);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testDeactivateListingWithdrawsOffer(): void
|
2026-05-17 22:43:52 +00:00
|
|
|
{
|
|
|
|
|
$this->article->setEbayListingId('offer-123');
|
|
|
|
|
|
|
|
|
|
$this->apiClient->expects($this->once())->method('withdrawOffer')->with('offer-123');
|
|
|
|
|
|
|
|
|
|
$this->adapter->deactivateListing($this->article);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-19 07:13:51 +00:00
|
|
|
public function testDeactivateListingIsNoopWhenNoListingId(): void
|
2026-05-17 22:43:52 +00:00
|
|
|
{
|
|
|
|
|
$this->apiClient->expects($this->never())->method('withdrawOffer');
|
|
|
|
|
|
|
|
|
|
$this->adapter->deactivateListing($this->article);
|
|
|
|
|
}
|
|
|
|
|
}
|