Skip to content

Commit bb923fe

Browse files
abueideclaude
andcommitted
feat: add E2E-latest (RN 0.84.1) to demonstrate upgrade challenges
Add E2E-latest example app running React Native 0.84.1 + React 19.2.3 to validate SDK compatibility with latest RN releases and document breaking changes that users will encounter. Key differences from E2E-compat: - React Native 0.84.1 (vs 0.72.9) - React 19.2.3 (vs 18.2.0) - New Architecture enabled by default - Updated iOS/Android build tools This app uses the same shared-e2e test library as E2E-compat, proving the test suite works across RN versions. Note: Some tests may fail due to third-party library compatibility issues with React Native 0.84's New Architecture, which is expected and demonstrates real-world upgrade challenges. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent c8190bd commit bb923fe

File tree

72 files changed

+17717
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+17717
-0
lines changed

examples/E2E-latest/.bundle/config

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
BUNDLE_PATH: "vendor/bundle"
2+
BUNDLE_FORCE_RUBY_PLATFORM: 1

examples/E2E-latest/.detoxrc.js

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
const {execSync} = require('child_process');
2+
3+
const defaultIOSDeviceCandidates = (() => {
4+
const fromEnv = (process.env.IOS_DEVICE_NAMES || 'iPhone 14')
5+
.split(',')
6+
.map(name => name.trim())
7+
.filter(Boolean);
8+
return Array.from(new Set(['iPhone 17', ...fromEnv, 'iPhone 14']));
9+
})();
10+
11+
const safeParseJSON = cmd => {
12+
try {
13+
return JSON.parse(
14+
execSync(cmd, {stdio: ['ignore', 'pipe', 'ignore']}).toString(),
15+
);
16+
} catch (_) {
17+
return null;
18+
}
19+
};
20+
21+
const listAvailableDevices = () => {
22+
const parsed = safeParseJSON('xcrun simctl list devices -j');
23+
if (!parsed || !parsed.devices) return [];
24+
const devices = [];
25+
Object.values(parsed.devices).forEach(group => {
26+
(group || []).forEach(device => {
27+
if (device.isAvailable || device.availability === '(available)') {
28+
devices.push(device);
29+
}
30+
});
31+
});
32+
return devices;
33+
};
34+
35+
const listAvailableDeviceTypes = () => {
36+
const parsed = safeParseJSON('xcrun simctl list devicetypes -j');
37+
if (!parsed || !parsed.devicetypes) return new Set();
38+
return new Set(parsed.devicetypes.map(dt => dt.name.toLowerCase()));
39+
};
40+
41+
const baseName = name => name.split(' (')[0].trim().toLowerCase();
42+
43+
const detectIOSDevice = () => {
44+
if (process.env.DETOX_IOS_DEVICE) {
45+
return {type: process.env.DETOX_IOS_DEVICE};
46+
}
47+
48+
const devices = listAvailableDevices();
49+
const preferredDevice = defaultIOSDeviceCandidates.find(candidate =>
50+
devices.some(d => baseName(d.name) === candidate.toLowerCase()),
51+
);
52+
if (preferredDevice) {
53+
const found = devices.find(
54+
d => baseName(d.name) === preferredDevice.toLowerCase(),
55+
);
56+
if (found) return {name: found.name};
57+
}
58+
const anyIphoneDevice = devices.find(d =>
59+
d.name.toLowerCase().includes('iphone'),
60+
);
61+
if (anyIphoneDevice) return {name: anyIphoneDevice.name};
62+
63+
const availableTypes = listAvailableDeviceTypes();
64+
const preferredType = defaultIOSDeviceCandidates.find(candidate =>
65+
availableTypes.has(candidate.toLowerCase()),
66+
);
67+
if (preferredType) return {type: preferredType};
68+
69+
const anyIphoneType = Array.from(availableTypes).find(t =>
70+
t.includes('iphone'),
71+
);
72+
if (anyIphoneType) return {type: anyIphoneType};
73+
74+
return {type: defaultIOSDeviceCandidates[0]};
75+
};
76+
77+
const iosDevice = detectIOSDevice();
78+
79+
/** @type {Detox.DetoxConfig} */
80+
module.exports = {
81+
testRunner: {
82+
args: {
83+
$0: 'jest',
84+
config: 'e2e/jest.config.js',
85+
forceExit: process.env.CI ? true : undefined,
86+
},
87+
jest: {
88+
setupTimeout: 240000,
89+
},
90+
detached: !!process.env.CI,
91+
retries: 3,
92+
},
93+
behavior: {
94+
init: {
95+
reinstallApp: true,
96+
exposeGlobals: false,
97+
},
98+
launchApp: 'auto',
99+
cleanup: {
100+
shutdownDevice: false,
101+
},
102+
},
103+
apps: {
104+
'ios.debug': {
105+
type: 'ios.app',
106+
binaryPath:
107+
'ios/build/Build/Products/Debug-iphonesimulator/AnalyticsReactNativeE2E.app',
108+
build:
109+
'xcodebuild -workspace ios/AnalyticsReactNativeE2E.xcworkspace -scheme AnalyticsReactNativeE2E -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build',
110+
},
111+
'ios.release': {
112+
type: 'ios.app',
113+
binaryPath:
114+
'ios/build/Build/Products/Release-iphonesimulator/AnalyticsReactNativeE2E.app',
115+
build:
116+
'xcodebuild -workspace ios/AnalyticsReactNativeE2E.xcworkspace -scheme AnalyticsReactNativeE2E -configuration Release -sdk iphonesimulator -derivedDataPath ios/build',
117+
},
118+
'android.debug': {
119+
type: 'android.apk',
120+
binaryPath: 'android/app/build/outputs/apk/debug/app-debug.apk',
121+
build:
122+
'cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug',
123+
reversePorts: [8081],
124+
},
125+
'android.release': {
126+
type: 'android.apk',
127+
binaryPath: 'android/app/build/outputs/apk/release/app-release.apk',
128+
build:
129+
'cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release',
130+
},
131+
},
132+
devices: {
133+
simulator: {
134+
type: 'ios.simulator',
135+
device: {
136+
// Allow CI/local override; defaults to an available simulator by name (or type fallback).
137+
...iosDevice,
138+
},
139+
},
140+
attached: {
141+
type: 'android.attached',
142+
device: {
143+
adbName: '.*',
144+
},
145+
},
146+
emulator: {
147+
type: 'android.emulator',
148+
device: {
149+
// Default to latest AVD name (arch-aware); override via DETOX_AVD. For minsdk testing, set DETOX_AVD to an API 21 AVD.
150+
avdName: (() => {
151+
if (process.env.DETOX_AVD) return process.env.DETOX_AVD;
152+
const arch = require('os').arch();
153+
return arch === 'arm64'
154+
? 'medium_phone_API33_arm64_v8a'
155+
: 'medium_phone_API33_x86_64';
156+
})(),
157+
},
158+
},
159+
},
160+
configurations: {
161+
'ios.sim.debug': {
162+
device: 'simulator',
163+
app: 'ios.debug',
164+
},
165+
'ios.sim.release': {
166+
device: 'simulator',
167+
app: 'ios.release',
168+
},
169+
'android.att.debug': {
170+
device: 'attached',
171+
app: 'android.debug',
172+
},
173+
'android.att.release': {
174+
device: 'attached',
175+
app: 'android.release',
176+
},
177+
'android.emu.debug': {
178+
device: 'emulator',
179+
app: 'android.debug',
180+
},
181+
'android.emu.release': {
182+
device: 'emulator',
183+
app: 'android.release',
184+
},
185+
},
186+
};

examples/E2E-latest/.gitignore

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# OSX
2+
#
3+
.DS_Store
4+
5+
# Xcode
6+
#
7+
build/
8+
*.pbxuser
9+
!default.pbxuser
10+
*.mode1v3
11+
!default.mode1v3
12+
*.mode2v3
13+
!default.mode2v3
14+
*.perspectivev3
15+
!default.perspectivev3
16+
xcuserdata
17+
*.xccheckout
18+
*.moved-aside
19+
DerivedData
20+
*.hmap
21+
*.ipa
22+
*.xcuserstate
23+
ios/.xcode.env.local
24+
25+
# Android/IntelliJ
26+
#
27+
build/
28+
.idea
29+
.gradle
30+
local.properties
31+
*.iml
32+
*.hprof
33+
.cxx/
34+
*.keystore
35+
!debug.keystore
36+
37+
# node.js
38+
#
39+
node_modules/
40+
npm-debug.log
41+
yarn-error.log
42+
43+
# fastlane
44+
#
45+
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
46+
# screenshots whenever they are needed.
47+
# For more information about the recommended setup visit:
48+
# https://docs.fastlane.tools/best-practices/source-control/
49+
50+
**/fastlane/report.xml
51+
**/fastlane/Preview.html
52+
**/fastlane/screenshots
53+
**/fastlane/test_output
54+
55+
# Bundle artifact
56+
*.jsbundle
57+
58+
# Ruby / CocoaPods
59+
/ios/Pods/
60+
/vendor/bundle/
61+
62+
# Temporary files created by Metro to check the health of the file watcher
63+
.metro-health-check*
64+
65+
# testing
66+
/coverage

examples/E2E-latest/.mise.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[tools]
2+
java = "zulu-11"
3+
node = "18"
4+
ruby = '3.3.0'
5+
cocoapods = "latest"

examples/E2E-latest/.prettierrc.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports = {
2+
arrowParens: 'avoid',
3+
bracketSameLine: true,
4+
bracketSpacing: false,
5+
singleQuote: true,
6+
trailingComma: 'all',
7+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

0 commit comments

Comments
 (0)