fix(screenshots): widen fakespeaker coverage and stabilize the pipeline

make screenshots was producing artifacts: a ghost Spotify pill on
ui-devices, empty Plan-card URL inputs on ui-migration with cascading
"localhost" warnings, and "Checking configuration…" placeholder text
instead of " Not configured" on ui-settings. Two root causes, fixed
together so the run is deterministic again.

1. Fakespeaker too thin for the post-wizard inspect pipeline. The new
   migration wizard probes /supportedURLs and reads /networkInfo and
   /sources alongside the existing /info, /presets, /recents. Those
   routes now exist with sanitized fixtures (deviceID DEADBEEFCAFE,
   loopback IPs, no real MACs or account IDs). The full group endpoint
   set is also wired: /getGroup and /removeGroup return the empty
   <group/> shape a real un-paired device emits; /addGroup and
   /updateGroup echo the posted body with <status>GROUP_OK</status>
   inserted before </group>, matching the success path documented in
   issue #252. /supportedURLs lists everything the fake now serves so
   any caller that probes capabilities first (e.g. marge_pairing.go)
   sees a coherent picture. Tests cover the GET routes' XML roots, the
   POST echo + GROUP_OK insertion contract, and /removeGroup's
   GET-only contract (405 with Allow: GET on other methods).

2. run.sh seed hit a DNS cliff. The :443 preflight shipped in 3727ae6
   resolves server_url on every /setup/settings call, and the
   populatePlannedNetworkConfig step does it again. With the previous
   seed of http://aftertouch.local:8000 each lookup burned ~5s on DNS
   timeout, which compounded across the wizard calls and pushed
   ui-migration past chromedp's 30s per-shot budget. Switched the seed
   to http://aftertouch.localhost:8000 — RFC 6761 means *.localhost
   resolves to loopback via the system resolver in milliseconds
   (verified ~8ms on macOS / glibc / systemd-resolved) — so the brand-
   friendly hostname survives in the captured PNGs without the
   timeout. Manifest settle times bumped (ui-settings 300→2000ms,
   ui-devices 500→2500ms, ui-sync 300→1000ms) to give fetchSettings +
   fetchSpotifyStatus time to complete in headless Chrome.

While here, softened validateURL's loopback message to acknowledge the
on-device-install case (AfterTouch running on the speaker itself, where
loopback works) instead of unconditionally telling users they're
wrong. The validation still flags 127.0.0.1 / localhost since it's the
wrong answer 99% of the time, but the message now frames the
constraint rather than scolding.

docs/images/ui-*.png regenerated against the new pipeline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tobias Gesellchen
2026-05-15 12:56:43 +02:00
co-authored by Claude Opus 4.7
parent 9cb8549c79
commit abae685a85
12 changed files with 324 additions and 11 deletions
+4 -4
View File
@@ -5,21 +5,21 @@
"path": "/",
"click_selector": "button[onclick*=\"tab-settings\"]",
"wait_selector": "#tab-settings.active",
"settle_ms": 300
"settle_ms": 2000
},
{
"name": "ui-devices",
"path": "/",
"click_selector": "button[onclick*=\"tab-devices\"]",
"wait_selector": "#tab-devices.active",
"settle_ms": 500
"settle_ms": 2500
},
{
"name": "ui-sync",
"path": "/",
"click_selector": "button[onclick*=\"tab-sync\"]",
"wait_selector": "#tab-sync.active",
"settle_ms": 300
"settle_ms": 1000
},
{
"name": "ui-migration",
@@ -31,4 +31,4 @@
"settle_ms": 4000
}
]
}
}
+10 -3
View File
@@ -39,11 +39,18 @@ go build -o "$LOG_DIR/soundtouch-service" ./cmd/soundtouch-service
go build -o "$LOG_DIR/dummy-speaker" ./cmd/dummy-speaker
go build -o "$LOG_DIR/screenshots" ./scripts/screenshots
echo "==> seeding settings.json (generic hostname + discovery off to avoid leaking real network info)"
echo "==> seeding settings.json (aftertouch.localhost + discovery off to avoid leaking real network info)"
# `aftertouch.localhost` is RFC 6761: any *.localhost name resolves to
# loopback via the system resolver in milliseconds (verified ~8ms on
# macOS / glibc / systemd-resolved). That gives us a brand-friendly URL
# in the screenshots without the ~5s DNS-timeout cliff that bites on
# unresolvable hostnames like aftertouch.local — that cliff compounds
# across /setup/settings + /setup/summary and pushes past the chromedp
# 30s per-shot budget.
cat > "$DATA_DIR/settings.json" <<'EOF'
{
"server_url": "http://aftertouch.local:8000",
"https_server_url": "https://aftertouch.local:8443",
"server_url": "http://aftertouch.localhost:8000",
"https_server_url": "https://aftertouch.localhost:8443",
"discovery_enabled": false,
"discovery_interval": "1h"
}