Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .maestro/01-signup-flow.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Story 15-4 — Flow 1: Sign-up
#
# Validates: a new user can create an account and reach the
# EmailVerificationGate (Story 12-9). Subsequent flows assume an
# already-verified test account.
#
# Selectors below carry # TODO markers — operator must verify against
# the actual app via `maestro studio` before first CI wire-up.
# See _bmad-output/planning-artifacts/runbooks/maestro-e2e-setup.md.

appId: com.companion.app
tags:
- smoke
- signup
---
# Launch the app cold
- launchApp:
clearState: true

# Sign-up CTA — auth screens carry an EN "Sign up" link (Story 14-1 R1-H6)
- assertVisible: "Sign up" # TODO: verify exact text matches login.tsx
- tapOn: "Sign up"

# Email + password fields
- assertVisible: "Email address" # TODO: verify placeholder / a11y label
- tapOn:
id: "input-email" # TODO: verify testID on signup.tsx email TextInput
- inputText: "e2e-test+signup-001@invalid.localdomain"

- tapOn:
id: "input-password" # TODO: verify testID
- inputText: "Abcdefghi1" # min 10 chars per Story 12-8 password policy

# R1 BH-3: signup.tsx has ONE password field (no confirm). Pre-R1 had a
# 3-line confirm block here — DELETED. Operator runbook §5 documents the
# single-password contract.

# Submit
- tapOn: "Create account" # TODO: verify exact button text

# Expect to land on EmailVerificationGate (Story 12-9). R1 BH-1: Story
# 14-1 R1-Q5 converted the gate's chrome to English; pre-R1 these were
# the FR strings ("Vérifiez votre adresse e-mail" / "J'ai vérifié —
# actualiser") which would have failed Day 1. Corrected to EN.
- assertVisible: "Verify your email address" # EN per Story 14-1 R1-Q5
- assertVisible: "I've verified — refresh" # TODO: verify exact CTA label against EmailVerificationGate.tsx
57 changes: 57 additions & 0 deletions .maestro/02-onboarding-flow.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Story 15-4 — Flow 2: Onboarding wizard + placement test
#
# Prerequisite: a verified test account already exists (created via Flow 1
# OR seeded via Supabase admin). The flow signs in with that account, then
# walks the 3-step onboarding + placement test → home.
#
# Test account credentials should live in `MAESTRO_TEST_EMAIL` /
# `MAESTRO_TEST_PASSWORD` env vars (operator-set per runbook).

appId: com.companion.app
tags:
- smoke
- onboarding

env:
TEST_EMAIL: "e2e-test+onboarding-001@invalid.localdomain" # TODO: replace with operator-seeded test account
TEST_PASSWORD: "Abcdefghi1"
---
- launchApp:
clearState: true

# Sign in (assumes account is verified)
- assertVisible: "Sign in" # TODO: verify exact text
- tapOn:
id: "input-email" # TODO: verify testID
- inputText: ${TEST_EMAIL}
- tapOn:
id: "input-password"
- inputText: ${TEST_PASSWORD}
- tapOn: "Sign in"

# Step 1 of 3 — goals
- assertVisible: "What are your goals?" # TODO: verify exact onboarding/index.tsx text
- tapOn: "TCF preparation" # TODO: verify goal label
- tapOn: "Continue"

# Step 2 of 3 — daily goal
- assertVisible: "Daily goal" # TODO
- tapOn: "15 min" # TODO
- tapOn: "Continue"

# Step 3 of 3 — placement test entry
- assertVisible: "Placement test" # TODO
- tapOn: "Start placement test" # TODO

# Placement test — answer all 15 questions (B1-ish)
- repeat:
times: 15
commands:
- tapOn:
index: 0 # tap first option
text: ".*"
- tapOn: "Next question" # TODO: verify

# Reach home tab
- assertVisible: "COMPANION" # home hero brand label (Story 14-1 R1-H4)
- assertVisible: "Hello" # greeting
52 changes: 52 additions & 0 deletions .maestro/03-first-exercise.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Story 15-4 — Flow 3: Complete the first practice exercise
#
# Prerequisite: an onboarded test account exists (Flow 2 completed).
# Validates: practice tab → grammar → AI exercise generation → answer →
# grade → result + activity-tracking persists.

appId: com.companion.app
tags:
- smoke
- exercise

env:
TEST_EMAIL: "e2e-test+exercise-001@invalid.localdomain" # TODO
TEST_PASSWORD: "Abcdefghi1"
---
- launchApp:
clearState: false # preserve any signed-in session

# If not signed in, sign in
- runFlow:
when:
visible: "Sign in"
commands:
- tapOn:
id: "input-email"
- inputText: ${TEST_EMAIL}
- tapOn:
id: "input-password"
- inputText: ${TEST_PASSWORD}
- tapOn: "Sign in"

# Navigate to Practice tab
- tapOn: "Practice" # bottom tab — Story 14-1 R1-H1 EN
- assertVisible: "Choose a skill to practice." # practice screen subtitle

# Choose Grammar
- tapOn: "Grammar" # SkillCard label (Story 14-1)
- assertVisible: "Generating exercise" # loading state

# Wait for the MCQ to appear (max 60s for AI gen)
- extendedWaitUntil:
visible: "Submit" # or "Check" — TODO verify the submit button label
timeout: 60000

# Tap first option then submit
- tapOn:
id: "mcq-option-0" # TODO: verify testID on MCQCard option Pressables
- tapOn: "Submit"

# Expect a result screen
- assertVisible: "Correct" # ideal — TODO: handle "Incorrect" path too
- tapOn: "Next exercise" # TODO: verify CTA
70 changes: 70 additions & 0 deletions .maestro/04-first-conversation.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Story 15-4 — Flow 4: First conversation (Realtime voice)
#
# Validates: conversation tab → topic → start → grant mic permission →
# session connects → user can speak (simulated) → end session.
#
# Note: Real-time voice depends on OpenAI Realtime API + microphone access.
# Maestro can simulate the mic-permission grant + the End button tap but
# CANNOT inject audio. This flow validates the SHELL — connection + UI
# state transitions — not the AI response content.

appId: com.companion.app
tags:
- smoke
- conversation

env:
TEST_EMAIL: "e2e-test+conversation-001@invalid.localdomain" # TODO
TEST_PASSWORD: "Abcdefghi1"
---
# R1 EH-4: Use Maestro's `launchApp.permissions` directive to grant
# RECORD_AUDIO upfront — bypasses the system permission dialog entirely
# AND works on both iOS Simulator + Android Emulator (eliminates the
# iOS-only "OK" / Android-only "Allow" / "While using the app" /
# "Only this time" alternation problem).
- launchApp:
clearState: false
permissions:
record_audio: allow

- runFlow:
when:
visible: "Sign in"
commands:
- tapOn:
id: "input-email"
- inputText: ${TEST_EMAIL}
- tapOn:
id: "input-password"
- inputText: ${TEST_PASSWORD}
- tapOn: "Sign in"

# Navigate to Conversation tab. R1 BH-2: the tab `title` is "Talk" per
# `app/(tabs)/_layout.tsx:61`, NOT "Conversation". The `headerTitle`
# (rendered in the screen hero) is "Conversation" — but Maestro's
# `tapOn` on the bottom tab matches the `title` value.
- tapOn: "Talk" # bottom-tab title per _layout.tsx:61
- assertVisible: "Talk with Companion" # hero title from conversation/index.tsx

# Pick the first topic (A1 — "Se présenter" greeting)
- tapOn:
text: "Se présenter" # FR content per Story 14-1 chrome rule
# TODO: confirm exact rendered text; topic card has both EN + FR labels

# Start the session
- assertVisible: "Talk" # or whatever the start CTA reads — TODO
- tapOn: "Talk"

# R1 EH-4: permission dialog bypassed via launchApp.permissions above.
# The pre-R1 `runFlow when: visible: "OK"` block (iOS-only) is DELETED.

# Wait for connection (status: "connected")
- extendedWaitUntil:
visible: "Companion is listening" # TODO: verify status text
timeout: 30000

# End the session
- tapOn: "End" # TODO: verify End button label

# Expect feedback screen or session-summary
- assertVisible: "Session summary" # TODO: verify post-session screen
61 changes: 61 additions & 0 deletions .maestro/05-mock-test-partial-review.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Story 15-4 — Flow 5: Mock test partial completion + review
#
# Validates: mock-test tab → start TCF full simulation → complete listening
# section → submit early → results screen renders with correct CEFR + TCF
# score reconstruction (Story 14-7 + 13-4 parallel section generation).

appId: com.companion.app
tags:
- smoke
- mock-test

env:
TEST_EMAIL: "e2e-test+mocktest-001@invalid.localdomain" # TODO
TEST_PASSWORD: "Abcdefghi1"
---
- launchApp:
clearState: false

- runFlow:
when:
visible: "Sign in"
commands:
- tapOn:
id: "input-email"
- inputText: ${TEST_EMAIL}
- tapOn:
id: "input-password"
- inputText: ${TEST_PASSWORD}
- tapOn: "Sign in"

# Navigate to TCF Test tab. R1 BH-2: tab `title` is "TCF Test" per
# `app/(tabs)/_layout.tsx:97`, NOT "Mock test". The screen content
# refers to "Mock test" but the bottom-tab label is "TCF Test".
- tapOn: "TCF Test" # bottom-tab title per _layout.tsx:97
- assertVisible: "TCF" # mock-test/index.tsx hero brand

# Tap the full TCF simulation card
- tapOn: "Start full simulation" # TODO: verify CTA label

# Generation: parallel per-section (Story 13-4); wait for first section
- extendedWaitUntil:
visible: "Question 1" # TODO: verify
timeout: 120000 # 2-minute budget for section 1 generation

# Answer listening section (29 questions per TCF Canada — answer all with index 0)
- repeat:
times: 29
commands:
- tapOn:
id: "mcq-option-0" # TODO: verify testID
- tapOn: "Next" # TODO: verify Next button

# Submit listening section early (won't wait for reading section to finish)
- tapOn: "Submit" # TODO: verify Submit early CTA / confirm dialog flow

# Results screen
- extendedWaitUntil:
visible: "Results" # TODO: verify results screen header
timeout: 30000
- assertVisible: "TCF Score" # TODO: verify
- assertVisible: "Listening"
15 changes: 15 additions & 0 deletions .maestro/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Maestro project config — Story 15-4
#
# Operator setup: see _bmad-output/planning-artifacts/runbooks/maestro-e2e-setup.md
#
# Run locally:
# maestro test .maestro/
#
# Run a single flow:
# maestro test .maestro/03-first-exercise.yaml

appId: com.companion.app

# Tags allow selective runs (`maestro test --include-tags=smoke`).
tags:
- epic-15
Loading
Loading