From cb907b0320981af58fecd0bd7804d871bc0f6b47 Mon Sep 17 00:00:00 2001 From: sepehr-safari Date: Sun, 12 Jul 2026 21:12:31 +0300 Subject: [PATCH] test: automation-driven GUI test suite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Grow the S0 launch smoke into a suite that DRIVES the headline flows through the automation protocol and asserts the semantics tree after each step, with screenshots of two surfaces as artifacts. - scripts/smoke.sh: after the CLI load-path assertions, click real widgets by accessibility name (a widget_id helper extracts the id from the snapshot's `@w/#` path, falling back to the dropbox snapshot.txt) and assert the result — the replay transport (Next → the detail pane unpacks event evt-0001), the filter facet (Call → "of 22 events", Clear restores it), and the Live tab (→ the capture control strip renders). Screenshots the inspector and live surfaces; the whole run asserts no error events. - ci.yml: the smoke step drives the GUI; the artifact upload now collects both screenshots (screenshot-*.png). No capture is started in the test (that would spawn a real proxy subprocess). Verified: bash -n clean, the automation build is clean. The driven flow runs under Xvfb in CI (it needs a display; the macOS window path is for local dev). Closes #71. --- .github/workflows/ci.yml | 8 ++-- CURRENT_STATE.md | 12 +++--- scripts/smoke.sh | 82 +++++++++++++++++++++++++++++++--------- 3 files changed, 75 insertions(+), 27 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef81918..ee8f741 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,12 +68,12 @@ jobs: run: npm install -g @native-sdk/cli@0.4.1 - name: Build headless app (automation enabled) run: native build -Dplatform=linux -Dautomation=true - - name: Drive the app headless and assert the widget tree + - name: Drive the GUI headless and assert the widget tree run: ./scripts/smoke.sh - - name: Upload rendered screenshot + - name: Upload rendered screenshots if: always() uses: actions/upload-artifact@v4 with: - name: smoke-screenshot - path: .zig-cache/native-sdk-automation/screenshot-main-canvas.png + name: gui-screenshots + path: .zig-cache/native-sdk-automation/screenshot-*.png if-no-files-found: ignore diff --git a/CURRENT_STATE.md b/CURRENT_STATE.md index 0846865..aabd4f3 100644 --- a/CURRENT_STATE.md +++ b/CURRENT_STATE.md @@ -19,10 +19,12 @@ criticals raise OS notifications live (#60, ADR-0011) — all **in-runner** **S6 — public release & launch (0.5.0): in progress.** Packaging is wired (#70) — `native package` builds a macOS `.app` (ad-hoc `.dmg`) and a Linux `.tar.gz`, and a tag-triggered [release workflow](.github/workflows/release.yml) -publishes both to a GitHub release (see [RELEASING.md](RELEASING.md)). Remaining: -GUI test suite (#71), the frozen conformance contract (#72), release-ready docs -(#73), and the v0.5.0 cut (#74). The menu-bar monitor and notarization are -post-0.5; see [ROADMAP.md](ROADMAP.md). +publishes both to a GitHub release (see [RELEASING.md](RELEASING.md)). The +automation smoke now **drives** the GUI (#71) — clicking the replay transport, +a filter facet, and the Live tab, asserting the semantics tree after each and +screenshotting the inspector + live surfaces. Remaining: the frozen conformance +contract (#72), release-ready docs (#73), and the v0.5.0 cut (#74). The menu-bar +monitor and notarization are post-0.5; see [ROADMAP.md](ROADMAP.md). ## What's done @@ -185,7 +187,7 @@ live inspector surface with notifications (#54–#60) — is landed. | Area | Status | | --- | --- | -| `repo` (tooling, CI) | ✅ S0 CI; 🔨 S6 packaging + release workflow (#70) | +| `repo` (tooling, CI) | ✅ S0 CI + S6 packaging/release (#70) + driven GUI suite (#71) | | `docs` (docs, ADRs) | ✅ done for S0 | | `ocpp` (engine) | ✅ S2 + ingestion (#29) + reports (#41) + anonymize (#42) + diff (#43) + replay core (#44); O(n) detection pending (#36) | | `ui` (native views) | ✅ S3 inspector (#27–#32) + replay transport (#44) + live-capture view (#59) + live notifications (#60) | diff --git a/scripts/smoke.sh b/scripts/smoke.sh index ef49400..ae4bf74 100755 --- a/scripts/smoke.sh +++ b/scripts/smoke.sh @@ -1,17 +1,19 @@ #!/usr/bin/env bash # -# Automation smoke test: launch the app, wait for its embedded automation -# server, assert the widget tree actually rendered, and capture a -# deterministic screenshot artifact. Portable — uses a virtual framebuffer -# (Xvfb) when available (CI), otherwise runs the window directly (local -# macOS). The app must be built with -Dautomation=true. +# Automation-driven GUI test: launch the app, wait for its embedded automation +# server, then DRIVE the headline flows through the automation protocol — +# clicking real widgets and asserting the rendered semantics tree after each +# step — and capture deterministic screenshots as artifacts. Portable: uses a +# virtual framebuffer (Xvfb) when available (CI), otherwise runs the window +# directly (local macOS). The app must be built with -Dautomation=true. # set -euo pipefail BIN=zig-out/bin/studio AUTO_DIR=.zig-cache/native-sdk-automation -# Launch with the vendored sample as a command-line trace argument, so the smoke -# test exercises the real CLI load path and lands on the loaded overview. +CANVAS=main-canvas +# Launch with the vendored sample as a command-line trace argument, so the test +# exercises the real CLI load path and lands on the loaded overview. SAMPLE=src/ocpp/testdata/normal-session.json if [ ! -x "$BIN" ]; then @@ -44,14 +46,42 @@ launch & APP_PID=$! trap 'kill "$APP_PID" >/dev/null 2>&1 || true' EXIT +# The numeric widget id for the widget whose accessibility name equals $1. Each +# snapshot line is `widget @w/# role= name="