Files
orderPRO/tests/Unit/AllegroTokenManagerTest.php
Jacek Pyziak 5ab87a5a20 feat(07-pre-expansion-fixes): complete phase 07 — milestone v0.2 done
Phase 7 complete (5 plans):
- 07-01: Performance (N+1→LEFT JOIN, static cache, DB indexes)
- 07-02: Stability (SSL verification, cron throttle DB, migration 000014b)
- 07-03: UX (orderpro_to_allegro disable, lista zamówień fixes, SSL hotfix)
- 07-04: Tests (12 unit tests for AllegroTokenManager + AllegroOrderImportService)
- 07-05: InPost ShipX API (natywny provider, workaround remap usunięty)

Additional fixes:
- 5 broken use-statements fixed across 4 files
- vendor/ excluded from ftp-kr auto-upload
- PHPUnit + dg/bypass-finals infrastructure

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 00:37:21 +01:00

268 lines
8.3 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Unit;
use App\Core\Exceptions\AllegroOAuthException;
use App\Modules\Settings\AllegroIntegrationRepository;
use App\Modules\Settings\AllegroOAuthClient;
use App\Modules\Settings\AllegroTokenManager;
use DateInterval;
use DateTimeImmutable;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
final class AllegroTokenManagerTest extends TestCase
{
private AllegroIntegrationRepository&MockObject $repository;
private AllegroOAuthClient&MockObject $oauthClient;
private AllegroTokenManager $manager;
protected function setUp(): void
{
$this->repository = $this->createMock(AllegroIntegrationRepository::class);
$this->oauthClient = $this->createMock(AllegroOAuthClient::class);
$this->manager = new AllegroTokenManager($this->repository, $this->oauthClient);
}
public function testResolveTokenReturnsCachedTokenWhenFresh(): void
{
$expiresAt = (new DateTimeImmutable('now'))
->add(new DateInterval('PT30M'))
->format('Y-m-d H:i:s');
$this->repository
->method('getTokenCredentials')
->willReturn([
'environment' => 'sandbox',
'client_id' => 'cid',
'client_secret' => 'cs',
'refresh_token' => 'rt',
'access_token' => 'fresh-token',
'token_expires_at' => $expiresAt,
]);
$this->oauthClient
->expects($this->never())
->method('refreshAccessToken');
$result = $this->manager->resolveToken();
$this->assertSame('fresh-token', $result[0]);
$this->assertSame('sandbox', $result[1]);
}
public function testResolveTokenRefreshesWhenExpiresWithinFiveMinutes(): void
{
$expiresAt = (new DateTimeImmutable('now'))
->add(new DateInterval('PT3M'))
->format('Y-m-d H:i:s');
$credentials = [
'environment' => 'production',
'client_id' => 'cid',
'client_secret' => 'cs',
'refresh_token' => 'rt',
'access_token' => 'old-token',
'token_expires_at' => $expiresAt,
];
$this->repository
->method('getTokenCredentials')
->willReturnOnConsecutiveCalls(
$credentials,
$credentials,
array_merge($credentials, ['access_token' => 'new-token'])
);
$this->oauthClient
->expects($this->once())
->method('refreshAccessToken')
->with('production', 'cid', 'cs', 'rt')
->willReturn([
'access_token' => 'new-token',
'refresh_token' => 'new-rt',
'token_type' => 'Bearer',
'scope' => '',
'expires_in' => 3600,
]);
$this->repository
->expects($this->once())
->method('saveTokens');
$result = $this->manager->resolveToken();
$this->assertSame('new-token', $result[0]);
$this->assertSame('production', $result[1]);
}
public function testResolveTokenRefreshesWhenAlreadyExpired(): void
{
$expiresAt = (new DateTimeImmutable('now'))
->sub(new DateInterval('PT10M'))
->format('Y-m-d H:i:s');
$credentials = [
'environment' => 'sandbox',
'client_id' => 'cid',
'client_secret' => 'cs',
'refresh_token' => 'rt',
'access_token' => 'expired-token',
'token_expires_at' => $expiresAt,
];
$this->repository
->method('getTokenCredentials')
->willReturnOnConsecutiveCalls(
$credentials,
$credentials,
array_merge($credentials, ['access_token' => 'refreshed-token'])
);
$this->oauthClient
->expects($this->once())
->method('refreshAccessToken')
->willReturn([
'access_token' => 'refreshed-token',
'refresh_token' => 'rt',
'token_type' => 'Bearer',
'scope' => '',
'expires_in' => 3600,
]);
$this->repository->expects($this->once())->method('saveTokens');
$result = $this->manager->resolveToken();
$this->assertSame('refreshed-token', $result[0]);
}
public function testResolveTokenThrowsWhenNoOAuthConfig(): void
{
$this->repository
->method('getTokenCredentials')
->willReturn(null);
$this->expectException(AllegroOAuthException::class);
$this->expectExceptionMessage('Brak polaczenia OAuth Allegro');
$this->manager->resolveToken();
}
public function testResolveTokenRefreshesWhenAccessTokenEmpty(): void
{
$credentials = [
'environment' => 'sandbox',
'client_id' => 'cid',
'client_secret' => 'cs',
'refresh_token' => 'rt',
'access_token' => '',
'token_expires_at' => '',
];
$this->repository
->method('getTokenCredentials')
->willReturnOnConsecutiveCalls(
$credentials,
$credentials,
array_merge($credentials, ['access_token' => 'brand-new'])
);
$this->oauthClient
->expects($this->once())
->method('refreshAccessToken')
->willReturn([
'access_token' => 'brand-new',
'refresh_token' => 'rt',
'token_type' => 'Bearer',
'scope' => '',
'expires_in' => 3600,
]);
$this->repository->expects($this->once())->method('saveTokens');
$result = $this->manager->resolveToken();
$this->assertSame('brand-new', $result[0]);
}
public function testForceRefreshReReadsTokenFromRepository(): void
{
$expiresAt = (new DateTimeImmutable('now'))
->sub(new DateInterval('PT1M'))
->format('Y-m-d H:i:s');
$credentials = [
'environment' => 'sandbox',
'client_id' => 'cid',
'client_secret' => 'cs',
'refresh_token' => 'rt',
'access_token' => 'stale',
'token_expires_at' => $expiresAt,
];
$this->repository
->expects($this->exactly(3))
->method('getTokenCredentials')
->willReturnOnConsecutiveCalls(
$credentials,
$credentials,
array_merge($credentials, ['access_token' => 'from-db'])
);
$this->oauthClient
->method('refreshAccessToken')
->willReturn([
'access_token' => 'api-returned',
'refresh_token' => 'rt',
'token_type' => 'Bearer',
'scope' => '',
'expires_in' => 3600,
]);
$this->repository->expects($this->once())->method('saveTokens');
$result = $this->manager->resolveToken();
// Token comes from re-read (3rd call), not directly from API response
$this->assertSame('from-db', $result[0]);
}
public function testResolveTokenRefreshesWhenExpiresAtInvalidFormat(): void
{
$credentials = [
'environment' => 'sandbox',
'client_id' => 'cid',
'client_secret' => 'cs',
'refresh_token' => 'rt',
'access_token' => 'some-token',
'token_expires_at' => 'not-a-date',
];
$this->repository
->method('getTokenCredentials')
->willReturnOnConsecutiveCalls(
$credentials,
$credentials,
array_merge($credentials, ['access_token' => 'refreshed'])
);
$this->oauthClient
->expects($this->once())
->method('refreshAccessToken')
->willReturn([
'access_token' => 'refreshed',
'refresh_token' => 'rt',
'token_type' => 'Bearer',
'scope' => '',
'expires_in' => 3600,
]);
$this->repository->expects($this->once())->method('saveTokens');
$result = $this->manager->resolveToken();
$this->assertSame('refreshed', $result[0]);
}
}