Skip to content

Commit e9a5406

Browse files
committed
test: fail fast when the DOM stub cannot find the confirm button
The stub auto-clicks the confirm button so customConfirm() resolves headlessly, but had no branch for "did not match". A reworded button would leave the client waiting forever and node would run to the caller's 120s subprocess timeout, surfacing as TimeoutExpired with a traceback - a multi-minute mystery instead of a diagnosis. Report and exit non-zero instead, naming the buttons that were seen and where to update the pattern. The branch is guarded on there being buttons at all: the ordinary error-path dialog has none, and firing on that would break every capture. Also correct what the predicate's comments claim. The two false-lead patterns name the regression that already happened; they are not what makes the guard general. Any substitution displaces the server's own text, so the server-body clause is what catches a reworded revival - the patterns alone would not.
1 parent e8fffa9 commit e9a5406

2 files changed

Lines changed: 26 additions & 7 deletions

File tree

tests/js/dom.mjs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,23 @@ const realAppend = body.appendChild.bind(body);
3939
body.appendChild = (child) => {
4040
realAppend(child);
4141
// The confirm modal resolves on a click; fire it so the flow continues.
42-
const confirmBtn = walk(child).find(
43-
(e) => e.tagName === 'BUTTON' && /confirm|yes|ok/i.test(e.textContent || '')
44-
);
45-
if (confirmBtn) setTimeout(() => confirmBtn.click(), 0);
42+
const buttons = walk(child).filter((e) => e.tagName === 'BUTTON');
43+
const confirmBtn = buttons.find((e) => /confirm|yes|ok/i.test(e.textContent || ''));
44+
if (confirmBtn) {
45+
setTimeout(() => confirmBtn.click(), 0);
46+
} else if (buttons.length) {
47+
// A dialog with buttons, none of which this stub recognizes: the client
48+
// would wait forever on customConfirm() and node would hang until the
49+
// caller's subprocess timeout, surfacing as a multi-minute mystery
50+
// rather than a diagnosis. Name what was seen and stop now.
51+
console.error(
52+
'capture_dialog: no confirm button matched /confirm|yes|ok/i, so the '
53+
+ 'client would block on customConfirm(). Buttons seen: '
54+
+ JSON.stringify(buttons.map((b) => b.textContent))
55+
+ '. Update the pattern in tests/js/dom.mjs if the button was reworded.'
56+
);
57+
process.exit(3);
58+
}
4659
return child;
4760
};
4861

tests/test_batch_404_dialog_guard.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,10 @@
5959
#: (`web.Response(status=404, text=...)` in glob/manager_server.py).
6060
SERVER_404_BODY = "A security error has occurred. Please check the terminal logs"
6161

62-
#: Fragments of the false message the fix removed. Kept as separate patterns
63-
#: because a reinstatement is more likely to be a reworded variant than a
64-
#: byte-identical copy.
62+
#: Fragments of the specific false message the fix removed. These name the known
63+
#: regression; they are NOT what makes the guard general — a reworded
64+
#: substitute would evade them, and is caught by the server-body clause instead
65+
#: (see _c1_violations).
6566
_FALSE_LEAD_PATTERNS = (
6667
re.compile(r"default\s+channel", re.I),
6768
re.compile(r"security\s+level\s+configuration", re.I),
@@ -137,6 +138,11 @@ def _c1_violations(payload):
137138
138139
Both arms call THIS function, so the RED arm demonstrates the failure of
139140
the same check the GREEN arm passes — not of a differently-worded cousin.
141+
142+
The load-bearing clause is the FIRST one: any substitution, however it is
143+
worded, displaces the server's own text and is caught. The phrase patterns
144+
below it only name the specific regression that already happened; a
145+
reworded revival would slip past them alone.
140146
"""
141147
dialog = payload["dialog"]
142148
problems = []

0 commit comments

Comments
 (0)