Files
shopPRO/tests/Unit/Domain/Integrations/IntegrationsRepositoryTest.php
Jacek Pyziak 3ae0bc95e0 ver. 0.310: logi integracji w panelu admin
Nowa zakladka "Logi" w sekcji Integracje - podglad tabeli pp_log
z paginacja, sortowaniem, filtrami i rozwijalnym kontekstem JSON.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 09:54:09 +01:00

367 lines
12 KiB
PHP

<?php
namespace Tests\Unit\Domain\Integrations;
use PHPUnit\Framework\TestCase;
use Domain\Integrations\IntegrationsRepository;
class IntegrationsRepositoryTest extends TestCase
{
private $mockDb;
private IntegrationsRepository $repository;
protected function setUp(): void
{
$this->mockDb = $this->createMock(\medoo::class);
$this->repository = new IntegrationsRepository($this->mockDb);
}
public function testGetSettingsReturnsArray(): void
{
$stmt = $this->createMock(\PDOStatement::class);
$stmt->expects($this->once())
->method('fetchAll')
->with(\PDO::FETCH_ASSOC)
->willReturn([
['name' => 'client-id', 'value' => 'abc123'],
['name' => 'client-secret', 'value' => 'secret'],
]);
$this->mockDb->expects($this->once())
->method('query')
->with('SELECT * FROM pp_shop_apilo_settings')
->willReturn($stmt);
$settings = $this->repository->getSettings('apilo');
$this->assertIsArray($settings);
$this->assertSame('abc123', $settings['client-id']);
$this->assertSame('secret', $settings['client-secret']);
}
public function testGetSettingReturnsValue(): void
{
$this->mockDb->expects($this->once())
->method('get')
->with('pp_shop_apilo_settings', 'value', ['name' => 'client-id'])
->willReturn('abc123');
$this->assertSame('abc123', $this->repository->getSetting('apilo', 'client-id'));
}
public function testGetSettingReturnsNullWhenNotFound(): void
{
$this->mockDb->expects($this->once())
->method('get')
->with('pp_shop_apilo_settings', 'value', ['name' => 'nonexistent'])
->willReturn(false);
$this->assertNull($this->repository->getSetting('apilo', 'nonexistent'));
}
public function testSaveSettingUpdatesExistingValue(): void
{
$this->mockDb->expects($this->once())
->method('count')
->with('pp_shop_apilo_settings', ['name' => 'client-id'])
->willReturn(1);
$this->mockDb->expects($this->once())
->method('update')
->with('pp_shop_apilo_settings', ['value' => 'new-value'], ['name' => 'client-id']);
$this->assertTrue($this->repository->saveSetting('apilo', 'client-id', 'new-value'));
}
public function testSaveSettingInsertsNewValue(): void
{
$this->mockDb->expects($this->once())
->method('count')
->with('pp_shop_shoppro_settings', ['name' => 'domain'])
->willReturn(0);
$this->mockDb->expects($this->once())
->method('insert')
->with('pp_shop_shoppro_settings', ['name' => 'domain', 'value' => 'example.com']);
$this->assertTrue($this->repository->saveSetting('shoppro', 'domain', 'example.com'));
}
public function testInvalidProviderThrowsException(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->repository->getSettings('sellasist');
}
public function testLinkProductUpdatesDatabase(): void
{
$this->mockDb->expects($this->once())
->method('update')
->with(
'pp_shop_products',
$this->callback(function ($data) {
return isset($data['apilo_product_id']) && isset($data['apilo_product_name']);
}),
['id' => 42]
)
->willReturn(1);
$this->assertTrue($this->repository->linkProduct(42, 'ext-123', 'Test Product'));
}
public function testUnlinkProductClearsFields(): void
{
$this->mockDb->expects($this->once())
->method('update')
->with(
'pp_shop_products',
['apilo_product_id' => null, 'apilo_product_name' => null],
['id' => 42]
)
->willReturn(1);
$this->assertTrue($this->repository->unlinkProduct(42));
}
public function testGetProductSkuReturnsValue(): void
{
$this->mockDb->expects($this->once())
->method('get')
->with('pp_shop_products', 'sku', ['id' => 10])
->willReturn('SKU-100');
$this->assertSame('SKU-100', $this->repository->getProductSku(10));
}
public function testGetProductSkuReturnsNullForMissing(): void
{
$this->mockDb->expects($this->once())
->method('get')
->with('pp_shop_products', 'sku', ['id' => 999])
->willReturn(false);
$this->assertNull($this->repository->getProductSku(999));
}
public function testApiloGetAccessTokenReturnsNullWithoutSettings(): void
{
$stmt = $this->createMock(\PDOStatement::class);
$stmt->method('fetchAll')->willReturn([]);
$this->mockDb->method('query')->willReturn($stmt);
$this->assertNull($this->repository->apiloGetAccessToken());
}
public function testShouldRefreshAccessTokenReturnsFalseForFarFutureDate(): void
{
$reflection = new \ReflectionClass($this->repository);
$method = $reflection->getMethod('shouldRefreshAccessToken');
$method->setAccessible(true);
$future = date('Y-m-d H:i:s', time() + 3600);
$result = $method->invoke($this->repository, $future, 300);
$this->assertFalse($result);
}
public function testShouldRefreshAccessTokenReturnsTrueForNearExpiryDate(): void
{
$reflection = new \ReflectionClass($this->repository);
$method = $reflection->getMethod('shouldRefreshAccessToken');
$method->setAccessible(true);
$near = date('Y-m-d H:i:s', time() + 120);
$result = $method->invoke($this->repository, $near, 300);
$this->assertTrue($result);
}
public function testApiloFetchListThrowsForInvalidType(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->repository->apiloFetchList('invalid');
}
public function testApiloFetchListResultReturnsDetailedErrorWhenConfigMissing(): void
{
$stmt = $this->createMock(\PDOStatement::class);
$stmt->expects($this->once())
->method('fetchAll')
->with(\PDO::FETCH_ASSOC)
->willReturn([]);
$this->mockDb->expects($this->once())
->method('query')
->with('SELECT * FROM pp_shop_apilo_settings')
->willReturn($stmt);
$result = $this->repository->apiloFetchListResult('payment');
$this->assertIsArray($result);
$this->assertFalse((bool)($result['success'] ?? true));
$this->assertStringContainsString('Brakuje konfiguracji Apilo', (string)($result['message'] ?? ''));
}
public function testApiloIntegrationStatusReturnsMissingConfigMessage(): void
{
$stmt = $this->createMock(\PDOStatement::class);
$stmt->expects($this->once())
->method('fetchAll')
->with(\PDO::FETCH_ASSOC)
->willReturn([]);
$this->mockDb->expects($this->once())
->method('query')
->with('SELECT * FROM pp_shop_apilo_settings')
->willReturn($stmt);
$status = $this->repository->apiloIntegrationStatus();
$this->assertIsArray($status);
$this->assertFalse((bool)($status['is_valid'] ?? true));
$this->assertStringContainsString('Brakuje konfiguracji Apilo', (string)($status['message'] ?? ''));
}
public function testAllPublicMethodsExist(): void
{
$expectedMethods = [
'getSettings', 'getSetting', 'saveSetting',
'linkProduct', 'unlinkProduct',
'apiloAuthorize', 'apiloGetAccessToken', 'apiloKeepalive', 'apiloIntegrationStatus',
'apiloFetchList', 'apiloFetchListResult', 'apiloProductSearch', 'apiloCreateProduct',
'getProductSku', 'shopproImportProduct',
];
foreach ($expectedMethods as $method) {
$this->assertTrue(
method_exists($this->repository, $method),
"Method $method does not exist"
);
}
}
public function testSettingsTableMapping(): void
{
// Verify apilo maps correctly
$stmt = $this->createMock(\PDOStatement::class);
$stmt->method('fetchAll')->willReturn([]);
$this->mockDb->method('query')
->with($this->stringContains('pp_shop_apilo_settings'))
->willReturn($stmt);
$this->assertIsArray($this->repository->getSettings('apilo'));
}
public function testShopproProviderWorks(): void
{
$stmt = $this->createMock(\PDOStatement::class);
$stmt->method('fetchAll')->willReturn([
['name' => 'domain', 'value' => 'test.com'],
]);
$this->mockDb->method('query')
->with($this->stringContains('pp_shop_shoppro_settings'))
->willReturn($stmt);
$settings = $this->repository->getSettings('shoppro');
$this->assertSame('test.com', $settings['domain']);
}
public function testNormalizeApiloMapListRejectsErrorPayload(): void
{
$reflection = new \ReflectionClass($this->repository);
$method = $reflection->getMethod('normalizeApiloMapList');
$method->setAccessible(true);
$result = $method->invoke($this->repository, [
'message' => 'Missing JWT token',
'code' => 401,
]);
$this->assertNull($result);
}
public function testNormalizeApiloMapListAcceptsIdNameList(): void
{
$reflection = new \ReflectionClass($this->repository);
$method = $reflection->getMethod('normalizeApiloMapList');
$method->setAccessible(true);
$payload = [
['id' => '1', 'name' => 'Przelew'],
['id' => '2', 'name' => 'Karta'],
];
$result = $method->invoke($this->repository, $payload);
$this->assertIsArray($result);
$this->assertCount(2, $result);
$this->assertSame('1', (string)$result[0]['id']);
$this->assertSame('Przelew', (string)$result[0]['name']);
}
// ── Logs ────────────────────────────────────────────────────
public function testGetLogsReturnsItemsAndTotal(): void
{
$this->mockDb->expects($this->once())
->method('count')
->with('pp_log', $this->anything())
->willReturn(2);
$this->mockDb->expects($this->once())
->method('select')
->with('pp_log', '*', $this->anything())
->willReturn([
['id' => 1, 'action' => 'send_order', 'message' => 'OK', 'date' => '2026-01-01 12:00:00'],
['id' => 2, 'action' => 'status_sync', 'message' => 'Synced', 'date' => '2026-01-02 12:00:00'],
]);
$result = $this->repository->getLogs([], 'id', 'DESC', 1, 15);
$this->assertIsArray($result);
$this->assertArrayHasKey('items', $result);
$this->assertArrayHasKey('total', $result);
$this->assertCount(2, $result['items']);
$this->assertSame(2, $result['total']);
}
public function testGetLogsReturnsEmptyWhenNoResults(): void
{
$this->mockDb->method('count')->willReturn(0);
$this->mockDb->method('select')->willReturn([]);
$result = $this->repository->getLogs([], 'id', 'DESC', 1, 15);
$this->assertSame(0, $result['total']);
$this->assertEmpty($result['items']);
}
public function testGetLogsHandlesNullFromSelect(): void
{
$this->mockDb->method('count')->willReturn(0);
$this->mockDb->method('select')->willReturn(null);
$result = $this->repository->getLogs([], 'id', 'DESC', 1, 15);
$this->assertSame([], $result['items']);
}
public function testDeleteLogCallsDelete(): void
{
$this->mockDb->expects($this->once())
->method('delete')
->with('pp_log', ['id' => 42]);
$this->assertTrue($this->repository->deleteLog(42));
}
public function testClearLogsDeletesAll(): void
{
$this->mockDb->expects($this->once())
->method('delete')
->with('pp_log', []);
$this->assertTrue($this->repository->clearLogs());
}
}