* test(demo): use full-text regex matches in demo Maestro flow The demo flow (added in #108, non-blocking lane) rendered correctly in CI but failed its own assertions: it matched bare substrings ('login button', 'Tests passed') against Maestro's full-text regex matcher, which needs .*…* to match a phrase inside a longer message. A CI run confirmed the demo screen renders (S2 screenshot shows the user message, assistant reasoning, and tool card) — only the assertions were wrong. Exact i18n labels (Thinking / Permission Required / Allow) already matched. Flow-only; the app and demo feature are unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T12AhSnQVrSxNnvwfCx2z6 * test(demo): scroll to diff after expanding the tool card CI got further with the regex fix but then failed asserting diff-view-scroll: the confirmed cause (failure screenshot) is that the Edit card is scrolled to the bottom of the viewport to be tapped, so its expanded diff opens below the fold, and assertVisible does not auto-scroll. Add a scrollUntilVisible for diff-view-scroll before the assert. Flow-only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T12AhSnQVrSxNnvwfCx2z6 * test(demo): scroll to completion message before asserting it Same below-the-fold pattern as the diff step: after approving the permission at the bottom of the viewport, the 'Tests passed' completion renders further down. Scroll to it before asserting. Preemptive, to avoid another CI cycle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T12AhSnQVrSxNnvwfCx2z6 --------- Co-authored-by: engineer <engineer@macbookpro.lan> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
117 lines
4.2 KiB
YAML
117 lines
4.2 KiB
YAML
appId: cc.agentlabs.opencode
|
|
name: Demo mode - offline scripted walkthrough (no server, zero-server activation)
|
|
---
|
|
# Covers the "Try a demo" activation path added for the ~0% 7-day retention
|
|
# problem: an installer with no self-hosted `opencode serve` server used to
|
|
# hit a dead end at the no-connection empty state (see activation-positive.yaml
|
|
# / activation-negative-401.yaml for the "has a server" paths). This flow
|
|
# never starts a mock opencode server and never taps add-connection-button —
|
|
# app/demo.tsx (src/lib/demo-script.ts) is fully offline, hardcoded, local
|
|
# data rendered through the same chat components a real session uses.
|
|
#
|
|
# Verifies: the empty-state CTA exists and doesn't disturb the pre-existing
|
|
# add-connection-button (same testID, same position — activation-positive.yaml
|
|
# still taps it first), the demo screen renders a scripted conversation
|
|
# (reasoning -> tool call -> diff -> permission prompt) through the real
|
|
# MessageBubble/ToolCallCard/DiffView/PermissionPrompt components, the
|
|
# permission step responds locally (no network — there is no server to talk
|
|
# to), and the closing CTA actually routes to the real connect form
|
|
# (app/connection/add.tsx), not a fake/dead link.
|
|
|
|
- launchApp:
|
|
clearState: true
|
|
- assertVisible:
|
|
id: "telemetry-consent-card"
|
|
- tapOn:
|
|
id: "telemetry-decline-button"
|
|
|
|
- assertVisible:
|
|
text: "No Connection"
|
|
- takeScreenshot: demo-S1_empty_state
|
|
# add-connection-button must still be the first/only thing tapped here — this
|
|
# flow only ever taps it in this reachability check (visible, not tapped),
|
|
# to lock in that its position wasn't disturbed by the new button.
|
|
- assertVisible:
|
|
id: "add-connection-button"
|
|
- tapOn:
|
|
id: "try-demo-button"
|
|
|
|
- assertVisible:
|
|
id: "demo-screen"
|
|
- assertVisible:
|
|
id: "demo-banner"
|
|
- takeScreenshot: demo-S2_demo_screen_opened
|
|
|
|
# Scripted conversation renders through the real chat components.
|
|
# Maestro `text` matches the element's FULL text as a regex, so a phrase
|
|
# taken from a longer message must be wrapped in `.*…*` (the user message is
|
|
# a full sentence, not the bare phrase). Verified against a CI run where the
|
|
# demo screen rendered correctly but this bare-substring assert failed.
|
|
- assertVisible:
|
|
id: "chat-bubble-user"
|
|
- assertVisible:
|
|
text: ".*login button.*"
|
|
- assertVisible:
|
|
id: "chat-bubble-assistant"
|
|
- assertVisible:
|
|
text: "Thinking"
|
|
- takeScreenshot: demo-S3_conversation
|
|
|
|
# Tool call card is collapsed by default (same behavior as a real session) —
|
|
# tapping it expands the card, which renders the diff DOWNWARD below the
|
|
# header. Because the card is scrolled to near the bottom of the viewport to
|
|
# tap it, the expanded diff opens off-screen — so scroll again to bring the
|
|
# diff into view before asserting (assertVisible does not auto-scroll).
|
|
# Verified from a CI failure screenshot where the demo rendered correctly but
|
|
# diff-view-scroll sat below the fold.
|
|
- scrollUntilVisible:
|
|
element:
|
|
text: ".*Edit src/components/LoginButton.tsx.*"
|
|
direction: DOWN
|
|
timeout: 10000
|
|
- tapOn:
|
|
text: ".*Edit src/components/LoginButton.tsx.*"
|
|
- scrollUntilVisible:
|
|
element:
|
|
id: "diff-view-scroll"
|
|
direction: DOWN
|
|
timeout: 10000
|
|
- assertVisible:
|
|
id: "diff-view-scroll"
|
|
- takeScreenshot: demo-S4_diff_view
|
|
|
|
# Permission prompt (approve/permission step) — replying only updates local
|
|
# demo state, never a real sessionClient.permission.reply() network call.
|
|
- scrollUntilVisible:
|
|
element:
|
|
text: "Permission Required"
|
|
direction: DOWN
|
|
timeout: 10000
|
|
- takeScreenshot: demo-S5_permission_prompt
|
|
- tapOn:
|
|
text: "Allow"
|
|
# Approving swaps the prompt for a completion message that renders below the
|
|
# fold; scroll to it (full sentence begins "Tests passed — …", matched as a
|
|
# substring regex).
|
|
- scrollUntilVisible:
|
|
element:
|
|
text: ".*Tests passed.*"
|
|
direction: DOWN
|
|
timeout: 10000
|
|
- assertVisible:
|
|
text: ".*Tests passed.*"
|
|
- takeScreenshot: demo-S6_permission_approved
|
|
|
|
# Closing CTA routes to the REAL connect form, not a dead link.
|
|
- scrollUntilVisible:
|
|
element:
|
|
id: "demo-connect-button"
|
|
direction: DOWN
|
|
timeout: 10000
|
|
- takeScreenshot: demo-S7_cta
|
|
- tapOn:
|
|
id: "demo-connect-button"
|
|
- assertVisible:
|
|
id: "connect-ip-input"
|
|
- takeScreenshot: demo-S8_connect_form_reached
|