context-menu: group delete (public/js/modules/context-menu.js):
* When the delete action targets a card that has children (a group
parent), the confirmation dialog is ALWAYS shown regardless of the
hyprcrd-confirm-delete setting — group deletion is destructive
enough that it should never happen accidentally. The dialog lists
every child card by title and the OK button reads
"Delete all N" (parent + children counted).
* Children are deleted first (avoids orphan flicker), then the parent.
* Undo: a single pushUndo entry recreates the parent via POST first,
then all children with parent_id pointing at the new parent id.
due_date is restored via a follow-up PATCH since POST doesn't
accept it. Ctrl+Z fully restores the group hierarchy.
* Non-group cards keep the existing behavior (simple confirm if the
setting is on, single delete, pushCardDelete for undo).
tests (public/plugins/tests/card-interactions.test.js):
* New describe "Card: Group Delete" with two tests:
- "deleting a group removes parent AND all children": creates a
parent + 2 children, right-clicks the parent, clicks delete,
asserts the dialog text contains both child titles, confirms,
verifies all 3 cards are gone from the API.
- "Ctrl+Z after group delete restores parent + children": creates
parent + 1 child, deletes the group, confirms both gone, fires
Ctrl+Z, finds the restored cards by title, asserts
child.parent_id === restoredParent.id.
Both tests save/restore the hyprcrd-confirm-delete localStorage
value and soft-skip if the parent isn't visible on the board.
runner: retry progress bar (public/plugins/tests/runner.js):
* hideProgress() was called inside runAll() at the end of the first
pass, which removed the #test-progress element before the retry
pass started. The retry ran invisibly — "retrying…" never showed.
Moved hideProgress() out of runAll() into run(), after both the
first pass and the retry pass are done. The bar now stays visible
for the whole sequence: first pass fills to 100%, retry resets the
fill to 0 (via updateProgress(0, total, 'retrying…', false)) and
fills again for just the failed tests.
chore: bump version to 0.9.10
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* runner.js: shows a 30px fixed-top progress strip during runs (label
"test x/total:", current suite/test name with ellipsis on the left,
fixed 50%-wide progress fill on the right that turns danger-red on
the first failure). The DOM node is created in loader.js so it appears
immediately on shortcut press; runner.js only updates it. The fill
width is fixed at flex:0 0 50% so it doesn't jiggle as the test name
changes length. Suites now live on window._testSuites as a defensive
fallback so two runner instances stay in sync.
* Cache invalidation: every test file's `from './runner.js'` is now
`from './runner.js?v=2'`, and loader.js imports the runner with the
same RUNNER_V suffix. Same URL → one module instance → suite
registration and runAll see the same array. Bumping RUNNER_V (in
loader.js + every test file in lock-step) is the way to force a
re-fetch when runner.js changes.
* loader.js: ensureProgressBar() draws the strip via setProperty(...,
'important') with z-index 2147483647 attached to documentElement so
nothing in user CSS, scanline overlay (z 9999) or modals can occlude
it. Auto-run path (?test=1) also pre-renders the strip.
chore: bump version to 0.9.1
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Plugin loader + runner shortcut moves to Ctrl+Shift+Alt+T (the old
Ctrl+Shift+T conflicts with the browser "reopen closed tab"). Loader
now imports runner.js *without* the cache-busting query so it picks
up the same module instance the test files register their suites
into — previously the shortcut opened a fresh runner with an empty
suites array and reported 0/0 passed.
New / fixed coverage:
- card-interactions: favorite toggle assertion is now case-insensitive
(context menu was capitalized to "Unfavorite"/"Favorite" earlier);
done-badge test guards against state.hideDone / hideTagged that would
filter the test card off the board; new test for the always-on
Mark done / Unmark done toggle on a card without due_date.
- context-menu: copy-text action exists; copy-text strips fenced code
blocks, image markdown and inline #tags. Mocks navigator.clipboard
via Object.defineProperty so the assertion works without a focused
/ secure-context clipboard.
- export: round-trip preserves a custom bucket color (covers the import
handler regression that was wiping bucket colors on every test run).
- theme: design preset selection persists in localStorage across
settings open/close, refreshPresetSelect ignores unknown keys.
afterEach restores both hyprcrd-design-active-preset and
hyprcrd-design so a test run can't permanently swap the user's
design.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>