Files
git-contribution-graph/tests/Unit/Service/Provider/ProbeTraitTest.php
T
haylan 4ff45b7c46 feat(store): fetch contributions incrementally and persist history in SQLite
Bound each provider's startFetch()/resolveFetch() to an optional
since/until window, wire a SQLite-backed ContributionStore into
ContributionAggregator (fetch only the trailing window past the last
stored date, merge into the store, prune by CONTRIBUTIONS_RETENTION_DAYS),
and add a graph:contributions:refetch command to force a full or ranged
re-fetch in <=365-day chunks. This is the root fix for the full
365-day-refetch timeout that used to hit on every cache miss.
2026-07-12 23:42:41 +02:00

130 lines
4.7 KiB
PHP

<?php
declare(strict_types=1);
namespace GitContributionGraph\Tests\Unit\Service\Provider;
use GitContributionGraph\Service\Provider\ProbeTrait;
use GitContributionGraph\Service\Provider\ProviderErrorCode;
use GitContributionGraph\Service\Provider\ProviderInterface;
use GitContributionGraph\Service\Provider\ProviderStatusType;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;
#[CoversClass(ProbeTrait::class)]
final class ProbeTraitTest extends TestCase
{
private function makeProvider(bool $configured, \Closure $ping): ProviderInterface
{
return new class($configured, $ping) implements ProviderInterface {
use ProbeTrait;
public function __construct(
private bool $configured,
private \Closure $ping,
) {}
public function isConfigured(): bool { return $this->configured; }
public function getName(): string { return 'test'; }
public function ping(): void { ($this->ping)(); }
public function startFetch(?\DateTimeImmutable $since = null, ?\DateTimeImmutable $until = null): mixed { return null; }
public function resolveFetch(mixed $handle): array { return []; }
};
}
#[Test]
public function it_returns_not_configured_when_provider_is_not_configured(): void
{
$provider = $this->makeProvider(false, fn() => null);
$status = $provider->probe();
$this->assertSame(ProviderStatusType::NotConfigured, $status->status);
$this->assertNull($status->error);
}
#[Test]
public function it_returns_ok_when_ping_succeeds(): void
{
$provider = $this->makeProvider(true, fn() => null);
$status = $provider->probe();
$this->assertSame(ProviderStatusType::Ok, $status->status);
$this->assertNull($status->error);
}
#[Test]
public function it_returns_url_unreachable_on_transport_failure(): void
{
$exception = $this->createStub(TransportExceptionInterface::class);
$provider = $this->makeProvider(true, fn() => throw $exception);
$status = $provider->probe();
$this->assertSame(ProviderStatusType::Error, $status->status);
$this->assertSame(ProviderErrorCode::UrlUnreachable, $status->error);
}
#[Test]
public function it_returns_auth_failed_on_401(): void
{
$response = $this->createStub(ResponseInterface::class);
$response->method('getStatusCode')->willReturn(401);
$exception = $this->createStub(ClientExceptionInterface::class);
$exception->method('getResponse')->willReturn($response);
$status = $this->makeProvider(true, fn() => throw $exception)->probe();
$this->assertSame(ProviderStatusType::Error, $status->status);
$this->assertSame(ProviderErrorCode::AuthFailed, $status->error);
}
#[Test]
public function it_returns_auth_failed_on_403(): void
{
$response = $this->createStub(ResponseInterface::class);
$response->method('getStatusCode')->willReturn(403);
$exception = $this->createStub(ClientExceptionInterface::class);
$exception->method('getResponse')->willReturn($response);
$status = $this->makeProvider(true, fn() => throw $exception)->probe();
$this->assertSame(ProviderStatusType::Error, $status->status);
$this->assertSame(ProviderErrorCode::AuthFailed, $status->error);
}
#[Test]
public function it_returns_url_unreachable_on_404(): void
{
$response = $this->createStub(ResponseInterface::class);
$response->method('getStatusCode')->willReturn(404);
$exception = $this->createStub(ClientExceptionInterface::class);
$exception->method('getResponse')->willReturn($response);
$status = $this->makeProvider(true, fn() => throw $exception)->probe();
$this->assertSame(ProviderStatusType::Error, $status->status);
$this->assertSame(ProviderErrorCode::UrlUnreachable, $status->error);
}
#[Test]
public function it_returns_unknown_error_on_unexpected_exception(): void
{
$provider = $this->makeProvider(true, fn() => throw new \RuntimeException('Something went wrong'));
$status = $provider->probe();
$this->assertSame(ProviderStatusType::Error, $status->status);
$this->assertSame(ProviderErrorCode::Unknown, $status->error);
$this->assertSame('Something went wrong', $status->message);
}
}