Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
a8e5bd4
chore(web): add Playwright devDependency and e2e directory structure
Ur-imazing Apr 17, 2026
6ca04b2
feat: add /qa skill with Layer 1 typecheck/lint and Layer 2 diff anal…
Ur-imazing Apr 17, 2026
fde1d83
chore: add component test infrastructure for web, mobile, and tv
Ur-imazing Apr 17, 2026
c70f32d
feat(web): add Playwright e2e setup with ~45 comprehensive browser flows
Ur-imazing Apr 17, 2026
9f9786a
feat(mobile): add Maestro e2e setup with ~55 comprehensive mobile flows
Ur-imazing Apr 17, 2026
d8eca0b
feat(tv): add custom YAML e2e runner with tvOS and Android TV adapters
Ur-imazing Apr 17, 2026
511e908
feat(tv): add ~35 comprehensive TV YAML flows for tvOS and Android TV
Ur-imazing Apr 17, 2026
9431456
feat: add Layer 4b visual review, pre-flight checks, and final polish…
Ur-imazing Apr 17, 2026
8a4c39a
fix(tv): harden TV YAML runner with security fixes and review correct…
Ur-imazing Apr 17, 2026
732a7d7
chore: merge main and resolve pnpm-lock.yaml conflict
Ur-imazing Apr 17, 2026
f8388f7
fix(tv): exclude e2e/ from tsconfig to fix CI typecheck
Ur-imazing Apr 17, 2026
f6426da
fix(qa): correct bundle IDs and Android TV launch for e2e pipeline
Ur-imazing Apr 17, 2026
d93c2f5
fix(qa): correct Maestro YAML syntax across all mobile flows
Ur-imazing Apr 17, 2026
e6fb925
feat(mobile): add testID props to components for Maestro e2e coverage
Ur-imazing Apr 17, 2026
d71df25
feat(web): add data-testid attributes for Playwright e2e coverage
Ur-imazing Apr 17, 2026
f3c107b
docs(qa): add testID coverage plan and first-runs solution doc
Ur-imazing Apr 17, 2026
0442b32
fix(web): use next/image for NavigationCarousel fallback img
Ur-imazing Apr 17, 2026
a40de14
docs(solutions): add lint-staged vs CI ESLint mismatch learning
Ur-imazing Apr 18, 2026
4a22bf3
Merge branch 'main' into feat/cross-platform-qa-pipeline
Ur-imazing Apr 18, 2026
8b71cae
feat(qa): add app-launch pre-flight before Layer 4a flows
Ur-imazing Apr 20, 2026
f2c4702
feat(qa): clear previous screenshots at Layer 4 pre-flight
Ur-imazing Apr 20, 2026
4495283
feat(qa): swap tvOS adapter from AppleScript to idb for headless input
Ur-imazing Apr 20, 2026
123b246
fix(qa): use idb ui key with HID codes for tvOS, not ui button
Ur-imazing Apr 20, 2026
87c7e8b
Merge branch 'main' into feat/cross-platform-qa-pipeline
Ur-imazing Apr 20, 2026
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
504 changes: 504 additions & 0 deletions .claude/commands/qa.md

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions apps/mobile/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ yarn-error.*

# typescript
*.tsbuildinfo

# e2e screenshots
e2e/screenshots/
16 changes: 16 additions & 0 deletions apps/mobile/.maestro/accordion-cta.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
appId: org.jesusfilm.forgewatch
tags:
- accordion
- cta
---
# Accordion CTA — Header button tap
- launchApp
- waitForAnimationToEnd
- scroll

# Tap CTA button in header
- tapOn:
id: "accordion-cta"
optional: true
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/accordion-cta/tapped
31 changes: 31 additions & 0 deletions apps/mobile/.maestro/accordion-questions.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
appId: org.jesusfilm.forgewatch
tags:
- accordion
- questions
---
# Related Questions Accordion — Expand, collapse, single open
- launchApp
- waitForAnimationToEnd
- scroll
- takeScreenshot: ../e2e/screenshots/${platform}/accordion-questions/visible

# Tap first question
- tapOn:
id: "accordion-question-0"
optional: true
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/accordion-questions/expanded

# Tap second question (first should collapse)
- tapOn:
id: "accordion-question-1"
optional: true
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/accordion-questions/second-expanded

# Collapse
- tapOn:
id: "accordion-question-1"
optional: true
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/accordion-questions/all-collapsed
15 changes: 15 additions & 0 deletions apps/mobile/.maestro/appstate-background.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
appId: org.jesusfilm.forgewatch
tags:
- appstate
- lifecycle
---
# AppState Background/Foreground — Video pause/resume
- launchApp
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/appstate-background/foreground

# Note: Maestro cannot directly simulate app backgrounding, but we can
# verify the app loads correctly after relaunch
- launchApp
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/appstate-background/relaunched
23 changes: 23 additions & 0 deletions apps/mobile/.maestro/appstate-video.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
appId: org.jesusfilm.forgewatch
tags:
- appstate
- video
---
# AppState Video — Mute persists, hero re-mutes on nav away
- launchApp
- waitForAnimationToEnd

# Toggle mute
- tapOn:
id: "mute-button"
optional: true
- takeScreenshot: ../e2e/screenshots/${platform}/appstate-video/mute-toggled

# Navigate away and back
- tapOn:
id: "tab-discover"
- waitForAnimationToEnd
- tapOn:
id: "tab-home"
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/appstate-video/returned-home
29 changes: 29 additions & 0 deletions apps/mobile/.maestro/carousel-bible-quotes.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
appId: org.jesusfilm.forgewatch
tags:
- carousel
- bible-quotes
---
# Bible Quotes Carousel — Paged, pagination dots, share
- launchApp
- waitForAnimationToEnd
- scroll
- takeScreenshot: ../e2e/screenshots/${platform}/carousel-bible-quotes/visible

# Swipe to next quote
- swipe:
direction: LEFT
- takeScreenshot: ../e2e/screenshots/${platform}/carousel-bible-quotes/next-quote

# Share button
- tapOn:
id: "share-quote"
optional: true
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/carousel-bible-quotes/share-sheet

# CTA link
- tapOn:
id: "quote-cta"
optional: true
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/carousel-bible-quotes/cta-tapped
22 changes: 22 additions & 0 deletions apps/mobile/.maestro/carousel-media.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
appId: org.jesusfilm.forgewatch
tags:
- carousel
- media
---
# Media Collection Carousel — 3:4 cards, badges, labels
- launchApp
- waitForAnimationToEnd
- scroll
- takeScreenshot: ../e2e/screenshots/${platform}/carousel-media/visible

# Swipe through
- swipe:
direction: LEFT
- takeScreenshot: ../e2e/screenshots/${platform}/carousel-media/swiped

# Tap a media item
- tapOn:
id: "media-collection-item-0"
optional: true
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/carousel-media/tapped
21 changes: 21 additions & 0 deletions apps/mobile/.maestro/carousel-navigation.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
appId: org.jesusfilm.forgewatch
tags:
- carousel
- navigation
---
# Navigation Carousel — Scroll-to-section, category labels
- launchApp
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/carousel-navigation/visible

# Tap a navigation item
- tapOn:
id: "nav-carousel-item-0"
optional: true
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/carousel-navigation/scrolled-to-section

# Swipe navigation carousel
- swipe:
direction: LEFT
- takeScreenshot: ../e2e/screenshots/${platform}/carousel-navigation/swiped
22 changes: 22 additions & 0 deletions apps/mobile/.maestro/carousel-video.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
appId: org.jesusfilm.forgewatch
tags:
- carousel
- video
---
# Video Carousel — Horizontal scroll, portrait cards, tap navigation
- launchApp
- waitForAnimationToEnd
- scroll
- takeScreenshot: ../e2e/screenshots/${platform}/carousel-video/visible

# Swipe carousel horizontally
- swipe:
direction: LEFT
- takeScreenshot: ../e2e/screenshots/${platform}/carousel-video/swiped

# Tap a card
- tapOn:
id: "video-carousel-card-0"
optional: true
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/carousel-video/card-tapped
20 changes: 20 additions & 0 deletions apps/mobile/.maestro/collection-player-states.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
appId: org.jesusfilm.forgewatch
tags:
- collection
- states
---
# Collection Player States — Loading, no playable, disabled items
- launchApp
- waitForAnimationToEnd
- scroll
- tapOn:
id: "collection-card-0"
optional: true
- takeScreenshot: ../e2e/screenshots/${platform}/collection-player-states/loading

- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/collection-player-states/loaded

# Scroll to see playlist items with disabled state
- scroll
- takeScreenshot: ../e2e/screenshots/${platform}/collection-player-states/playlist-items
24 changes: 24 additions & 0 deletions apps/mobile/.maestro/collection-player-switch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
appId: org.jesusfilm.forgewatch
tags:
- collection
- switching
---
# Collection Player Switch — Tap item to switch video
- launchApp
- waitForAnimationToEnd
- scroll
- tapOn:
id: "collection-card-0"
optional: true
- waitForAnimationToEnd

# Tap a different playlist item
- scroll
- tapOn:
id: "playlist-item-1"
optional: true
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/collection-player-switch/switched

# Verify active item badge
- takeScreenshot: ../e2e/screenshots/${platform}/collection-player-switch/active-badge
23 changes: 23 additions & 0 deletions apps/mobile/.maestro/collection-player.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
appId: org.jesusfilm.forgewatch
tags:
- collection
- player
---
# Collection Player — Playlist, active item, auto-advance
- launchApp
- waitForAnimationToEnd
- scroll

# Navigate to a collection
- tapOn:
id: "collection-card-0"
optional: true
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/collection-player/loaded

# Verify 16:9 player
- takeScreenshot: ../e2e/screenshots/${platform}/collection-player/player-dimensions

# Scroll to playlist
- scroll
- takeScreenshot: ../e2e/screenshots/${platform}/collection-player/playlist
20 changes: 20 additions & 0 deletions apps/mobile/.maestro/discover-clear.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
appId: org.jesusfilm.forgewatch
tags:
- discover
---
# Discover Clear Search — Reset to empty state
- launchApp
- tapOn:
id: "tab-discover"
- waitForAnimationToEnd

- tapOn:
id: "search-input"
optional: true
- inputText: "Jesus"
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/discover-clear/with-results

- eraseText
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/discover-clear/cleared
18 changes: 18 additions & 0 deletions apps/mobile/.maestro/discover-error.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
appId: org.jesusfilm.forgewatch
tags:
- discover
- error
---
# Discover Error — Network error, rate limit handling
- launchApp
- tapOn:
id: "tab-discover"
- waitForAnimationToEnd

# Search to trigger potential error states
- tapOn:
id: "search-input"
optional: true
- inputText: "test"
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/discover-error/state
20 changes: 20 additions & 0 deletions apps/mobile/.maestro/discover-keyboard.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
appId: org.jesusfilm.forgewatch
tags:
- discover
- keyboard
---
# Discover Keyboard — Dismiss on scroll
- launchApp
- tapOn:
id: "tab-discover"
- waitForAnimationToEnd

- tapOn:
id: "search-input"
optional: true
- inputText: "Jesus"
- takeScreenshot: ../e2e/screenshots/${platform}/discover-keyboard/keyboard-visible

# Scroll to dismiss keyboard
- scroll
- takeScreenshot: ../e2e/screenshots/${platform}/discover-keyboard/keyboard-dismissed
17 changes: 17 additions & 0 deletions apps/mobile/.maestro/discover-no-results.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
appId: org.jesusfilm.forgewatch
tags:
- discover
- empty
---
# Discover No Results — Empty state for nonexistent query
- launchApp
- tapOn:
id: "tab-discover"
- waitForAnimationToEnd

- tapOn:
id: "search-input"
optional: true
- inputText: "xyznonexistentquery12345"
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/discover-no-results/empty-state
27 changes: 27 additions & 0 deletions apps/mobile/.maestro/discover-pagination.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
appId: org.jesusfilm.forgewatch
tags:
- discover
- pagination
---
# Discover Pagination — Load more results
- launchApp
- tapOn:
id: "tab-discover"
- waitForAnimationToEnd

- tapOn:
id: "search-input"
optional: true
- inputText: "Jesus"
- waitForAnimationToEnd

# Scroll to load more
- scroll
- takeScreenshot: ../e2e/screenshots/${platform}/discover-pagination/scrolled

# Tap load more if visible
- tapOn:
text: "Load more"
optional: true
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/discover-pagination/more-loaded
23 changes: 23 additions & 0 deletions apps/mobile/.maestro/discover-rapid-typing.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
appId: org.jesusfilm.forgewatch
tags:
- discover
- debounce
---
# Discover Rapid Typing — Only latest query fires (requestId)
- launchApp
- tapOn:
id: "tab-discover"
- waitForAnimationToEnd

- tapOn:
id: "search-input"
optional: true
- inputText: "first"
- waitForAnimationToEnd
- eraseText
- inputText: "second"
- waitForAnimationToEnd
- eraseText
- inputText: "Jesus"
- waitForAnimationToEnd
- takeScreenshot: ../e2e/screenshots/${platform}/discover-rapid-typing/latest-result
Loading
Loading