Skip to content
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
fc83a68
Improvements
Rohit3523 Feb 23, 2026
21ec68e
Merge branch 'develop' into maestro-changes
Rohit3523 Feb 23, 2026
83f8c02
Added retry logic for maestro api calling
Rohit3523 Feb 23, 2026
b0882fb
use macos 14
Rohit3523 Feb 23, 2026
a76c24a
Add maestro path in android
Rohit3523 Feb 23, 2026
9653ebb
fix api...
Rohit3523 Feb 23, 2026
8a972e7
Add maestro in path
Rohit3523 Feb 23, 2026
d7eae22
improve
Rohit3523 Feb 23, 2026
312cfff
Use hidekeyboard from helper
Rohit3523 Feb 23, 2026
d814fb7
Refactor iOS workflow for Maestro installation and setup
Rohit3523 Feb 24, 2026
1d575a4
try 16 pro
Rohit3523 Feb 24, 2026
8966d77
More fix
Rohit3523 Feb 24, 2026
a3d4b2c
Ignore user test fix
Rohit3523 Feb 24, 2026
25ce5ea
chore: format code and fix lint issues
Rohit3523 Feb 24, 2026
a63daba
possible fix
Rohit3523 Feb 24, 2026
7ff31c1
Merge branch 'maestro-changes' of https://github.com/RocketChat/Rocke…
Rohit3523 Feb 24, 2026
ede8727
upload everything for ios temp
Rohit3523 Feb 25, 2026
94df785
another try to fix it
Rohit3523 Feb 25, 2026
9236738
id fix
Rohit3523 Feb 25, 2026
fe600b2
Retry step
Rohit3523 Feb 25, 2026
1a68c31
Merge branch 'develop' into maestro-changes
Rohit3523 Feb 26, 2026
ecf2306
fix
Rohit3523 Feb 26, 2026
6afdb77
fix
Rohit3523 Feb 26, 2026
5f12139
Remove latin test
Rohit3523 Feb 26, 2026
bb8f4a6
chore: format code and fix lint issues
Rohit3523 Feb 26, 2026
3918b2f
more changes
Rohit3523 Feb 26, 2026
b747b3b
Merge branch 'maestro-changes' of https://github.com/RocketChat/Rocke…
Rohit3523 Feb 26, 2026
ca9a38a
store images in ios
Rohit3523 Feb 26, 2026
bb62452
Update scripts/create-avd.sh
Rohit3523 Feb 26, 2026
0cb8a41
use arrow function
Rohit3523 Feb 27, 2026
dbbc6e3
revert change requested by coderabbit
Rohit3523 Feb 27, 2026
95744c9
Merge branch 'develop' into maestro-changes
Rohit3523 Mar 2, 2026
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
36 changes: 29 additions & 7 deletions .github/workflows/maestro-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ jobs:
android-test:
name: 'Android Tests'
runs-on: ubuntu-latest
env:
MAESTRO_VERSION: 2.2.0

steps:
- name: Checkout Repository
Expand All @@ -19,8 +21,22 @@ jobs:
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
distribution: temurin
java-version: 17

- name: Cache Android AVD
uses: actions/cache@v4
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-${{ runner.os }}-api34

- name: Cache Maestro
uses: actions/cache@v4
with:
path: ~/.maestro
key: maestro-${{ runner.os }}-${{ env.MAESTRO_VERSION }}

- name: Download APK
uses: actions/download-artifact@v4
Expand All @@ -34,21 +50,26 @@ jobs:

- name: Install Maestro
run: |
curl -fsSL "https://get.maestro.mobile.dev" | bash
echo "$HOME/.maestro/bin" >> $GITHUB_PATH
curl -Ls "https://get.maestro.mobile.dev" | bash
echo "$HOME/.maestro/bin" >> "$GITHUB_PATH"

- name: Enable KVM group permissions
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm

- name: Disable unnecessary services (improves emulator stability)
run: |
sudo systemctl stop docker || true
sudo systemctl stop snapd || true

- 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: 120
timeout-minutes: 60
with:
api-level: 34
disk-size: 4096M
Expand All @@ -58,8 +79,9 @@ jobs:
cores: 4
ram-size: 4096M
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
emulator-boot-timeout: 900
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -accel on
script: ./.github/scripts/run-maestro.sh android ${{ inputs.shard }}

- name: Android Maestro Logs
Expand Down
85 changes: 45 additions & 40 deletions .github/workflows/maestro-ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ on:
jobs:
ios-test:
runs-on: macos-14
env:
MAESTRO_VERSION: 2.2.0

steps:
- name: Checkout Repo
Expand All @@ -18,8 +20,8 @@ jobs:
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
distribution: temurin
java-version: "17"

- name: Download App
uses: actions/download-artifact@v4
Expand All @@ -32,70 +34,73 @@ jobs:
with:
E2E_ACCOUNT: ${{ secrets.E2E_ACCOUNT }}

- name: Install Maestro
- name: Cache Maestro
uses: actions/cache@v4
with:
path: ~/.maestro
key: maestro-${{ runner.os }}-${{ env.MAESTRO_VERSION }}

- name: Install Maestro + idb
run: |
brew tap facebook/fb
brew install facebook/fb/idb-companion
curl -fsSL "https://get.maestro.mobile.dev" | bash
echo "$HOME/.maestro/bin" >> $GITHUB_PATH
echo "$HOME/.maestro/bin" >> "$GITHUB_PATH"

- name: Configure Simulator
run: |
defaults write com.apple.iphonesimulator ConnectHardwareKeyboard -bool false
defaults write com.apple.iphonesimulator ShowSingleTouches 1
defaults write com.apple.iphonesimulator SlowAnimations -bool false
defaults write com.apple.iphonesimulator ShowDeviceBezels -bool false
defaults write com.apple.iphonesimulator DisableShadows -bool true
defaults write com.apple.iphonesimulator AllowFullscreenMode -bool false
defaults write com.apple.iphonesimulator PasteboardAutomaticSync -bool false
defaults write com.apple.iphonesimulator ShowChrome -bool false
defaults write com.apple.iphonesimulator DeviceFramebufferOnly -bool true

- name: Boot Simulator
timeout-minutes: 30
timeout-minutes: 15
run: |
SIM_NAME="iPhone 16 Pro Max"
TIMEOUT=300 # 5 minutes in seconds
INTERVAL=5 # Check every 5 seconds
SIM_NAME="iPhone 16 Pro"

echo "Booting simulator: $SIM_NAME"

xcrun simctl boot "$SIM_NAME" || true

ELAPSED=0
while true; do
BOOTED=$(xcrun simctl list devices | grep "$SIM_NAME (" | grep "(Booted)")
if [ -n "$BOOTED" ]; then
echo "$SIM_NAME is booted"
break
fi

if [ $ELAPSED -ge $TIMEOUT ]; then
echo "Simulator did not boot within 5 minutes. Retrying..."
xcrun simctl shutdown "$SIM_NAME"
xcrun simctl boot "$SIM_NAME"
ELAPSED=0
fi

sleep $INTERVAL
ELAPSED=$((ELAPSED + INTERVAL))
done

xcrun simctl bootstatus "$SIM_NAME" -b

echo "Disabling animations"
xcrun simctl spawn booted defaults write -g UIAnimationDragCoefficient -float 10

echo "Warming SpringBoard"
xcrun simctl launch booted com.apple.springboard
sleep 15

echo "Booted devices:"
xcrun simctl list devices | grep Booted

- name: Get Simulator UDID
- name: Get Booted Simulator UDID
id: booted-sim
run: |
UDID=$(xcrun simctl list devices | grep "iPhone 16 Pro Max (" | grep "(Booted)" | grep -oE '[A-F0-9-]{36}' | head -n1)
UDID=$(xcrun simctl list devices booted | grep -oE '[A-F0-9-]{36}' | head -n1)
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"
xcrun simctl install booted ios-simulator-app

- name: Run Tests
timeout-minutes: 120
run: ./.github/scripts/run-maestro.sh ios ${{ inputs.shard }}
- name: Make Maestro Script Executable
run: chmod +x .github/scripts/run-maestro.sh

- name: Run Maestro Tests
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 2
retry_on: timeout
command: ./.github/scripts/run-maestro.sh ios ${{ inputs.shard }}
Comment thread
Rohit3523 marked this conversation as resolved.

- name: iOS Maestro Logs
- name: Upload Maestro Logs
if: always()
uses: actions/upload-artifact@v4
with:
Expand Down
2 changes: 1 addition & 1 deletion .maestro/helpers/create-account.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ tags:
- tapOn:
id: register-view-confirm-password
- inputText: ${output.user.password}
- hideKeyboard
- runFlow: './hide-keyboard.yaml'
- scrollUntilVisible:
element:
id: register-view-submit
Expand Down
2 changes: 2 additions & 0 deletions .maestro/helpers/search-room.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ tags:
---
- assertVisible:
id: 'rooms-list-view'
- waitForAnimationToEnd:
timeout: 5000
- tapOn:
id: 'rooms-list-view-search'
- tapOn:
Expand Down
65 changes: 54 additions & 11 deletions .maestro/scripts/data-setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const getDeepLink = (method, server, ...params) => {


const login = (username, password) => {
const response = http.post(`${data.server}/api/v1/login`, {
const response = postWithRetry(`${data.server}/api/v1/login`, {
headers: {
'Content-Type': 'application/json'
},
Expand All @@ -44,7 +44,7 @@ const createUser = (customProps) => {

login(output.account.adminUser, output.account.adminPassword);

http.post(`${data.server}/api/v1/users.create`, {
postWithRetry(`${data.server}/api/v1/users.create`, {
headers: {
'Content-Type': 'application/json',
...headers
Expand Down Expand Up @@ -74,19 +74,20 @@ const deleteCreatedUser = async ({ username: usernameToDelete }) => {
try {
login(output.account.adminUser, output.account.adminPassword);

const result = http.get(`${data.server}/api/v1/users.info?username=${usernameToDelete}`, {
const result = getWithRetry(`${data.server}/api/v1/users.info?username=${usernameToDelete}`, {
headers: {
'Content-Type': 'application/json',
...headers
}
});

const userId = json(result.body)?.data?.user?._id;
http.post(`${data.server}/api/v1/users.delete`, { userId, confirmRelinquish: true }, {
postWithRetry(`${data.server}/api/v1/users.delete`, {
headers: {
'Content-Type': 'application/json',
...headers
}
},
body: JSON.stringify({ userId, confirmRelinquish: true })
});
} catch (error) {
console.log(JSON.stringify(error));
Expand All @@ -98,7 +99,7 @@ const createRandomTeam = (username, password) => {

const teamName = output.randomTeamName();

http.post(`${data.server}/api/v1/teams.create`, {
postWithRetry(`${data.server}/api/v1/teams.create`, {
headers: {
'Content-Type': 'application/json',
...headers
Expand All @@ -113,7 +114,7 @@ const createRandomRoom = (username, password, type = 'c') => {
login(username, password);
const room = `room${output.random()}`;

const response = http.post(`${data.server}/api/v1/${type === 'c' ? 'channels.create' : 'groups.create'}`, {
const response = postWithRetry(`${data.server}/api/v1/${type === 'c' ? 'channels.create' : 'groups.create'}`, {
headers: {
'Content-Type': 'application/json',
...headers
Expand All @@ -133,7 +134,7 @@ const sendMessage = (username, password, channel, msg, tmid) => {
login(username, password);
const channelParam = tmid ? { roomId: channel } : { channel };

const response = http.post(`${data.server}/api/v1/chat.postMessage`, {
const response = postWithRetry(`${data.server}/api/v1/chat.postMessage`, {
headers: {
'Content-Type': 'application/json',
...headers
Expand All @@ -153,7 +154,7 @@ const sendMessage = (username, password, channel, msg, tmid) => {
const getProfileInfo = (userId) => {
login(output.account.adminUser, output.account.adminPassword);

const result = http.get(`${data.server}/api/v1/users.info?userId=${userId}`, {
const result = getWithRetry(`${data.server}/api/v1/users.info?userId=${userId}`, {
headers: {
'Content-Type': 'application/json',
...headers
Expand All @@ -168,7 +169,7 @@ const getProfileInfo = (userId) => {
const post = (endpoint, username, password, body) => {
login(username, password);

const response = http.post(`${data.server}/api/v1/${endpoint}`, {
const response = postWithRetry(`${data.server}/api/v1/${endpoint}`, {
headers: {
'Content-Type': 'application/json',
...headers
Expand All @@ -182,7 +183,7 @@ const post = (endpoint, username, password, body) => {
const createDM = (username, password, otherUsername) => {
login(username, password);

const result = http.post(`${data.server}/api/v1/im.create`, {
const result = postWithRetry(`${data.server}/api/v1/im.create`, {
headers: {
'Content-Type': 'application/json',
...headers
Expand All @@ -208,6 +209,48 @@ function logAccounts() {
console.log(JSON.stringify(data.accounts));
}

const sleep = (ms) => {
const start = Date.now();
while (Date.now() - start < ms) { }
}

const retryRequest = (fn, {
retries = 3,
delay = 1000,
factor = 2
} = {}) => {
let lastError;
for (let attempt = 1; attempt <= retries; attempt++) {
try {
const response = fn();

if (response && response.status >= 200 && response.status < 300) {
return response;
}

if (response && response.status >= 400 && response.status < 500) {
throw new Error(`Non-retryable error ${response.status}`);
}

lastError = new Error(`HTTP ${response ? response.status : 'unknown'}`);
} catch (err) {
lastError = err;
}
Comment thread
OtavioStasiak marked this conversation as resolved.

if (attempt < retries) {
const wait = delay * Math.pow(factor, attempt - 1);
console.log(`Retry ${attempt}/${retries} after ${wait}ms`);
sleep(wait);
}
}

throw lastError;
};

const postWithRetry = (url, options) => retryRequest(() => http.post(url, options));

const getWithRetry = (url, options) => retryRequest(() => http.get(url, options));
Comment thread
OtavioStasiak marked this conversation as resolved.

output.utils = {
createUser,
createUserWithPasswordChange,
Expand Down
2 changes: 1 addition & 1 deletion .maestro/tests/assorted/broadcast.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ tags:
- tapOn:
id: 'create-channel-name'
- inputText: ${output.room}
- hideKeyboard
- runFlow: '../../helpers/hide-keyboard.yaml'
- assertVisible:
id: 'create-channel-broadcast'
- tapOn:
Expand Down
2 changes: 1 addition & 1 deletion .maestro/tests/assorted/change-avatar.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ tags:
timeout: 60000
- tapOn:
text: 'Fetch image from URL'
- hideKeyboard
- runFlow: '../../helpers/hide-keyboard.yaml'
- extendedWaitUntil:
visible:
id: 'change-avatar-view-submit'
Expand Down
2 changes: 1 addition & 1 deletion .maestro/tests/e2ee/flows/create-e2ee-room.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ tags:
- tapOn:
id: 'create-channel-name'
- inputText: ${ROOM}
- hideKeyboard
- runFlow: '../../../helpers/hide-keyboard.yaml'
- extendedWaitUntil:
visible:
id: 'create-channel-encrypted'
Expand Down
Loading
Loading