Skip to content
Merged
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
11 changes: 11 additions & 0 deletions dev-packages/e2e-tests/maestro/captureReplay.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,16 @@ jsEngine: graaljs
file: utils/launchTestAppClear.yml
env:
replaysOnErrorSampleRate: 1.0
# Prime the native replay buffer before capturing the exception so a replay_id
# is attached to the event (iOS only; Android does not reliably capture replays
# in CI โ€” see https://github.com/getsentry/sentry-react-native/pull/4277).
- runFlow:
file: utils/primeReplayBuffer.yml
when:
platform: iOS
- tapOn: "Capture Exception"
- runFlow: utils/assertEventIdVisible.yml
- runFlow:
file: utils/assertReplay.yml
when:
platform: iOS
23 changes: 23 additions & 0 deletions dev-packages/e2e-tests/maestro/utils/assertReplay.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
appId: ${APP_ID}
jsEngine: graaljs
---
- extendedWaitUntil:
visible:
id: "eventId"
timeout: 60_000 # 60 seconds

- copyTextFrom:
id: "eventId"
- assertTrue: ${maestro.copiedText}

- runScript:
file: sentryApi.js
env:
fetch: replay
eventId: ${maestro.copiedText}
sentryAuthToken: ${SENTRY_AUTH_TOKEN}

- assertTrue: ${output.replayId}
- assertTrue: ${output.replayDuration}
- assertTrue: ${output.replaySegments}
- assertTrue: ${output.replayCodec == "ftypmp42"}
16 changes: 16 additions & 0 deletions dev-packages/e2e-tests/maestro/utils/primeReplayBuffer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
appId: ${APP_ID}
jsEngine: graaljs
---
# Buffer-mode replay (replaysOnErrorSampleRate) only attaches a replay_id to the
# error event if the native replay buffer captured at least one frame before the
# error fired. Immediately after launch the buffer can still be empty on slow CI
# simulators, so the event is sent without a replay_id and no server-side retry
# can recover it. Tap the "Replay Ping" counter repeatedly to mutate the view
# hierarchy (and spend a few seconds of wall-clock while Maestro re-reads the UI
# between taps) so the native capture records frames before the exception is
# captured. If this proves insufficient on CI, increase the repeat count.
- repeat:
times: 8
commands:
- tapOn:
id: 'replayPing'
9 changes: 9 additions & 0 deletions dev-packages/e2e-tests/src/EndToEndTests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ const EndToEndTestsScreen = (): React.JSX.Element => {
const [isReady, setIsReady] = React.useState(false);
const [eventId, setEventId] = React.useState<string | null>(null);
const [error, setError] = React.useState<string>('No error');
// Buffer-mode replay (replaysOnErrorSampleRate) only attaches a replay_id to
// an error event if the native replay buffer captured at least one frame
// before the error fired. This counter is tapped by the captureReplay e2e
// flow to mutate the view hierarchy (side-effect free, no events sent) so the
// buffer records frames before the exception is captured.
const [replayPingCount, setReplayPingCount] = React.useState(0);

React.useEffect(() => {
const client: Sentry.ReactNativeClient | undefined = Sentry.getClient();
Expand Down Expand Up @@ -78,6 +84,9 @@ const EndToEndTestsScreen = (): React.JSX.Element => {
<Text onPress={() => setEventId(null)}>
Clear Event Id
</Text>
<Text testID='replayPing' onPress={() => setReplayPingCount((count) => count + 1)}>
Replay Ping {replayPingCount}
</Text>
{testCases.map((testCase) => (
<Text key={testCase.id} onPress={testCase.action}>
{testCase.name}
Expand Down
Loading