Fix/maestro e2e flows for ios#2076
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThis PR enhances E2E test reliability by replacing text-based selectors with deterministic element IDs across Maestro flows, adding platform-specific interaction logic for iOS/Android differences, and introducing corresponding testID instrumentation in React Native components. Additional changes include updating logout flow button labels and adjusting catalog type definitions. ChangesE2E Test Infrastructure & Deterministic Selectors
Package Dependency Update
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Deploying packrat-guides with
|
| Latest commit: |
8f69f89
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://9b6ea4a7.packrat-guides-6gq.pages.dev |
| Branch Preview URL: | https://fix-maestro-e2e-flows-for-io.packrat-guides-6gq.pages.dev |
Deploying packrat-landing with
|
| Latest commit: |
8f69f89
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://9734f716.packrat-landing.pages.dev |
| Branch Preview URL: | https://fix-maestro-e2e-flows-for-io.packrat-landing.pages.dev |
…karound for interacting with elements in a modal in Maestro
- Update Pack Name input to use 'move, Pack Name' on iOS - Update Description inputs to use 'newspaper, Description' on iOS (packs/trips) and 'info, Description' on iOS (items) - Update Trip Name input to use 'show map, Trip Name' on iOS - Update Item Name input to use 'backpack.fill, Item Name' on iOS - Add platform-specific runFlow blocks following existing patterns - Maintain Android compatibility with original placeholder text
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
packrat-admin | 8f69f89 | Commit Preview URL Branch Preview URL |
May 04 2026, 09:40 PM |
Coverage Report for API Unit Tests Coverage (./packages/api)
File CoverageNo changed files found. |
Coverage Report for Expo Unit Tests Coverage (./apps/expo)
File CoverageNo changed files found. |
- Fix missing 'TRIP DETAILS' text element in create-trip-flow - Fix logout confirmation button tap issue in logout-flow - Update profile component and localization for test compatibility
83f9ae3 to
38f881b
Compare
There was a problem hiding this comment.
Actionable comments posted: 12
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/scripts/e2e.sh:
- Around line 36-37: Remove the hardcoded fallback credentials for TEST_EMAIL
and TEST_PASSWORD in the e2e.sh script: stop defaulting them to
"qa1.admin@packratai.com" / "Ab12345." and instead either require the env vars
to be present (fail fast with a clear error) or use the alternate E2E_TEST_EMAIL
/ E2E_TEST_PASSWORD variables as the fallback; update the references to
TEST_EMAIL/TEST_PASSWORD in the script (including the other occurrences noted
around lines 53-54) so they read from the secure envs and exit with a non-zero
error and message if neither the primary nor fallback envs are supplied.
In @.github/workflows/e2e-tests.yml:
- Around line 67-69: Replace mutable action refs with full 40-character commit
SHAs for all GitHub Actions used in the workflow: locate every "uses:
maxim-lobanov/setup-xcode@v1" and other "uses:" entries (e.g., the one shown as
maxim-lobanov/setup-xcode@v1 and the other noted `@v2.37.0`) and update them to
the corresponding pinned form "owner/repo@<full-commit-sha>"; verify each SHA on
the action's GitHub repo (Releases/Commits) and replace the tag with that SHA so
no actions remain using mutable tags like `@v1` or `@v2.37.0`.
In @.maestro/flows/catalog/catalog-browse-flow.yaml:
- Around line 12-19: The locale-dependent regex selectors used in assertVisible
and scrollUntilVisible (the text fields ".*items.*" and "Showing.*items") are
fragile; update these steps to target stable testIDs instead (e.g., replace
assertVisible:text and scrollUntilVisible:element.text with assertions that use
element.testID or a testID-specific selector), ensuring you reference the same
logical UI elements (the count/showing label) when modifying the assertVisible
and scrollUntilVisible steps so the flow stops relying on English copy.
In @.maestro/flows/catalog/catalog-item-detail-flow.yaml:
- Around line 39-44: The iOS back step in runFlow currently taps by text using
tapOn with text: ".*Back.*", which is brittle; instead add a deterministic
testID to the back control in the screen/header (e.g., headerBackButton testID)
and change the runFlow tap step to use tapOn with id: "<headerBackButton-id>"
(replace with the actual testID); update the tapOn invocation in the
catalog-item-detail-flow to reference that id so tests tap the header back
control deterministically.
- Around line 9-14: Replace the loose assertVisible on ".*items.*" with a direct
wait for the target element id before tapping: change the step that currently
uses assertVisible (text: ".*items.*") to wait for the element with id
"catalog-item" (the same id used in the tapOn step), then perform tapOn with id:
"catalog-item" and index: 0 so the tap only occurs after the specific card is
present and interactable.
In @.maestro/flows/dashboard/dashboard-tiles-flow.yaml:
- Around line 7-8: The tap action currently uses a locale-dependent text
selector (tapOn: text: "Dashboard"); change it to use a stable identifier by
replacing the text selector with an id/testID selector (e.g., tapOn: id:
"dashboard-tab" or tapOn: testID: "dashboardTab") and update the app code to
expose that id if it doesn't exist; keep the same tapOn key and only swap the
selector type so the flow reliably taps the Dashboard tab across locales.
In @.maestro/flows/negative/empty-trip-submit-flow.yaml:
- Around line 24-30: The iOS platform block under runFlow has misaligned
indentation: the commands key (platform: iOS, commands, swipe) is indented only
4 spaces instead of matching the Android block's indentation for the list item
(e.g., the `- back` entry); fix by increasing the indentation of the `commands:`
block and its nested `- swipe:`/properties so they align with the equivalent
platform list item (ensure `commands` and its children are indented to the same
level as the `- back` entry under runFlow when platform is Android).
In @.maestro/flows/packs/add-item-manual-flow.yaml:
- Around line 40-83: Add the missing testID prop to the description TextField in
CreatePackItemForm.tsx using testIds.items.descriptionInput, then update the
Maestro flow entries that use text selectors ("Item Name", "Description",
"backpack.fill, Item Name", "info, Description") to use stable id selectors for
both platforms and for both assertVisible and tapOn commands: use id:
items:name-input (testIds.items.nameInput) and id: items:description-input
(testIds.items.descriptionInput); keep the existing inputText commands
unchanged.
In @.maestro/flows/packs/create-pack-flow.yaml:
- Around line 19-32: The iOS runFlow step is tapping the wrong label ("move,
Pack Name") so the name input isn't focused; update the iOS branch in runFlow to
tap the same selector as Android (e.g., tapOn text: "Pack Name") or use the
input's accessibility label used by the PackForm component (PackForm's pack name
field/icon "folder") to reliably target the name field, keeping the subsequent
inputText ${PACK_NAME} call unchanged.
In @.maestro/flows/trips/create-trip-flow.yaml:
- Around line 51-53: The flow is tapping on legacy IDs "start-date-input" and
"end-date-input" which don't match the actual test IDs; update the tapOn actions
that reference id "start-date-input" and "end-date-input" to use the real
testIds from the app (testIds.trips.startDateInput -> "trips:start-date-input"
and testIds.trips.endDateInput -> "trips:end-date-input") so the tap targets
match TripForm's exported IDs and the date selection steps proceed.
In `@apps/expo/app/auth/`(login)/index.tsx:
- Around line 116-120: The wrapper View around the email input currently shares
the same testID as the inner TextField, causing Android test flakiness; remove
the testID prop from the View (the wrapper returned in the render of form.Field)
so only the TextField (the inner component rendered by the form.Field callback)
has testID={testIds.auth.emailInput}; locate the occurrence in
apps/expo/app/auth/(login)/index.tsx where View and TextField are both using
testIds.auth.emailInput and delete the testID from the View (or conditionally
omit it for Android) leaving the TextField as the sole element exposing that
test ID.
In `@apps/expo/features/catalog/components/CatalogItemCard.tsx`:
- Line 28: The testID on the TouchableWithoutFeedback in the CatalogItemCard
component is shared across all cards; update the testID to be unique per item
(e.g., include the item's id or slug) by changing the testID prop on the
TouchableWithoutFeedback inside CatalogItemCard to something like
`catalog-item-${item.id}` (or `- ${item.slug}`) and ensure CatalogItemCard
receives the item identifier (fallback to index or "unknown" if absent) so E2E
selectors can target a deterministic, per-card testID.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 53001a75-094a-4dc4-95cd-9e9a0912872f
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock,!bun.lock
📒 Files selected for processing (26)
.github/scripts/e2e.sh.github/workflows/e2e-tests.yml.maestro/flows/auth/login-flow.yaml.maestro/flows/auth/logout-flow.yaml.maestro/flows/catalog/catalog-browse-flow.yaml.maestro/flows/catalog/catalog-item-detail-flow.yaml.maestro/flows/dashboard/dashboard-tiles-flow.yaml.maestro/flows/negative/empty-pack-submit-flow.yaml.maestro/flows/negative/empty-trip-submit-flow.yaml.maestro/flows/packs/add-item-actions-flow.yaml.maestro/flows/packs/add-item-manual-flow.yaml.maestro/flows/packs/create-pack-flow.yaml.maestro/flows/packs/pack-detail-flow.yaml.maestro/flows/trips/create-trip-flow.yaml.maestro/flows/trips/trip-detail-flow.yamlapps/expo/app/(app)/(tabs)/profile/index.tsxapps/expo/app/auth/(login)/index.tsxapps/expo/features/ai/components/AIChatTile.tsxapps/expo/features/catalog/components/CatalogItemCard.tsxapps/expo/features/packs/components/PackCard.tsxapps/expo/features/trips/components/TripCard.tsxapps/expo/features/trips/components/TripForm.tsxapps/expo/lib/i18n/locales/en.jsonapps/expo/lib/testIds.tspackages/web-ui/package.jsonpackages/web-ui/src/components/chart.tsx
| -e TEST_EMAIL="${TEST_EMAIL:-qa1.admin@packratai.com}" \ | ||
| -e TEST_PASSWORD="${TEST_PASSWORD:-Ab12345.}" \ |
There was a problem hiding this comment.
Remove the hardcoded fallback credentials.
These defaults turn a missing secret into a silent login against a shared repo-known account, and they bypass the env-based contract already used by packages/api/src/db/seed-e2e-user.ts:1-20. Fail fast, or fall back to E2E_TEST_EMAIL / E2E_TEST_PASSWORD instead of embedding credentials here.
Suggested fix
- -e TEST_EMAIL="${TEST_EMAIL:-qa1.admin@packratai.com}" \
- -e TEST_PASSWORD="${TEST_PASSWORD:-Ab12345.}" \
+ -e TEST_EMAIL="${TEST_EMAIL:-${E2E_TEST_EMAIL:?E2E_TEST_EMAIL is required}}" \
+ -e TEST_PASSWORD="${TEST_PASSWORD:-${E2E_TEST_PASSWORD:?E2E_TEST_PASSWORD is required}}" \
@@
- -e TEST_EMAIL="${TEST_EMAIL:-qa1.admin@packratai.com}" \
- -e TEST_PASSWORD="${TEST_PASSWORD:-Ab12345.}" \
+ -e TEST_EMAIL="${TEST_EMAIL:-${E2E_TEST_EMAIL:?E2E_TEST_EMAIL is required}}" \
+ -e TEST_PASSWORD="${TEST_PASSWORD:-${E2E_TEST_PASSWORD:?E2E_TEST_PASSWORD is required}}" \Also applies to: 53-54
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/scripts/e2e.sh around lines 36 - 37, Remove the hardcoded fallback
credentials for TEST_EMAIL and TEST_PASSWORD in the e2e.sh script: stop
defaulting them to "qa1.admin@packratai.com" / "Ab12345." and instead either
require the env vars to be present (fail fast with a clear error) or use the
alternate E2E_TEST_EMAIL / E2E_TEST_PASSWORD variables as the fallback; update
the references to TEST_EMAIL/TEST_PASSWORD in the script (including the other
occurrences noted around lines 53-54) so they read from the secure envs and exit
with a non-zero error and message if neither the primary nor fallback envs are
supplied.
| uses: maxim-lobanov/setup-xcode@v1 | ||
| with: | ||
| xcode-version: '26.2' | ||
| xcode-version: "26.2" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Finds any uses: entry not pinned to a 40-char commit SHA
rg -nP '^\s*uses:\s*[^@]+@(?![0-9a-f]{40}$).+' .github/workflows/e2e-tests.ymlRepository: PackRat-AI/PackRat
Length of output: 982
🏁 Script executed:
rg -nP '^\s*uses:\s*[^@]+@(?![0-9a-f]{40}$).+' .github/workflows/e2e-tests.ymlRepository: PackRat-AI/PackRat
Length of output: 982
Pin all third-party GitHub Actions to full commit SHAs.
The touched blocks use mutable action refs (@v1 on line 67, @v2.37.0 on line 432), violating the supply-chain security guideline. Verification confirms this is a systemic issue across the entire workflow—23 unpinned actions exist. Pin all actions to their full 40-character commit SHA to prevent supply-chain attacks.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/e2e-tests.yml around lines 67 - 69, Replace mutable action
refs with full 40-character commit SHAs for all GitHub Actions used in the
workflow: locate every "uses: maxim-lobanov/setup-xcode@v1" and other "uses:"
entries (e.g., the one shown as maxim-lobanov/setup-xcode@v1 and the other noted
`@v2.37.0`) and update them to the corresponding pinned form
"owner/repo@<full-commit-sha>"; verify each SHA on the action's GitHub repo
(Releases/Commits) and replace the tag with that SHA so no actions remain using
mutable tags like `@v1` or `@v2.37.0`.
| - assertVisible: | ||
| text: ".*items.*" | ||
| - scrollUntilVisible: | ||
| element: | ||
| text: ".*\\$.*" | ||
| text: "Showing.*items" | ||
| direction: DOWN | ||
|
|
||
| # Go back to a stable state | ||
| timeout: 10000 | ||
| speed: 20 |
There was a problem hiding this comment.
Locale-dependent text matching makes this flow fragile.
.*items.* and Showing.*items depend on English copy. The screen text is translation-driven, so this can break with locale changes. Prefer testID-based assertions for the count/showing labels.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.maestro/flows/catalog/catalog-browse-flow.yaml around lines 12 - 19, The
locale-dependent regex selectors used in assertVisible and scrollUntilVisible
(the text fields ".*items.*" and "Showing.*items") are fragile; update these
steps to target stable testIDs instead (e.g., replace assertVisible:text and
scrollUntilVisible:element.text with assertions that use element.testID or a
testID-specific selector), ensuring you reference the same logical UI elements
(the count/showing label) when modifying the assertVisible and
scrollUntilVisible steps so the flow stops relying on English copy.
| - assertVisible: | ||
| text: ".*items.*" | ||
| # Tap first visible item using index | ||
| - tapOn: | ||
| id: "catalog-item" | ||
| index: 0 |
There was a problem hiding this comment.
Wait for the target element ID before tapping.
assertVisible on .*items.* can pass before cards are interactable (and is copy-dependent). Wait for id: "catalog-item" directly, then tap.
Proposed change
-- assertVisible:
- text: ".*items.*"
+- assertVisible:
+ id: "catalog-item"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.maestro/flows/catalog/catalog-item-detail-flow.yaml around lines 9 - 14,
Replace the loose assertVisible on ".*items.*" with a direct wait for the target
element id before tapping: change the step that currently uses assertVisible
(text: ".*items.*") to wait for the element with id "catalog-item" (the same id
used in the tapOn step), then perform tapOn with id: "catalog-item" and index: 0
so the tap only occurs after the specific card is present and interactable.
| - runFlow: | ||
| when: | ||
| platform: iOS | ||
| commands: | ||
| - tapOn: | ||
| text: ".*Back.*" |
There was a problem hiding this comment.
The iOS back step is brittle with text: ".*Back.*".
This assumes a visible English back label, which is not guaranteed. Add a deterministic back control testID in the screen/header and tap by id here.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.maestro/flows/catalog/catalog-item-detail-flow.yaml around lines 39 - 44,
The iOS back step in runFlow currently taps by text using tapOn with text:
".*Back.*", which is brittle; instead add a deterministic testID to the back
control in the screen/header (e.g., headerBackButton testID) and change the
runFlow tap step to use tapOn with id: "<headerBackButton-id>" (replace with the
actual testID); update the tapOn invocation in the catalog-item-detail-flow to
reference that id so tests tap the header back control deterministically.
| - runFlow: | ||
| when: | ||
| platform: iOS | ||
| commands: | ||
| - assertVisible: | ||
| text: "backpack.fill, Item Name" | ||
| - runFlow: | ||
| when: | ||
| platform: Android | ||
| commands: | ||
| - assertVisible: | ||
| text: "Item Name" | ||
|
|
||
| # Fill in Item Name | ||
| - tapOn: | ||
| text: "Item Name" | ||
| - inputText: "Test Headlamp" | ||
| - runFlow: | ||
| when: | ||
| platform: iOS | ||
| commands: | ||
| - tapOn: | ||
| text: "backpack.fill, Item Name" | ||
| - inputText: "Test Headlamp" | ||
| - runFlow: | ||
| when: | ||
| platform: Android | ||
| commands: | ||
| - tapOn: | ||
| text: "Item Name" | ||
| - inputText: "Test Headlamp" | ||
|
|
||
| # Fill in Description | ||
| - tapOn: | ||
| text: "Description" | ||
| - inputText: "Lightweight headlamp for hiking" | ||
| - runFlow: | ||
| when: | ||
| platform: iOS | ||
| commands: | ||
| - tapOn: | ||
| text: "info, Description" | ||
| - inputText: "Lightweight headlamp for hiking" | ||
| - runFlow: | ||
| when: | ||
| platform: Android | ||
| commands: | ||
| - tapOn: | ||
| text: "Description" | ||
| - inputText: "Lightweight headlamp for hiking" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify current text-based selectors in Maestro flow and discover candidate testIDs in app code.
# 1) Locate the brittle selectors in Maestro flows
rg -n -C2 'backpack\.fill, Item Name|info, Description|text:\s*"Item Name"|text:\s*"Description"' .maestro/flows
# 2) Find input testIDs in React Native code (likely TS/JS files)
rg -n -C3 --iglob '*.{ts,tsx,js,jsx}' 'testID\s*=\s*["'\''][^"'\'']*(item|name|description)[^"'\'']*["'\'']'
# Expected: concrete input testIDs for item-name/description fields.
# Then replace the `text:` selectors in this flow with corresponding `id:` selectors.Repository: PackRat-AI/PackRat
Length of output: 3959
🏁 Script executed:
fd -e tsx -e ts | xargs rg -l 'Item Name|Description' | grep -i 'screen\|form\|item' | head -20Repository: PackRat-AI/PackRat
Length of output: 800
🏁 Script executed:
# Search for AddItem or CreateItem screens/components
fd -e tsx -e ts | xargs rg -l 'addItem|AddItem|CreateItem|add.*item' -i | head -20Repository: PackRat-AI/PackRat
Length of output: 983
🏁 Script executed:
# Look for input components with testID in the codebase
rg -n 'testID.*=.*["\']' apps/expo --type ts --type tsx -A 2 | grep -i 'item\|description\|name' | head -30Repository: PackRat-AI/PackRat
Length of output: 131
🏁 Script executed:
cat apps/expo/lib/testIds.tsRepository: PackRat-AI/PackRat
Length of output: 4663
🏁 Script executed:
cat apps/expo/features/packs/screens/CreatePackItemForm.tsxRepository: PackRat-AI/PackRat
Length of output: 17466
🏁 Script executed:
# Also check if AddCatalogItemDetailsScreen is related
head -100 apps/expo/features/catalog/screens/AddCatalogItemDetailsScreen.tsxRepository: PackRat-AI/PackRat
Length of output: 3401
Replace text-based selectors with stable testID selectors and add missing testID to description input.
The Maestro flow uses brittle text selectors ("Item Name", "Description", "backpack.fill, Item Name", "info, Description") that will break when placeholders or i18n copy changes. Stable testIDs already exist in the centralized registry (testIds.items.nameInput = 'items:name-input', testIds.items.descriptionInput = 'items:description-input').
However, CreatePackItemForm.tsx has a blocker: the description input is missing the testID assignment. Fix that first by adding testID={testIds.items.descriptionInput} to the description TextField, then update the Maestro flow to use id: items:name-input and id: items:description-input instead of text-based selectors for both assertVisible and tapOn commands across all platform conditions.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.maestro/flows/packs/add-item-manual-flow.yaml around lines 40 - 83, Add the
missing testID prop to the description TextField in CreatePackItemForm.tsx using
testIds.items.descriptionInput, then update the Maestro flow entries that use
text selectors ("Item Name", "Description", "backpack.fill, Item Name", "info,
Description") to use stable id selectors for both platforms and for both
assertVisible and tapOn commands: use id: items:name-input
(testIds.items.nameInput) and id: items:description-input
(testIds.items.descriptionInput); keep the existing inputText commands
unchanged.
| - runFlow: | ||
| when: | ||
| platform: iOS | ||
| commands: | ||
| - tapOn: | ||
| text: "move, Pack Name" | ||
| - inputText: ${PACK_NAME} | ||
| - runFlow: | ||
| when: | ||
| platform: Android | ||
| commands: | ||
| - tapOn: | ||
| text: "Pack Name" | ||
| - inputText: ${PACK_NAME} |
There was a problem hiding this comment.
iOS Pack Name selector likely mismatches the actual field label.
Line 24 taps "move, Pack Name", but apps/expo/features/packs/components/PackForm.tsx (lines 147-193) shows the pack name field icon as folder. This can make the iOS branch fail to focus the name input.
Proposed fix
- - tapOn:
- text: "move, Pack Name"
+ - tapOn:
+ text: "folder, Pack Name"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.maestro/flows/packs/create-pack-flow.yaml around lines 19 - 32, The iOS
runFlow step is tapping the wrong label ("move, Pack Name") so the name input
isn't focused; update the iOS branch in runFlow to tap the same selector as
Android (e.g., tapOn text: "Pack Name") or use the input's accessibility label
used by the PackForm component (PackForm's pack name field/icon "folder") to
reliably target the name field, keeping the subsequent inputText ${PACK_NAME}
call unchanged.
| <View testID={testIds.auth.emailInput}> | ||
| <form.Field name="email"> | ||
| {(field) => ( | ||
| <TextField | ||
| testID={testIds.auth.emailInput} |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, find and examine the login file
fd -t f "index.tsx" apps/expo/app/auth | head -10Repository: PackRat-AI/PackRat
Length of output: 174
🏁 Script executed:
# Check the structure of the auth directory
find apps/expo/app/auth -type f -name "*.tsx" -o -name "*.ts" | head -20Repository: PackRat-AI/PackRat
Length of output: 478
🏁 Script executed:
# Read the relevant section of the login file around lines 116-120
sed -n '110,130p' apps/expo/app/auth/\(login\)/index.tsxRepository: PackRat-AI/PackRat
Length of output: 973
🏁 Script executed:
# Check for the Maestro flow file
find . -path "*maestro/flows/auth/login-flow.yaml" -o -path "*.maestro*login*.yaml" | head -10Repository: PackRat-AI/PackRat
Length of output: 150
🏁 Script executed:
# Read the Maestro login flow to see what selectors it uses around lines 24-30
sed -n '20,35p' .maestro/flows/auth/login-flow.yamlRepository: PackRat-AI/PackRat
Length of output: 358
🏁 Script executed:
# Search for testIds definition to see what the actual value is
rg "testIds\s*=" apps/expo -A 5 -B 2 | head -50Repository: PackRat-AI/PackRat
Length of output: 590
🏁 Script executed:
# Find where testIds.auth.emailInput is defined
rg "emailInput" apps/expo --type ts --type tsx -B 2 -A 2 | head -40Repository: PackRat-AI/PackRat
Length of output: 90
🏁 Script executed:
# Get more context around the email field structure to understand the form better
sed -n '100,150p' apps/expo/app/auth/\(login\)/index.tsxRepository: PackRat-AI/PackRat
Length of output: 2273
🏁 Script executed:
# Check if there are other places in the codebase with similar patterns
rg "View testID=" apps/expo --type ts -A 3 | head -30Repository: PackRat-AI/PackRat
Length of output: 385
🏁 Script executed:
# Verify Platform import and usage in this file
rg "Platform\." apps/expo/app/auth/\(login\)/index.tsx | head -10Repository: PackRat-AI/PackRat
Length of output: 549
Duplicate testID on wrapper and field causes Android test flakiness.
On Android, .maestro/flows/auth/login-flow.yaml:27 taps id: "email-input", which matches both the View wrapper and the TextField. Since the wrapper is non-focusable, Maestro may resolve it first, causing the subsequent inputText to fail. Apply the fix to expose the testID only on the field for Android:
Suggested fix
- <View testID={testIds.auth.emailInput}>
+ <View testID={Platform.OS === 'ios' ? testIds.auth.emailInput : undefined}>
<form.Field name="email">
{(field) => (
<TextField
- testID={testIds.auth.emailInput}
+ testID={Platform.OS === 'android' ? testIds.auth.emailInput : undefined}
placeholder={Platform.select({
ios: 'Email',
default: '',📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <View testID={testIds.auth.emailInput}> | |
| <form.Field name="email"> | |
| {(field) => ( | |
| <TextField | |
| testID={testIds.auth.emailInput} | |
| <View testID={Platform.OS === 'ios' ? testIds.auth.emailInput : undefined}> | |
| <form.Field name="email"> | |
| {(field) => ( | |
| <TextField | |
| testID={Platform.OS === 'android' ? testIds.auth.emailInput : undefined} | |
| placeholder={Platform.select({ | |
| ios: 'Email', | |
| default: '', |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/expo/app/auth/`(login)/index.tsx around lines 116 - 120, The wrapper
View around the email input currently shares the same testID as the inner
TextField, causing Android test flakiness; remove the testID prop from the View
(the wrapper returned in the render of form.Field) so only the TextField (the
inner component rendered by the form.Field callback) has
testID={testIds.auth.emailInput}; locate the occurrence in
apps/expo/app/auth/(login)/index.tsx where View and TextField are both using
testIds.auth.emailInput and delete the testID from the View (or conditionally
omit it for Android) leaving the TextField as the sole element exposing that
test ID.
…naming convention
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
.maestro/flows/catalog/catalog-item-detail-flow.yaml (2)
9-14:⚠️ Potential issue | 🟠 Major | ⚡ Quick winWait for the actual tappable item before tapping.
Line 9 currently gates on generic copy (
.*items.*), which can pass before cards are interactable. Gate on the same item selector used at Line 13.Proposed flow change
- assertVisible: - text: ".*items.*" + id: "catalog:item-.*"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.maestro/flows/catalog/catalog-item-detail-flow.yaml around lines 9 - 14, The assertVisible check is using a generic text selector (".*items.*") which can pass before the actual tappable card is ready; change the pre-tap guard to assertVisible on the same item selector used by tapOn (id: "catalog:item-.*") so the flow waits for the actual tappable element (the same id pattern used in tapOn) before invoking the tap action.
39-44:⚠️ Potential issue | 🟠 Major | 🏗️ Heavy liftThe iOS back step is still brittle with
text: ".*Back.*".Line 44 depends on visible English text and nav label behavior. Prefer tapping a deterministic back control
id(add a back-button testID in the header config, then reference it here).Flow-side change after adding header back testID in app code
- runFlow: when: platform: iOS commands: - tapOn: - text: ".*Back.*" + id: "header-back-button"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.maestro/flows/catalog/catalog-item-detail-flow.yaml around lines 39 - 44, The iOS back step in runFlow is brittle because tapOn uses a regex text matcher (text: ".*Back.*"); change this to tap the deterministic testID for the header back button instead: add a testID (e.g., back-button) to the header component in app code and then replace the tapOn entry in the runFlow with a tapOn that targets id: "back-button" (refer to the runFlow and tapOn symbols in the diff to locate the change).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.maestro/flows/trips/create-trip-flow.yaml:
- Around line 67-79: The iOS branch of runFlow uses tapOn with bare day tokens
(${TODAY_DATE}, ${START_DAY}, ${END_DAY}) which is fragile across month
boundaries; update the flow so the iOS path targets a full date label or
performs month-aware navigation before tapping a day: e.g., after tapping
"${TODAY_DATE}" use a loop-like sequence that checks for the full-date label (or
tries to tap a month-next control) until "${START_DAY}" / "${END_DAY}" is
visible, then tapOn that full date label, and keep waitForAnimationToEnd between
steps; modify the tapOn actions in the iOS runFlow (and the duplicate block at
lines referenced in the comment) to use full date selectors or explicit
next-month navigation instead of bare day numbers.
- Around line 25-31: The iOS branch of runFlow still taps the old placeholder
text "Description", so update the tapOn command in the iOS when block to target
the renamed iOS placeholder "newspaper, Description" (keep the following
inputText: "Created by Maestro E2E test" unchanged) so the flow will focus the
description field on iOS; locate the runFlow block and replace the tapOn text
value accordingly.
---
Duplicate comments:
In @.maestro/flows/catalog/catalog-item-detail-flow.yaml:
- Around line 9-14: The assertVisible check is using a generic text selector
(".*items.*") which can pass before the actual tappable card is ready; change
the pre-tap guard to assertVisible on the same item selector used by tapOn (id:
"catalog:item-.*") so the flow waits for the actual tappable element (the same
id pattern used in tapOn) before invoking the tap action.
- Around line 39-44: The iOS back step in runFlow is brittle because tapOn uses
a regex text matcher (text: ".*Back.*"); change this to tap the deterministic
testID for the header back button instead: add a testID (e.g., back-button) to
the header component in app code and then replace the tapOn entry in the runFlow
with a tapOn that targets id: "back-button" (refer to the runFlow and tapOn
symbols in the diff to locate the change).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 53ad9272-b265-47e9-8e0d-022470e8bbb1
📒 Files selected for processing (9)
.github/scripts/e2e.sh.maestro/flows/catalog/catalog-item-detail-flow.yaml.maestro/flows/packs/add-item-actions-flow.yaml.maestro/flows/packs/create-pack-flow.yaml.maestro/flows/packs/pack-detail-flow.yaml.maestro/flows/trips/create-trip-flow.yaml.maestro/flows/trips/trip-detail-flow.yamlapps/expo/features/packs/components/PackCard.tsxapps/expo/features/trips/components/TripCard.tsx
| - runFlow: | ||
| when: | ||
| platform: iOS | ||
| commands: | ||
| - tapOn: | ||
| text: "Description" | ||
| - inputText: "Created by Maestro E2E test" |
There was a problem hiding this comment.
Use the renamed iOS description placeholder here.
The iOS branch still taps "Description", but this PR’s iOS trip form placeholder was changed to "newspaper, Description". As written, the flow won't focus the description field on iOS.
Suggested fix
- runFlow:
when:
platform: iOS
commands:
- tapOn:
- text: "Description"
+ text: "newspaper, Description"
- inputText: "Created by Maestro E2E test"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.maestro/flows/trips/create-trip-flow.yaml around lines 25 - 31, The iOS
branch of runFlow still taps the old placeholder text "Description", so update
the tapOn command in the iOS when block to target the renamed iOS placeholder
"newspaper, Description" (keep the following inputText: "Created by Maestro E2E
test" unchanged) so the flow will focus the description field on iOS; locate the
runFlow block and replace the tapOn text value accordingly.
| - runFlow: | ||
| when: | ||
| platform: iOS | ||
| commands: | ||
| - tapOn: "${START_MONTH} ${START_DAY}" | ||
| - tapOn: | ||
| point: "5%,5%" | ||
|
|
||
| text: "${TODAY_DATE}" | ||
| - waitForAnimationToEnd | ||
| - tapOn: | ||
| text: "${START_DAY}" | ||
| - waitForAnimationToEnd | ||
| - tapOn: | ||
| point: "50%,90%" | ||
| - waitForAnimationToEnd |
There was a problem hiding this comment.
The iOS date-picker path is still month-boundary fragile.
.github/scripts/e2e.sh:10-25 drives these values from today + 7 days and today + 14 days. After tapping ${TODAY_DATE}, this flow only taps ${START_DAY} / ${END_DAY} in the currently visible grid. When either target date falls into the next month and is not visible yet, the flow becomes calendar-dependent and will fail intermittently in CI. Make the iOS branch month-aware, or target a full date label instead of a bare day number.
Also applies to: 98-109
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.maestro/flows/trips/create-trip-flow.yaml around lines 67 - 79, The iOS
branch of runFlow uses tapOn with bare day tokens (${TODAY_DATE}, ${START_DAY},
${END_DAY}) which is fragile across month boundaries; update the flow so the iOS
path targets a full date label or performs month-aware navigation before tapping
a day: e.g., after tapping "${TODAY_DATE}" use a loop-like sequence that checks
for the full-date label (or tries to tap a month-next control) until
"${START_DAY}" / "${END_DAY}" is visible, then tapOn that full date label, and
keep waitForAnimationToEnd between steps; modify the tapOn actions in the iOS
runFlow (and the duplicate block at lines referenced in the comment) to use full
date selectors or explicit next-month navigation instead of bare day numbers.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
.github/scripts/e2e.sh (1)
36-37:⚠️ Potential issue | 🟠 Major | ⚡ Quick winFail fast when test credentials are missing.
TEST_EMAIL/TEST_PASSWORDare injected even when unset, which can silently run login with empty inputs and produce misleading E2E failures (see.maestro/flows/auth/login-flow.yamlusages of both vars). Add required-env validation (or secure fallback toE2E_TEST_*) before invoking Maestro.Suggested patch
PLATFORM=$1 # "ios" or "android" shift # Remove first argument so $@ contains only the additional options +# Resolve credentials from primary envs or secure fallback envs, then fail fast if still missing +TEST_EMAIL="${TEST_EMAIL:-${E2E_TEST_EMAIL:-}}" +TEST_PASSWORD="${TEST_PASSWORD:-${E2E_TEST_PASSWORD:-}}" +: "${TEST_EMAIL:?TEST_EMAIL or E2E_TEST_EMAIL is required}" +: "${TEST_PASSWORD:?TEST_PASSWORD or E2E_TEST_PASSWORD is required}" + # Generate unique ID for this test run UNIQUE_ID=$(date +%s) @@ - -e TEST_EMAIL="${TEST_EMAIL}" \ - -e TEST_PASSWORD="${TEST_PASSWORD}" \ + -e TEST_EMAIL="$TEST_EMAIL" \ + -e TEST_PASSWORD="$TEST_PASSWORD" \ @@ - -e TEST_EMAIL="${TEST_EMAIL}" \ - -e TEST_PASSWORD="${TEST_PASSWORD}" \ + -e TEST_EMAIL="$TEST_EMAIL" \ + -e TEST_PASSWORD="$TEST_PASSWORD" \#!/bin/bash # Read-only verification: confirm whether required credential guards exist and where vars are injected. rg -n '\$\{TEST_EMAIL:\?|\$\{TEST_PASSWORD:\?|\$\{E2E_TEST_EMAIL:\?|\$\{E2E_TEST_PASSWORD:\?' .github/scripts/e2e.sh || true rg -n ' -e TEST_EMAIL=| -e TEST_PASSWORD=' .github/scripts/e2e.sh -C2Also applies to: 53-54
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/scripts/e2e.sh around lines 36 - 37, Add a fail-fast guard before invoking Maestro: check TEST_EMAIL and TEST_PASSWORD and, if unset, fallback to E2E_TEST_EMAIL/E2E_TEST_PASSWORD; if both primary and fallback are empty, print a clear error and exit 1. Implement this by resolving final variables (e.g., resolved_email and resolved_password) from TEST_EMAIL || E2E_TEST_EMAIL and TEST_PASSWORD || E2E_TEST_PASSWORD, export those for the existing Maestro invocation that uses TEST_EMAIL/TEST_PASSWORD, and replace or set the -e TEST_EMAIL / -e TEST_PASSWORD environment injections to use the validated values; also apply the same guard for the second invocation around lines currently injecting TEST_EMAIL/TEST_PASSWORD (the other -e occurrences).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/api/src/schemas/catalog.ts`:
- Around line 97-98: The catalog route handler currently returns raw DB items
from CatalogService.getCatalogItems(), which have Date objects for
createdAt/updatedAt; update the handler in the route (the function handling the
response) to map result.items and replace each item's createdAt and updatedAt
with ISO strings (use item.createdAt.toISOString() and
item.updatedAt.toISOString()) before returning, following the same mapping
pattern used in feed/index.ts and packs/index.ts so the response matches the
schema expecting z.string().datetime().
---
Duplicate comments:
In @.github/scripts/e2e.sh:
- Around line 36-37: Add a fail-fast guard before invoking Maestro: check
TEST_EMAIL and TEST_PASSWORD and, if unset, fallback to
E2E_TEST_EMAIL/E2E_TEST_PASSWORD; if both primary and fallback are empty, print
a clear error and exit 1. Implement this by resolving final variables (e.g.,
resolved_email and resolved_password) from TEST_EMAIL || E2E_TEST_EMAIL and
TEST_PASSWORD || E2E_TEST_PASSWORD, export those for the existing Maestro
invocation that uses TEST_EMAIL/TEST_PASSWORD, and replace or set the -e
TEST_EMAIL / -e TEST_PASSWORD environment injections to use the validated
values; also apply the same guard for the second invocation around lines
currently injecting TEST_EMAIL/TEST_PASSWORD (the other -e occurrences).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: a0c0ace1-4d26-4e9e-8bfa-ed05efa736f1
📒 Files selected for processing (4)
.github/scripts/e2e.shapps/expo/features/catalog/components/CatalogItemCard.tsxapps/expo/features/catalog/types.tspackages/api/src/schemas/catalog.ts
… by adjusting tab bar visibility checks
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.maestro/flows/auth/login-flow.yaml (1)
71-74:⚠️ Potential issue | 🟠 Major | ⚡ Quick winThe pre-existing 15 s wait gates the new 35 s wait, making the new check dead code.
Execution is sequential: if
"Packs"doesn't appear within the firstextendedWaitUntil(15 000 ms, lines 71-74), Maestro aborts the flow right there — lines 82-85 are never reached. The only case where the 35 s check runs is when"Packs"already appeared within 15 s, at which point the second check passes instantly and adds zero value.This directly defeats the stated goal of the PR (improving stability on slow post-login iOS routing). The fix is to either remove the old 15 s check or raise its timeout to match the new one.
🔧 Proposed fix — replace the old check with the new one
-# Wait for navigation to complete — login can take a few seconds -- extendedWaitUntil: - visible: - text: "Packs" - timeout: 15000 - -- waitForAnimationToEnd - # Wait for the main tab bar to appear — confirms we are logged in and on the main app. # We only assert the tab bar is visible here; navigation to specific tabs is left to # subsequent flows (dashboard-tiles-flow taps Packs, providing a stable entry point for # create-pack-flow). Navigating to Packs directly after login is unreliable on iOS # because Expo Router's post-login routing is still settling at this point. -- extendedWaitUntil: +- extendedWaitUntil: visible: text: "Packs" timeout: 35000Also applies to: 82-85
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.maestro/flows/auth/login-flow.yaml around lines 71 - 74, The existing short wait gate uses extendedWaitUntil with visible:text:"Packs" and timeout: 15000 which preempts the intended longer stability check; replace the 15_000ms timeout (extendedWaitUntil visible:text:"Packs") with 35000 (or remove the earlier extendedWaitUntil block) so the 35_000ms check is the effective wait (also update the duplicate extendedWaitUntil instance that appears later to the same 35000ms if keeping both), ensuring the longer timeout is actually exercised.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.maestro/flows/auth/login-flow.yaml:
- Line 39: The TEST_PASSWORD placeholder is unquoted while TEST_EMAIL is quoted,
which can break YAML parsing for passwords containing special characters; update
the login-flow.yaml entries that set inputText: ${TEST_PASSWORD} in both the iOS
block (the inputText line near the iOS step) and the Android block (the
analogous inputText line) so they use the same quoted form as inputText:
"${TEST_EMAIL}"—i.e., wrap ${TEST_PASSWORD} in double quotes to match and
prevent YAML tokenization errors.
---
Outside diff comments:
In @.maestro/flows/auth/login-flow.yaml:
- Around line 71-74: The existing short wait gate uses extendedWaitUntil with
visible:text:"Packs" and timeout: 15000 which preempts the intended longer
stability check; replace the 15_000ms timeout (extendedWaitUntil
visible:text:"Packs") with 35000 (or remove the earlier extendedWaitUntil block)
so the 35_000ms check is the effective wait (also update the duplicate
extendedWaitUntil instance that appears later to the same 35000ms if keeping
both), ensuring the longer timeout is actually exercised.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: e10a5ff1-31e3-4f21-80d2-91b5288ada65
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock,!bun.lock
📒 Files selected for processing (1)
.maestro/flows/auth/login-flow.yaml
| commands: | ||
| - tapOn: | ||
| text: "Password" | ||
| - inputText: ${TEST_PASSWORD} |
There was a problem hiding this comment.
Quote ${TEST_PASSWORD} consistently with ${TEST_EMAIL}.
inputText: ${TEST_PASSWORD} is unquoted while inputText: "${TEST_EMAIL}" is quoted. If a test password contains YAML-special characters (:, #, [, {, *, etc.), the unquoted form will cause a YAML parse error or silent mis-tokenisation at load time.
🔧 Proposed fix
- - inputText: ${TEST_PASSWORD}
+ - inputText: "${TEST_PASSWORD}"Apply to both line 39 (iOS block) and line 46 (Android block).
Also applies to: 46-46
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.maestro/flows/auth/login-flow.yaml at line 39, The TEST_PASSWORD
placeholder is unquoted while TEST_EMAIL is quoted, which can break YAML parsing
for passwords containing special characters; update the login-flow.yaml entries
that set inputText: ${TEST_PASSWORD} in both the iOS block (the inputText line
near the iOS step) and the Android block (the analogous inputText line) so they
use the same quoted form as inputText: "${TEST_EMAIL}"—i.e., wrap
${TEST_PASSWORD} in double quotes to match and prevent YAML tokenization errors.
There was a problem hiding this comment.
♻️ Duplicate comments (1)
.maestro/flows/catalog/catalog-item-detail-flow.yaml (1)
9-14:⚠️ Potential issue | 🟠 Major | ⚡ Quick winWait for the target element ID pattern before tapping.
assertVisiblewithtext: ".*items.*"is copy-dependent and can pass before cards are interactable. Since you're tappingid: "catalog:item-.*", wait for that same pattern instead.Proposed fix
# Wait for items to load - assertVisible: - text: ".*items.*" + id: "catalog:item-.*" # Tap first visible item using index - tapOn: id: "catalog:item-.*" index: 0🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.maestro/flows/catalog/catalog-item-detail-flow.yaml around lines 9 - 14, The current flow uses assertVisible with text ".*items.*" which can pass prematurely; change the pre-tap wait to assertVisible (or equivalent wait) targeting the same id pattern you tap (id: "catalog:item-.*") so the element matching id "catalog:item-.*" is confirmed visible/interactable before calling tapOn (id: "catalog:item-.*", index: 0); update the assertVisible invocation to use the id pattern or add a new assertVisible for id "catalog:item-.*" immediately before the tapOn step so you wait for the exact target element.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In @.maestro/flows/catalog/catalog-item-detail-flow.yaml:
- Around line 9-14: The current flow uses assertVisible with text ".*items.*"
which can pass prematurely; change the pre-tap wait to assertVisible (or
equivalent wait) targeting the same id pattern you tap (id: "catalog:item-.*")
so the element matching id "catalog:item-.*" is confirmed visible/interactable
before calling tapOn (id: "catalog:item-.*", index: 0); update the assertVisible
invocation to use the id pattern or add a new assertVisible for id
"catalog:item-.*" immediately before the tapOn step so you wait for the exact
target element.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: c259168c-c76a-4f7b-958a-a29472154323
📒 Files selected for processing (3)
.maestro/flows/auth/login-flow.yaml.maestro/flows/catalog/catalog-item-detail-flow.yamlapps/expo/lib/i18n/locales/en.json
Fix/maestro e2e flows for ios
Fix all failing maestro e2e flows for ios
Summary by CodeRabbit
Release Notes
New Features
Bug Fixes
Tests