mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-04 13:48:57 +00:00
test(adoption): the post-write smoke resets its own pending writes
Review r2 M1. The smoke's reset() left the previous scenario's debounced config/layout write pending; _deleteSpace flushes whatever is pending before it writes, the fake socket answers without a rev, and the documented rev+1 fallback then moved the revision on a body from another scenario. The refused branch looked as if it had adopted: onboardingDeleteRefusedAdoptsNothing was red on every run. The scenarios are supposed to be independent, so reset() now cancels both debounced writers, as smoke_danger_confirmation already does. 37/37 green, three runs in a row; with the cancel removed the same single check goes red again. The refused-tail fix from r1 had no witness in CI at all: no mutant named this smoke as its guard, so the review gate never ran it and a red witness survived a whole round. A witness that never runs is not a witness, so the early return in _undoPlanOptimization now has a mutant that names the smoke. Issue: #500 User-Visible: no
This commit is contained in:
@@ -80,6 +80,13 @@ const out = await page.evaluate(async () => {
|
||||
};
|
||||
|
||||
const reset = async (scenario) => {
|
||||
// Ревью r2 M1: отложенная запись предыдущего сценария иначе доживает до
|
||||
// следующего и флашится безусловным `if (pending) flush()` внутри
|
||||
// `_deleteSpace`; мок отвечает `{}` без `rev`, запасной путь «rev + 1»
|
||||
// двигает ревизию по ЧУЖОМУ телу, и отказная ветка выглядит принявшей.
|
||||
// Сценарии обязаны быть независимы — так же чистится smoke_danger_confirmation.
|
||||
card._saveConfigDebounced.cancel();
|
||||
card._persistLayout.cancel();
|
||||
server = { config: freshConfig(), layout: {}, cfgRev: 10, layRev: 20 };
|
||||
concurrentHref = `media-source://image/${scenario}-500`;
|
||||
adoption.restoreCached({ config: structuredClone(server.config), rev: 10, layout: {}, layout_rev: 20 });
|
||||
|
||||
@@ -8555,6 +8555,20 @@ const MUTANT_DEFINITIONS = [
|
||||
+ ' || contentFingerprint(current) !== attempt.attemptedFingerprint) return false;',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'post-write-tail-runs-on-refused-gate',
|
||||
guard: 'node demo/smoke_post_write_adoption.mjs',
|
||||
because: '#500 r1 M1: a post-write caller whose adoption was refused must skip its tail — '
|
||||
+ 'clearing history, bumping the geometry epoch and toasting «отменено» on a body the card '
|
||||
+ 'never adopted leaves the frontend describing state the server does not have; the scheduled '
|
||||
+ 'reload owns the tail. Guarded by the smoke, so the review gate runs it (r2 M1: the witness '
|
||||
+ 'was red for a round and nobody saw it — CI never ran this smoke)',
|
||||
patches: [{
|
||||
file: 'src/houseplan-editor-runtime.ts',
|
||||
find: " if (adopted.status !== 'adopted') return; // asset wait: the scheduled reload owns the tail",
|
||||
replace: ' void adopted; // mutant: the tail runs on a body that was never adopted',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'post-write-skips-asset-gate',
|
||||
guard: 'node --test test/config-adoption.test.mjs',
|
||||
|
||||
Reference in New Issue
Block a user