Skip to content

Commit 47b4ae7

Browse files
KrzysztofWojnarKrzysztof Wojnarkkafar
authored
chore(e2e): detox config general cleanup and ios management (#3412)
## Description This is first of three PRs in the scope of [labs issue 569](https://github.com/software-mansion/react-native-screens-labs/issues/569). Realizing plans from [labs discussion 572](https://github.com/software-mansion/react-native-screens-labs/discussions/572). ## Changes e2e tests could be run in more parametrized way - choosing ios version/device before the start. CI_AVD_NAME and DETOX_AVD_NAME env variables combined into `RNS_E2E_AVD_NAME` `RNS_ADB_NAME` environment variable introduced for local testing against attached [physical] devices. Common e2e scripts restructured. ## Screenshots / GIFs Here you can add screenshots / GIFs documenting your change. You can add before / after section if you're changing some behavior. ### Before Choosing apple simulator by changing config file for "ios.simulator" entry ### After Running test script with optional `RNS_E2E_APPLE_SIM_NAME` and `RNS_E2E_IOS_VERSION` environment variables. ## Checklist - [x] Included code example that can be used to test this change - [x] Updated TS types - [x] Updated documentation: <!-- For adding new props to native-stack --> - [x] https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md - [x] https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md - [x] https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx - [x] https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx - [x] Ensured that CI passes --------- Co-authored-by: Krzysztof Wojnar <krzysztof.wojnar@swmansion.com> Co-authored-by: Kacper Kafara <kacper.kafara@swmansion.com> Co-authored-by: Kacper Kafara <kacperkafara@gmail.com>
1 parent 46052f3 commit 47b4ae7

File tree

7 files changed

+81
-27
lines changed

7 files changed

+81
-27
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,5 @@ android/.settings
6464
# Local environment (direnv)
6565
.envrc
6666

67+
# e2e
68+
*Example/artifacts

Example/.detoxrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
const utils = require('../scripts/detox-utils.cjs');
1+
const utils = require('../scripts/e2e/detox-utils.cjs');
22
module.exports = utils.commonDetoxConfigFactory('ScreensExample');

Example/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
"format": "prettier --write --list-different './src/**/*.{js,ts,tsx}'",
1010
"lint": "eslint --ext '.js,.ts,.tsx' --fix src && yarn check-types && yarn format",
1111
"check-types": "tsc --noEmit",
12-
"build-e2e-ios": "detox build --configuration ios.release",
13-
"build-e2e-android": "detox build --configuration android.release",
14-
"test-e2e-ios": "detox test --configuration ios.release --take-screenshots failing",
15-
"test-e2e-android": "detox test --configuration android.release --take-screenshots failing",
12+
"build-e2e-ios": "detox build --configuration ios.sim.release",
13+
"build-e2e-android": "detox build --configuration android.emu.release",
14+
"test-e2e-ios": "detox test --configuration ios.sim.release --take-screenshots failing",
15+
"test-e2e-android": "detox test --configuration android.emu.release --take-screenshots failing",
1616
"postinstall": "patch-package"
1717
},
1818
"dependencies": {

FabricExample/.detoxrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
const utils = require('../scripts/detox-utils.cjs');
1+
const utils = require('../scripts/e2e/detox-utils.cjs');
22
module.exports = utils.commonDetoxConfigFactory('FabricExample');
33

FabricExample/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
"lint": "eslint .",
99
"start": "npx react-native start",
1010
"test": "jest",
11-
"build-e2e-ios": "detox build --configuration ios.release",
12-
"build-e2e-android": "detox build --configuration android.release",
13-
"test-e2e-ios": "detox test --configuration ios.release --take-screenshots failing",
14-
"test-e2e-android": "detox test --configuration android.release --take-screenshots failing",
11+
"build-e2e-ios": "detox build --configuration ios.sim.release",
12+
"build-e2e-android": "detox build --configuration android.emu.release",
13+
"test-e2e-ios": "detox test --configuration ios.sim.release --take-screenshots failing",
14+
"test-e2e-android": "detox test --configuration android.emu.release --take-screenshots failing",
1515
"postinstall": "patch-package"
1616
},
1717
"dependencies": {

scripts/detox-utils.cjs renamed to scripts/e2e/detox-utils.cjs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
const ChildProcess = require('node:child_process');
2+
const { iosDevice } = require('./ios-devices');
23

3-
const CI_AVD_NAME = 'e2e_emulator';
4+
// Should be kept in sync with the constant defined in e2e workflow file
5+
const DEFAULT_CI_AVD_NAME = 'e2e_emulator';
46

57
const isRunningCI = process.env.CI != null;
68

7-
// Assumes that local developement is done on arm64-v8a.
9+
// Assumes that local development is done on arm64-v8a.
810
const apkBulidArchitecture = isRunningCI ? 'x86_64' : 'arm64-v8a';
911
// test-butler requires AOSP emulator image, which is not available to download for arm64-v8a in Android Studio SDK Manager, therefore
1012
// it is assumed here that arm64-v8a AOSP emulator is not available in local setup.
1113
const testButlerApkPath = isRunningCI ? ['../Example/e2e/apps/test-butler-app-2.2.1.apk'] : undefined;
1214

1315
function detectLocalAndroidEmulator() {
14-
// "DETOX_AVD_NAME" can be set for local developement
15-
const detoxAvdName = process.env.DETOX_AVD_NAME ?? null;
16-
if (detoxAvdName !== null) {
17-
return detoxAvdName
16+
// "RNS_E2E_AVD_NAME" can be set for local development
17+
const avdName = process.env.RNS_E2E_AVD_NAME ?? null;
18+
if (avdName !== null) {
19+
return avdName
1820
}
1921

2022
// Fallback: try to use Android SDK
2123
try {
22-
let stdout = ChildProcess.execSync("emulator -list-avds")
24+
let stdout = ChildProcess.execSync("emulator -list-avds");
2325

2426
// Possibly convert Buffer to string
2527
if (typeof stdout !== 'string') {
@@ -32,22 +34,22 @@ function detectLocalAndroidEmulator() {
3234
throw new Error('No installed AVDs detected on the device');
3335
}
3436

35-
// Just select first one in the list.
37+
// Just select first one in the list.
3638
// TODO: consider giving user a choice here.
3739
return avdList[0];
3840
} catch (error) {
39-
const errorMessage = `Failed to find Android emulator. Set "DETOX_AVD_NAME" env variable pointing to one. Cause: ${error}`
41+
const errorMessage = `Failed to find Android emulator. Set "RNS_E2E_AVD_NAME" env variable pointing to one. Cause: ${error}`;
4042
console.error(errorMessage);
4143
throw new Error(errorMessage);
4244
}
4345
}
4446

4547
function detectAndroidEmulatorName() {
46-
return isRunningCI ? CI_AVD_NAME : detectLocalAndroidEmulator();
48+
// "RNS_E2E_AVD_NAME" can be set for local development
49+
return isRunningCI ? DEFAULT_CI_AVD_NAME : detectLocalAndroidEmulator();
4750
}
4851

4952
/**
50-
* @type {Detox.DetoxConfig}
5153
* @param {string} applicationName name (FabricExample / ScreensExample)
5254
* @returns {Detox.DetoxConfig}
5355
*/
@@ -94,14 +96,12 @@ function commonDetoxConfigFactory(applicationName) {
9496
devices: {
9597
simulator: {
9698
type: 'ios.simulator',
97-
device: {
98-
type: 'iPhone 16 Pro',
99-
},
99+
device: iosDevice,
100100
},
101101
attached: {
102102
type: 'android.attached',
103103
device: {
104-
adbName: CI_AVD_NAME,
104+
adbName: process.env.RNS_ADB_NAME,
105105
},
106106
utilBinaryPaths: testButlerApkPath,
107107
},
@@ -147,10 +147,10 @@ function commonDetoxConfigFactory(applicationName) {
147147
app: 'android.release',
148148
},
149149
},
150-
}
150+
};
151151
}
152152

153153
module.exports = {
154154
commonDetoxConfigFactory,
155155
isRunningCI,
156-
}
156+
};

scripts/e2e/ios-devices.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
const DEFAULT_APPLE_DEVICE = 'iPhone 17';
2+
const DEFAULT_IOS_VERSION = 'iOS 26.2';
3+
4+
/**
5+
* @return {string}
6+
*/
7+
function getAppleDevice() {
8+
const envVariableKey = 'RNS_E2E_APPLE_SIM_NAME';
9+
const passedDevice = process.env[envVariableKey];
10+
if (passedDevice) {
11+
if (/^(iPhone|iPad)\s.+/.test(passedDevice)) {
12+
return passedDevice;
13+
} else {
14+
throw new Error(`Environment variable ${envVariableKey} should be "iPhone xyz" or "iPad xyz".`);
15+
}
16+
}
17+
return process.env.RNS_E2E_APPLE_SIM_NAME || DEFAULT_APPLE_DEVICE;
18+
}
19+
/**
20+
* @return {`iOS ${string}`} requested version of ios, or default if not specified
21+
*/
22+
function getIOSVersion() {
23+
const envVariableKey = 'RNS_E2E_IOS_VERSION';
24+
const passedVersion = process.env[envVariableKey];
25+
if (passedVersion) {
26+
if (/^(iOS)\s.+/.test(passedVersion)) {
27+
return /** @type {`iOS ${string}`} */ (passedVersion);
28+
} else {
29+
throw new Error(`Environment variable ${envVariableKey} should be "iOS xyz".`);
30+
}
31+
}
32+
return DEFAULT_IOS_VERSION;
33+
}
34+
35+
/**
36+
* @typedef {Object} AppleDevice - represents Detox's config for an Apple device
37+
* @property {string} type - a string which represents a model of an iPhone
38+
* @property {`iOS ${string}`} os - operation system version
39+
*/
40+
41+
/**
42+
* @satisfies {AppleDevice}
43+
* @readonly
44+
* */
45+
const iosDevice = {
46+
type: getAppleDevice(),
47+
os: getIOSVersion(),
48+
};
49+
50+
module.exports = {
51+
iosDevice,
52+
};

0 commit comments

Comments
 (0)