Also tightens stat/post-video rendering so "0" prints as "0" and not
"0.0" (Number::abbreviate(0, precision: 1) stringifies as "0.0", which
leaked into the About tab's Total Views card and post-video badges).
Four tests covering:
- /@username opens the matching channel.
- /@invalid url (space) 404s.
- Owner view shows id="postForm"; preview?preview=1 hides it.
- Zero-view playlist doesn't render "bi-eye … 0.0"; "1 videos" never
renders in place of "1 video".
Fixed a Blade dupe-declaration fatal that only fired in feature tests
(two requests in one PHP process would redeclare notifVal()). Guarded
with function_exists.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
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]>
- All three type-specific watch templates (generic / music / match)
were still rendering the Up Next list as <div onclick="recGoTo(...)">
— only show.blade.php had been converted in the earlier commit.
Convert each to <a href> so middle-click / right-click / cmd-click
open-in-new-tab work, keeping the SPA swap on normal left-click via
an onclick guard that lets modified clicks fall through.
- 9 feature tests covering: singular/plural comment counts, top-level
vs reply separation, ?lc= permalink HREFs, markdown header
promotion in HtmlSanitizer::render(), passthrough of plain text,
download access gate for both MP4 and MP3 at disabled + registered
tiers, and sidebar anchor-card presence.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Six feature tests:
- Trending accepts hours=24|168|720, snaps garbage input to 24.
- Trending ranks by in-window views then likes; videos with zero
in-window views are dropped.
- Music feed opens on the newest video (regression test for the
skipped-->latest() call in VideoController@index).
- Old /videos/search?q=... returns a 301 to /search?q=...
- /search matches on video title, channel name, and playlist name
separately; each surfaces in its own Section.
- Empty /search?q= redirects to /videos browse.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Seven feature tests covering:
- the per-card edit modal is gone (id="editVideoModal{slug}" and the
.cute-edit-modal class),
- owner sees Edit/Delete and no Report/Not-interested,
- non-owner sees Report/Not-interested and no Edit/Delete,
- card thumbnail img carries width/height and loading="lazy",
- feedMore returns JSON with items + next_cursor + has_more,
- feedMore rejects unknown filters by returning an empty slice,
- comments component ships the reply <template>, not inline forms.
While wiring these up I also deleted the 300-line .cute-edit-modal CSS
block that was still shipping in card-styles.blade.php even though its
markup was removed in the previous commit — the CSS was pointing at
IDs that no longer exist.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Seven feature tests, run against an in-memory SQLite forced via putenv
in setUp (keeps the shared dev DB safe). Covers:
- Reserved-identifier rule rejects admin / super_admin / takeone /
support / etc, matches both name and email local-part only, and
lets normal names through.
- SafeNotifier swallows a notification throw without re-raising.
- Identical comments within 60s collapse to the first row.
- X-Idempotency-Key returns the first comment on retry.
- Owner viewing their own video does not insert a video_views row.
AppServiceProvider stops force-upgrading the scheme in the testing env
so the HTTP test client isn't 302'd before reaching the controller.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>