tests: snapshot and reset view state around runs
Tests assume a normal board — no super-view, no bucket filter, manual sort, no hides. When the runner fired with the app left in super-view or with filters on, selectors like `.card[data-id]` missed the `.superview-item` DOM and multi-select / due-date assertions read the wrong initial values. Snapshot the relevant bits of window.state before the run, force a clean baseline, then restore the user's view afterwards so opening the runner doesn't silently wipe their context. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
1d6499e5dd
commit
1a889ea435
1 file changed
+84
@@ -170,6 +170,71 @@ export function csrf() {
|
|||||||
return getCsrf();
|
return getCsrf();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Snapshot the view-affecting bits of window.state so we can force a
|
||||||
|
// neutral baseline (normal board, no filter, manual sort, no hides)
|
||||||
|
// for the test run and restore the user's view afterwards. Tests were
|
||||||
|
// flaky when the runner fired while the board was in super-view: DOM
|
||||||
|
// selectors like `.card[data-id]` don't match `.superview-item`, so
|
||||||
|
// multi-select and due-date tests read wrong initial values.
|
||||||
|
export function snapshotViewState() {
|
||||||
|
const s = window.state;
|
||||||
|
if (!s) return null;
|
||||||
|
return {
|
||||||
|
superView: s.superView,
|
||||||
|
activeBucket: s.activeBucket,
|
||||||
|
activeTags: [...(s.activeTags || [])],
|
||||||
|
activeGroup: s.activeGroup,
|
||||||
|
sortMode: s.sortMode,
|
||||||
|
hideTermine: s.hideTermine,
|
||||||
|
hideDone: s.hideDone,
|
||||||
|
hideTagged: s.hideTagged,
|
||||||
|
boardSplitOpen: s.boardSplitOpen,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resetViewState() {
|
||||||
|
const s = window.state;
|
||||||
|
if (!s) return;
|
||||||
|
s.superView = false;
|
||||||
|
s.activeBucket = 'all';
|
||||||
|
s.activeTags = [];
|
||||||
|
s.activeGroup = null;
|
||||||
|
s.sortMode = 'manual';
|
||||||
|
s.hideTermine = false;
|
||||||
|
s.hideDone = false;
|
||||||
|
s.hideTagged = false;
|
||||||
|
s.boardSplitOpen = false;
|
||||||
|
s.selectedIds?.clear?.();
|
||||||
|
// Sync super-view toggle visuals with the reset state so tests that
|
||||||
|
// inspect the button see the correct pose.
|
||||||
|
const btn = document.getElementById('superview-toggle');
|
||||||
|
const icon = btn?.querySelector('i');
|
||||||
|
if (icon) icon.className = 'ph ph-list text-sm';
|
||||||
|
btn?.classList.remove('active');
|
||||||
|
window._renderBoard?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function restoreViewState(snap) {
|
||||||
|
const s = window.state;
|
||||||
|
if (!s || !snap) return;
|
||||||
|
Object.assign(s, {
|
||||||
|
superView: snap.superView,
|
||||||
|
activeBucket: snap.activeBucket,
|
||||||
|
activeTags: snap.activeTags,
|
||||||
|
activeGroup: snap.activeGroup,
|
||||||
|
sortMode: snap.sortMode,
|
||||||
|
hideTermine: snap.hideTermine,
|
||||||
|
hideDone: snap.hideDone,
|
||||||
|
hideTagged: snap.hideTagged,
|
||||||
|
boardSplitOpen: snap.boardSplitOpen,
|
||||||
|
});
|
||||||
|
const btn = document.getElementById('superview-toggle');
|
||||||
|
const icon = btn?.querySelector('i');
|
||||||
|
if (icon) icon.className = `ph ${snap.superView ? 'ph-squares-four' : 'ph-list'} text-sm`;
|
||||||
|
btn?.classList.toggle('active', !!snap.superView);
|
||||||
|
window._renderBoard?.();
|
||||||
|
}
|
||||||
|
|
||||||
export async function closeAll() {
|
export async function closeAll() {
|
||||||
document.getElementById('hterm')?.classList.add('hidden');
|
document.getElementById('hterm')?.classList.add('hidden');
|
||||||
for (const id of ['settings-overlay', 'help', 'shortcuts', 'search', 'calendar', 'gallery', 'detail', 'modal', 'tasks', 'dialog']) {
|
for (const id of ['settings-overlay', 'help', 'shortcuts', 'search', 'calendar', 'gallery', 'detail', 'modal', 'tasks', 'dialog']) {
|
||||||
@@ -452,6 +517,15 @@ async function run() {
|
|||||||
stopBackgroundSync();
|
stopBackgroundSync();
|
||||||
window._testRunning = true;
|
window._testRunning = true;
|
||||||
|
|
||||||
|
// 2b. Snapshot + reset view state. Tests assume a normal board with
|
||||||
|
// no filters / super-view off / manual sort — if the user left the
|
||||||
|
// app in super-view or with a bucket filter active, assertions on
|
||||||
|
// .card[data-id], card count, etc. read wrong initial values.
|
||||||
|
const viewSnap = snapshotViewState();
|
||||||
|
await closeAll();
|
||||||
|
resetViewState();
|
||||||
|
await sleep(50);
|
||||||
|
|
||||||
// 3. Hide panel so tests run against visible UI
|
// 3. Hide panel so tests run against visible UI
|
||||||
panel.style.display = 'none';
|
panel.style.display = 'none';
|
||||||
await sleep(100);
|
await sleep(100);
|
||||||
@@ -476,6 +550,11 @@ async function run() {
|
|||||||
await window._reloadAll?.();
|
await window._reloadAll?.();
|
||||||
await sleep(200);
|
await sleep(200);
|
||||||
} catch {}
|
} catch {}
|
||||||
|
// Re-reset the view in case a failing test left it in super-view,
|
||||||
|
// a bucket filter, or a sorted mode — otherwise the retry runs
|
||||||
|
// against the same wrong baseline that flaked it the first time.
|
||||||
|
resetViewState();
|
||||||
|
await sleep(50);
|
||||||
const retryResults = await runAll(failedKeys);
|
const retryResults = await runAll(failedKeys);
|
||||||
const retryMap = new Map();
|
const retryMap = new Map();
|
||||||
for (const sr of retryResults) {
|
for (const sr of retryResults) {
|
||||||
@@ -508,6 +587,11 @@ async function run() {
|
|||||||
await sleep(200);
|
await sleep(200);
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
|
// 6b. Put the view back the way the user left it (super-view, sort,
|
||||||
|
// filters, …) so launching the test runner doesn't silently wipe
|
||||||
|
// their working context.
|
||||||
|
restoreViewState(viewSnap);
|
||||||
|
|
||||||
// 7. Resume background sync (delay to avoid immediate re-sync creating duplicates)
|
// 7. Resume background sync (delay to avoid immediate re-sync creating duplicates)
|
||||||
window._testRunning = false;
|
window._testRunning = false;
|
||||||
setTimeout(() => startBackgroundSync(), 60000);
|
setTimeout(() => startBackgroundSync(), 60000);
|
||||||
|
|||||||
Reference in new issue
Block a user