fedi-feed-router/tests/Unit/Dashboard/Stats/PublishSuccessRateTest.php

144 lines
4.8 KiB
PHP
Raw Normal View History

<?php
namespace Tests\Unit\Dashboard\Stats;
use App\Dashboard\Stats\PublishSuccessRate;
use App\Enums\PublishStatusEnum;
use App\Models\RouteArticle;
use App\Support\DateRange;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon;
use Tests\TestCase;
class PublishSuccessRateTest extends TestCase
{
use RefreshDatabase;
private function range(): DateRange
{
return new DateRange(
Carbon::parse('2026-07-01 00:00:00'),
Carbon::parse('2026-07-31 23:59:59'),
);
}
/**
* @return array<string, float|null>
*/
private function values(): array
{
$result = (new PublishSuccessRate)->for($this->range());
return array_combine($result->labels, $result->series[0]->values);
}
private function attempt(PublishStatusEnum $status, string $updatedAt): RouteArticle
{
/** @var RouteArticle $article */
$article = RouteArticle::factory()->create(['publish_status' => $status]);
// Model::update() would re-stamp updated_at to now(); bypass via the query builder.
RouteArticle::query()
->whereKey($article->getKey())
->update(['updated_at' => Carbon::parse($updatedAt)]);
return $article;
}
public function test_it_computes_the_published_share_of_daily_attempts(): void
{
$this->attempt(PublishStatusEnum::PUBLISHED, '2026-07-10 09:00:00');
$this->attempt(PublishStatusEnum::PUBLISHED, '2026-07-10 10:00:00');
$this->attempt(PublishStatusEnum::PUBLISHED, '2026-07-10 11:00:00');
$this->attempt(PublishStatusEnum::ERROR, '2026-07-10 12:00:00');
$this->assertSame(75.0, $this->values()['2026-07-10']);
}
public function test_it_excludes_skipped_articles_from_the_denominator(): void
{
$this->attempt(PublishStatusEnum::PUBLISHED, '2026-07-10 09:00:00');
$this->attempt(PublishStatusEnum::SKIPPED, '2026-07-10 10:00:00');
$this->assertSame(100.0, $this->values()['2026-07-10']);
}
public function test_it_excludes_articles_still_in_flight(): void
{
$this->attempt(PublishStatusEnum::PUBLISHED, '2026-07-10 09:00:00');
$this->attempt(PublishStatusEnum::PUBLISHING, '2026-07-10 10:00:00');
$this->attempt(PublishStatusEnum::UNPUBLISHED, '2026-07-10 11:00:00');
$this->assertSame(100.0, $this->values()['2026-07-10']);
}
public function test_it_reports_no_rate_for_a_day_with_no_attempts(): void
{
$this->attempt(PublishStatusEnum::PUBLISHED, '2026-07-10 09:00:00');
$this->assertNull($this->values()['2026-07-11']);
}
public function test_it_reports_a_zero_rate_when_every_attempt_failed(): void
{
$this->attempt(PublishStatusEnum::ERROR, '2026-07-10 09:00:00');
$this->assertSame(0.0, $this->values()['2026-07-10']);
}
public function test_it_counts_an_article_on_the_day_it_was_last_touched(): void
{
$this->attempt(PublishStatusEnum::ERROR, '2026-07-10 09:00:00');
$this->attempt(PublishStatusEnum::PUBLISHED, '2026-07-12 09:00:00');
$values = $this->values();
$this->assertSame(0.0, $values['2026-07-10']);
$this->assertSame(100.0, $values['2026-07-12']);
}
public function test_a_retry_moves_the_article_to_the_retry_day(): void
{
$article = $this->attempt(PublishStatusEnum::ERROR, '2026-07-10 09:00:00');
RouteArticle::query()
->whereKey($article->getKey())
->update([
'publish_status' => PublishStatusEnum::PUBLISHED,
'updated_at' => Carbon::parse('2026-07-12 09:00:00'),
]);
$values = $this->values();
$this->assertNull($values['2026-07-10']);
$this->assertSame(100.0, $values['2026-07-12']);
}
public function test_it_ignores_attempts_outside_the_range(): void
{
$this->attempt(PublishStatusEnum::PUBLISHED, '2026-06-30 23:00:00');
$this->attempt(PublishStatusEnum::ERROR, '2026-08-01 01:00:00');
$this->assertSame([], array_filter($this->values(), fn (?float $value): bool => $value !== null));
}
public function test_it_rounds_the_rate_to_one_decimal(): void
{
$this->attempt(PublishStatusEnum::PUBLISHED, '2026-07-10 09:00:00');
$this->attempt(PublishStatusEnum::PUBLISHED, '2026-07-10 10:00:00');
$this->attempt(PublishStatusEnum::ERROR, '2026-07-10 11:00:00');
$this->assertSame(66.7, $this->values()['2026-07-10']);
}
public function test_it_refuses_to_bucket_a_range_wider_than_the_day_limit(): void
{
$result = (new PublishSuccessRate)->for(new DateRange(
Carbon::parse('2020-01-01 00:00:00'),
Carbon::parse('2026-12-31 23:59:59'),
));
$this->assertTrue($result->isTooWide());
}
}