Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
import { describe, it } from "@suaveplan/testing/runner";
import * as fc from "fast-check";
import { createCommand } from "../../src/command/command.js";
import { UndoStack } from "../../src/stack/stack.js";
interface Counter {
value: number;
}
describe("property: UndoStack invariants", () => {
it("push N, undo all, redo all: final state = after-push state", {
timeout: 30000,
}, () => {
fc.assert(
fc.property(
fc.array(fc.integer({ min: 1, max: 10 }), {
minLength: 1,
maxLength: 20,
}),
(deltas) => {
const s = new UndoStack<Counter>({ value: 0 });
for (const d of deltas) {
s.push(
createCommand(
"D",
(st) => ({ value: st.value + d }),
(st) => ({ value: st.value - d })
)
);
}
const afterPush = s.current.value;
for (let i = 0; i < deltas.length; i++) s.undo();
for (let i = 0; i < deltas.length; i++) s.redo();
return s.current.value === afterPush;
}
),
{ numRuns: 200 }
);
});
it("undoSize never exceeds maxEntries", { timeout: 30000 }, () => {
fc.assert(
fc.property(
fc.integer({ min: 1, max: 20 }),
fc.array(fc.integer({ min: 1, max: 5 }), {
minLength: 0,
maxLength: 50,
}),
(maxEntries, deltas) => {
const s = new UndoStack<Counter>(
{ value: 0 },
{ maxEntries }
);
for (const d of deltas) {
s.push(
createCommand(
"D",
(st) => ({ value: st.value + d }),
(st) => ({ value: st.value - d })
)
);
}
return s.undoSize <= maxEntries;
}
),
{ numRuns: 200 }
);
});
it("undoSize + redoSize = total pushed (within maxEntries limit)", {
timeout: 30000,
}, () => {
fc.assert(
fc.property(
fc.array(fc.integer({ min: 1, max: 5 }), {
minLength: 0,
maxLength: 15,
}),
fc.integer({ min: 0, max: 15 }),
(deltas, undoSteps) => {
const s = new UndoStack<Counter>({ value: 0 });
for (const d of deltas) {
s.push(
createCommand(
"D",
(st) => ({ value: st.value + d }),
(st) => ({ value: st.value - d })
)
);
}
const steps = Math.min(undoSteps, deltas.length);
for (let i = 0; i < steps; i++) s.undo();
return s.undoSize + s.redoSize === deltas.length;
}
),
{ numRuns: 200 }
);
});
});