summaryrefslogtreecommitdiff
path: root/web/test/is-user-editing.test.mjs
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-03-08 21:03:50 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-03-08 21:03:50 +0000
commit632ea5a44731af94b6238f330a3b5440906c8ae7 (patch)
treed8c780412598d66b89ef390b5729e379fdfd9d5b /web/test/is-user-editing.test.mjs
parent406247b14985ab57902e8e42898dc8cb8960290d (diff)
parent93a4c852bf726b00e8014d385165f847763fa214 (diff)
merge: pull latest from master and resolve conflicts
- Resolve conflicts in API server, CLI, and executor. - Maintain Gemini classification and assignment logic. - Update UI to use generic agent config and project_dir. - Fix ProjectDir/WorkingDir inconsistencies in Gemini runner. - All tests passing after merge.
Diffstat (limited to 'web/test/is-user-editing.test.mjs')
-rw-r--r--web/test/is-user-editing.test.mjs65
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);
+ });
+});