Skip to content

Fix/maestro e2e flows for ios#2076

Merged
mikib0 merged 26 commits into
developmentfrom
fix/Maestro-E2E-flows-for-iOS
May 5, 2026
Merged

Fix/maestro e2e flows for ios#2076
mikib0 merged 26 commits into
developmentfrom
fix/Maestro-E2E-flows-for-iOS

Conversation

@Isthisanmol

@Isthisanmol Isthisanmol commented Apr 11, 2026

Copy link
Copy Markdown
Collaborator

Fix all failing maestro e2e flows for ios

Summary by CodeRabbit

Release Notes

  • New Features

    • Added platform-specific handling for form field interactions to improve cross-platform consistency.
    • Added new logout confirmation option with updated messaging.
  • Bug Fixes

    • Improved login and logout flow reliability through enhanced test automation.
    • Updated dashboard navigation and catalog browsing logic for better stability.
  • Tests

    • Expanded end-to-end test coverage for authentication, packing, and trip management flows.
    • Enhanced test targeting with deterministic element identification.

@coderabbitai

coderabbitai Bot commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This 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.

Changes

E2E Test Infrastructure & Deterministic Selectors

Layer / File(s) Summary
Script Infrastructure
.github/scripts/e2e.sh
Removes credential guard, adds platform-specific TODAY_DATE calculation for iOS/Android, updates quoting for credential environment variables, and adjusts Android day parsing.
Maestro Credential Input
.maestro/flows/auth/login-flow.yaml
Login flow now uses platform-specific tapping (iOS taps text labels, Android taps element IDs) before credential input; post-login verification waits for "Packs" label visibility instead of direct tap.
Maestro Logout & Dialog
.maestro/flows/auth/logout-flow.yaml
Updates "Sync in progress" dialog button from "Log Out" to "Proceed".
Maestro Catalog & Navigation
.maestro/flows/catalog/catalog-browse-flow.yaml, catalog-item-detail-flow.yaml
Catalog flows now use deterministic ID-based selectors (e.g., catalog:item-.*) instead of text matching; item detail scrolling adds explicit timeout and speed parameters; back navigation becomes platform-specific via runFlow.
Maestro Dashboard & Tile Selection
.maestro/flows/dashboard/dashboard-tiles-flow.yaml
Replaces "Home" tab with "Dashboard" and switches PackRat AI tile selection from text to id-based selectors.
Maestro Pack Operations
.maestro/flows/packs/create-pack-flow.yaml, pack-detail-flow.yaml, add-item-actions-flow.yaml, add-item-manual-flow.yaml
Pack flows use deterministic ID-based list-item selectors (packs:list-item-${PACK_NAME}); input handling refactored into platform-specific runFlow branches; platform-specific back navigation (Android back vs iOS text tap).
Maestro Trip Operations
.maestro/flows/trips/create-trip-flow.yaml, trip-detail-flow.yaml
Trip selection now uses deterministic IDs (trips:list-item-${TRIP_NAME}); date picking refactored with TODAY_DATE support and platform-specific logic (Android month-tapping loops, iOS date cell selection); back navigation becomes platform-specific.
Maestro Negative Test Flows
.maestro/flows/negative/empty-pack-submit-flow.yaml, empty-trip-submit-flow.yaml
Sheet dismissal replaced with platform-specific runFlow (Android back, iOS swipe + animation wait); assertion comments clarified to reference validation blocking.
React Native testID Instrumentation
apps/expo/features/catalog/components/CatalogItemCard.tsx, packs/components/PackCard.tsx, trips/components/TripCard.tsx, ai/components/AIChatTile.tsx
Adds deterministic testID values to card components using testIds.*() helpers for E2E targeting.
Test ID Registry
apps/expo/lib/testIds.ts
Exports new static IDs: trips.startDateInput and trips.endDateInput.
Auth Screen Updates
apps/expo/app/auth/(login)/index.tsx
Removes conditional accessible props from form containers; restructures email input wiring by introducing wrapping View with testID.
Profile & Logout Text
apps/expo/app/(app)/(tabs)/profile/index.tsx
Updates sign-out button testID to testIds.profile.signOutBtn and changes logout confirmation button text from auth.logOut to auth.proceedLogOut.
TripForm testID Updates
apps/expo/features/trips/components/TripForm.tsx
Replaces old TestIds with new testIds namespace; adds testIDs for start/end date inputs and updates submit button testID.
Localization
apps/expo/lib/i18n/locales/en.json
Adds auth.proceedLogOut: "Proceed" translation key.
Type Definition
apps/expo/features/catalog/types.ts
Changes CatalogItem.createdAt and CatalogItem.updatedAt from Date to string types.

Package Dependency Update

Layer / File(s) Summary
Runtime Dependency
packages/web-ui/package.json
Promotes recharts from devDependencies / peerDependencies to dependencies so consumers install it directly.
Tooltip & Legend Formatting
packages/web-ui/src/components/chart.tsx
Reformats three getPayloadConfigFromPayload invocations to multi-line structure; no logic changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • andrew-bierman
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title claims to fix maestro E2E flows for iOS, but the changeset addresses failing flows across both iOS and Android platforms, modifies test IDs, translations, and dependencies unrelated to iOS-specific fixes. Revise the title to accurately reflect the full scope: something like 'Fix maestro E2E flows for iOS and Android with platform-specific handling' or 'Update maestro E2E flows and test infrastructure for iOS and Android'.
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/Maestro-E2E-flows-for-iOS

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the ci/cd label Apr 13, 2026
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Deploying packrat-guides with  Cloudflare Pages  Cloudflare Pages

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

View logs

@Isthisanmol Isthisanmol marked this pull request as ready for review April 13, 2026 08:29
@Isthisanmol Isthisanmol requested a review from mikib0 April 13, 2026 08:29
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Deploying packrat-landing with  Cloudflare Pages  Cloudflare Pages

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

View logs

mikib0 added 4 commits April 15, 2026 11:06
…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
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

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

@github-actions github-actions Bot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file api web labels Apr 16, 2026
@github-actions

github-actions Bot commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for API Unit Tests Coverage (./packages/api)

Status Category Percentage Covered / Total
🔵 Lines 72.93% 609 / 835
🔵 Statements 72.93% (🎯 65%) 609 / 835
🔵 Functions 96% 48 / 50
🔵 Branches 88.27% 271 / 307
File CoverageNo changed files found.
Generated in workflow #1060 for commit 8f69f89 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for Expo Unit Tests Coverage (./apps/expo)

Status Category Percentage Covered / Total
🔵 Lines 81.7% 536 / 656
🔵 Statements 81.7% (🎯 75%) 536 / 656
🔵 Functions 92.98% 53 / 57
🔵 Branches 89.73% 201 / 224
File CoverageNo changed files found.
Generated in workflow #1060 for commit 8f69f89 by the Vitest Coverage Report Action

mikib0 added 4 commits April 16, 2026 12:18
- 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
@github-actions github-actions Bot removed documentation Improvements or additions to documentation api web labels Apr 17, 2026
@mikib0 mikib0 force-pushed the fix/Maestro-E2E-flows-for-iOS branch from 83f9ae3 to 38f881b Compare April 23, 2026 08:34

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between cdeb103 and bf15a10.

⛔ Files ignored due to path filters (1)
  • bun.lock is 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.yaml
  • apps/expo/app/(app)/(tabs)/profile/index.tsx
  • apps/expo/app/auth/(login)/index.tsx
  • apps/expo/features/ai/components/AIChatTile.tsx
  • apps/expo/features/catalog/components/CatalogItemCard.tsx
  • apps/expo/features/packs/components/PackCard.tsx
  • apps/expo/features/trips/components/TripCard.tsx
  • apps/expo/features/trips/components/TripForm.tsx
  • apps/expo/lib/i18n/locales/en.json
  • apps/expo/lib/testIds.ts
  • packages/web-ui/package.json
  • packages/web-ui/src/components/chart.tsx

Comment thread .github/scripts/e2e.sh Outdated
Comment on lines +36 to +37
-e TEST_EMAIL="${TEST_EMAIL:-qa1.admin@packratai.com}" \
-e TEST_PASSWORD="${TEST_PASSWORD:-Ab12345.}" \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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.

Comment thread .github/workflows/e2e-tests.yml Outdated
Comment on lines +67 to +69
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: '26.2'
xcode-version: "26.2"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 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.yml

Repository: PackRat-AI/PackRat

Length of output: 982


🏁 Script executed:

rg -nP '^\s*uses:\s*[^@]+@(?![0-9a-f]{40}$).+' .github/workflows/e2e-tests.yml

Repository: 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`.

Comment on lines +12 to +19
- assertVisible:
text: ".*items.*"
- scrollUntilVisible:
element:
text: ".*\\$.*"
text: "Showing.*items"
direction: DOWN

# Go back to a stable state
timeout: 10000
speed: 20

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

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.

Comment on lines +9 to +14
- assertVisible:
text: ".*items.*"
# Tap first visible item using index
- tapOn:
id: "catalog-item"
index: 0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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.

Comment on lines +39 to +44
- runFlow:
when:
platform: iOS
commands:
- tapOn:
text: ".*Back.*"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

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.

Comment on lines +40 to +83
- 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"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 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 -20

Repository: 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 -20

Repository: 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 -30

Repository: PackRat-AI/PackRat

Length of output: 131


🏁 Script executed:

cat apps/expo/lib/testIds.ts

Repository: PackRat-AI/PackRat

Length of output: 4663


🏁 Script executed:

cat apps/expo/features/packs/screens/CreatePackItemForm.tsx

Repository: PackRat-AI/PackRat

Length of output: 17466


🏁 Script executed:

# Also check if AddCatalogItemDetailsScreen is related
head -100 apps/expo/features/catalog/screens/AddCatalogItemDetailsScreen.tsx

Repository: 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.

Comment on lines +19 to +32
- 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}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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.

Comment thread .maestro/flows/trips/create-trip-flow.yaml
Comment on lines +116 to +120
<View testID={testIds.auth.emailInput}>
<form.Field name="email">
{(field) => (
<TextField
testID={testIds.auth.emailInput}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, find and examine the login file
fd -t f "index.tsx" apps/expo/app/auth | head -10

Repository: 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 -20

Repository: 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.tsx

Repository: 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 -10

Repository: 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.yaml

Repository: 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 -50

Repository: 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 -40

Repository: 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.tsx

Repository: 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 -30

Repository: 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 -10

Repository: 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.

Suggested change
<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.

Comment thread apps/expo/features/catalog/components/CatalogItemCard.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
.maestro/flows/catalog/catalog-item-detail-flow.yaml (2)

9-14: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Wait 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 lift

The 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

📥 Commits

Reviewing files that changed from the base of the PR and between bf15a10 and 12aa52e.

📒 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.yaml
  • apps/expo/features/packs/components/PackCard.tsx
  • apps/expo/features/trips/components/TripCard.tsx

Comment on lines +25 to +31
- runFlow:
when:
platform: iOS
commands:
- tapOn:
text: "Description"
- inputText: "Created by Maestro E2E test"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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.

Comment on lines 67 to 79
- 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

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.

@github-actions github-actions Bot added the api label May 1, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
.github/scripts/e2e.sh (1)

36-37: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fail fast when test credentials are missing.

TEST_EMAIL/TEST_PASSWORD are injected even when unset, which can silently run login with empty inputs and produce misleading E2E failures (see .maestro/flows/auth/login-flow.yaml usages of both vars). Add required-env validation (or secure fallback to E2E_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 -C2

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, 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

📥 Commits

Reviewing files that changed from the base of the PR and between 12aa52e and 42bc875.

📒 Files selected for processing (4)
  • .github/scripts/e2e.sh
  • apps/expo/features/catalog/components/CatalogItemCard.tsx
  • apps/expo/features/catalog/types.ts
  • packages/api/src/schemas/catalog.ts

Comment thread packages/api/src/schemas/catalog.ts Outdated
@github-actions github-actions Bot removed the api label May 1, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

The 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 first extendedWaitUntil (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: 35000

Also 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

📥 Commits

Reviewing files that changed from the base of the PR and between 42bc875 and 09fecf9.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock, !bun.lock
📒 Files selected for processing (1)
  • .maestro/flows/auth/login-flow.yaml

commands:
- tapOn:
text: "Password"
- inputText: ${TEST_PASSWORD}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
.maestro/flows/catalog/catalog-item-detail-flow.yaml (1)

9-14: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Wait for the target element ID pattern before tapping.

assertVisible with text: ".*items.*" is copy-dependent and can pass before cards are interactable. Since you're tapping id: "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

📥 Commits

Reviewing files that changed from the base of the PR and between 09fecf9 and 8f69f89.

📒 Files selected for processing (3)
  • .maestro/flows/auth/login-flow.yaml
  • .maestro/flows/catalog/catalog-item-detail-flow.yaml
  • apps/expo/lib/i18n/locales/en.json

@mikib0 mikib0 merged commit a4cb13b into development May 5, 2026
17 of 19 checks passed
@mikib0 mikib0 deleted the fix/Maestro-E2E-flows-for-iOS branch May 5, 2026 07:33
andrew-bierman pushed a commit that referenced this pull request May 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd dependencies Pull requests that update a dependency file mobile

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants