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
9 changes: 8 additions & 1 deletion .claude/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@
"Bash(yarn tsc:*)",
"Bash(yarn ios:pod*)",
"Bash(yarn coverage:*)",
"Bash(yarn maestro*)"
"Bash(yarn maestro*)",
"mcp__codegraph__codegraph_search",
"mcp__codegraph__codegraph_context",
"mcp__codegraph__codegraph_callers",
"mcp__codegraph__codegraph_callees",
"mcp__codegraph__codegraph_impact",
"mcp__codegraph__codegraph_node",
"mcp__codegraph__codegraph_status"
]
},
"hooks": {
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,5 @@ shared/tests/results/
CLAUDE.md
.tsOuts
docs
.codegraph
.mcp.json
63 changes: 35 additions & 28 deletions plans/flow-test.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# E2E Flow Test Coverage — Page Checklist

**Skill:** Use the `keybase-e2e-tests` skill for testID conventions, Playwright gotchas, Maestro command patterns, and iOS navigation structure.

Comment thread
chrisnojima marked this conversation as resolved.
Each bucket is a logical group for one or more PRs. Items are ordered easiest-first within each bucket. Validate after each bucket before moving on.

**Pairing rule:** Do Electron and iOS for each bucket together before moving to the next bucket.

**Branch scripts:** `yarn test:e2e:electron:branch` and `yarn test:e2e:ios:branch` run only the new flows being developed. When a flow is verified working on both platforms, remove it from the branch scripts. When adding a new bucket's test files, add them to both scripts.
**Branch scripts:** `yarn test:e2e:desktop:branch` and `yarn test:e2e:ios:branch` run only the new flows being developed. When a flow is verified working on both platforms, remove it from the branch scripts. When adding a new bucket's test files, add them to both scripts.

Out of scope = screens that create, delete, add, invite, or remove something. Everything else is in scope even if it requires app state to reach.

Expand All @@ -27,18 +29,20 @@ Navigate to each sub-tab in the Crypto section.

Type something in each sub-tab and run it to see the output screen. Local-only operation, no server mutation.

- [ ] Encrypt → output screen renders
- [ ] Decrypt → output screen renders (with valid ciphertext)
- [ ] Sign → output screen renders
- [ ] Verify → output screen renders (with valid signed text)
- [x] Encrypt → output screen renders (Electron ✓, iOS written)
- [x] Decrypt → output screen renders — encrypt first, feed ciphertext to decrypt (Electron ✓, iOS: needs clipboard support, skipped)
- [x] Sign → output screen renders (Electron ✓, iOS written)
- [x] Verify → output screen renders — sign first, feed signed text to verify (Electron ✓, iOS: needs clipboard support, skipped)

---

## Bucket 3 — Chat: conversation view

Open an existing conversation. No sending.

- [ ] Open first inbox row → message list renders
- [x] Open first inbox row → message list renders (Electron ✓, iOS written)
- [x] Chat input visible in open conversation (Electron ✓, iOS: chat-send-message.yaml already covers this)
- [x] Return to inbox from conversation (Electron ✓, iOS written)

---

Expand All @@ -64,27 +68,27 @@ From an open conversation, open each of these. Dismiss/cancel without submitting

Navigate from the Settings nav. Confirm renders, go back.

- [ ] About
- [ ] Advanced
- [ ] Display
- [ ] Notifications
- [ ] Feedback
- [ ] Password (modal: `settingsTabs.password`)
- [x] About (Electron ✓, iOS written)
- [x] Advanced (Electron ✓, iOS written)
- [x] Display (Electron ✓, iOS written)
- [x] Notifications (Electron ✓, iOS written)
- [x] Feedback (Electron ✓, iOS written)
- [ ] Password (modal: `settingsTabs.password`) — needs Account settings navigation; no testID yet

---

## Bucket 6 — Settings sub-pages (batch 2)

Same pattern. Devices and Git reuse their main tab screen components.

- [ ] Chat
- [ ] Files
- [ ] Git (reuses git root component)
- [ ] Devices (reuses devices root component)
- [x] Chat (Electron ✓, iOS written via settings-subpages.yaml)
- [x] Files (Electron ✓, iOS written via settings-subpages.yaml)
- [x] Git reuses git root component (Electron ✓, iOS ✓ via git.yaml)
- [x] Devices reuses devices root component (Electron ✓, iOS ✓ via devices-view.yaml)
- [ ] Wallet
- [ ] Archive / Backup
- [x] Archive / Backup (Electron ✓, iOS written via settings-subpages.yaml)
- [ ] Contacts (mobile only, `settingsTabs.contactsTab`)
- [ ] Screen Protector (mobile only, `settingsTabs.screenprotector`)
- [x] Screen Protector (mobile only, `settingsTabs.screenprotector`) (Electron ✓, iOS: Android only)

---

Expand All @@ -103,26 +107,26 @@ Settings-adjacent modals that are viewable without mutating.

From the Devices tab, click a device row.

- [ ] Device detail page renders
- [x] Device detail page renders (Electron ✓, iOS written)

---

## Bucket 9 — Team detail tabs

Open a team, navigate each internal tab.

- [ ] Members tab renders
- [ ] Channels tab renders
- [ ] Bots tab renders
- [ ] Settings tab renders (team settings, not app settings)
- [x] Members tab renders (Electron ✓, iOS written)
- [x] Channels tab renders — conditional on big team/admin (Electron ✓, iOS written)
- [x] Bots tab renders (Electron ✓, iOS written)
- [x] Settings tab renders (Electron ✓, iOS written)

---

## Bucket 10 — Team sub-screens

From within a team.

- [ ] Team member page (click a member row from Members tab)
- [x] Team member page (Electron ✓, iOS written) — taps smoke user's username in member list
- [ ] Edit channel modal — open, cancel (`teamEditChannel`)
- [ ] Team description edit modal — open, cancel (`teamEditTeamDescription`)
- [ ] Team info edit modal — open, cancel (`teamEditTeamInfo`)
Expand All @@ -135,7 +139,7 @@ From within a team.

## Bucket 11 — Profile page and modals

- [ ] Profile page renders (via People feed item click)
- [x] Profile page renders (Electron ✓ via People tab header; iOS written — conditional on username in feed)
- [ ] Proofs list modal (`profileProofsList`) — open from a profile, view, close
- [ ] Showcase team offer (`profileShowcaseTeamOffer`) — open from own profile, view, cancel

Expand All @@ -145,15 +149,18 @@ From within a team.

From the Files root, tap each TLF type then back.

- [ ] Navigate into `public/` → browser renders
- [ ] Navigate into `private/` → browser renders
- [ ] Navigate into `team/` → browser renders
- [x] Navigate into `public/` → browser renders (Electron ✓, iOS written)
- [x] Navigate into `private/` → browser renders (Electron ✓, iOS written)
- [x] Navigate into `team/` → browser renders (Electron ✓, iOS written)
- [ ] Navigate back to files root from subfolder (Electron ✓, iOS written)
- [ ] Destination picker (`destinationPicker`) — open move/copy flow, cancel

---

## Bucket 13 — Git

- [x] Git repo list renders (Electron ✓, iOS written)
- [x] Git repo row is visible (Electron ✓, iOS written)
- [ ] Git repo detail (investigate first — clicking a row may open a mutation modal or nothing)
- [ ] Git select channel (`gitSelectChannel`) — open from a repo to set a notification channel, cancel

Expand Down
1 change: 0 additions & 1 deletion plans/todo.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
go screen by screen and find cleanup
legends to more desktop
move to clickablebox3
crypto screens button doesn't stick to keyboard well
automated testing of all screens
any leftover zustand store
Expand Down
32 changes: 32 additions & 0 deletions shared/.maestro/e2e/flows/chat-conversation.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
appId: keybase.ios
---
- runFlow: ../subflows/escape-to-tabs.yaml
# Navigate via Teams first to avoid ambiguity: "Chat" also appears in the More tab menu
- tapOn:
text: "Teams"
- tapOn:
text: "Chat"
- extendedWaitUntil:
visible:
id: "chat-inbox-list"
timeout: 5000
- takeScreenshot: tests/results/ios-debug/chat-conversation-inbox
- runFlow:
when:
visible:
id: "chat-inbox-row"
commands:
- tapOn:
id: "chat-inbox-row"
index: 0
- extendedWaitUntil:
visible:
id: "chat-message-list"
timeout: 5000
- takeScreenshot: tests/results/ios-debug/chat-conversation-open
- tapOn:
id: "backButton"
- extendedWaitUntil:
visible:
id: "chat-inbox-list"
timeout: 5000
61 changes: 61 additions & 0 deletions shared/.maestro/e2e/flows/crypto-outputs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
appId: keybase.ios
---
- runFlow: ../subflows/escape-to-tabs.yaml
- tapOn:
text: "More"
- scrollUntilVisible:
element:
text: ".*Crypto"
direction: up
timeout: 3000
- tapOn:
text: ".*Crypto"
retryTapIfNoChange: false
- extendedWaitUntil:
visible:
id: "crypto-input"
timeout: 3000

# Encrypt → output renders
- tapOn:
id: "crypto-nav-encryptTab"
- extendedWaitUntil:
visible:
id: "crypto-encrypt-input"
timeout: 3000
- tapOn:
id: "crypto-encrypt-input"
- inputText: "hello e2e"
- tapOn:
id: "crypto-run-button"
- extendedWaitUntil:
visible:
id: "crypto-output"
timeout: 10000
- takeScreenshot: tests/results/ios-debug/crypto-outputs-encrypt
- tapOn:
text: "Cancel"
- tapOn:
id: "backButton"

# Sign → output renders
- tapOn:
id: "crypto-nav-signTab"
- extendedWaitUntil:
visible:
id: "crypto-sign-input"
timeout: 3000
- tapOn:
id: "crypto-sign-input"
- inputText: "hello e2e"
- tapOn:
id: "crypto-run-button"
- extendedWaitUntil:
visible:
id: "crypto-output"
timeout: 10000
- takeScreenshot: tests/results/ios-debug/crypto-outputs-sign
- tapOn:
text: "Cancel"
- tapOn:
id: "backButton"
26 changes: 26 additions & 0 deletions shared/.maestro/e2e/flows/device-detail.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
appId: keybase.ios
---
- runFlow: ../subflows/escape-to-tabs.yaml
- tapOn:
text: "More"
- tapOn:
text: ".*Devices"
retryTapIfNoChange: false
- extendedWaitUntil:
visible:
id: "devices-list"
timeout: 3000
- extendedWaitUntil:
visible:
id: "devices-row"
timeout: 3000
- tapOn:
id: "devices-row"
index: 0
- extendedWaitUntil:
visible:
id: "device-page"
timeout: 5000
- takeScreenshot: tests/results/ios-debug/device-detail
- tapOn:
id: "backButton"
62 changes: 62 additions & 0 deletions shared/.maestro/e2e/flows/files-folders.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
appId: keybase.ios
---
- runFlow: ../subflows/escape-to-tabs.yaml
# Navigate via Teams first to avoid ambiguity: "Files" also appears in the More tab menu
- tapOn:
text: "Teams"
- tapOn:
text: "Files"
- extendedWaitUntil:
visible:
id: "files-browser"
timeout: 3000
- takeScreenshot: tests/results/ios-debug/files-folders-root

# Navigate into private folder (index 0)
- tapOn:
id: "files-tlf-row"
index: 0
- extendedWaitUntil:
visible:
id: "backButton"
timeout: 3000
- takeScreenshot: tests/results/ios-debug/files-folders-private
- tapOn:
id: "backButton"
- extendedWaitUntil:
visible:
id: "files-tlf-row"
timeout: 3000

# Navigate into public folder (index 1)
- tapOn:
id: "files-tlf-row"
index: 1
- extendedWaitUntil:
visible:
id: "backButton"
timeout: 3000
- takeScreenshot: tests/results/ios-debug/files-folders-public
- tapOn:
id: "backButton"
- extendedWaitUntil:
visible:
id: "files-tlf-row"
timeout: 3000

# Navigate into team folder (index 2)
- tapOn:
id: "files-tlf-row"
index: 2
- extendedWaitUntil:
visible:
id: "backButton"
timeout: 3000
- takeScreenshot: tests/results/ios-debug/files-folders-team
- tapOn:
id: "backButton"
- extendedWaitUntil:
visible:
id: "files-tlf-row"
timeout: 3000
- takeScreenshot: tests/results/ios-debug/files-folders-back-to-root
19 changes: 19 additions & 0 deletions shared/.maestro/e2e/flows/git.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
appId: keybase.ios
---
- runFlow: ../subflows/escape-to-tabs.yaml
- tapOn:
text: "More"
- tapOn:
text: ".*Git"
retryTapIfNoChange: false
- extendedWaitUntil:
visible:
id: "git-repo-list"
timeout: 3000
- takeScreenshot: tests/results/ios-debug/git
- runFlow:
when:
visible:
id: "git-repo-row"
commands:
- takeScreenshot: tests/results/ios-debug/git-repo-row
Loading