markTestSkipped('EBAY_* env vars not set'); } $http = HttpClient::create(); $cache = new ArrayAdapter(); $oauth = new EbayOAuthClient( $http, $cache, (string) $clientId, (string) $clientSecret, (string) $oauthBaseUrl, ); $this->apiClient = new EbayInventoryApiClient( $http, $oauth, (string) $apiBaseUrl, (string) $marketplaceId, ); $this->adapter = new EbayAdapter($this->apiClient); $userToken = $_SERVER['EBAY_USER_TOKEN'] ?? getenv('EBAY_USER_TOKEN'); $this->userTokenAvailable = (bool) $userToken; // Build a realistic sandbox article for listing tests $type = new ArticleType('Notebook'); $this->article = new Article( $type, 'SS3K-TEST-'.time(), 'INV-TEST-001', 1, ArticleCondition::Good, ); $this->article->setManufacturer('Lenovo'); $this->article->setModelName('ThinkBook 14 G6 IRL'); $this->article->setModelNumber('21KG00NQGE'); $this->article->setEbayTitle('Lenovo ThinkBook 14 G6 IRL — Sandbox Test'); $this->article->setEbayDescription('Integration test listing — do not bid.'); $this->article->setListingPrice('1.00'); } protected function tearDown(): void { if ('' !== $this->createdListingId) { try { $this->adapter->deactivateListing($this->article); } catch (\Throwable) { // best-effort cleanup } } } public function test_publish_listing_creates_live_sandbox_listing(): void { if (!$this->userTokenAvailable) { $this->markTestSkipped( 'EBAY_USER_TOKEN not set. Generate a sandbox user token via Authorization Code '. 'flow (sell.inventory scope) and add it to .env.local to enable this test.' ); } $listingId = $this->adapter->publishListing($this->article); $this->assertNotEmpty($listingId); $this->createdListingId = $listingId; // Store so deactivateListing in tearDown finds it $this->article->setEbayListingId($listingId); } public function test_update_stock_changes_quantity(): void { if (!$this->userTokenAvailable) { $this->markTestSkipped('EBAY_USER_TOKEN not set — see test_publish_listing_creates_live_sandbox_listing'); } // First publish to create the item $this->adapter->publishListing($this->article); $this->article->setEbayListingId($this->createdListingId); // Should not throw $this->adapter->updateStock($this->article, 2); $this->addToAssertionCount(1); } public function test_deactivate_listing_withdraws_offer(): void { if (!$this->userTokenAvailable) { $this->markTestSkipped('EBAY_USER_TOKEN not set — see test_publish_listing_creates_live_sandbox_listing'); } $listingId = $this->adapter->publishListing($this->article); $this->article->setEbayListingId($listingId); // Should not throw $this->adapter->deactivateListing($this->article); $this->createdListingId = ''; // already deactivated, skip tearDown cleanup $this->addToAssertionCount(1); } public function test_deactivate_listing_is_noop_when_no_listing_id(): void { // No listing ID set — should silently return, no API call $this->adapter->deactivateListing($this->article); $this->addToAssertionCount(1); } }