Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
33 changes: 33 additions & 0 deletions .argent/flows/simple-tap-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
steps:
- echo: Launching Expo Example
- launch: com.example.ExpoExample
- await: { visible: { text: "Empty Example" }, timeout: 15000 }
- echo: "On the Home list, search for tap example"
- type: { text: "tap", into: { id: "search-examples" } }
- echo: "Tap the example to open it"
- tap: "Basic Tap"
- echo: "Clear console"
- await: { visible: "open-console-button" }
- tap: "open-console-button"
- await: { visible: "clear-console-button" }
- tap: "clear-console-button"
- tap: "close-console-button"
- wait: 1000 # TODO: investigate why this is needed (closing modal intercepts tap on the box)
- echo: "Tap the box and check if tap count is updated"
- await: { visible: "Tap count: 0" }
- assert: { visible: "tap-box" }
- tap: "tap-box"
- assert: { visible: "Tap count: 1" }
- echo: "Check if console logs are printed in order"
- tap: "open-console-button"
- await: { visible: "close-console-button" }
- assert: { visible: "1. onBegin" }
- assert: { visible: "2. onActivate" }
- assert: { visible: "3. onDeactivate" }
- assert: { visible: "4. onFinalize" }
- tap: "close-console-button"
- wait: 1000 # TODO: investigate why this is needed (closing modal intercepts tap on the box)
- await: { visible: "Tap count: 1" }
- echo: "Tap the box again and check if tap count is updated"
- tap: "tap-box"
- assert: { visible: "Tap count: 2" }
132 changes: 132 additions & 0 deletions .github/workflows/android-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
name: Test Android e2e

on:
pull_request:
paths:
- .argent/flows/*
- .github/workflows/android-e2e.yml
- packages/react-native-gesture-handler/android/**
- apps/expo-example/android/**
- apps/expo-example/package.json
- rnrepo.config.json
- yarn.lock
push:
branches:
- main
workflow_dispatch:

jobs:
build:
if: github.repository == 'software-mansion/react-native-gesture-handler'

runs-on: ubuntu-latest
timeout-minutes: 60
concurrency:
group: android-e2e-${{ github.ref }}
cancel-in-progress: true

# Pin the emulator "discovery directory" for BOTH the emulator (launched by
# the action) and the simulator-server backend (spawned by the tool-server
# inside the action's script). The Android touch/key backend finds the
# running emulator's gRPC console by scanning $XDG_RUNTIME_DIR/avd/running/
# pid_*.ini for grpc.port/grpc.token. XDG_RUNTIME_DIR is unset on GitHub
# runners and /run/user/$UID doesn't exist for the runner user, so the
# emulator and the backend can otherwise resolve DIFFERENT fallback dirs —
# the backend then logs "Failed to find any running emulator" and exits
# before becoming ready. Pinning it (checked first by both) removes that
# divergence. Job-level env reaches every step, including the emulator
# subprocess the action spawns.
env:
XDG_RUNTIME_DIR: /tmp/xdg-runtime

steps:
- name: checkout
uses: actions/checkout@v4

- name: Use Java 17
uses: actions/setup-java@v4
with:
distribution: oracle
java-version: 17

- name: Use Node.js 24
uses: actions/setup-node@v6
with:
node-version: 24
cache: yarn

- name: Install node dependencies
working-directory: apps/expo-example
run: yarn install --immutable

- name: Build app in Release mode
working-directory: apps/expo-example/android
run: ./gradlew :app:assembleRelease --console=plain -PreactNativeArchitectures=x86_64

- name: Install Argent
run: npx @swmansion/argent init --yes

- name: Enable KVM
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

# Must exist BEFORE the emulator boots: the emulator falls back to another
# dir if XDG_RUNTIME_DIR points at a missing path. 0700 per the XDG spec.
- name: Prepare shared XDG_RUNTIME_DIR
run: |
mkdir -p "$XDG_RUNTIME_DIR"
chmod 700 "$XDG_RUNTIME_DIR"

# Start the tool-server out-of-band and hand `flow run` its URL via
# $GITHUB_ENV. The simulator-server it later spawns inherits this step's
# env; XDG_RUNTIME_DIR (pinned at job level) keeps its emulator-discovery
# dir aligned with the emulator's, and adb is already on PATH from the
# preinstalled SDK — so it no longer has to run inside the emulator step.
# Backgrounded with our own readiness poll to dodge flow-run's hard ~15s
# in-process startup timeout. SIMSERVER_LOG=debug surfaces the backend's
# discovery/connect steps in argent-server.log (drop once green).
- name: Start Argent tool-server
run: |
nohup env SIMSERVER_LOG=debug argent server start --detach --no-auth --port 3001 \
> argent-server.log 2>&1 &
echo "Waiting for Argent tool-server on :3001..."
for i in $(seq 1 60); do
if curl -fsS http://127.0.0.1:3001/tools >/dev/null 2>&1; then
echo "tool-server is ready"
echo "ARGENT_TOOLS_URL=http://127.0.0.1:3001" >> "$GITHUB_ENV"
exit 0
fi
sleep 2
done
echo "Argent tool-server failed to become ready in time" >&2
cat argent-server.log >&2
exit 1

- name: Set up emulator and run tap E2E test
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 34
target: google_apis
arch: x86_64
force-avd-creation: false
# `-grpc 8554` guarantees grpc.port is written to the discovery ini
# (token-less is fine — the backend handles a missing grpc.token).
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -grpc 8554 -camera-back none
disable-animations: true
# android-emulator-runner runs each line of `script` as a separate
# `sh -c`, so exported vars don't persist between lines and multi-line
# constructs (if/fi) break. Keep every command self-contained on one
# line. ARGENT_TOOLS_URL is inherited from the tool-server step above
# via $GITHUB_ENV, so `flow run` reuses that server.
script: |
adb install -r "$(find "$GITHUB_WORKSPACE/apps/expo-example/android/app/build/outputs/apk/release" -name '*.apk' | head -1)"
argent flow run simple-tap-test --device "$(adb devices | awk 'NR>1 && $2=="device"{print $1; exit}')"

# The simulator-server's stderr (prefixed `[sim <udid>]`) is written to the
# tool-server log — this is where a "simulator-server exited before ready"
# crash reason shows up. Always print it so failures are diagnosable.
- name: Print Argent tool-server log
if: always()
run: cat argent-server.log 2>/dev/null || echo "no argent-server.log"
122 changes: 122 additions & 0 deletions .github/workflows/ios-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
name: Test iOS e2e

on:
pull_request:
paths:
- .argent/flows/*
- .github/workflows/ios-e2e.yml
- packages/react-native-gesture-handler/RNGestureHandler.podspec
- packages/react-native-gesture-handler/apple/**
- apps/expo-example/ios/**
- apps/expo-example/package.json
- rnrepo.config.json
- yarn.lock
push:
branches:
- main
workflow_dispatch:

jobs:
build:
if: github.repository == 'software-mansion/react-native-gesture-handler'

runs-on: macos-26
timeout-minutes: 60
concurrency:
group: ios-e2e-${{ github.ref }}
cancel-in-progress: true

steps:
- name: checkout
uses: actions/checkout@v4

- name: Use latest stable Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: '26.4.1'

- name: Use Node.js 24
uses: actions/setup-node@v6
with:
node-version: 24
cache: yarn

- name: Install node dependencies
working-directory: apps/expo-example
run: yarn install --immutable

- name: Build app in Release mode
working-directory: apps/expo-example/ios
run: |
xcodebuild \
-workspace ExpoExample.xcworkspace \
-scheme ExpoExample \
-configuration Release \
-sdk iphonesimulator \
-destination 'generic/platform=iOS Simulator' \
-derivedDataPath build \
CODE_SIGNING_ALLOWED=NO \
build

- name: Set up iPhone 17 Pro simulator
run: |
UDID=$(xcrun simctl list devices available | grep -E "iPhone 17 Pro \(" | head -1 | grep -oE "[0-9A-Fa-f-]{36}" || true)
if [ -z "$UDID" ]; then
echo "iPhone 17 Pro not found, creating one"
RUNTIME=$(xcrun simctl list runtimes ios -j | jq -r '.runtimes | map(select(.isAvailable)) | last | .identifier')
UDID=$(xcrun simctl create "iPhone 17 Pro" "com.apple.CoreSimulator.SimDeviceType.iPhone-17-Pro" "$RUNTIME")
fi
echo "Using simulator $UDID"
xcrun simctl boot "$UDID" || true
xcrun simctl bootstatus "$UDID"
echo "SIMULATOR_UDID=$UDID" >> "$GITHUB_ENV"

- name: Install app on simulator
working-directory: apps/expo-example/ios
run: |
APP_PATH=$(find build/Build/Products/Release-iphonesimulator -maxdepth 1 -name "*.app" -type d | head -1)
if [ -z "$APP_PATH" ]; then
echo "Could not find built .app" >&2
exit 1
fi
echo "Installing $APP_PATH on $SIMULATOR_UDID"
xcrun simctl install "$SIMULATOR_UDID" "$APP_PATH"

- name: Install Argent
run: npx @swmansion/argent init --yes

# Start the tool-server out-of-band and hand `flow run` its URL, so it
# reuses this server instead of spawning one in-process and hitting the
# hard ~15s startup timeout on cold CI runners (first run downloads the
# simulator-server binary).
#
# `server start --detach` can fail to return on CI (its parent keeps the
# child's stdout pipe referenced), so background it with output redirected
# to a file — never the runner's pipe — and poll the port for readiness
# ourselves.
- name: Start Argent tool-server
run: |
nohup argent server start --detach --no-auth --port 3001 \
> argent-server.log 2>&1 &
echo "Waiting for Argent tool-server on :3001..."
for i in $(seq 1 60); do
if curl -fsS http://127.0.0.1:3001/tools >/dev/null 2>&1; then
echo "tool-server is ready"
echo "ARGENT_TOOLS_URL=http://127.0.0.1:3001" >> "$GITHUB_ENV"
exit 0
fi
sleep 2
done
echo "Argent tool-server failed to become ready in time" >&2
cat argent-server.log >&2
exit 1

- name: Run tap E2E test
run: argent flow run simple-tap-test --device $SIMULATOR_UDID

# The simulator-server's stderr (prefixed `[sim <udid>]`) is written to the
# tool-server log — this is where a "simulator-server exited before ready"
# crash reason shows up. Always print it so failures are diagnosable.
- name: Print Argent tool-server log
if: always()
run: cat argent-server.log 2>/dev/null || echo "no argent-server.log"
2 changes: 2 additions & 0 deletions apps/common-app/src/console/ConsoleModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ function ConsoleModalContent({ entries, visible, onClose }: ConsoleModalProps) {
</View>
<View style={styles.modalActions}>
<Touchable
testID="clear-console-button"
accessibilityRole="button"
disabled={entries.length === 0}
activeOpacity={0.5}
Expand All @@ -250,6 +251,7 @@ function ConsoleModalContent({ entries, visible, onClose }: ConsoleModalProps) {
</Text>
</Touchable>
<Touchable
testID="close-console-button"
accessibilityRole="button"
accessibilityLabel="Close console"
activeOpacity={0.5}
Expand Down
14 changes: 7 additions & 7 deletions apps/common-app/src/new_api/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ export const NEW_EXAMPLES: ExamplesSection[] = [
{
sectionTitle: 'Simple Gestures',
data: [
{ name: 'Fling', component: FlingExample },
{ name: 'Tap', component: TapExample },
{ name: 'LongPress', component: LongPressExample },
{ name: 'Hover', component: HoverExample },
{ name: 'Pinch', component: PinchExample },
{ name: 'Rotation', component: RotationExample },
{ name: 'Pan', component: PanExample },
{ name: 'Basic Fling', component: FlingExample },
{ name: 'Basic Tap', component: TapExample },
{ name: 'Basic LongPress', component: LongPressExample },
{ name: 'Basic Hover', component: HoverExample },
{ name: 'Basic Pinch', component: PinchExample },
{ name: 'Basic Rotation', component: RotationExample },
{ name: 'Basic Pan', component: PanExample },
],
},
{
Expand Down
Loading
Loading