Files
opencode-mobile/.maestro/flows/directory-picker.yaml
Den 2285f80e81 fix(e2e): harden activation-e2e newer flows (issue #104) (#105)
Root-caused directory-picker's directory-row-frontend failure: all four
in-app @gorhom/bottom-sheet sheets (DirectoryBrowserSheet, DirectorySwitcher,
ModelPicker, VariantPicker) provide static percentage snapPoints but rely on
v5's enableDynamicSizing default (true), which never resolves without content
wrapped in a size-reporting component — so useAnimatedDetents() permanently
early-exits and the sheets can never actually open. Set
enableDynamicSizing={false} on all four (they already have explicit
snapPoints, so dynamic sizing was never needed).

variant-picker's chip failure was a stale test assumption: src/lib/
model-selection.ts's chooseModelSelection() deliberately returns null for a
fresh session (issue #37/#35 — the provider registry default is unreliable),
so a brand-new session has no model selected and the reasoning-effort chip
has nothing to key off of. Added testIDs (model-chip, model-option-*) and
updated the flow to explicitly pick a model first, matching real usage.

diff-scroll's missing markdown text: switched src/components/markdown/
Markdown.tsx from react-native-marked's FlatList-based default export to its
useMarkdown() hook rendered into a plain View. The chat screen already nests
this inside its own *inverted* FlatList (one row per message) — a nested
VirtualizedList inside an inverted outer list is a known RN footgun where the
inner content can render at zero height instead of just warning. We already
forced scrollEnabled:false + a large initialNumToRender, defeating
virtualization anyway, so rendering the parsed blocks directly loses nothing.
Extended the existing react-native-marked .d.ts shim (added for a React
18/19 ReactNode mismatch) to also declare useMarkdown/useMarkdownHookOptions.

Added diagnostic screenshots to directory-picker.yaml and diff-scroll.yaml
at the previously-failing steps for faster triage if these regress again.

Closes #104.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 15:41:28 -07:00

122 lines
3.9 KiB
YAML

appId: cc.agentlabs.opencode
name: Directory picker - browse server folders and create a session in one
---
# New-feature regression coverage for DirectoryBrowserSheet
# (src/components/chat/DirectoryBrowserSheet.tsx): New Session -> Browse
# Folders -> the sheet lists the mock server's fake directory tree -> tapping
# a folder navigates into it -> Up navigation returns to the parent -> tapping
# "Use this folder" creates a session scoped to the chosen directory.
#
# The CI job starts `node tests/fixtures/mock-opencode-server.ts --port 4099`
# (normal mode, no --fail-auth / --seed-sessions) on the runner host BEFORE
# this flow runs. Its fake filesystem (FAKE_FILE_TREE in
# tests/fixtures/mock-opencode-server.ts) is:
# /mock/project -> frontend/ (dir), backend/ (dir), README.md (file)
# /mock/project/frontend -> (empty)
# /mock/project/backend -> (empty)
# and GET /project (FAKE_SERVER_PROJECTS) additionally lists a "docs-project"
# server-known project, exercised as a secondary assertion below.
- launchApp:
clearState: true
- assertVisible:
id: "telemetry-consent-card"
- tapOn:
id: "telemetry-decline-button"
- assertVisible:
text: "No Connection"
- tapOn:
id: "add-connection-button"
- tapOn:
id: "connect-ip-input"
- inputText: "127.0.0.1:4099"
- hideKeyboard
- tapOn:
id: "connect-submit-button"
# 40s margin: see activation-positive.yaml — the connect handshake's own
# fetches are individually capped at 30s (src/lib/sdk.ts REQUEST_TIMEOUT_MS).
- extendedWaitUntil:
visible:
id: "connection-status-dot"
timeout: 40000
- takeScreenshot: dirpicker-S1_connected
# Open the New Session modal (long-press the FAB for the full options sheet)
- longPressOn:
id: "new-session-fab"
- assertVisible:
text: "New Session"
# GET /project surfaces "docs-project" under "Server Projects" (excludes the
# current project, mock-project) — confirms the project-list endpoint wired up.
# The modal fetches it async on open, so wait rather than assert immediately.
- extendedWaitUntil:
visible:
text: "docs-project"
timeout: 10000
- takeScreenshot: dirpicker-S2_new_session_modal
# Open the folder browser
- tapOn:
id: "browse-folders-button"
- assertVisible:
text: "Browse Folders"
# Diagnostic screenshot before the (previously flaky, see issue #104) wait
# below — if this ever regresses again, compare this frame against
# dirpicker-S2 to see whether the sheet actually opened.
- takeScreenshot: dirpicker-S2b_browser_sheet_opened
- extendedWaitUntil:
visible:
id: "directory-row-frontend"
timeout: 10000
- assertVisible:
id: "directory-row-backend"
# README.md is a FILE, not a directory — DirectoryBrowserSheet filters entries
# to type === "directory", so it must never appear as a row.
- assertNotVisible:
text: "README.md"
- takeScreenshot: dirpicker-S3_root_listing
# Navigate into "frontend"
- tapOn:
id: "directory-row-frontend"
- extendedWaitUntil:
visible:
text: "No subfolders here"
timeout: 10000
- takeScreenshot: dirpicker-S4_inside_frontend
# Up navigation must return to the root listing
- tapOn:
id: "directory-up-button"
- extendedWaitUntil:
visible:
id: "directory-row-frontend"
timeout: 10000
- assertVisible:
id: "directory-row-backend"
- takeScreenshot: dirpicker-S5_up_navigation_back_to_root
# Navigate into "backend" and select it
- tapOn:
id: "directory-row-backend"
- extendedWaitUntil:
visible:
text: "No subfolders here"
timeout: 10000
- takeScreenshot: dirpicker-S6_inside_backend
- tapOn:
id: "directory-select-button"
# The app creates a session scoped to /mock/project/backend (mock POST
# /session reads x-opencode-directory) and navigates straight to it — the
# native header's directory badge must show "backend".
- extendedWaitUntil:
visible:
id: "chat-message-input"
timeout: 15000
- assertVisible:
text: "backend"
- takeScreenshot: dirpicker-S7_session_created_in_backend