diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-03-08 20:46:35 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-03-08 20:46:35 +0000 |
| commit | 188fe9b078e263bb6b648d7949f92dcb7b899953 (patch) | |
| tree | 6df6cd38bf1925ff702fed479630ba83a7b260b4 /web/test/is-user-editing.test.mjs | |
| parent | 095db94030455bde497f18da94d0b404dcf042ea (diff) | |
web/test: add active-pane, focus-preserve, is-user-editing, render-dedup tests
Unit tests for UI helper functions: active pane detection, input focus
preservation during polls, user-editing guard, and render deduplication.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'web/test/is-user-editing.test.mjs')
| -rw-r--r-- | web/test/is-user-editing.test.mjs | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/web/test/is-user-editing.test.mjs b/web/test/is-user-editing.test.mjs new file mode 100644 index 0000000..844d3cd --- /dev/null +++ b/web/test/is-user-editing.test.mjs @@ -0,0 +1,65 @@ +// is-user-editing.test.mjs — contract tests for isUserEditing() +// +// isUserEditing(activeEl) returns true when the browser has focus in an element +// that a poll-driven DOM refresh would destroy: INPUT, TEXTAREA, contenteditable, +// or any element inside a [role="dialog"]. +// +// Run with: node --test web/test/is-user-editing.test.mjs + +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import { isUserEditing } from '../app.js'; + +// ── Mock helpers ─────────────────────────────────────────────────────────────── + +function makeEl(tagName, extras = {}) { + return { + tagName: tagName.toUpperCase(), + isContentEditable: false, + closest(sel) { return null; }, + ...extras, + }; +} + +// ── Tests ────────────────────────────────────────────────────────────────────── + +describe('isUserEditing', () => { + it('returns false for null', () => { + assert.strictEqual(isUserEditing(null), false); + }); + + it('returns false for undefined', () => { + assert.strictEqual(isUserEditing(undefined), false); + }); + + it('returns true for INPUT element', () => { + assert.strictEqual(isUserEditing(makeEl('INPUT')), true); + }); + + it('returns true for TEXTAREA element', () => { + assert.strictEqual(isUserEditing(makeEl('TEXTAREA')), true); + }); + + it('returns true for contenteditable element', () => { + assert.strictEqual(isUserEditing(makeEl('DIV', { isContentEditable: true })), true); + }); + + it('returns true for element inside [role="dialog"]', () => { + const el = makeEl('SPAN', { + closest(sel) { return sel === '[role="dialog"]' ? {} : null; }, + }); + assert.strictEqual(isUserEditing(el), true); + }); + + it('returns false for a non-editing BUTTON', () => { + assert.strictEqual(isUserEditing(makeEl('BUTTON')), false); + }); + + it('returns false for a non-editing DIV without contenteditable', () => { + assert.strictEqual(isUserEditing(makeEl('DIV')), false); + }); + + it('returns false for a non-editing SPAN not inside a dialog', () => { + assert.strictEqual(isUserEditing(makeEl('SPAN')), false); + }); +}); |
