|
36 | 36 | // |
37 | 37 | // The file owns its boot (and its database file): it writes ledger rows, so it |
38 | 38 | // may not share a showcase with any other file. |
| 39 | +// |
| 40 | +// The task the Mark Done cases act on is picked as a not-done one in a stable |
| 41 | +// order, and its `done === false` is asserted in `beforeAll`: the seed carries |
| 42 | +// done tasks too, and an unordered first row could be one of them, which |
| 43 | +// acceptance[0]'s "nothing written" check cannot tell from a refusal. |
39 | 44 |
|
40 | 45 | import { describe, it, expect, beforeAll, afterAll } from 'vitest'; |
41 | 46 | import { mkdtempSync, rmSync } from 'node:fs'; |
@@ -65,7 +70,6 @@ describe('[#26572] a disabled packaged action is refused at both doors, over HTT |
65 | 70 | let dir: string; |
66 | 71 | let dbFile: string; |
67 | 72 | let taskId: string; |
68 | | - let markDoneRowId: unknown; |
69 | 73 |
|
70 | 74 | const boot = (file: string) => bootShowcase({ databaseFile: file, extraPlugins: [new MCPServerPlugin()] }); |
71 | 75 |
|
@@ -115,9 +119,13 @@ describe('[#26572] a disabled packaged action is refused at both doors, over HTT |
115 | 119 | dbFile = join(dir, 'showcase.db'); |
116 | 120 | stack = await boot(dbFile); |
117 | 121 | admin = await stack.signIn(); |
118 | | - const list = await call(admin, 'GET', '/data/showcase_task?$top=1'); |
119 | | - taskId = list.json.records[0].id; |
120 | | - expect(taskId).toBeTruthy(); |
| 122 | + const notDone = encodeURIComponent(JSON.stringify({ done: false })); |
| 123 | + const list = await call(admin, 'GET', `/data/showcase_task?$filter=${notDone}&$orderby=id&$top=1`); |
| 124 | + expect(list.status, list.text).toBe(200); |
| 125 | + taskId = list.json.records[0]?.id; |
| 126 | + expect(taskId, 'setup: the showcase seed has no task with done = false').toBeTruthy(); |
| 127 | + // The precondition acceptance[0] rests on, asserted before any switch flips. |
| 128 | + expect((await readTask(taskId)).done, `setup: task ${taskId} was picked as not done`).toBe(false); |
121 | 129 | }, 240_000); |
122 | 130 |
|
123 | 131 | afterAll(async () => { |
@@ -152,9 +160,7 @@ describe('[#26572] a disabled packaged action is refused at both doors, over HTT |
152 | 160 | .toEqual({ done: before.done, progress: before.progress, updated_at: before.updated_at }); |
153 | 161 | expect(after.done).toBe(false); |
154 | 162 |
|
155 | | - const rows = await actionRows('showcase_mark_done'); |
156 | | - expect(rows).toHaveLength(1); |
157 | | - markDoneRowId = rows[0].id; |
| 163 | + expect(await actionRows('showcase_mark_done')).toHaveLength(1); |
158 | 164 | }); |
159 | 165 |
|
160 | 166 | it('acceptance[1]: the consult precedes the param contract — 409 disabled, 400 enabled, for the identical request', async () => { |
@@ -233,6 +239,12 @@ describe('[#26572] a disabled packaged action is refused at both doors, over HTT |
233 | 239 | }); |
234 | 240 |
|
235 | 241 | it('acceptance[5] / [2]: after a cold boot the switch holds; re-enabling updates the same row and re-arms dispatch', async () => { |
| 242 | + // The row acceptance[0]'s switch wrote, read here before the reboot. |
| 243 | + const rowsBeforeBoot = await actionRows('showcase_mark_done'); |
| 244 | + expect(rowsBeforeBoot, 'acceptance[0] disables showcase_mark_done; this clause re-reads the ledger row it wrote') |
| 245 | + .toHaveLength(1); |
| 246 | + const markDoneRowId = rowsBeforeBoot[0].id; |
| 247 | + |
236 | 248 | await stack.stop(); |
237 | 249 | stack = await boot(dbFile); |
238 | 250 | admin = await stack.signIn(); |
|
0 commit comments