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]>
Context: on 2026-10-21 the dev SQLite DB was wiped because an early
revision of Phase 1 tests called RefreshDatabase before the per-test
config() swap had been applied, so migrate:fresh ran against the real
database file. Restored from data/backups/db-20261020-033001.sqlite
(24 users, 72 videos, 32 comments recovered); anything created between
Oct 20 03:30 and Oct 21 08:25 needs manual rebuild from NAS.
Two layers of defense added so this cannot recur:
1. .env.testing — forces DB_CONNECTION=sqlite and DB_DATABASE=:memory:
at the earliest bootstrap stage, before any trait setUp hook runs.
Also carries the APP_KEY and testing-safe defaults for mail/queue
/session.
2. TestCase::assertSafeTestDatabase() — a belt-and-braces guard that
aborts the whole phpunit run (exit code 2) if the resolved default
DB target is anything other than :memory: or a /testing/ or /tmp/
path. The abort happens BEFORE any query can execute.
Running the suite with a bad DB target now prints a stderr banner and
stops instantly; the dev file is safe even if someone writes a new
test that forgets to override the connection.
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]>