diff --git a/tests/Feature/Phase5ShortsTest.php b/tests/Feature/Phase5ShortsTest.php new file mode 100644 index 0000000..9a468c0 --- /dev/null +++ b/tests/Feature/Phase5ShortsTest.php @@ -0,0 +1,141 @@ +withoutMiddleware([ + VerifyCsrfToken::class, + \Illuminate\Session\Middleware\AuthenticateSession::class, + ]); + } + + // ─── /shorts/{id} deep-link ────────────────────── + + public function test_shorts_deep_link_renders_feed_scrolled_to_target(): void + { + $owner = $this->makeUser(); + $short = $this->makeShort($owner, 'DEEP LINK SHORT'); + + $html = $this->get(route('videos.shorts.focused', $short))->assertOk()->getContent(); + + $this->assertStringContainsString('DEEP LINK SHORT', $html); + // The in-page scroller is driven by data-id matching the start id. + $this->assertStringContainsString('data-id="' . $short->id . '"', $html); + $this->assertStringContainsString('scrollIntoView', $html); + } + + public function test_shorts_deep_link_404s_on_non_short(): void + { + $owner = $this->makeUser(); + $regular = Video::create([ + 'user_id' => $owner->id, + 'title' => 'not a short', + 'description'=> '', + 'filename' => 'users/x/videos/y/video.mp4', + 'path' => 'users/x/videos/y/video.mp4', + 'type' => 'generic', + 'visibility' => 'public', + 'status' => 'ready', + 'is_shorts' => false, + 'share_token'=> bin2hex(random_bytes(8)), + ]); + + $this->get('/shorts/' . Video::encodeId($regular->id))->assertStatus(404); + } + + // ─── Home shelf ────────────────────────────────── + + public function test_home_shows_shorts_shelf_when_shorts_exist(): void + { + $owner = $this->makeUser(); + $s = $this->makeShort($owner, 'SHELF SHORT'); + + $html = $this->get(route('home'))->assertOk()->getContent(); + + $this->assertStringContainsString('home-shorts-shelf', $html); + $this->assertStringContainsString('SHELF SHORT', $html); + $this->assertStringContainsString('/shorts/' . Video::encodeId($s->id), $html); + } + + public function test_home_omits_shorts_shelf_when_no_shorts(): void + { + $owner = $this->makeUser(); + // A regular video so the home feed renders, but no shorts. + Video::create([ + 'user_id' => $owner->id, + 'title' => 'reg', + 'description'=> '', + 'filename' => 'users/x/videos/y/video.mp4', + 'path' => 'users/x/videos/y/video.mp4', + 'type' => 'generic', + 'visibility' => 'public', + 'status' => 'ready', + 'is_shorts' => false, + 'share_token'=> bin2hex(random_bytes(8)), + ]); + + $html = $this->get(route('home'))->assertOk()->getContent(); + + $this->assertStringNotContainsString('home-shorts-shelf', $html); + } + + // ─── Branded 404 ───────────────────────────────── + + public function test_unknown_url_renders_branded_404(): void + { + $r = $this->get('/no-such-page')->assertStatus(404); + + $r->assertSee('Error 404', false); + } + + // ─── Helpers ───────────────────────────────────── + + private function makeUser(): User + { + return User::factory()->create([ + 'username' => 'u'.substr(bin2hex(random_bytes(4)), 0, 8), + ]); + } + + private function makeShort(User $u, string $title): Video + { + return Video::create([ + 'user_id' => $u->id, + 'title' => $title, + 'description'=> '', + 'filename' => 'users/x/videos/'.substr(bin2hex(random_bytes(4)), 0, 8).'/video.mp4', + 'path' => 'users/x/videos/'.substr(bin2hex(random_bytes(4)), 0, 8).'/video.mp4', + 'type' => 'generic', + 'visibility' => 'public', + 'status' => 'ready', + 'is_shorts' => true, + 'duration' => 45, + 'orientation'=> 'portrait', + 'share_token'=> bin2hex(random_bytes(8)), + ]); + } +}