Fix flaky Maestro E2E sign-in setup on iOS

The e2eSignInAlice button only mounts once the proxy is configured, which
previously relied solely on the proxy TextInput's onSubmitEditing handler
triggered via `pressKey: Enter`. Enter is unreliable on the iOS simulator,
so the sign-in buttons sometimes never appeared and flows failed with
"Element not found: e2eSignInAlice".

- TestCtrls.e2e.tsx: extract the proxy-configuration logic into a named
  onConfigureProxy function, still called by onSubmitEditing (Enter remains
  a fallback), and add a dedicated e2eConfigureProxy Pressable that is
  always rendered so setup can tap it deterministically.
- setupApp.yml: tap e2eConfigureProxy instead of pressing Enter, then guard
  with an extendedWaitUntil for e2eSignInAlice (60000ms) so the race becomes
  an explicit bounded wait shared by every flow reusing this setup.
- run-nightly-e2e.sh: add `--retries 2` to the maestro test invocation so a
  single flaky miss doesn't fail the whole nightly run.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Umqi3SMj5PvH2ZVxQYWCcx
This commit is contained in:
Claude
2026-07-26 07:45:31 +00:00
parent d5e335e575
commit a27c019e70
3 changed files with 21 additions and 8 deletions
+1
View File
@@ -159,6 +159,7 @@ phase "Running Maestro flows"
set +e set +e
maestro test \ maestro test \
--udid "$device_id" \ --udid "$device_id" \
--retries 2 \
--format JUNIT \ --format JUNIT \
--output "$artifact_dir/report.xml" \ --output "$artifact_dir/report.xml" \
--config __e2e__/config.yml \ --config __e2e__/config.yml \
+6 -1
View File
@@ -33,4 +33,9 @@ appId: xyz.blueskyweb.app
- tapOn: - tapOn:
id: e2eProxyHeaderInput id: e2eProxyHeaderInput
- inputText: ${output.result} - inputText: ${output.result}
- pressKey: Enter - tapOn:
id: e2eConfigureProxy
- extendedWaitUntil:
visible:
id: e2eSignInAlice
timeout: 60000
+14 -7
View File
@@ -62,6 +62,13 @@ export function TestCtrls() {
setShowLoggedOut(false) setShowLoggedOut(false)
} }
const [proxyHeader, setProxyHeader] = useState('') const [proxyHeader, setProxyHeader] = useState('')
const onConfigureProxy = () => {
const header = `${proxyHeader}#bsky_appview`
BLUESKY_PROXY_HEADER.set(header)
agent.configureProxy(header as any)
hasConfiguredProxy = true
setIsProxyConfigured(true)
}
return ( return (
<View style={{position: 'absolute', top: 100, right: 0, zIndex: 100}}> <View style={{position: 'absolute', top: 100, right: 0, zIndex: 100}}>
<TextInput <TextInput
@@ -72,13 +79,13 @@ export function TestCtrls() {
autoComplete="off" autoComplete="off"
autoCorrect={false} autoCorrect={false}
autoCapitalize="none" autoCapitalize="none"
onSubmitEditing={() => { onSubmitEditing={onConfigureProxy}
const header = `${proxyHeader}#bsky_appview` style={BTN}
BLUESKY_PROXY_HEADER.set(header) />
agent.configureProxy(header as any) <Pressable
hasConfiguredProxy = true testID="e2eConfigureProxy"
setIsProxyConfigured(true) onPress={onConfigureProxy}
}} accessibilityRole="button"
style={BTN} style={BTN}
/> />
{isProxyConfigured && ( {isProxyConfigured && (