v1.3.36.4 -- Capture: host-row trigger fix¶
A bugfix on top of v1.3.36.3. The host-form modal still didn't capture correctly post-v1.3.36.3 because the spec was clicking a <tr> element with no onClick handler — the v1.3.36.3 modal-visibility wait worked perfectly but had nothing to wait for.
argosVersion and frontend/package.json deliberately stay at 1.3.35.4 (tooling-only). scripts/capture/package.json bumps 1.3.36.3 → 1.3.36.4.
Why¶
PHASE 0 source-code investigation of Hosts.tsx:
<tr key={h.id} className="border-t border-slate-800">
...cells...
<td>
<IconButton label="edit" onClick={() => openEdit(h)}>
<Pencil className="w-4 h-4" />
</IconButton>
</td>
</tr>
The <tr> has no onClick. The modal opens via the <IconButton label="edit"> which renders as <button aria-label="edit" title="edit"> (per IconButton at Hosts.tsx:676-700). v1.3.36.x clicked the row → the click bubbled up unhandled → setModalOpen(true) never fired → waitForSelector('.fixed.inset-0.z-40') correctly timed out at 5 s because the modal genuinely was not in the DOM.
The v1.3.36.3 modal-visibility wait was correct in concept but irrelevant in practice — it was waiting for an element React never rendered.
Modal infrastructure (re-verified, no changes needed)¶
Modal.tsxis a plain function component (no framer-motion, no React.createPortal, no opacity transitions).if (!open) return null;— overlay isn't in the DOM untilopenflips totrue; at that moment the entire subtree paints synchronously..fixed.inset-0.z-40IS the correct overlay selector.- The 400 ms animation-settle in
openModal()is harmless (no animation in practice) and remains for future-proofing in case the panel adds CSS transitions later.
Fix¶
Three call sites in capture.spec.js updated to scope the click to the IconButton instead of the row:
| Line | Test | Before | After |
|---|---|---|---|
| 159 | host-form | table tbody tr:first-child | table tbody tr:first-child button[aria-label="edit"] |
| 175 | host-form-dns-provider-dropdown (first openModal) | table tbody tr:first-child | table tbody tr:first-child button[aria-label="edit"] |
| 235 | host-form-true-detect | table tbody tr:has(span:has-text("DETECT")) | table tbody tr:has(span:has-text("DETECT")) button[aria-label="edit"] |
The selector chains the row scope (first row, or the row with the DETECT badge) with the specific edit-trigger button via Playwright's :has-text and descendant combinator. aria-label is set programmatically by IconButton from its label prop (Hosts.tsx:691), so the selector is stable unless the IconButton component itself is refactored.
The DNS-01 radio click in test 6 (second openModal call) is unchanged — it's an in-modal form-state click, not a new modal-open.
The safeHover on the security-scenarios row (test 15) is unchanged — hovers don't depend on onClick handlers, and the row hover is what surfaces the description tooltip via React state.
The target-group-form selector (Add target group) is unchanged — that surface uses a direct button, not row delegation, and v1.3.36.3 already fixed it.
Smoke phase 11¶
scripts/smoke/capture-automation.sh gains two new asserts:
11. host-row triggers click button[aria-label="edit"]:
- active-code 'tr ... button[aria-label="edit"]' occurrences: 3
- PASS: 3 call sites click the edit-trigger button (not the row)
- synthetic verify: Hosts.tsx IconButton renders aria-label={label}
AND <IconButton label="edit"> exists -- so aria-label resolves
to "edit" at runtime; selector is stable.
The synthetic verify reads frontend/src/pages/Hosts.tsx directly to confirm: 1. The IconButton component still has aria-label={label} in its <button> JSX. 2. The hosts list still has at least one <IconButton label="edit".
If either fails, the selector is broken and phase 11 fails loudly — saving an operator a 5s timeout per host capture.
Smoke result post-fix¶
phase 1: run.sh refuses without .env... PASS
phase 2: .env is git check-ignore'd... PASS
phase 3: .env.example placeholders only... PASS
phase 4: safeClick synthetic test... PASS (13/13)
phase 5: working tree unchanged by smoke... PASS
phase 6: storageState wiring (v1.3.36.1)... PASS (5/5)
phase 7: banner output uses fs.readFileSync... PASS
phase 8: viewport 1440x1080 + shotFullScroll... PASS
phase 9: waitForSettled helper (timing fix)... PASS (5/5)
phase 10: openModal modal-visibility wait + TG selector... PASS (6/6)
phase 11: host-row triggers click button[aria-label=edit]... PASS (2/2)
scripts/check-no-personal-data.sh clean. mkdocs build --strict clean.
Files changed¶
scripts/capture/capture.spec.js— 3 trigger selectors scoped tobutton[aria-label="edit"]; comments document the v1.3.36.3 click-no-op failure mode.scripts/capture/package.json—1.3.36.3→1.3.36.4.scripts/smoke/capture-automation.sh— phase 11 added.docs/release-notes/v1.3.36.4.md— this file.CHANGELOG.md,mkdocs.yml.
NOT changed: argosVersion stays at 1.3.35.4; frontend/package.json version stays at 1.3.35.4. No Go code; no frontend code; no panel binary change.
Operator workflow post-fix¶
cd ~/argos-edge && git pull
scripts/capture/run.sh
# Verify three things:
# 1. host-form.png shows the EDIT MODAL (form fields visible
# with dark scrim) — NOT the hosts list table behind a
# background.
# 2. host-form-dns-provider-dropdown.png shows the same modal
# with DNS-01 radio selected and DNSProviderPicker rendered
# below the radios.
# 3. No regression on other surfaces (target-group-form,
# totp-setup, etc. unchanged from v1.3.36.3).
The mid-impl smoke fixed an overreach in the proposed phase 11b ("no bare 'tr:first-child' selectors anywhere") — the security-scenarios test legitimately uses bare row selectors for safeHover (the row hover surfaces the description tooltip and doesn't need a click trigger). Removed the overreach; the affirmative count + synthetic verify cover what matters.
Versioning¶
scripts/capture/package.json 1.3.36.3 → 1.3.36.4. Tag-without-rebuild precedent for tooling-only patches: v1.3.27.1, v1.3.34, v1.3.35.1, v1.3.35.5.