Skip to content

v1.3.36.3 -- Capture: modal timing + target-group selector

A bugfix on top of v1.3.36.2 closing two issues found in the operator's second prod capture session:

  • BUG A: host-form.png and host-form-dns-provider- dropdown.png showed the hosts-list table as background, no modal visible. Cause: openModal returned immediately after the click; page.screenshot() fired before the modal mounted.
  • BUG B: target-group-form.png failed at the openModal waitForSelector step. Cause: the trigger selector list (Create / New target group / [data-testid="create-tg"]) didn't match the real button text "Add target group".

argosVersion and frontend/package.json deliberately stay at 1.3.35.4 (tooling-only). scripts/capture/package.json bumps 1.3.36.21.3.36.3.

BUG A — modal-open timing

Root cause

The openModal(page, triggerSelector, reason) helper in lib/safe-page.js did:

await handle.click();
console.log(...);
return;

— no wait for the modal to actually mount + paint after the click. React's setState → render → paint cycle plus any CSS transition (~200-400 ms) finished after the spec called page.screenshot(). Result: capture showed the page state immediately after the click trigger but before the modal became visible.

Fix

openModal gains an optional 4th positional argument modalSelector. When provided, the helper:

  1. waitForSelector(modalSelector, { state: 'visible', timeout: 5_000 }) — blocks until the modal element is in the DOM AND visible.
  2. waitForTimeout(400) — animation-settle delay matching the typical framer-motion / CSS transition duration.

When modalSelector is null/undefined (the optional default), the helper behaves exactly as before — used for clicks INSIDE an already-open modal that change form state without opening a new dialog (the DNS-01 radio inside the host edit modal).

I inspected frontend/src/components/Modal.tsx to find the right selector: the panel's shared <Modal> component renders an outer overlay div with the class set:

fixed inset-0 z-40 flex items-center justify-center bg-black/70 px-4 py-4

.fixed.inset-0.z-40 is the Playwright-friendly selector that matches every modal opened by the panel — host edit, host create, target-group create, TOTP enrollment all share the same component.

Per-call-site updates

Five openModal invocations gain the overlay selector (modal-open path):

test 5  host-form               .fixed.inset-0.z-40
test 6  host-form-dns-provider  .fixed.inset-0.z-40   (first call)
test 8  host-form-true-detect   .fixed.inset-0.z-40
test 9  target-group-form       .fixed.inset-0.z-40
test 28 totp-setup              .fixed.inset-0.z-40

The DNS-01 radio click inside the already-open host modal (test 6, second openModal call) deliberately omits the 4th arg — it's a form-state change inside an existing modal, not a new modal-open.

The picker render after the radio click is synchronous (React state → render in the next tick), so a 300 ms waitForTimeout covers it; no waitForSelector needed for the picker itself.

BUG B — target-group-form selector mismatch

Root cause

capture.spec.js test #9 used:

'button:has-text("Create"), button:has-text("New target group"), [data-testid="create-tg"]'

I inspected frontend/src/pages/TargetGroups.tsx:60-67:

<button onClick={openCreate} ...>
  <Plus className="w-4 h-4" />
  Add target group
</button>

The button text is "Add target group". The previous selector list had three options, none of which matched. openModal's waitForSelector timed out at 10 s.

Fix

Replace the selector with the real button text:

'button:has-text("Add target group")'

The old fallback strings (Create, New target group, [data-testid="create-tg"]) are removed from active code. Comments in the test now document the v1.3.36.x failure mode so future readers don't reintroduce them.

Smoke phase 10

scripts/smoke/capture-automation.sh gains six new asserts under phase 10:

10. openModal modal-visibility wait + target-group selector:
    - openModal() accepts modalSelector argument
    - openModal() waits for modalSelector visibility post-click
    - openModal() applies animation-settle delay
    - capture.spec.js .fixed.inset-0.z-40 references: 6 (>= 5)
    - target-group-form uses "Add target group" selector
    - old TG selector fallbacks removed from active code (comments
      documenting the bug history are allowed)

Last assert uses a grep -v '^\s*[0-9]*:\s*//' filter to skip comment lines — same pattern as the v1.3.36.1 phase 7 fix that allows commit-format comments to mention the trailer string.

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)

scripts/check-no-personal-data.sh clean. mkdocs build --strict clean.

Files changed

  • scripts/capture/lib/safe-page.jsopenModal gains optional modalSelector 4th arg with waitForSelector + animation-settle.
  • scripts/capture/capture.spec.js — five modal-open call sites pass .fixed.inset-0.z-40; target-group-form selector replaced with Add target group. Some prior waitForTimeout(300) pre-screenshot lines removed where the new openModal animation-settle covers the same purpose.
  • scripts/capture/package.json1.3.36.21.3.36.3.
  • scripts/smoke/capture-automation.sh — phase 10 added.
  • docs/release-notes/v1.3.36.3.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, dark scrim
#    behind), not the hosts list table.
# 2. host-form-dns-provider-dropdown.png shows the modal with
#    the DNS-01 radio selected and the picker dropdown rendered
#    below.
# 3. target-group-form.png captures the "Add target group" modal.

If any specific surface still captures wrongly, paste the file name + what you see in the next iteration.

Versioning

scripts/capture/package.json 1.3.36.21.3.36.3. Tag-without-rebuild precedent for tooling-only patches: v1.3.27.1, v1.3.34, v1.3.35.1, v1.3.35.5.