withHeaders(['Accept-Language' => 'es']); Queue::fake(); } #[Test] public function a_page_stays_off_the_site_until_its_date(): void { Page::factory()->create([ 'status' => PageStatus::Published, 'title' => ['es' => 'El anuncio'], 'slug' => ['es' => 'el-anuncio'], 'published_at' => now()->addDay(), ]); $this->getJson('/api/public/v1/pages/el-anuncio')->assertNotFound(); $this->travel(2)->days(); $this->getJson('/api/public/v1/pages/el-anuncio')->assertOk(); } #[Test] public function a_page_drops_off_the_site_on_its_end_date(): void { Page::factory()->create([ 'status' => PageStatus::Published, 'title' => ['es' => 'Taller de octubre'], 'slug' => ['es' => 'taller'], 'published_at' => now()->subWeek(), 'unpublish_at' => now()->addDay(), ]); $this->getJson('/api/public/v1/pages/taller')->assertOk(); $this->travel(2)->days(); // Nobody has to remember to take it down, which is the whole point: // nobody ever does. $this->getJson('/api/public/v1/pages/taller')->assertNotFound(); } #[Test] public function the_window_holds_without_anything_running(): void { Page::factory()->create([ 'status' => PageStatus::Published, 'title' => ['es' => 'Caducada'], 'slug' => ['es' => 'caducada'], 'published_at' => now()->subMonth(), 'unpublish_at' => now()->subDay(), ]); // No command, no queue, no scheduler — the scope is what decides. $this->getJson('/api/public/v1/pages') ->assertOk() ->assertJsonCount(0, 'data'); } #[Test] public function an_expired_project_leaves_the_url_list_too(): void { Project::factory()->published()->create([ 'title' => ['es' => 'Terminado'], 'slug' => ['es' => 'terminado'], 'unpublish_at' => now()->subDay(), ]); $slugs = $this->getJson('/api/public/v1/slugs')->assertOk()->json('data'); // Otherwise the frontend would keep it in the sitemap and point search // engines at a 404. $this->assertEmpty($slugs['projects'] ?? []); } #[Test] public function preview_still_reaches_content_outside_its_window(): void { config()->set('site.preview_token', 'secreto'); Page::factory()->create([ 'status' => PageStatus::Published, 'title' => ['es' => 'Aún no'], 'slug' => ['es' => 'aun-no'], 'published_at' => now()->addWeek(), ]); // Checking a scheduled page before its date is exactly what preview is // for. $this->withHeaders(['X-Preview-Token' => 'secreto']) ->getJson('/api/public/v1/pages/aun-no') ->assertOk(); } #[Test] public function the_command_closes_a_call_whose_date_has_passed(): void { $call = Call::factory()->create([ 'project_id' => null, 'status' => CallStatus::Open, 'closes_at' => now()->subWeek(), ]); $this->artisan('content:schedule')->assertSuccessful(); // The site already stopped offering it; this is about the panel not // claiming otherwise, and a counter that stays worth reading. $this->assertSame(CallStatus::Closed, $call->refresh()->status); } #[Test] public function the_command_leaves_a_call_that_is_still_open(): void { $open = Call::factory()->create([ 'project_id' => null, 'status' => CallStatus::Open, 'closes_at' => now()->addWeek(), ]); $undated = Call::factory()->create([ 'project_id' => null, 'status' => CallStatus::Open, 'closes_at' => null, ]); $this->artisan('content:schedule')->assertSuccessful(); $this->assertSame(CallStatus::Open, $open->refresh()->status); $this->assertSame(CallStatus::Open, $undated->refresh()->status); } #[Test] public function a_dry_run_changes_nothing(): void { $call = Call::factory()->create([ 'project_id' => null, 'status' => CallStatus::Open, 'closes_at' => now()->subWeek(), ]); $this->artisan('content:schedule', ['--dry-run' => true])->assertSuccessful(); $this->assertSame(CallStatus::Open, $call->refresh()->status); } #[Test] public function the_panel_can_tell_the_three_states_apart(): void { $scheduled = Page::factory()->create([ 'status' => PageStatus::Published, 'published_at' => now()->addDays(3), ]); $expired = Page::factory()->create([ 'status' => PageStatus::Published, 'published_at' => now()->subMonth(), 'unpublish_at' => now()->subDay(), ]); $live = Page::factory()->create([ 'status' => PageStatus::Published, 'published_at' => now()->subDay(), ]); // A panel that reports "Published" for something the site is not // showing is lying to whoever wrote it. $this->assertTrue($scheduled->isScheduled()); $this->assertFalse($scheduled->hasExpired()); $this->assertTrue($expired->hasExpired()); $this->assertFalse($expired->isScheduled()); $this->assertFalse($live->isScheduled()); $this->assertFalse($live->hasExpired()); } #[Test] public function content_about_to_go_can_be_spotted_in_advance(): void { $soon = Page::factory()->create([ 'status' => PageStatus::Published, 'published_at' => now()->subMonth(), 'unpublish_at' => now()->addDays(2), ]); $later = Page::factory()->create([ 'status' => PageStatus::Published, 'published_at' => now()->subMonth(), 'unpublish_at' => now()->addMonths(2), ]); $this->assertTrue($soon->expiresSoon()); $this->assertFalse($later->expiresSoon()); } }