get('/admin/instances'); $response->assertStatus(200); } public function test_admin_instances_page_shows_each_instance_url_and_last_polled_at(): void { $mastodon = Instance::factory() ->type(InstanceType::Mastodon) ->enabled() ->create([ 'url' => 'https://mastodon.social', 'last_polled_at' => '2024-06-01 12:00:00', ]); $lemmy = Instance::factory() ->type(InstanceType::Lemmy) ->enabled() ->create([ 'url' => 'https://lemmy.world', 'last_polled_at' => '2024-06-01 13:00:00', ]); $response = $this->get('/admin/instances'); $response->assertSee($mastodon->url); $response->assertSee($lemmy->url); $response->assertSee($mastodon->last_polled_at->toDateString()); $response->assertSee($lemmy->last_polled_at->toDateString()); } public function test_admin_instances_page_shows_error_count_per_instance(): void { $first = Instance::factory() ->type(InstanceType::Mastodon) ->enabled() ->create(['url' => 'https://aardvark.example']); $second = Instance::factory() ->type(InstanceType::Lemmy) ->enabled() ->create(['url' => 'https://zebra.example']); // First instance: 3 failed + 2 non-failed pages Page::factory() ->count(3) ->sequence(fn ($s) => ['url' => "https://aardvark.example/fail-{$s->index}"]) ->createQuietly(['instance_id' => $first->id, 'status' => PageStatusEnum::Failed]); Page::factory() ->count(2) ->sequence(fn ($s) => ['url' => "https://aardvark.example/ok-{$s->index}"]) ->createQuietly(['instance_id' => $first->id, 'status' => PageStatusEnum::Fetched]); // Second instance: 1 failed + 4 non-failed pages Page::factory() ->count(1) ->sequence(fn ($s) => ['url' => "https://zebra.example/fail-{$s->index}"]) ->createQuietly(['instance_id' => $second->id, 'status' => PageStatusEnum::Failed]); Page::factory() ->count(4) ->sequence(fn ($s) => ['url' => "https://zebra.example/ok-{$s->index}"]) ->createQuietly(['instance_id' => $second->id, 'status' => PageStatusEnum::Fetched]); $response = $this->get('/admin/instances'); // Each error-count cell must render as "{n} errors" — this string cannot // collide with dates, IDs, or the "URLs" column. The counts (3 and 1) // are distinct and non-equal so the assertion proves per-row mapping, // not a leaked total. $response->assertSeeInOrder([ $first->url, '3 errors', $second->url, '1 errors', ]); } public function test_admin_instances_page_shows_url_count_per_instance(): void { $first = Instance::factory() ->type(InstanceType::Mastodon) ->enabled() ->create(['url' => 'https://aardvark.example']); $second = Instance::factory() ->type(InstanceType::Lemmy) ->enabled() ->create(['url' => 'https://zebra.example']); Page::factory() ->count(7) ->sequence(fn ($s) => ['url' => "https://aardvark.example/page-{$s->index}"]) ->createQuietly(['instance_id' => $first->id]); Page::factory() ->count(2) ->sequence(fn ($s) => ['url' => "https://zebra.example/page-{$s->index}"]) ->createQuietly(['instance_id' => $second->id]); $response = $this->get('/admin/instances'); // Each count cell must render as "{n} URLs" — this string cannot // collide with dates, IDs, or any other incidental numeric content, // so the assertion only passes when a real count column is wired in. $response->assertSeeInOrder([ $first->url, '7 URLs', $second->url, '2 URLs', ]); } }