Files
hyprcrd/public/plugins/tests/tests.js
T
thandClaude Opus 4.6 3078906548 find/replace: editor (Ctrl+H/F) + board-wide (Ctrl+Shift+H)
Editor find/replace (public/js/modules/editor.js, public/index.php):
* New #editor-find-bar inside #editor-pane (above the textarea, pushes
  it down via flex-col). Two rows: find input + match count + prev/next
  + close, and replace input + replace-one + replace-all.
* Ctrl+H opens find+replace, Ctrl+F opens find-only (replace row
  hidden). Same shortcut toggles off if already open in the same mode.
* runFind(): case-insensitive indexOf scan, all match positions stored.
  jumpTo() sets textarea.setSelectionRange for the Nth match.
  findNext/findPrev cycle with wrap-around.
* replaceOne(): body.setRangeText at the current match position, re-scan.
  replaceAll(): regex-based global replace on body.value.
* Enter in find input = next (Shift+Enter = prev). Enter in replace
  input = replace one. Escape closes the bar + refocuses textarea.
* closeModal() calls closeFindBar() to clean up on editor close.

Board-wide find/replace (public/js/app.js):
* Ctrl+Shift+H opens a centered overlay that fetches all cards with
  full bodies (api('api/cards'), bypasses lazy-load).
* Live search: typing in the find input scans all card bodies case-
  insensitive. Matches shown as a scrollable list with color dot,
  card title, occurrence count, and a context snippet with <mark>
  highlight around the first match.
* Status line: "12 occurrences in 5 cards" or "no matches".
* Replace All button (danger-styled, disabled until both inputs have
  text and matches exist). Click opens a showDialog confirmation:
  "Replace 12 occurrences of 'foo' with 'bar' across 5 cards?"
  On confirm: regex replace per card body → PATCH → _reloadAll.
* Escape / click-outside / Close button dismiss the overlay.

Shortcuts registered in the central registry for the help screen:
* ⌃ H (editor), ⌃ F (editor), ⌃ ⇧ H (global board-wide).

Tests (public/plugins/tests/board-find-replace.test.js):
* Ctrl+Shift+H opens the overlay (polls for #board-find-replace).
* Typing in find shows matching cards (creates 3 cards, 2 match,
  asserts status count + list contains matching titles + excludes
  non-matching title).
* Replace all updates card bodies after confirmation (creates 2
  cards with "hello", replaces with "goodbye", confirms dialog,
  verifies via API that bodies are "goodbye world goodbye" and
  "goodbye there").
* Replace all button disabled without replace text.

detail.test.js: "closes on ESC" stabilized — guard that detail is
actually open before dispatching Escape, poll (20×50ms) instead of
fixed sleep(150) for the .open class to be removed.

chore: bump version to 0.9.21

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:23:18 +02:00

58 lines
1.6 KiB
JavaScript

// ── hyprcrd Test Index ──
//
// Loads all test suites via dynamic imports with a shared cache-busting
// query string. This ensures edits to any test file are picked up without
// requiring a hard refresh — each module URL becomes unique per page load.
const V = '?v=' + Date.now();
const FILES = [
'./shell.test.js',
'./settings.test.js',
'./board.test.js',
'./toolbar.test.js',
'./buckets.test.js',
'./bucket-context.test.js',
'./super-buckets.test.js',
'./context-menu.test.js',
'./card-interactions.test.js',
'./card-join.test.js',
'./board-find-replace.test.js',
'./filtering.test.js',
'./sorting.test.js',
'./state-functions.test.js',
'./favorites.test.js',
'./search.test.js',
'./search-logic.test.js',
'./calendar.test.js',
'./calendar-popup.test.js',
'./rrule.test.js',
'./datepicker.test.js',
'./gallery.test.js',
'./help.test.js',
'./multiselect.test.js',
'./detail.test.js',
'./detail-interactions.test.js',
'./editor.test.js',
'./editor-features.test.js',
'./editor-save.test.js',
'./editor-toolbar.test.js',
'./line-numbers.test.js',
'./canvas.test.js',
'./snippets.test.js',
'./image-fullscreen.test.js',
'./markdown.test.js',
'./markdown-edge.test.js',
'./undo.test.js',
'./api.test.js',
'./api-edge.test.js',
'./export.test.js',
'./relay.test.js',
'./notifications.test.js',
'./quick-capture.test.js',
'./theme.test.js',
];
// Await all imports so the runner can start in a deterministic state.
await Promise.all(FILES.map(f => import(f + V)));