Add a regression test for the newest change winning
The existing tests cover the scheduling: serial-batches asserts that only one rebuild runs at a time, and the watcher tests cover event filtering and shutdown flushing. Neither asserts the outcome the bug was reported as — that what ends up written is the newest change. This drives the watcher wiring with an older change whose rebuild is slow and a newer change whose rebuild is fast, and asserts the newer result is written last. Against the previous fire-and-forget behaviour the two rebuilds overlap and the stale one lands on top, so the test fails. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Lcj4iQ3fBxMwAu2rf4zLbC
This commit is contained in:
parent
35a16706c7
commit
2b9a5c4112
1 changed files with 38 additions and 0 deletions
|
|
@ -76,3 +76,41 @@ it('waits for an entered watcher callback before shutdown flushes changes', asyn
|
|||
await queue.close()
|
||||
expect(calls).toEqual([['delayed-change']])
|
||||
})
|
||||
|
||||
it('writes the newest change last when an earlier rebuild is slower', async () => {
|
||||
// The reported bug: a rebuild for an older change finished *after* the rebuild
|
||||
// for a newer one and overwrote it, leaving stale CSS on disk. The serial
|
||||
// batches tests pin the scheduling on its own; this pins the outcome through
|
||||
// the watcher wiring, which is the shape the bug was reported in.
|
||||
let written: string[] = []
|
||||
let releaseSlowRebuild!: () => void
|
||||
let slowRebuildCanFinish = new Promise<void>((resolve) => (releaseSlowRebuild = resolve))
|
||||
|
||||
let queue = serializeBatches<string>(async (files) => {
|
||||
// Make the *first* rebuild the slow one. Without serialization the second
|
||||
// rebuild finishes first and this stale result lands on top of it.
|
||||
if (written.length === 0) await slowRebuildCanFinish
|
||||
written.push(files.at(-1)!)
|
||||
})
|
||||
let fake = fakeWatcher()
|
||||
await createWatchers(
|
||||
['/watch'],
|
||||
async () => {},
|
||||
queue,
|
||||
fake.watcher,
|
||||
async () => ({
|
||||
isFile: () => true,
|
||||
isSymbolicLink: () => false,
|
||||
}),
|
||||
)
|
||||
|
||||
await fake.callbacks[0](null, [{ type: 'update', path: 'older-change' }])
|
||||
await nextTask()
|
||||
await fake.callbacks[0](null, [{ type: 'update', path: 'newer-change' }])
|
||||
await nextTask()
|
||||
|
||||
releaseSlowRebuild()
|
||||
await queue.close()
|
||||
|
||||
expect(written).toEqual(['older-change', 'newer-change'])
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue