Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a7c03bc
test: fix e2ee nav tests (#6816)
diegolmello Dec 3, 2025
0cd33c0
feat(a11y): directory search result announcement (#6788)
OtavioStasiak Dec 3, 2025
91967fc
chore: migrate from react-native-vector-icons to @expo/vector-icons (…
Rohit3523 Dec 3, 2025
6c4637a
regression: go back instead of closing app on rooms search (#6750)
Rohit3523 Dec 3, 2025
f3e1497
test: fix unread badge test (#6752)
Rohit3523 Dec 3, 2025
48beb99
chore: migrate from momentjs to dayjs (#6724)
Rohit3523 Dec 3, 2025
1bd62a2
chore: Remove otp.js (#6836)
diegolmello Dec 3, 2025
639ace2
feat: show @all and @here in mention list based on user permission (#…
Rohit3523 Dec 12, 2025
4185c60
test: rerun only failed test on action (#6831)
Rohit3523 Dec 12, 2025
5585f5d
fix: e2ee attachment getting locked after interaction (#6735)
Rohit3523 Dec 12, 2025
65bfa8a
fix: custom emoji align vertically in message (#6738)
Rohit3523 Dec 12, 2025
b55299e
test(Android): fix flakiness on join from directory and in-app notifi…
Rohit3523 Dec 12, 2025
bddcf52
fix: custom status text wrap in drawer (#6778)
Yaddalapalli-Charan-Kumar-Naidu Dec 12, 2025
7215cda
feat: migrate react-native-mmkv-storage to react-native-mmkv (#6744)
OtavioStasiak Dec 15, 2025
6250fd7
chore: remove deprecated methods for 8.0 (#6852)
OtavioStasiak Dec 16, 2025
0c1f9ca
fix: added default value in useUserPreferences (#6855)
Rohit3523 Dec 17, 2025
59e873a
chore(ci): fix iOS builds hanging on Github Actions (#6854)
diegolmello Dec 18, 2025
de3e696
chore: Migrate to expo-notifications (#6846)
diegolmello Dec 22, 2025
0156694
feat(a11y): spotlight announcement (#6795)
OtavioStasiak Dec 22, 2025
a04c42a
feat: Room Invited State (#6857)
aleksandernsilva Dec 23, 2025
5e1dc7e
feat: Disabled message read receipt in federated rooms (#6858)
aleksandernsilva Dec 23, 2025
d019d4b
feat(federation): Added room license and settings validations (#6859)
aleksandernsilva Dec 23, 2025
2d81c44
feat: Attribute Based Access Control (ABAC) (#6856)
diegolmello Dec 23, 2025
0d13c14
chore: new test workspace (#6841)
Rohit3523 Dec 24, 2025
6db5ffb
feat(a11y): adjust the name and role of the multi-select (#6499)
OtavioStasiak Dec 30, 2025
3315fb4
fix: i18n missing translation and duplicated picker (#6869)
OtavioStasiak Dec 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 200 additions & 0 deletions .github/scripts/run-maestro.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
#!/usr/bin/env bash
set -euo pipefail

PLATFORM="${1:-${PLATFORM:-android}}"
SHARD="${2:-${SHARD:-default}}"
FLOWS_DIR=".maestro/tests"
MAIN_REPORT="maestro-report.xml"
MAX_RERUN_ROUNDS="${MAX_RERUN_ROUNDS:-3}"
RERUN_REPORT_PREFIX="maestro-rerun"
export MAESTRO_DRIVER_STARTUP_TIMEOUT="${MAESTRO_DRIVER_STARTUP_TIMEOUT:-120000}"

if ! command -v maestro >/dev/null 2>&1; then
echo "ERROR: maestro not found in PATH"
exit 2
fi

if [ "$PLATFORM" = "android" ]; then
if ! command -v adb >/dev/null 2>&1; then
echo "ERROR: adb not found"
exit 2
fi
else
if ! command -v xcrun >/dev/null 2>&1; then
echo "ERROR: xcrun not found"
exit 2
fi
fi

MAPFILE="$(mktemp)"
trap 'rm -f "$MAPFILE"' EXIT

while IFS= read -r -d '' file; do
if grep -qE "^[[:space:]]*-[[:space:]]*['\"]?test-${SHARD}['\"]?([[:space:]]*$|[[:space:]]*,|[[:space:]]*\\])" "$file"; then
raw_name="$(grep -m1 -E '^[[:space:]]*name:' "$file" || true)"
if [ -n "$raw_name" ]; then
name_val="$(echo "$raw_name" | sed -E 's/^[[:space:]]*name:[[:space:]]*//; s/^["'\'']//; s/["'\'']$//; s/[[:space:]]*$//')"
name_val="$(echo "$name_val" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//')"
if [ -n "$name_val" ]; then
printf '%s\t%s\n' "$name_val" "$file" >> "$MAPFILE"
fi
fi
fi
done < <(find "$FLOWS_DIR" -type f \( -iname '*.yml' -o -iname '*.yaml' \) -print0)

if [ ! -s "$MAPFILE" ]; then
echo "No flows for test-${SHARD}"
exit 1
fi

echo "Mapped flows for tag test-${SHARD}:"
awk -F'\t' '{ printf " %s -> %s\n", $1, $2 }' "$MAPFILE"

FLOW_FILES=()
SEEN_PATHS=""

while IFS=$'\t' read -r name path; do
if ! printf '%s\n' "$SEEN_PATHS" | grep -Fqx "$path"; then
FLOW_FILES+=("$path")
SEEN_PATHS="${SEEN_PATHS}"$'\n'"$path"
fi
done < "$MAPFILE"

echo "Main run will execute:"
printf ' %s\n' "${FLOW_FILES[@]}"

if [ "$PLATFORM" = "android" ]; then
adb shell settings put system show_touches 1 || true
adb install -r "app-experimental-release.apk" || true
adb shell monkey -p "chat.rocket.reactnative" -c android.intent.category.LAUNCHER 1 || true
sleep 6
adb shell am force-stop "chat.rocket.reactnative" || true

maestro test "${FLOW_FILES[@]}" \
--exclude-tags=util \
--include-tags="test-${SHARD}" \
--format junit \
--output "$MAIN_REPORT" || true

else
maestro test "${FLOW_FILES[@]}" \
--exclude-tags=util \
--include-tags="test-${SHARD}" \
--exclude-tags=android-only \
--format junit \
--output "$MAIN_REPORT" || true
fi

if [ ! -f "$MAIN_REPORT" ]; then
echo "Main report not found"
exit 1
fi

FAILED_NAMES="$(python3 - <<PY
import sys,xml.etree.ElementTree as ET
try:
tree = ET.parse("$MAIN_REPORT")
except:
sys.exit(0)
root = tree.getroot()
failed=[]
for tc in root.findall(".//testcase"):
if tc.find("failure") is not None or tc.find("error") is not None:
if tc.get("name"):
failed.append(tc.get("name").strip())
for n in sorted(set(failed)):
print(n)
PY
)"

if [ -z "$FAILED_NAMES" ]; then
echo "All tests passed."
exit 0
fi

IFS=$'\n' read -rd '' -a FAILED_ARRAY <<<"$FAILED_NAMES" || true

CANDIDATE_FILES=()
SEEN2=""
for NAME in "${FAILED_ARRAY[@]}"; do
FILE="$(awk -F'\t' -v n="$NAME" '$1==n {print $2; exit}' "$MAPFILE" || true)"
if [ -n "$FILE" ] && ! printf '%s\n' "$SEEN2" | grep -Fq "$FILE"; then
CANDIDATE_FILES+=("$FILE")
SEEN2="${SEEN2}"$'\n'"${FILE}"
fi
done

if [ ${#CANDIDATE_FILES[@]} -eq 0 ]; then
echo "No flow files to retry"
exit 1
fi

CURRENT_FAILS=("${CANDIDATE_FILES[@]}")
ROUND=1

while [ ${#CURRENT_FAILS[@]} -gt 0 ] && [ "$ROUND" -le "$MAX_RERUN_ROUNDS" ]; do
echo "=== RERUN ROUND $ROUND (${#CURRENT_FAILS[@]} flows) ==="

RPT="${RERUN_REPORT_PREFIX}-round-${ROUND}.xml"

if [ "$PLATFORM" = "android" ]; then
maestro test "${CURRENT_FAILS[@]}" \
--exclude-tags=util \
--include-tags="test-${SHARD}" \
--format junit \
--output "$RPT" || true
else
maestro test "${CURRENT_FAILS[@]}" \
--exclude-tags=util \
--include-tags="test-${SHARD}" \
--exclude-tags=android-only \
--format junit \
--output "$RPT" || true
fi

if [ ! -f "$RPT" ]; then
echo "Rerun report missing"
break
fi

NEXT_FAILED="$(python3 - <<PY
import sys,xml.etree.ElementTree as ET
try:
tree = ET.parse("$RPT")
except:
sys.exit(0)
root = tree.getroot()
failed=[]
for tc in root.findall(".//testcase"):
if tc.find("failure") is not None or tc.find("error") is not None:
if tc.get("name"):
failed.append(tc.get("name").strip())
for n in sorted(set(failed)):
print(n)
PY
)"

if [ -z "$NEXT_FAILED" ]; then
echo "All retried flows passed in this round."
exit 0
fi

IFS=$'\n' read -rd '' -a NEXT_FAILED_ARRAY <<<"$NEXT_FAILED" || true

NEXT_FILES=()
SEEN3=""
for NAME in "${NEXT_FAILED_ARRAY[@]}"; do
FILE="$(awk -F'\t' -v n="$NAME" '$1==n {print $2; exit}' "$MAPFILE" || true)"
if [ -n "$FILE" ] && ! printf '%s\n' "$SEEN3" | grep -Fq "$FILE"; then
NEXT_FILES+=("$FILE")
SEEN3="${SEEN3}"$'\n'"${FILE}"
fi
done

CURRENT_FAILS=("${NEXT_FILES[@]}")
ROUND=$((ROUND+1))
done

echo "Retry strategy finished with remaining failures:"
printf '%s\n' "${CURRENT_FAILS[@]}"
exit 1
73 changes: 7 additions & 66 deletions .github/workflows/maestro-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,63 +43,12 @@ jobs:
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm

- name: Create Maestro script
run: |
cat << 'EOF' > run-maestro.sh
#!/bin/bash
SHARD=${{ inputs.shard }}
echo "Running shard: $SHARD"

adb shell settings put system show_touches 1
adb install app-experimental-release.apk
adb shell monkey -p chat.rocket.reactnative -c android.intent.category.LAUNCHER 1
sleep 10
adb shell am force-stop chat.rocket.reactnative
export MAESTRO_DRIVER_STARTUP_TIMEOUT=120000

MAX_RETRIES=3
ATTEMPT=1
FINAL_EXIT_CODE=1

while [ $ATTEMPT -le $MAX_RETRIES ]; do
echo "Attempt $ATTEMPT of $MAX_RETRIES"

echo "Starting screen recording..."
adb shell screenrecord /sdcard/test_run.mp4 > /dev/null 2>&1 &
RECORD_PID=$!

maestro test .maestro --exclude-tags=util --include-tags=test-$SHARD --format junit --output maestro-report.xml
TEST_EXIT_CODE=$?

echo "Stopping screen recording..."
kill -INT $RECORD_PID || true
sleep 2

echo "Pulling video from device..."
adb pull /sdcard/test_run.mp4 test_run_${SHARD}_attempt_${ATTEMPT}.mp4 || true
adb shell rm /sdcard/test_run.mp4 || true

if [ $TEST_EXIT_CODE -eq 0 ]; then
echo "Maestro passed on attempt $ATTEMPT"
FINAL_EXIT_CODE=0
break
else
echo "Maestro failed on attempt $ATTEMPT"
fi

ATTEMPT=$((ATTEMPT+1))
done

exit $FINAL_EXIT_CODE
EOF

chmod +x run-maestro.sh
env:
SHARD: ${{ inputs.shard }}
- name: Make Maestro script executable
run: chmod +x .github/scripts/run-maestro.sh

- name: Start Android Emulator and Run Maestro Tests
uses: reactivecircus/android-emulator-runner@v2
timeout-minutes: 60
timeout-minutes: 120
with:
api-level: 34
disk-size: 4096M
Expand All @@ -111,20 +60,12 @@ jobs:
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: ./run-maestro.sh
script: ./.github/scripts/run-maestro.sh android ${{ inputs.shard }}

- name: Upload Test Report
- name: Android Maestro Logs
if: always()
uses: actions/upload-artifact@v4
with:
name: Android Test Report - Shard ${{ inputs.shard }}
path: maestro-report.xml
name: Android Maestro Logs - Shard ${{ inputs.shard }}
path: ~/.maestro/tests/**/*.png
retention-days: 7

- name: Upload Screen Recording
if: always()
uses: actions/upload-artifact@v4
with:
name: maestro-video-${{ inputs.shard }}
path: test_run_${{ inputs.shard }}_attempt_*.mp4
retention-days: 7
33 changes: 7 additions & 26 deletions .github/workflows/maestro-ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,40 +84,21 @@ jobs:
echo "UDID=$UDID"
echo "UDID=$UDID" >> $GITHUB_ENV

- name: Make Maestro script executable
run: chmod +x .github/scripts/run-maestro.sh

- name: Install App
run: |
xcrun simctl install $UDID "ios-simulator-app"

- name: Run Tests
id: maestro-tests
uses: nick-fields/retry@v3
with:
max_attempts: 3
timeout_minutes: 60
command: |
SHARD=${{ inputs.shard }}
echo "Running shard: $SHARD"
export MAESTRO_DRIVER_STARTUP_TIMEOUT=120000

maestro test .maestro \
--exclude-tags=util \
--include-tags=test-$SHARD \
--exclude-tags=android-only \
--format junit \
--output maestro-report.xml

- name: Maestro Test Report
if: always()
uses: actions/upload-artifact@v4
with:
name: Test Report - Shard ${{ inputs.shard }}
path: maestro-report.xml
retention-days: 28
timeout-minutes: 120
run: ./.github/scripts/run-maestro.sh ios ${{ inputs.shard }}

- name: iOS Maestro Logs
if: always()
uses: actions/upload-artifact@v4
with:
name: iOS Maestro Logs - Shard ${{ inputs.shard }}
path: ~/.maestro/tests/
retention-days: 28
path: ~/.maestro/tests/**/*.png
retention-days: 7
2 changes: 1 addition & 1 deletion .maestro/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Contains the scripts that are going to be executed by the flows before running t
#### `data.js`

- Contains seeds to common test data, like server url, public channels, etc
- Currently we point to https://mobile.rocket.chat as main server
- Currently we point to https://mobile.qa.rocket.chat as main server
- Pointing to a local server is not recommended yet, as you would need to create a few public channels and change some permissions
- Ideally we should point to a docker or even a mocked server, but that's tbd
- Try not to add new data there. Use random values instead.
Expand Down
4 changes: 2 additions & 2 deletions .maestro/scripts/data.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const data = {
server: 'https://mobile.rocket.chat',
server: 'https://mobile.qa.rocket.chat',
alternateServer: 'https://stable.rocket.chat',
...output.account,
accounts: [],
Expand All @@ -15,4 +15,4 @@ const data = {
e2eePassword: 'Password1@abcdefghijklmnopqrst'
};

output.data = data;
output.data = data;
Loading
Loading