Application behavior tests #
These tests preserve Sift's behavior across the Bun migration and cover its
repaired defects. They do not modify application source files or use the
repository's lists.db.
Run #
Use Node.js 24 or newer for the test runner and SQLite fixture inspection, Bun
1.4.4 for the application, and agent-browser with Chromium for browser
tests. The orb already provides Node and the browser tools; .agents/setup
installs Bun and locked development dependencies.
./tests/run baseline
./tests/run regression
./tests/run all
baselinechecks existing behavior and should exit successfully.regressioncovers defects reproduced before the port. These are ordinary assertions, not skipped or expected-failure tests; they must now pass.allruns both groups and must pass.bun run testruns this command too.
Run one area independently with Node's test runner:
node --test tests/database.baseline.test.mjs
node --test tests/protocol.regression.test.mjs
node --test tests/browser.regression.test.mjs
The runner launches Bun, which executes TypeScript without type checking. Check the server and database types separately:
bun run check
Isolation and migration #
Each fixture copies the application's server, database module, and static assets into a temporary directory. Database workers and HTTP servers run there in child processes. Tests close connections, stop the processes, and remove their temporary databases. No live service or application data is required.
Passing database, protocol, and browser tests start with an explicitly created version-4 database. This isolates their behavior from fresh-database migration; it is not evidence that fresh startup works. Migration regressions instead start from an absent database or a historical schema and exercise the migration code.
The v2 fixture comes from the historical migration SQL. The v1 fixture is a reconstruction: no original v1 schema creator survives in available history. Its documented six-character room constraint is an assumption; its real foreign keys reproduce the child-data loss independently of that constraint. Cleanup tests advance only the isolated worker's JavaScript clock, not the machine clock.
HTTP/WebSocket tests use real connections, and browser tests use Chromium against the real server. Database tests call public database operations in separate processes and inspect persisted SQLite data. No production driver or transport is mocked.
Defects reproduced before the port #
| Contract | Observed failure before the port |
|---|---|
| Complete all pending migrations before use | Fresh/v1 stop at v2; v2 stops at v3; fresh reads/writes encounter missing columns |
| Preserve data during v1 migration | Rooms survive, but existing items and votes disappear |
| Return the number of expired rooms deleted | Two rooms disappear, but the helper returns zero |
| Expire empty rooms created after a v3 upgrade | A new room survives forty days because its activity is NULL |
| Enforce the WebSocket limit in bytes | Oversized UTF-8 input changes the shared title instead of closing with 1009 |
| Navigate and vote using loaded room items | j does not advance selection and 1 does not cast a vote |
Multiple tests expose the migration defects separately so one early failure does not hide missing columns or data loss. These are not ten unrelated bug fixes. The pre-port test commit retains the original Deno launcher and failing results. The Bun port changes the launcher, not those assertions. Node remains the independent test runner.
Additional regressions found during the Bun port #
These defects were reproduced against the port before applying their fixes:
| Contract | Observed failure |
|---|---|
| Preserve recent activity during upgrades | Startup cleanup deletes old rooms with recent items or votes |
| Expire legacy rooms with NULL activity | Already-v4 rooms created by the old insertion code never expire |
| Filter invalid bulk entries before database writes | A NUL-prefixed item rolls back otherwise valid additions |
| Escape cancels inline edits | Removing the focused editor triggers blur and persists the canceled draft |
| Help blocks list shortcuts | Enter votes instead of activating the focused close button |
| Room changes reset selection | A new room retains the previous room's selected item ID and cannot receive keyboard votes |
| Leaving discards undo history | Rejoining a room lets undo change a vote from the previous visit |
| Replacing or disabling an editor never saves its draft | A rerender overwrites a collaborator's edit; disconnect queues an unfinished draft for saving on reconnect |
| Unrelated updates preserve item drafts, focus, and text selection | Any list update cancels the editor, including another row's vote |
session.test.mjs exercises the public room-session interface against real Bun
servers and WebSockets. It replays late transport events to verify disposal and
socket replacement, checks reconnect/undo behavior, and checks the pending-message
limit. It runs with ./tests/run all or node --test tests/session.test.mjs.