test fixes: dialog selector, closeAll scope, copy filter, runner ?v=3
* 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>
This commit is contained in:
1 parent
56c90225cb
commit
c8835825e7
47 files changed
+126
-56
No files matched your search
@@ -171,7 +171,7 @@ export function csrf() {
|
||||
}
|
||||
|
||||
export async function closeAll() {
|
||||
for (const id of ['settings-overlay', 'help', 'search', 'calendar', 'gallery', 'detail', 'modal', 'tasks']) {
|
||||
for (const id of ['settings-overlay', 'help', 'search', 'calendar', 'gallery', 'detail', 'modal', 'tasks', 'dialog']) {
|
||||
const el = document.getElementById(id);
|
||||
if (el?.classList.contains('open')) el.classList.remove('open');
|
||||
}
|
||||
@@ -179,6 +179,8 @@ export async function closeAll() {
|
||||
document.querySelector('#select-bar')?.classList.add('hidden');
|
||||
document.querySelector('.bucket-picker')?.remove();
|
||||
document.querySelector('.orphan-lightbox')?.remove();
|
||||
document.getElementById('bucket-super-popover')?.remove();
|
||||
document.getElementById('gitea-overlay')?.classList.remove('open');
|
||||
// Clear multi-select
|
||||
document.querySelectorAll('.card-selected').forEach(el => {
|
||||
el.classList.remove('card-selected');
|
||||
@@ -289,6 +291,7 @@ async function runAll(only = null) {
|
||||
// ── UI Panel ──
|
||||
|
||||
let panel = null;
|
||||
let lastResults = null;
|
||||
|
||||
function createPanel() {
|
||||
if (panel) { panel.remove(); panel = null; }
|
||||
@@ -309,9 +312,35 @@ function createPanel() {
|
||||
document.body.appendChild(panel);
|
||||
panel.querySelector('#test-close-btn').addEventListener('click', close);
|
||||
panel.querySelector('#test-run-btn').addEventListener('click', run);
|
||||
// Copy: when failures exist, only copy the failed + flaky tests so
|
||||
// the user can paste the relevant part without wading through 200+
|
||||
// lines of green. When everything passed, copy the full output.
|
||||
panel.querySelector('#test-copy-btn').addEventListener('click', () => {
|
||||
const output = panel.querySelector('#test-output');
|
||||
const text = output.innerText;
|
||||
let text;
|
||||
if (lastResults) {
|
||||
const hasFailures = lastResults.some(s => s.tests.some(t => t.status === 'fail' || t.retried));
|
||||
if (hasFailures) {
|
||||
const lines = [];
|
||||
for (const s of lastResults) {
|
||||
const relevant = s.tests.filter(t => t.status === 'fail' || t.retried);
|
||||
if (!relevant.length) continue;
|
||||
lines.push(s.name);
|
||||
for (const t of relevant) {
|
||||
const icon = t.status === 'fail' ? '✗' : '⚠';
|
||||
const note = t.retried ? (t.status === 'pass' ? ' (flaky — passed on retry)' : ' (failed twice)') : '';
|
||||
lines.push(`${icon} ${t.name} ${t.time}ms${note}`);
|
||||
if (t.error) lines.push(` ${t.error}`);
|
||||
if (t.originalError) lines.push(` first run: ${t.originalError}`);
|
||||
}
|
||||
lines.push('');
|
||||
}
|
||||
text = lines.join('\n').trim();
|
||||
} else {
|
||||
text = panel.querySelector('#test-output').innerText;
|
||||
}
|
||||
} else {
|
||||
text = panel.querySelector('#test-output').innerText;
|
||||
}
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
const btn = panel.querySelector('#test-copy-btn');
|
||||
btn.textContent = 'copied';
|
||||
@@ -322,6 +351,7 @@ function createPanel() {
|
||||
}
|
||||
|
||||
function renderResults(results) {
|
||||
lastResults = results;
|
||||
const output = panel.querySelector('#test-output');
|
||||
const summary = panel.querySelector('#test-summary');
|
||||
let total = 0, passed = 0, failed = 0, flaky = 0, totalTime = 0;
|
||||
|
||||
Reference in new issue
Block a user