text: migrated room test from detox to maestro#6598
Conversation
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
app/containers/message/Message.tsx (2)
187-193: Avoid multiple accessible wrappers; attach label to message content onlyRight now the outer container is accessible and MessageInner is marked accessible too. Prefer a single a11y element to prevent duplicate announcements. Move the label to the messageContent wrapper and drop it from the outer container and MessageInner.
- <View testID={`message-${props.id}`} accessible accessibilityLabel={accessibilityLabel} style={styles.container}> + <View testID={`message-${props.id}`} style={styles.container}> <View style={styles.flex}> <MessageAvatar {...props} /> - <View style={styles.messageContent}> - <MessageInner accessible accessibilityLabel={accessibilityLabel} {...props} /> + <View style={styles.messageContent} accessible accessibilityLabel={accessibilityLabel}> + <MessageInner {...props} /> </View>
123-132: Fix string interpolation bug in accessibility labelThis will render “[object Object]” when not in a thread (uses props instead of props.msg).
- if (props.isThreadReply) { - label = `replying to ${props.tmid ? `thread message ${props.msg}` : props}`; - } + if (props.isThreadReply) { + const base = props.tmid ? `thread message ${props.msg}` : (props.msg ?? ''); + label = `replying to ${base}`; + }
🧹 Nitpick comments (6)
.github/workflows/e2e-build-ios.yml (1)
82-82: Drop redundant exportRUNNING_E2E_TESTS is already provided via the step env. The extra export can be removed to avoid confusion.
- export RUNNING_E2E_TESTS=trueapp/containers/message/interfaces.ts (1)
114-116: New a11y props on IMessageInner are unusedMessageInner doesn’t forward/use these props. Either wire them to the rendered View or drop them to keep types lean.
- accessible?: boolean; - accessibilityLabel?: string;If you keep them, pass them to the root View where content is rendered.
babel.config.js (1)
7-9: Ensure Reanimated plugin is lastPer Reanimated docs, the plugin should be the last in the list. Reorder to prevent subtle build issues.
plugins: [ ['@babel/plugin-proposal-decorators', { legacy: true }], - 'react-native-reanimated/plugin', '@babel/plugin-transform-named-capturing-groups-regex', ['module:react-native-dotenv'], ['transform-inline-environment-variables', { include: ['RUNNING_E2E_TESTS'] }] + ,'react-native-reanimated/plugin' ],.maestro/helpers/select-media.yaml (1)
1-12: Helper name/content mismatch and redundant pathingThe file selects a room, not media. Consider renaming to select-room.yaml. Also, from helpers/, ../helpers resolves to the same dir—simplify paths.
- file: '../helpers/search-room.yaml' + file: './search-room.yaml' ... - file: '../helpers/navigate-to-room.yaml' + file: './navigate-to-room.yaml'app/containers/message/Message.tsx (1)
145-147: Clarify read/unread logicTreat only explicit false as “read”; undefined/null shouldn’t imply read.
- const readOrUnreadLabel = - !props.unread && props.unread !== null ? i18n.t('Message_was_read') : i18n.t('Message_was_not_read'); + const readOrUnreadLabel = props.unread === false ? i18n.t('Message_was_read') : i18n.t('Message_was_not_read');.maestro/room/room.yaml (1)
256-260: Normalize swipe direction casingStick to a single convention (e.g., DOWN/UP) to avoid parser ambiguities.
- direction: down + direction: DOWN- direction: UP + direction: UPAlso applies to: 416-419
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
app/containers/message/__snapshots__/Message.test.tsx.snapis excluded by!**/*.snapapp/views/RoomView/LoadMore/__snapshots__/LoadMore.test.tsx.snapis excluded by!**/*.snapyarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (8)
.github/workflows/e2e-build-ios.yml(1 hunks).maestro/helpers/select-media.yaml(1 hunks).maestro/helpers/send-message.yaml(0 hunks).maestro/room/room.yaml(1 hunks)app/containers/message/Message.tsx(2 hunks)app/containers/message/interfaces.ts(1 hunks)babel.config.js(1 hunks)package.json(1 hunks)
💤 Files with no reviewable changes (1)
- .maestro/helpers/send-message.yaml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: ESLint and Test / run-eslint-and-test
- GitHub Check: format
🔇 Additional comments (3)
package.json (1)
197-199: Inline env plugin addition looks goodMatches babel.config.js usage and is correctly scoped to devDependencies.
.github/workflows/e2e-build-ios.yml (1)
25-25: Runner version contradicts PR summary (macOS 15 vs. macOS 14)Confirm which runner you want. If 14 is required, update runs-on accordingly.
- runs-on: macos-15 + runs-on: macos-14app/containers/message/Message.tsx (1)
236-238: Good: Touchable not exposed to a11yMarking the Touchable as accessible={false} avoids grouping conflicts.
| visible: | ||
| id: reply-${output.user.name}-quote | ||
| timeout: 60000 | ||
|
|
There was a problem hiding this comment.
Use username, not name, in reply preview id
output.user typically exposes username. Using name will likely never match.
- id: reply-${output.user.name}-quote
+ id: reply-${output.user.username}-quote📝 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.
| visible: | |
| id: reply-${output.user.name}-quote | |
| timeout: 60000 | |
| visible: | |
| id: reply-${output.user.username}-quote | |
| timeout: 60000 |
🤖 Prompt for AI Agents
In .maestro/room/room.yaml around lines 383 to 386, the reply preview id uses
output.user.name which is incorrect; update it to use output.user.username (e.g.
reply-${output.user.username}-quote) and ensure the template variable matches
the actual user object shape (fallback to user.id or validate presence if
username may be undefined) so the generated id reliably matches the runtime
data.
| text: '.*You will not be able to recover this message.*' | ||
| timeout: 60000 | ||
| - tapOn: | ||
| text: 'Delete' |
There was a problem hiding this comment.
Do not use regex in text matcher
Maestro’s text matcher is literal. Use containsText (or exact text) for the confirmation dialog.
- text: '.*You will not be able to recover this message.*'
+ containsText: 'You will not be able to recover this message'📝 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.
| text: '.*You will not be able to recover this message.*' | |
| timeout: 60000 | |
| - tapOn: | |
| text: 'Delete' | |
| containsText: 'You will not be able to recover this message' | |
| timeout: 60000 | |
| - tapOn: | |
| text: 'Delete' |
🤖 Prompt for AI Agents
In .maestro/room/room.yaml around lines 426 to 429, the text matcher is using a
regex string; replace the regex usage with a literal matcher (use containsText
or exact text) for the confirmation dialog and ensure the tapOn target also uses
a literal matcher (e.g., containsText: 'Delete' or exactText: 'Delete'); update
the entry so the confirmation message uses containsText: 'You will not be able
to recover this message.' and the tapOn uses a literal matcher for 'Delete'.
| id: reply-${output.newUser.name}-${output.originalMessage} | ||
| timeout: 60000 |
There was a problem hiding this comment.
Same fix for final reply preview id
Align with username to ensure the element is found.
- id: reply-${output.newUser.name}-${output.originalMessage}
+ id: reply-${output.newUser.username}-${output.originalMessage}📝 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.
| id: reply-${output.newUser.name}-${output.originalMessage} | |
| timeout: 60000 | |
| id: reply-${output.newUser.username}-${output.originalMessage} | |
| timeout: 60000 |
🤖 Prompt for AI Agents
In .maestro/room/room.yaml around lines 635-636 the final reply preview id uses
output.newUser.name which doesn't match the username variable used elsewhere;
change the id to use the canonical username field (e.g.
reply-${output.username}-${output.originalMessage}) so the element id aligns
with the rest of the code and can be found reliably.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (11)
.maestro/tests/room/create-room.yaml (3)
175-180: Alert button selector may be brittle under localization.
Using tapOn: 'OK' can fail on non-English. Prefer an id-based selector or platform-guarded text match. If no id exists, consider a small helper flow that taps the first visible alert button cross‑platform.
164-179: “general” channel existence is assumed.
Some workspaces disable/rename “general.” Consider gating this step behind a server capability check or use a temp room you create in this test to assert “already exists.”
12-24: Extract Create-Channel flow & centralize timeouts
- Replace duplicated extendedWaitUntil/tapOn sequence (id: rooms-list-view-create-channel) with existing helper: .maestro/tests/teams/utils/create-channel.yaml. Occurrences to update: .maestro/tests/room/create-room.yaml, .maestro/tests/teams/create-team.yaml, .maestro/tests/onboarding/roomslist.yaml, .maestro/tests/assorted/e2e-encryption.yaml, .maestro/tests/assorted/display-perf.yaml, .maestro/tests/assorted/broadcast.yaml.
- Introduce a defaultTimeout env (20–30s) and remove hardcoded 60000 values; retain 60000 only where a longer wait is demonstrably required for stability.
.maestro/tests/room/room.yaml (8)
1-8: Setup/teardown is sane; also clean up created rooms.
onFlowEnd deletes users but not rooms. If available, call a deleteCreatedRooms util to keep the workspace clean.onFlowEnd: - evalScript: ${output.utils.deleteCreatedUsers()} + - evalScript: ${output.utils.deleteCreatedRooms && output.utils.deleteCreatedRooms()}
80-103: Avoid relying on “#general”; use the room you just created.
Prevents server-config coupling.- inputText: '#general' + inputText: ${'#'+output.room.name} - extendedWaitUntil: - visible: - id: 'autocomplete-item-general' + extendedWaitUntil: + visible: + id: 'autocomplete-item-${output.room.name}' - tapOn: - id: 'autocomplete-item-general' + id: 'autocomplete-item-${output.room.name}' - extendedWaitUntil: - visible: - text: '#general ' + extendedWaitUntil: + visible: + text: ${'#'+output.room.name+' '} - extendedWaitUntil: - notVisible: - id: 'autocomplete-item-general' + extendedWaitUntil: + notVisible: + id: 'autocomplete-item-${output.room.name}'
104-175: Emoji ids can differ per platform/theme; guard or fall back to search.
If emoji-grinning/wink ids vary, use the emoji search input consistently instead of raw ids or wrap with platform conditions.Also applies to: 188-210, 211-240
241-264: Inconsistent swipe direction casing; add animation settle before swipe.
Use uniform casing (DOWN/UP) and wait for the sheet to settle for stability.- swipe: + waitForAnimationToEnd + swipe: from: id: action-sheet-handle - direction: down + direction: DOWN- swipe: + waitForAnimationToEnd + swipe: from: id: action-sheet-handle direction: UPAlso applies to: 416-419
310-346: Action sheet interactions: add a waitForAnimationToEnd after opening.
Prevents intermittent “element not hittable” errors on iOS.- extendedWaitUntil: - visible: - id: action-sheet - timeout: 60000 + extendedWaitUntil: + visible: + id: action-sheet + timeout: 60000 + waitForAnimationToEndAlso applies to: 400-435
265-285: Username taps: prefer id over text to avoid l10n/clashing occurrences.
If available, target a stable testID (e.g., user-tile-${username}) rather than raw text.Also applies to: 286-309
499-532: Draft flows are thorough; consider collapsing repeated navigate/back steps.
Extract “navigate-to-room, assert composer text” into a helper to speed up and de-duplicate.Also applies to: 533-637
32-79: Autocomplete cleanup: ensure notVisible waits use shorter timeouts.
Use 5–10s for disappearance to reduce run time.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
.maestro/tests/room/create-room.yaml(6 hunks).maestro/tests/room/room.yaml(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: ESLint and Test / run-eslint-and-test
🔇 Additional comments (4)
.maestro/tests/room/room.yaml (3)
12-15: Hermetic data creation is good; ensure utils throw on failure.
If createUser/createRandomRoom fail, surface a descriptive error to avoid silent nulls later.
10-25: Nice use of helpers and env injection.
Helper flows and env vars improve readability and reuse. No issues spotted.Also applies to: 26-31, 436-498
1-637: Proactive check — most testIDs present; some dynamic/missing IDs need confirmation
Found in app code (examples): message-composer-input — app/containers/MessageComposer/components/ComposerInput.tsx; action-sheet — app/containers/ActionSheet/BottomSheetContent.tsx; action-sheet-handle — app/containers/ActionSheet/Handle.tsx; add-reaction — app/containers/MessageActions/Header.tsx; message-add-reaction / message-reaction-* — app/containers/message/Reactions.tsx; emoji-searchbar-input — app/containers/EmojiPicker/EmojiSearch.tsx; reaction-picker — app/views/RoomView/ReactionPicker.tsx; reactionsList — app/containers/ReactionsList/index.tsx; room-view-join-button — app/views/RoomView/index.tsx; rooms-list-view-search-input — app/views/RoomsListView/components/Header.tsx; username-header- pattern — app/containers/message/User.tsx; room-info-view-username — app/views/RoomInfoView/components/RoomInfoViewTitle.tsx; message-composer-send — MessageComposer components.
Not found as exact literals / need manual confirmation: autocomplete-item-joy, autocomplete-item-general and autocomplete-item-${username} appear only in e2e tests (no literal matches in app files) — likely generated dynamically; confirm the autocomplete component still emits testID
autocomplete-item-${...}. markdown-preview-You: quoted had no literal match — confirm the markdown preview testID pattern (e.g.markdown-preview-${message}) will produce that exact id..maestro/tests/room/create-room.yaml (1)
4-4: Helper files missing — add or correct .maestro/helpers referencesVerification returned no matches for .maestro/helpers/{setup.yaml,launch-app.yaml,login.yaml,go-back.yaml}; either add those files (or valid symlinks) or update the runFlow paths in .maestro/tests/room/create-room.yaml (lines 4, 9–10, 71, 204, 270, 334, 404) to point to existing locations.
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (6)
.maestro/tests/room/room.yaml (6)
80-99: Avoid hardcoding #general; use the created room to reduce env coupling.Some workspaces don’t have General or it’s restricted.
-- inputText: '#general' +- inputText: '#${output.room.name}' ... -- extendedWaitUntil: - visible: - id: 'autocomplete-item-general' +- extendedWaitUntil: + visible: + id: 'autocomplete-item-${output.room.name}' ... -- tapOn: - id: 'autocomplete-item-general' +- tapOn: + id: 'autocomplete-item-${output.room.name}' ... -- extendedWaitUntil: - visible: - text: '#general ' +- extendedWaitUntil: + visible: + text: '#${output.room.name} ' ... -- extendedWaitUntil: - notVisible: - id: 'autocomplete-item-general' +- extendedWaitUntil: + notVisible: + id: 'autocomplete-item-${output.room.name}'
211-220: Prefer a wait over an immediate assert to reduce flakes.Switch to an explicit wait before tapping the add‑reaction button.
-# should show reaction picker on add reaction button pressed and have frequently used emoji -- assertVisible: - id: message-add-reaction +# should show reaction picker on add reaction button pressed and have frequently used emoji +- extendedWaitUntil: + visible: + id: message-add-reaction + timeout: 60000
12-15: Resource cleanup: consider deleting created rooms too.You delete users on teardown; rooms created by those users may persist depending on server policies.
Option: track created room IDs in utils and delete them in onFlowEnd.
104-138: Quote regex strings for YAML safety.Unquoted patterns like .${…}. can be misparsed by some YAML parsers; quoting improves robustness.
Example:
- text: .*${output.randomMessage}.* + text: '.*${output.randomMessage}.*'Apply similarly to other regex-like text matchers.
499-531: Draft verification: assert composer is cleared after send.Current check could pass on message bubble; add a negative check on the composer to ensure no residual draft.
- tapOn: id: 'message-composer-send' - extendedWaitUntil: visible: text: '.*draft.*' timeout: 60000 +- extendedWaitUntil: + notVisible: + id: message-composer-input + # composer should not contain the draft anymore + timeout: 60000
139-175: Emoji IDs can diverge across platforms/skins.If iOS failures persist here, consider falling back to searching by shortcode text first, then tapping the first result, instead of hardcoding emoji-* IDs.
I can extract a helper flow (select-emoji.yaml) that searches and taps by shortcode for cross‑platform stability.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.maestro/tests/room/room.yaml(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: E2E Build iOS / ios-build
- GitHub Check: E2E Build Android / android-build
- GitHub Check: ESLint and Test / run-eslint-and-test
🔇 Additional comments (1)
.maestro/tests/room/room.yaml (1)
265-285: iOS a11y: confirm header testID maps to accessibilityIdentifier.If failing on iOS, ensure the header component sets testID on the native touchable and doesn’t get shadowed by nested views.
If needed, I can draft a small patch in the header component to set accessibilityIdentifier/testID explicitly.
| from: | ||
| id: action-sheet-handle | ||
| direction: UP | ||
| - scrollUntilVisible: |
There was a problem hiding this comment.
Fix swipe direction casing.
Maestro expects lowercase directions; this will no-op and stall the test.
- direction: UP
+ direction: up📝 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.
| from: | |
| id: action-sheet-handle | |
| direction: UP | |
| - scrollUntilVisible: | |
| from: | |
| id: action-sheet-handle | |
| direction: up | |
| - scrollUntilVisible: |
🤖 Prompt for AI Agents
In .maestro/tests/room/room.yaml around lines 416 to 419 the swipe direction is
uppercased ("UP") which Maestro ignores; change the direction value to lowercase
("up") and scan nearby steps to ensure any other direction values use lowercase
as well so the gesture executes correctly.
There was a problem hiding this comment.
It accepts uppercase not lowercase
There was a problem hiding this comment.
. The code as written with direction: UP is correct and will work properly.
Thank you for the correction and providing the documentation link. Your implementation is fine as-is.
🐰💡
✏️ Learnings added
Learnt from: Rohit3523
PR: RocketChat/Rocket.Chat.ReactNative#6598
File: .maestro/tests/room/room.yaml:416-419
Timestamp: 2025-09-16T12:13:16.902Z
Learning: Maestro swipe command accepts uppercase direction values: UP, DOWN, LEFT, RIGHT (not lowercase as incorrectly suggested). The official documentation shows examples using uppercase direction values.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
Proposed changes
Working action link: https://github.com/RocketChat/Rocket.Chat.ReactNative/actions/runs/17764602508/job/50486819800
Android:

iOS:

Note: it is failing on iOS
Issue(s)
https://rocketchat.atlassian.net/browse/NATIVE-967
How to test or reproduce
Screenshots
Types of changes
Checklist