Files
git-contribution-graph/tests/Unit/Service/Provider/GiteaProviderTest.php
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

156 lines
5.0 KiB
PHP

<?php
declare(strict_types=1);
namespace GitContributionGraph\Tests\Unit\Service\Provider;
use GitContributionGraph\Service\Provider\GiteaProvider;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;
#[CoversClass(GiteaProvider::class)]
final class GiteaProviderTest extends TestCase
{
private function makeProvider(
string $username = 'user',
string $token = 'token',
string $baseUrl = 'https://gitea.example.com',
?HttpClientInterface $client = null,
): GiteaProvider {
return new GiteaProvider(
$client ?? $this->createStub(HttpClientInterface::class),
$username,
$token,
$baseUrl,
$this->createStub(LoggerInterface::class),
);
}
/** @param array<int, array{timestamp: int, contributions: int}> $data */
private function stubResponse(array $data): ResponseInterface
{
$response = $this->createStub(ResponseInterface::class);
$response->method('toArray')->willReturn($data);
return $response;
}
#[Test]
public function it_returns_gitea_as_name(): void
{
$this->assertSame('gitea', $this->makeProvider()->getName());
}
#[Test]
public function it_is_configured_when_all_credentials_are_set(): void
{
$this->assertTrue($this->makeProvider()->isConfigured());
}
#[Test]
public function it_is_not_configured_when_username_is_empty(): void
{
$this->assertFalse($this->makeProvider(username: '')->isConfigured());
}
#[Test]
public function it_is_not_configured_when_token_is_empty(): void
{
$this->assertFalse($this->makeProvider(token: '')->isConfigured());
}
#[Test]
public function it_is_not_configured_when_base_url_is_empty(): void
{
$this->assertFalse($this->makeProvider(baseUrl: '')->isConfigured());
}
#[Test]
public function it_parses_heatmap_entries_into_contributions(): void
{
$now = time();
$client = $this->createStub(HttpClientInterface::class);
$client->method('request')->willReturn($this->stubResponse([
['timestamp' => $now, 'contributions' => 5],
]));
$provider = $this->makeProvider(client: $client);
$result = $provider->resolveFetch($provider->startFetch());
$this->assertSame(5, $result[date('Y-m-d', $now)]);
}
#[Test]
public function it_filters_out_entries_older_than_365_days(): void
{
$old = (new \DateTimeImmutable('-366 days'))->getTimestamp();
$client = $this->createStub(HttpClientInterface::class);
$client->method('request')->willReturn($this->stubResponse([
['timestamp' => $old, 'contributions' => 3],
]));
$provider = $this->makeProvider(client: $client);
$result = $provider->resolveFetch($provider->startFetch());
$this->assertSame([], $result);
}
#[Test]
public function it_returns_empty_when_response_has_no_entries(): void
{
$client = $this->createStub(HttpClientInterface::class);
$client->method('request')->willReturn($this->stubResponse([]));
$provider = $this->makeProvider(client: $client);
$result = $provider->resolveFetch($provider->startFetch());
$this->assertSame([], $result);
}
#[Test]
public function it_filters_out_entries_before_since(): void
{
$since = new \DateTimeImmutable('2024-01-10');
$before = $since->modify('-1 day')->getTimestamp();
$after = $since->modify('+1 day')->getTimestamp();
$client = $this->createStub(HttpClientInterface::class);
$client->method('request')->willReturn($this->stubResponse([
['timestamp' => $before, 'contributions' => 3],
['timestamp' => $after, 'contributions' => 2],
]));
$provider = $this->makeProvider(client: $client);
$result = $provider->resolveFetch($provider->startFetch($since));
$this->assertArrayNotHasKey(date('Y-m-d', $before), $result);
$this->assertSame(2, $result[date('Y-m-d', $after)]);
}
#[Test]
public function it_filters_out_entries_after_until(): void
{
$until = new \DateTimeImmutable('-10 days');
$before = $until->modify('-1 day')->getTimestamp();
$after = $until->modify('+1 day')->getTimestamp();
$client = $this->createStub(HttpClientInterface::class);
$client->method('request')->willReturn($this->stubResponse([
['timestamp' => $before, 'contributions' => 3],
['timestamp' => $after, 'contributions' => 2],
]));
$provider = $this->makeProvider(client: $client);
$result = $provider->resolveFetch($provider->startFetch(null, $until));
$this->assertSame(3, $result[date('Y-m-d', $before)]);
$this->assertArrayNotHasKey(date('Y-m-d', $after), $result);
}
}