Five tests:
- /shorts/{id} renders the vertical feed with data-id matching the
target short and includes the scrollIntoView bootstrap.
- /shorts/{id} 404s when the id resolves to a non-short video.
- Home page shows .home-shorts-shelf when at least one short exists,
with a link to /shorts/{id} for every shelf card.
- Home page omits the shelf entirely when no shorts exist.
- An unknown URL returns 404 with the branded view, not the bare
framework stacktrace.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
142 lines
4.8 KiB
PHP
142 lines
4.8 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Http\Middleware\VerifyCsrfToken;
|
|
use App\Models\User;
|
|
use App\Models\Video;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Tests\TestCase;
|
|
|
|
/**
|
|
* Phase 5 — Shorts.
|
|
*
|
|
* Guards against regressions in the deep-link route, the Home shelf, and
|
|
* the branded 404 fallback.
|
|
*/
|
|
class Phase5ShortsTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
putenv('DB_CONNECTION=sqlite');
|
|
putenv('DB_DATABASE=:memory:');
|
|
$_ENV['DB_CONNECTION'] = 'sqlite';
|
|
$_ENV['DB_DATABASE'] = ':memory:';
|
|
|
|
parent::setUp();
|
|
|
|
$this->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)),
|
|
]);
|
|
}
|
|
}
|