* card-interactions.test.js: group delete tests used `.dialog-ok` (class selector) but the button has `id="dialog-ok"`. querySelector returned null, the click was skipped, the dialog stayed open and blocked every downstream test. Fixed to getElementById. * runner.js closeAll(): added #dialog, #bucket-super-popover (remove), and #gitea-overlay to the cleanup list. A failed test that leaves any of these open no longer poisons the rest of the suite. * runner.js copy handler: when there are failures or flaky tests, the "copy" button now builds the clipboard text from lastResults — only failed + flaky lines (suite name, test name, timing, error, original error for retried). When everything passed, copies the full output as before. lastResults is set in renderResults(). * bucket-context.test.js: move-left test used `[data-bucket]` to find user bucket tabs, which misses super-bucket tiles (they carry `data-bucket-super`). Changed to `[data-bucket-drag]` which is on both regular and super-bucket tiles but not on fixed filters. * context-menu.test.js: make-ticket pre-fill assertion now polls up to 2s for the title input to be populated (async openCreateForm repo-fetch was racing against the immediate assertion). * card-join.test.js: clickJoin sleep bumped from 400ms → 800ms. joinSelectedCards does 3+ serial API calls (fetch bodies, PATCH winner, N×DELETE losers, _reloadAll) which sometimes exceeded the old 400ms window on slow runs. * Runner cache: RUNNER_V bumped from ?v=2 → ?v=3 in loader.js + all 42 test files so the browser picks up the new runner.js content (copy handler, closeAll, retry progress bar) without a hard reload. super-buckets: remember last selection per group * buckets.js: module-scope lastSuperSelection Map tracks the last active member per super-bucket parent. Updated in renderBar() whenever activeBucket matches a group member. tileFor() uses it as a fallback when the user is on a different bucket — the tile shows the last-picked child's name and color instead of reverting to the parent. The dropdown popover also highlights the last selection when no member is currently active. chore: bump version to 0.9.11 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
86 lines
3.8 KiB
JavaScript
86 lines
3.8 KiB
JavaScript
// ── Tests Plugin: conditional loader ──
|
|
//
|
|
// The test runner is heavy (40+ test files), so we only load it when:
|
|
// - URL contains ?test query param → auto-run
|
|
// - Ctrl+Shift+Alt+T pressed → manual open
|
|
//
|
|
// Tests are completely optional — without this plugin the app has no
|
|
// test runner code loaded at all.
|
|
|
|
const hyprcrd = window.hyprcrd;
|
|
|
|
// Cache-bust the test modules so edits to test files are picked up without
|
|
// a hard refresh. The browser treats each unique URL as a distinct module,
|
|
// so a fresh query string on each page load forces re-import.
|
|
const V = '?v=' + Date.now();
|
|
|
|
// Auto-load if ?test in query string
|
|
if (new URLSearchParams(location.search).has('test')) {
|
|
ensureProgressBar();
|
|
import('./tests.js' + V);
|
|
}
|
|
|
|
// Keyboard shortcut: Ctrl+Shift+Alt+T → open runner.
|
|
//
|
|
// runner.js is imported with the SAME `?v=2` query string the test
|
|
// files use (see RUNNER_V below). Same URL → same module instance, so
|
|
// suite registration in test files and runAll in the loader run against
|
|
// the same `suites` array. Bump RUNNER_V whenever runner.js changes
|
|
// in a way that needs cache invalidation across users.
|
|
document.addEventListener('keydown', e => {
|
|
if (e.ctrlKey && e.shiftKey && e.altKey && (e.key === 'T' || e.key === 't')) {
|
|
e.preventDefault();
|
|
ensureProgressBar();
|
|
import('./tests.js' + V).then(() =>
|
|
import('./runner.js' + RUNNER_V).then(m => m.open?.())
|
|
);
|
|
}
|
|
});
|
|
|
|
// Must match the `?v=…` suffix used in test files' `from './runner.js?v=…'`
|
|
// imports — bump both in lock-step to invalidate the runner.js cache.
|
|
const RUNNER_V = '?v=3';
|
|
|
|
function ensureProgressBar() {
|
|
if (document.getElementById('test-progress')) return;
|
|
// Push the whole document down by 30px AND shrink the body by the
|
|
// same amount so the footer doesn't get clipped (body is h-screen +
|
|
// overflow-hidden, so without the height shrink the bottom 30px get
|
|
// pushed off-viewport). hideProgress() reverts both.
|
|
document.body.style.marginTop = '30px';
|
|
document.body.style.height = 'calc(100vh - 30px)';
|
|
const bar = document.createElement('div');
|
|
bar.id = 'test-progress';
|
|
const s = bar.style;
|
|
s.setProperty('position', 'fixed', 'important');
|
|
s.setProperty('top', '0', 'important');
|
|
s.setProperty('left', '0', 'important');
|
|
s.setProperty('right', '0', 'important');
|
|
s.setProperty('height', '30px', 'important');
|
|
s.setProperty('z-index', '2147483647', 'important');
|
|
s.setProperty('background', '#000', 'important');
|
|
s.setProperty('color', '#cbd5e1', 'important');
|
|
s.setProperty('font-family', 'monospace', 'important');
|
|
s.setProperty('font-size', '11px', 'important');
|
|
s.setProperty('display', 'flex', 'important');
|
|
s.setProperty('align-items', 'center', 'important');
|
|
s.setProperty('gap', '10px', 'important');
|
|
s.setProperty('padding', '0 12px', 'important');
|
|
s.setProperty('border-bottom', '1px solid #334155', 'important');
|
|
s.setProperty('pointer-events', 'none', 'important');
|
|
bar.innerHTML = `
|
|
<span id="test-progress-label" style="white-space:nowrap;color:#38bdf8;font-weight:bold;flex-shrink:0;">tests starting…</span>
|
|
<span id="test-progress-name" style="flex:1 1 0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#94a3b8;"></span>
|
|
<div style="position:relative;flex:0 0 50%;height:10px;background:#1e293b;border:1px solid #334155;">
|
|
<div id="test-progress-fill" style="position:absolute;left:0;top:0;bottom:0;width:0%;background:#38bdf8;transition:width 0.15s linear;"></div>
|
|
</div>
|
|
`;
|
|
document.documentElement.appendChild(bar);
|
|
}
|
|
|
|
hyprcrd?.registerPlugin?.({
|
|
name: 'tests',
|
|
version: '1.0.0',
|
|
description: 'UI + state test runner',
|
|
});
|