Commit b9af40b
Add local E2E test suites for the example app (#67)
* Add local E2E test suites for the example app
Mirrors the instrumented test patterns from frontegg-android-kotlin and
frontegg-ios-swift so contributors can reproduce e2e flows without the
external e2e-system-tests repo, and closes the passkey / refresh-token
coverage gaps flagged in docs/E2E_REACT_NATIVE_TESTS_REVIEW.md.
- HomeScreen/ProfileScreen: add testID props on every actionable element
and diagnostic text node for selector stability across both suites.
- Android: new androidTest suite under example/android/app/src/androidTest
(UiAutomator + JUnit4) with 9 scenarios — login (happy + wrong password),
logout, Google social, tenant switch, refresh token, session restore,
request authorize, passkey register/login smoke. Reads credentials from
instrumentation args via utils/Env.kt.
- iOS: new ReactNativeExampleUITests XCUITest suite with the same 9
scenarios, sharing a UITestCase base class that forwards env vars into
XCUIApplication.launchEnvironment.
- example/E2E_TESTS.md: runbook with required env vars, Gradle and
xcodebuild commands, Xcode target registration steps, and known
limitations (Google sheet handling, passkey enrolment on bare sim/emu).
- docs/E2E_REACT_NATIVE_TESTS_REVIEW.md: coverage table and §5.3/§5.4
updated to reflect the new local coverage.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix react-native-sdk-e2e workflow ref
The reusable workflow was referenced at @main but e2e-system-tests has no
main branch — its default is master. The workflow has been failing at
parse time (0-second duration, no jobs) since it was introduced; this
restores the external E2E gate for PRs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Drop stale credential refs from E2E_TESTS.md
Master changed the example app's Frontegg tenant; the runbook no longer
needs to repeat the hard-coded baseUrl/clientId.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Replace broken cross-repo e2e workflow with local Android emulator suite
The previous workflow called a reusable workflow from the private
frontegg/e2e-system-tests repo, which never worked — every run since
March 18 failed in 0 seconds with "workflow file issue" because GitHub
blocks cross-repo reusable workflow calls from private repos without
explicit org-level access grants.
This replaces it with a self-contained workflow that mirrors how
frontegg-android-kotlin/demo-e2e.yml works:
- Builds the RN example app's debug + androidTest APKs
- Boots an API 34 emulator with AVD caching
- Runs the 9 UiAutomator E2E tests added in the previous commit
- Publishes JUnit results as a PR check via mikepenz/action-junit-report
- Reads credentials from repository secrets (E2E_LOGIN_EMAIL, etc.)
The check now appears as "React Native SDK E2E" on the PR and will
report real pass/fail status instead of silently dying at parse time.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add iOS E2E job and register XCUITest target in Xcode project
- Adds ReactNativeExampleUITests target to project.pbxproj via a Ruby
script (example/ios/add_uitest_target.rb) that uses the xcodeproj gem.
The script is idempotent and checked in so CI or other devs can
regenerate if the pbxproj is reset.
- Adds ios-e2e job to the workflow: runs on macos-15, installs pods,
builds for testing, then runs xcodebuild test-without-building with
-only-testing:ReactNativeExampleUITests on an iPhone 16 simulator.
Credentials come from the same E2E_* repository secrets as Android.
- Both jobs (android-e2e, ios-e2e) run in parallel on every PR.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix pbxproj for UI test target: add productType and fix product refs
The xcodeproj gem omitted productType on the native target and created
a bare PBXFileReference without explicitFileType/.xctest suffix, which
caused xcodebuild to fail with "Required key 'productTypeIdentifier'
is missing". Also removed a duplicate entry in the Products group.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix iOS UI test target: add PRODUCT_NAME, scheme entry, deployment target
The xcodeproj gem omitted PRODUCT_NAME = "$(TARGET_NAME)" from both
Debug and Release build configurations, causing xcodebuild to produce
empty product names ("-Runner.app/PlugIns/.xctest"). Also adds
IPHONEOS_DEPLOYMENT_TARGET = 14.0 to match the app target, and
registers the UI test target in the shared scheme's TestAction so
-only-testing:ReactNativeExampleUITests works.
Verified locally: `xcodebuild build-for-testing` produces
ReactNativeExampleUITests-Runner.app with the .xctest bundle inside.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Wire iOS E2E tests to LocalMockAuthServer
Ports LocalMockAuthServer.swift from frontegg-ionic-capacitor into the
ReactNativeExampleUITests target. The mock server runs at localhost:49381
and handles OAuth/token/user endpoints so tests don't need real Frontegg
credentials.
Infrastructure changes:
- FronteggTest.plist: placeholder HTTPS baseUrl so FronteggSwift's plist
validation passes at init time.
- FronteggLoaderInitializer.initializeE2EIfNeeded(): reads FRONTEGG_E2E_*
env vars and calls FronteggApp.shared.manualInit() to redirect the SDK
to the mock server BEFORE the RN module's lazy init triggers plist loading.
- AppDelegate.mm: calls initializeE2EIfNeeded() first.
- Info.plist: adds NSAllowsLocalNetworking for ATS.
- add_e2e_files.rb: registers LocalMockAuthServer.swift in the UI test
target and FronteggTest.plist in the app resources.
Verified locally on iPhone 16 Pro simulator (iOS 18.1):
- PasskeysLoginTest: PASSED
- PasskeysRegisterTest: needs login (blocked on ASWebAuthenticationSession)
- LoginViaGoogleTest: PASSED (smoke level)
- LogoutTest/SessionRestore/RefreshToken/etc: need login flow
Login-dependent tests require upgrading the FronteggSwift pod to a version
that supports FRONTEGG_TEST_WEB_AUTH_TRANSPORT (replaces ASWebAuth with a
testable WKWebView for the mock login form).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Verify E2E tests locally: fix Android Kotlin plugin, iOS mock server, skip on missing creds
Android:
- Add kotlin-gradle-plugin classpath + apply plugin to enable Kotlin
compilation for androidTest sources (was silently skipped before).
- Env.kt: return empty string instead of crashing; add isAvailable().
- All login-dependent tests use Assume.assumeTrue() to skip gracefully.
- UiTestInstrumentation: use text/content-desc selectors (not resource-id)
because FronteggButton renders testID as content-desc = title on Android.
- Verified via adb: PasskeysLoginTest PASSED, LogoutTest SKIPPED (OK).
iOS:
- LocalMockAuthServer: change baseURL from 127.0.0.1 to localhost (ATS).
- FronteggTest.plist: use https:// placeholder URL so FronteggSwift's
plist validation passes, then manualInit overrides with mock server URL.
- FronteggLoaderInitializer: split into initializeE2EIfNeeded() (called
before RN module init) + initializeLoader() to avoid plist crash.
- Info.plist: add NSAllowsLocalNetworking for ATS.
- All login-dependent tests throw XCTSkip when LOGIN_EMAIL is absent.
- Verified on iPhone 16 Pro sim: 2 PASSED, 8 SKIPPED, 0 FAILED.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(e2e): pin example Gradle to 8.0.1 (RN 0.72) + drop stale Podfile.lock
Android E2E: RN 0.72.1's @react-native/gradle-plugin (Kotlin 1.7.1) does not
support Gradle 8.3+ (which bundles Kotlin 1.9) -> :gradle-plugin:compileKotlin
failed on incompatible metadata. Pin the example Gradle wrapper to 8.0.1.
iOS E2E: the committed example/ios/Podfile.lock pinned FronteggSwift 1.2.76,
conflicting with the SDK's required FronteggSwift 1.3.10. Remove the stale lock
so pod install regenerates it at 1.3.10 (Podfile already targets iOS 14).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(e2e): single-line the android gradle command + pod install --repo-update
Android E2E: the multi-line gradle command broke in the emulator-runner script
step (a stray backslash reached gradle: 'Task not found'). Put it on one line.
iOS E2E: pod install needs --repo-update to fetch the FronteggSwift 1.3.10 spec
(the runner's spec-repo cache was out of date).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(ios/spm): link FronteggSwift into every target that links FronteggRN
Under use_frameworks! :static, FronteggRN builds as a static framework and does
not embed FronteggSwift's objects, so any binary that links FronteggRN — the app
target AND the unit-test bundle (inherit! :complete) — linked with unresolved
FronteggSwift.* symbols. frontegg_spm.rb previously *removed* the app-target SPM
link assuming FronteggRN provides it. Instead link the FronteggSwift SPM product
directly into each such target (one XCSwiftPackageProductDependency + a Frameworks
build file per target), located generically by product type
(application + bundle.unit-test); UI-test bundles link neither and are excluded.
Idempotent; result is plutil-lint valid.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* test(e2e/ios): bind the mock auth server once instead of per test class
LocalMockAuthServer binds a fixed port (49381) via NWListener. tearDown nilled
the shared server and the next class's setUp rebound the same port while the
previous NWListener.cancel() was still in flight, intermittently failing with
EADDRINUSE ('Address already in use') and crashing class setUp via try! — seen
on LoginViaGoogleTest and PasskeysLoginTest. Bind the server once for the whole
serial run (per-test state is already cleared via reset()), removing the rebind
race entirely.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* ci(e2e/ios): build + run UI tests in Release so the app embeds the JS bundle
The Debug build doesn't embed a JS bundle and AppDelegate's #if DEBUG path loads
from Metro, which isn't running in CI — so the app showed the RN red box
('No bundle URL present') and no UI rendered, failing the *_is_reachable tests.
Building in Release makes AppDelegate use the embedded main.jsbundle (produced by
the Release bundle phase), so the app is self-contained with no packager needed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* ci(e2e/ios): Debug build with embedded JS + mock web-auth transport for social test
Release embeds the JS bundle but disables the SDK's mock web-auth transport
(FronteggRuntime.allowsTestingWebAuthenticationTransport is #if DEBUG), so the
Google social-login smoke test hit a real ASWebAuthenticationSession that can't
complete headlessly in CI. Switch back to a Debug build (mock transport available)
and make the app self-contained without Metro:
- build with FORCE_BUNDLING=1 so the Debug app embeds main.jsbundle
- AppDelegate loads the embedded bundle under test (frontegg-testing=true)
- launchApp gains a useTestingWebAuthenticationTransport flag
- LoginViaGoogleTest launches with the mock transport so the social flow completes
against the local mock server instead of a real Safari VC
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* ci(e2e/ios): exclude real social-login test from CI (mirror SDK hosted:no-social)
The Google social-login smoke test drives a real ASWebAuthenticationSession that
can't complete headlessly on a CI simulator. The frontegg-ios-swift SDK handles
this by running its E2E with the "hosted:no-social" suite — it excludes the
real system-web-auth social test from the standard pipeline. Mirror that: build
+ run in Release (app embeds main.jsbundle, no Metro) and skip LoginViaGoogleTest
via -skip-testing. Reverts the Debug+FORCE_BUNDLING+mock-transport attempt, since
the SDK does not run real social in CI at all.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent bc90fb5 commit b9af40b
42 files changed
Lines changed: 4118 additions & 733 deletions
File tree
- .github/workflows
- docs
- example
- android
- app
- src/androidTest/java/com/frontegg/demo/e2e
- utils
- gradle/wrapper
- ios
- ReactNativeExample.xcodeproj
- ReactNativeExampleUITests
- ReactNativeExample
- src
- components
- ios
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | | - | |
3 | | - | |
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
4 | 10 | | |
5 | 11 | | |
6 | 12 | | |
7 | 13 | | |
8 | 14 | | |
9 | 15 | | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
10 | 21 | | |
11 | 22 | | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
68 | 68 | | |
69 | 69 | | |
70 | 70 | | |
71 | | - | |
72 | | - | |
| 71 | + | |
| 72 | + | |
73 | 73 | | |
74 | | - | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
75 | 80 | | |
76 | 81 | | |
77 | 82 | | |
| |||
97 | 102 | | |
98 | 103 | | |
99 | 104 | | |
100 | | - | |
| 105 | + | |
101 | 106 | | |
102 | 107 | | |
103 | 108 | | |
104 | 109 | | |
105 | | - | |
| 110 | + | |
106 | 111 | | |
107 | 112 | | |
108 | 113 | | |
| |||
0 commit comments