111 lines
3.6 KiB
PHP
111 lines
3.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Unit\Models;
|
|
|
|
use App\Enums\CrawlOutcomeEnum;
|
|
use App\Models\Page;
|
|
use App\Models\PageCrawl;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Tests\TestCase;
|
|
|
|
class PageCrawlTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
public function test_page_crawl_fillable_fields_persist_and_casts_are_applied(): void
|
|
{
|
|
$page = Page::factory()->create(['url' => 'https://example.com/page-1']);
|
|
|
|
$scheduledFor = Carbon::parse('2026-05-01 10:00:00');
|
|
$lockedAt = Carbon::parse('2026-05-01 10:01:00');
|
|
$completedAt = Carbon::parse('2026-05-01 10:01:05');
|
|
|
|
$crawl = PageCrawl::create([
|
|
'page_id' => $page->id,
|
|
'domain' => 'example.com',
|
|
'priority' => 5,
|
|
'scheduled_for' => $scheduledFor,
|
|
'locked_at' => $lockedAt,
|
|
'completed_at' => $completedAt,
|
|
'outcome' => CrawlOutcomeEnum::Success,
|
|
'status_code' => 200,
|
|
'error_message' => null,
|
|
]);
|
|
|
|
$fresh = $crawl->fresh();
|
|
|
|
$this->assertNotNull($fresh);
|
|
|
|
// domain / priority round-trip
|
|
$this->assertSame('example.com', $fresh->domain);
|
|
$this->assertSame(5, $fresh->priority);
|
|
|
|
// outcome is cast to the enum
|
|
$this->assertInstanceOf(CrawlOutcomeEnum::class, $fresh->outcome);
|
|
$this->assertSame(CrawlOutcomeEnum::Success, $fresh->outcome);
|
|
|
|
// datetime casts
|
|
$this->assertInstanceOf(Carbon::class, $fresh->scheduled_for);
|
|
$this->assertInstanceOf(Carbon::class, $fresh->locked_at);
|
|
$this->assertInstanceOf(Carbon::class, $fresh->completed_at);
|
|
|
|
$this->assertTrue($scheduledFor->equalTo($fresh->scheduled_for));
|
|
$this->assertTrue($lockedAt->equalTo($fresh->locked_at));
|
|
$this->assertTrue($completedAt->equalTo($fresh->completed_at));
|
|
|
|
// nullable columns
|
|
$this->assertNull($fresh->error_message);
|
|
|
|
// status_code persists
|
|
$this->assertSame(200, $fresh->status_code);
|
|
}
|
|
|
|
public function test_page_crawl_belongs_to_a_page(): void
|
|
{
|
|
$page = Page::factory()->create(['url' => 'https://example.com/page-2']);
|
|
|
|
$crawl = PageCrawl::create([
|
|
'page_id' => $page->id,
|
|
'domain' => 'example.com',
|
|
'priority' => 1,
|
|
'scheduled_for' => Carbon::now(),
|
|
]);
|
|
|
|
$related = $crawl->page;
|
|
|
|
$this->assertInstanceOf(Page::class, $related);
|
|
$this->assertSame($page->id, $related->id);
|
|
}
|
|
|
|
public function test_deleting_a_page_cascades_to_its_page_crawls(): void
|
|
{
|
|
$page = Page::factory()->create(['url' => 'https://example.com/page-cascade']);
|
|
|
|
PageCrawl::factory()->page($page)->create();
|
|
PageCrawl::factory()->page($page)->successful()->create();
|
|
PageCrawl::factory()->page($page)->failed('timeout during fetch')->create();
|
|
|
|
$this->assertSame(3, PageCrawl::count());
|
|
|
|
$page->delete();
|
|
|
|
$this->assertSame(0, PageCrawl::count());
|
|
}
|
|
|
|
public function test_pending_crawls_are_filtered_by_null_outcome(): void
|
|
{
|
|
$page = Page::factory()->create(['url' => 'https://example.com/page-pending']);
|
|
|
|
$pending = PageCrawl::factory()->page($page)->create();
|
|
PageCrawl::factory()->page($page)->successful()->create();
|
|
PageCrawl::factory()->page($page)->failed('connection refused')->create();
|
|
|
|
$this->assertSame(1, PageCrawl::whereNull('outcome')->count());
|
|
$this->assertSame($pending->id, PageCrawl::whereNull('outcome')->first()->id);
|
|
|
|
$this->assertSame(2, PageCrawl::whereNotNull('outcome')->count());
|
|
}
|
|
}
|