Http::response([], 500)); $this->artisan('etsy:sync')->assertExitCode(0); Http::assertNothingSent(); } public function test_etsy_sync_refreshes_receipts_and_listings(): void { $this->connectShop(); Http::fake([ '*/receipts*' => Http::response(['count' => 1, 'results' => [[ 'receipt_id' => 1, 'status' => 'open', 'was_paid' => true, 'was_shipped' => false, ]]]), '*/listings*' => Http::response(['count' => 1, 'results' => [['listing_id' => 11]]]), ]); $this->artisan('etsy:sync')->assertExitCode(0); Http::assertSentCount(2); } public function test_etsy_refresh_token_skips_cleanly_when_shop_is_not_connected(): void { Http::fake(fn () => Http::response([], 500)); $this->artisan('etsy:refresh-token')->assertExitCode(0); Http::assertNothingSent(); } public function test_etsy_refresh_token_proactively_refreshes_an_expired_token(): void { $connection = $this->connectShop(expiresAt: now()->subMinute()); Http::fake([ '*/oauth/token' => Http::response([ 'access_token' => 'new-access-token', 'refresh_token' => 'new-refresh-token', 'expires_in' => 3600, ]), ]); $this->artisan('etsy:refresh-token')->assertExitCode(0); Http::assertSentCount(1); $connection->refresh(); $this->assertSame('new-access-token', $connection->access_token); $this->assertTrue($connection->expires_at->isFuture()); } public function test_etsy_refresh_token_does_not_call_etsy_when_token_is_still_fresh(): void { $this->connectShop(expiresAt: now()->addMinutes(30)); Http::fake(); $this->artisan('etsy:refresh-token')->assertExitCode(0); Http::assertNothingSent(); } private function connectShop(?Carbon $expiresAt = null): EtsyConnection { EtsyAppCredential::create([ 'id' => 1, 'keystring' => 'key', 'shared_secret' => 'secret', 'shop_name' => 'HickLab3D', ]); return EtsyConnection::create([ 'shop_id' => 123, 'shop_name' => 'HickLab3D', 'access_token' => 'token', 'refresh_token' => 'refresh', 'expires_at' => $expiresAt ?? now()->addHour(), 'scopes' => 'listings_r listings_w transactions_r transactions_w shops_r', ]); } }