test(e2e): say what the backup journey really touches, and pin it to promises

The file claimed it stayed inside its own account. "Backup now" enqueues the
pass for every account on the instance, so the header says that now, and says
what is confined instead: the restore's transaction, and the instance-wide
settings the dialog's opt-in leaves alone — which the journey asserts is clear
before it confirms, because a default that flipped would hand this file the
power to rewrite the document size cap for every spec sharing the server.

The run's own answer is asserted where it happens. Without it a missing worker
cost two minutes of polling and then blamed the backup pass for a 503 about
something else; the failure now names the endpoint in two seconds.

The rest are the assertions that pinned incidentals rather than promises: the
Argon2 cost comes from the constant the writer exports, so a legitimate cost
bump is not a red spec; the document is found by id rather than by position;
the poll compares the row against the row it saw before the click rather than
against the runner's clock; the non-admin bounce is pinned by pathname; the
empty-state CTA has its own test id, so nothing has to pick between two
buttons that share one; the deliberately corrupted copy is deleted when the
control is done with it instead of sitting in the console's list; and the
fixture orders by id after the timestamp so a tie cannot present as a change.
This commit is contained in:
Marc-André Bombeck committed 2026-09-10 05:48:18 +02:00
1 parent 6e4f3fb4c4
commit 343d6397a0
3 files changed
+113 -13

No files matched your search

+19 -2
View File
@@ -163,6 +163,19 @@ export async function storeTamperedCopy(backupId: string): Promise<string> {
});
}
/**
* Drop one stored copy again.
*
* The tampered copy the refusal control writes is the journey's own litter: it
* is not deleted until the next repetition's `beforeAll`, and until then it
* sits in the console's list for anyone who opens `/admin/backups`.
*/
export async function deleteStoredCopy(backupId: string): Promise<void> {
await withPool(async (pool) => {
await pool.query(`DELETE FROM data_backups WHERE id = $1`, [backupId]);
});
}
/** Every reading the account holds, tombstoned ones included. */
export async function storedMeasurements(): Promise<StoredMeasurement[]> {
const userId = await backupAccountId();
@@ -173,8 +186,12 @@ export async function storedMeasurements(): Promise<StoredMeasurement[]> {
value: string;
deleted_at: Date | null;
}>(
// `id` after the timestamp: the journey compares two whole arrays to
// prove a refusal changed nothing, and two readings sharing a timestamp
// could otherwise come back in either order and present as a change.
`SELECT id, type, value, deleted_at
FROM measurements WHERE user_id = $1 ORDER BY measured_at ASC`,
FROM measurements WHERE user_id = $1
ORDER BY measured_at ASC, id ASC`,
[userId],
);
return rows.map((row) => ({
@@ -194,7 +211,7 @@ export async function storedIntakeIds(): Promise<
return withPool(async (pool) => {
const { rows } = await pool.query<{ id: string; deleted_at: Date | null }>(
`SELECT id, deleted_at FROM medication_intake_events
WHERE user_id = $1 ORDER BY scheduled_for ASC`,
WHERE user_id = $1 ORDER BY scheduled_for ASC, id ASC`,
[userId],
);
return rows.map((row) => ({