Skip to content

Commit 6eed515

Browse files
chore: fix tests
chore: update ios test timeout chore: inrease maestro driver setup timeout chore: address flaky tests chore: fix tests
1 parent 6a8677c commit 6eed515

8 files changed

Lines changed: 85 additions & 13 deletions

File tree

.github/scripts/determine-widget-scope.sh

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ all_widgets=$(echo "$widget_dirs" | jq -R -s -c 'split("\n") | map(select(length
1919
all_widgets_and_js=$(echo "$widget_dirs" | jq -R -s -c 'split("\n") | map(select(length > 0)) + ["mobile-resources-native", "nanoflow-actions-native"]')
2020

2121
# Convert a space-separated list of widget names into a JSON array (or [] when empty).
22+
# Deduplicates entries as a safety measure.
2223
to_json_array() {
2324
if [[ -z "$1" ]]; then
2425
echo "[]"
2526
else
26-
echo "[\"$(echo "$1" | sed 's/ /","/g')\"]"
27+
# Sort and deduplicate, then convert to JSON array
28+
echo "$1" | tr ' ' '\n' | sort -u | jq -R -s -c 'split("\n") | map(select(length > 0))'
2729
fi
2830
}
2931

@@ -54,15 +56,16 @@ if [ "$event_name" == "pull_request" ]; then
5456
if [[ $file == packages/pluggableWidgets/* ]]; then
5557
widget=$(echo $file | cut -d'/' -f3)
5658
subdir=$(echo $file | cut -d'/' -f4)
57-
if [[ ! $selected_workspaces =~ $widget ]]; then
59+
# Use word boundary check to prevent both duplicates and substring false matches
60+
if [[ ! " $selected_workspaces " =~ " $widget " ]]; then
5861
selected_workspaces="$selected_workspaces $widget"
5962
fi
6063
# A change confined to the widget's e2e/ folder (Maestro flows + screenshots) changes
6164
# only the TEST, not the built artifact — so it should NOT trigger a rebuild. The widget
6265
# still goes into selected_workspaces above (it gets TESTED), but it's kept out of the
6366
# BUILD scope; its .mpk comes from the test project's committed baseline, exactly like
6467
# every other not-rebuilt widget in a partial run.
65-
if [[ "$subdir" != "e2e" ]] && [[ ! $build_workspaces =~ $widget ]]; then
68+
if [[ "$subdir" != "e2e" ]] && [[ ! " $build_workspaces " =~ " $widget " ]]; then
6669
build_workspaces="$build_workspaces $widget"
6770
fi
6871
elif [[ $file == packages/jsActions/mobile-resources-native/* ]] || [[ $file == packages/jsActions/nanoflow-actions-native/* ]]; then

.github/workflows/NativePipeline.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,7 @@ jobs:
751751
# truncated — at 20 min several shards (accordion, background-image, bottom-sheet,
752752
# color-picker, safe-area-view) were cancelled mid-flow. If a shard still hits 30 the cause
753753
# is real app instability, not the cap.
754-
timeout-minutes: 30
754+
timeout-minutes: 35
755755
strategy:
756756
max-parallel: 4
757757
matrix:

maestro/Smoke.yaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ appId: "${APP_ID}"
22
---
33
# Fast-fail smoke check (S6). Run ONCE per shard before any widget flows: if the app can't
44
# launch and render the "Widgets menu", the build/bundle is fundamentally broken and every
5-
# flow would fail the same way. Bail in ~1.5 min instead of grinding 8-9 flows × retries up
6-
# to the job timeout. Short timeout + NO retry block on purpose — this is the cheap probe.
5+
# flow would fail the same way. Bail in ~2 min instead of grinding 8-9 flows × retries up
6+
# to the job timeout. Timeout was 60s but gallery-native on Android needs extra time for
7+
# initial asset loading. 90s gives room while still being a fast-fail probe.
78
- launchApp:
89
clearState: true
910
permissions:
1011
camera: allow
1112
notifications: allow
1213
- extendedWaitUntil:
1314
visible: "Widgets menu"
14-
timeout: 60000
15+
timeout: 90000

maestro/helpers/helpers.sh

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ RETRY_DELAY=10
88

99
# Timeout for the Maestro driver (instrumentation) to come up. Maestro's default is 15s;
1010
# CI emulators/simulators are slower, but 5 min (300000) was the per-attempt multiplier that
11-
# amplified broken-build runs to ~25 min. 2 min is generous for the driver to start while
12-
# keeping the worst-case failure time bounded.
13-
MAESTRO_DRIVER_STARTUP_TIMEOUT=120000
11+
# amplified broken-build runs to ~25 min. 3 min balances driver startup on loaded CI runners
12+
# (macos-26 with 4 parallel shards) while still failing fast on genuinely broken builds.
13+
# Override via env var if needed: export MAESTRO_DRIVER_STARTUP_TIMEOUT=240000
14+
MAESTRO_DRIVER_STARTUP_TIMEOUT="${MAESTRO_DRIVER_STARTUP_TIMEOUT:-180000}"
1415

1516
# --- Per-flow video recording (BrowserStack-style debugging) ----------------------------
1617
# We record a screen video around every flow, then KEEP it only if the flow FAILS and DELETE
@@ -78,9 +79,24 @@ stop_recording() {
7879
REC_FILE=""
7980
}
8081

82+
# Function to clean up stale XCTest processes (iOS only)
83+
cleanup_xctest_processes() {
84+
if [ "$PLATFORM" != "ios" ]; then
85+
return 0
86+
fi
87+
echo "🧹 Cleaning up stale XCTest processes..."
88+
# Kill any leftover XCTest runner processes that might be blocking driver initialization
89+
pkill -9 -f "XCTRunner" 2>/dev/null || true
90+
pkill -9 -f "xctest" 2>/dev/null || true
91+
pkill -9 -f "maestro.*driver" 2>/dev/null || true
92+
sleep 2
93+
}
94+
8195
# Function to restart the iOS simulator
8296
restart_simulator() {
8397
echo "🔄 Restarting iOS Simulator..."
98+
# Clean up XCTest processes first
99+
cleanup_xctest_processes
84100
# Shut down whatever is booted; the device is auto-selected in prepare_ios.sh,
85101
# so we don't depend on a hardcoded device name here.
86102
xcrun simctl shutdown all || true
@@ -135,6 +151,28 @@ ensure_emulator_ready() {
135151
done
136152
}
137153

154+
# Function to verify Mendix runtime is responding (Android only - uses adb reverse)
155+
verify_runtime_ready() {
156+
if [ "$PLATFORM" != "android" ]; then
157+
return 0 # iOS doesn't need this check - runtime is on localhost
158+
fi
159+
local max_attempts=5 # Reduced from 10 since we're checking from host side
160+
local attempt=1
161+
echo "Verifying Mendix runtime connectivity..."
162+
while [ "$attempt" -le "$max_attempts" ]; do
163+
# Check from host side (runner) - if host can reach it, the adb reverse tunnel will work
164+
if curl -fsS -o /dev/null --max-time 2 "http://localhost:8080/" 2>/dev/null; then
165+
echo "✅ Runtime is reachable (attempt $attempt)"
166+
return 0
167+
fi
168+
echo "Runtime not ready yet (attempt $attempt/$max_attempts), waiting..."
169+
sleep 2
170+
attempt=$((attempt + 1))
171+
done
172+
echo "⚠️ Runtime verification timed out - proceeding anyway (app will handle connection errors)"
173+
return 0 # Don't fail hard - let the app/smoke check handle it
174+
}
175+
138176
# Function to run tests
139177
run_tests() {
140178
local test_files=("$@")
@@ -177,6 +215,7 @@ smoke_check() {
177215
if [ "$PLATFORM" == "android" ]; then
178216
ensure_emulator_ready
179217
set_status_bar
218+
verify_runtime_ready # Ensure runtime is reachable before launching app
180219
fi
181220
start_recording "smoke-attempt-$attempt"
182221
if $HOME/.local/bin/maestro/bin/maestro test --env APP_ID=$APP_ID --env PLATFORM=$PLATFORM --env MAESTRO_DRIVER_STARTUP_TIMEOUT=$MAESTRO_DRIVER_STARTUP_TIMEOUT "$script_dir/Smoke.yaml"; then

maestro/run_maestro_jsactions_tests.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,16 @@ run_jsactions_tests() {
9797
fi
9898
}
9999

100+
# Clean up any stale XCTest processes before starting (iOS only)
101+
if [ "$PLATFORM" == "ios" ]; then
102+
cleanup_xctest_processes
103+
fi
104+
105+
# Fast-fail smoke check before running jsActions tests (same as widget tests)
106+
if ! smoke_check; then
107+
exit 1
108+
fi
109+
100110
# Run jsActions tests
101111
run_jsactions_tests
102112
if [ $? -ne 0 ]; then

packages/pluggableWidgets/bottom-sheet-native/e2e/specs/maestro/Botton_sheet_expanding_fullscreen.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ appId: "${APP_ID}"
88
text: "Bottom Sheet"
99
- tapOn:
1010
text: "Expanding fullscreen"
11-
# Because the image loading can take some time due to resources on emulator, we need to wait for the image to be visible
12-
- extendedWaitUntil:
11+
# Because the image loading and animation can take some time due to resources on emulator, we need to wait
12+
- extendedWaitUntil:
1313
visible: randText # Any random text that does not exist in the UI
1414
optional: true # This should be true so that the test won't fail
15-
timeout: 10000 # 10 seconds
15+
timeout: 15000 # 15 seconds to allow for animation to complete
1616
- takeScreenshot:
1717
path: "maestro/images/actual/${PLATFORM}/bottom_sheet_expanding_fullscreen"
1818
- assertScreenshot:

packages/pluggableWidgets/bottom-sheet-native/e2e/specs/maestro/Modal_basic_non_native.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ appId: "${APP_ID}"
88
text: "Bottom Sheet"
99
- tapOn:
1010
text: "Modal basic non native"
11+
# Wait for the page to fully load before tapping Open
12+
- extendedWaitUntil:
13+
visible: "Open"
14+
timeout: 10000
1115
- tapOn:
1216
text: "Open"
1317

packages/pluggableWidgets/intro-screen-native/e2e/specs/maestro/IntroScreen.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,29 @@ appId: "${APP_ID}"
3939
timeout: 5000
4040
- tapOn:
4141
text: "OK"
42+
# Wait for dialog to dismiss before navigating back
43+
- extendedWaitUntil:
44+
visible: "Go back"
45+
timeout: 3000
4246
- tapOn: "Go back"
47+
# Wait for widgets menu to appear before tapping intro screen again
48+
- extendedWaitUntil:
49+
visible: "Widgets menu"
50+
timeout: 5000
4351
- tapOn:
4452
text: "Intro screen"
4553
- extendedWaitUntil:
4654
visible: "Active slide: 2"
4755
timeout: 5000
4856
- tapOn:
4957
text: "NEXT"
58+
# Wait for slide transition to complete - longer timeout for Android emulator
59+
- extendedWaitUntil:
60+
visible: "Active slide: 3"
61+
timeout: 10000
62+
- extendedWaitUntil:
63+
visible: "FINISH"
64+
timeout: 10000
5065
- tapOn:
5166
text: "FINISH"
5267
- extendedWaitUntil:

0 commit comments

Comments
 (0)