1
1
#!/usr/bin/env node
2
2
'use strict' ;
3
3
4
- import { execSync , spawn } from 'child_process' ;
4
+ import { execSync , execFileSync , spawn } from 'child_process' ;
5
5
import * as fs from 'fs' ;
6
6
import * as path from 'path' ;
7
7
import { argv , env } from 'process' ;
@@ -64,8 +64,9 @@ const appRepoDir = `${e2eDir}/react-native-versions/${RNVersion}`;
64
64
const appName = 'RnDiffApp' ;
65
65
const appDir = `${ appRepoDir } /${ appName } ` ;
66
66
const testAppName = `${ appName } .${ platform == 'ios' ? 'app' : 'apk' } ` ;
67
- const runtime = env . IOS_RUNTIME ? env . IOS_RUNTIME : 'latest' ;
68
- const device = env . IOS_DEVICE ? env . IOS_DEVICE : 'iPhone 15' ;
67
+ const testApp = `${ e2eDir } /${ testAppName } ` ;
68
+ const appId = platform === 'ios' ? 'org.reactjs.native.example.RnDiffApp' : 'com.rndiffapp' ;
69
+ const sentryAuthToken = env . SENTRY_AUTH_TOKEN ;
69
70
70
71
// Build and publish the SDK - we only need to do this once in CI.
71
72
// Locally, we may want to get updates from the latest build so do it on every app build.
@@ -112,9 +113,12 @@ if (actions.includes('create')) {
112
113
env : Object . assign ( env , { YARN_ENABLE_IMMUTABLE_INSTALLS : false } ) ,
113
114
} ) ;
114
115
115
- console . log ( `done` ) ;
116
-
117
- console . log ( `done2` ) ;
116
+ execSync ( `yarn add [email protected] ` , {
117
+ stdio : 'inherit' ,
118
+ cwd : appDir ,
119
+ // yarn v3 run immutable install by default in CI
120
+ env : Object . assign ( env , { YARN_ENABLE_IMMUTABLE_INSTALLS : false } ) ,
121
+ } ) ;
118
122
119
123
// Patch the app
120
124
execSync ( `patch --verbose --strip=0 --force --ignore-whitespace --fuzz 4 < ${ patchScriptsDir } /rn.patch` , {
@@ -138,7 +142,6 @@ if (actions.includes('create')) {
138
142
cwd : `${ appDir } /ios` ,
139
143
env : env ,
140
144
} ) ;
141
- console . log ( `done3` ) ;
142
145
143
146
if ( fs . existsSync ( `${ appDir } /Gemfile` ) ) {
144
147
execSync ( `bundle install` , { stdio : 'inherit' , cwd : appDir , env : env } ) ;
@@ -185,7 +188,8 @@ if (actions.includes('build')) {
185
188
-workspace ${ appName } .xcworkspace \
186
189
-configuration ${ buildType } \
187
190
-scheme ${ appName } \
188
- -destination 'platform=iOS Simulator,OS=${ runtime } ,name=${ device } ' \
191
+ -sdk 'iphonesimulator' \
192
+ -destination 'generic/platform=iOS Simulator' \
189
193
ONLY_ACTIVE_ARCH=yes \
190
194
-derivedDataPath DerivedData \
191
195
build | tee xcodebuild.log | xcbeautify` ,
@@ -202,123 +206,40 @@ if (actions.includes('build')) {
202
206
appProduct = `${ appDir } /android/app/build/outputs/apk/release/app-release.apk` ;
203
207
}
204
208
205
- var testApp = `${ e2eDir } /${ testAppName } ` ;
206
209
console . log ( `Moving ${ appProduct } to ${ testApp } ` ) ;
207
210
if ( fs . existsSync ( testApp ) ) fs . rmSync ( testApp , { recursive : true } ) ;
208
211
fs . renameSync ( appProduct , testApp ) ;
209
212
}
210
213
211
214
if ( actions . includes ( 'test' ) ) {
212
- if (
213
- platform == 'ios' &&
214
- ! fs . existsSync ( `${ e2eDir } /DerivedData/Build/Products/Debug-iphonesimulator/WebDriverAgentRunner-Runner.app` )
215
- ) {
216
- // Build iOS WebDriverAgent
217
- execSync (
218
- `set -o pipefail && xcodebuild \
219
- -project node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj \
220
- -scheme WebDriverAgentRunner \
221
- -destination 'platform=iOS Simulator,OS=${ runtime } ,name=${ device } ' \
222
- GCC_TREAT_WARNINGS_AS_ERRORS=0 \
223
- COMPILER_INDEX_STORE_ENABLE=NO \
224
- ONLY_ACTIVE_ARCH=yes \
225
- -derivedDataPath DerivedData \
226
- build | tee xcodebuild-agent.log | xcbeautify` ,
227
- { stdio : 'inherit' , cwd : e2eDir , env : env } ,
228
- ) ;
229
- }
230
-
231
- // Start the appium server.
232
- var processesToKill = { } ;
233
- async function newProcess ( name , process ) {
234
- await new Promise ( ( resolve , reject ) => {
235
- process . on ( 'error' , e => {
236
- console . error ( `Failed to start process '${ name } ': ${ e } ` ) ;
237
- reject ( e ) ;
238
- } ) ;
239
- process . on ( 'spawn' , ( ) => {
240
- console . log ( `Process '${ name } ' (${ process . pid } ) started` ) ;
241
- resolve ( ) ;
242
- } ) ;
243
- } ) ;
244
-
245
- processesToKill [ name ] = {
246
- process : process ,
247
- complete : new Promise ( ( resolve , _reject ) => {
248
- process . on ( 'close' , resolve ) ;
249
- } ) ,
250
- } ;
251
- }
252
- await newProcess (
253
- 'appium' ,
254
- spawn ( 'node_modules/.bin/appium' , [ '--log-timestamp' , '--log-no-colors' , '--log' , `appium${ platform } .log` ] , {
255
- stdio : 'inherit' ,
256
- cwd : e2eDir ,
257
- env : env ,
258
- shell : false ,
259
- } ) ,
260
- ) ;
261
-
262
- try {
263
- await waitForAppium ( ) ;
264
-
265
- // Run e2e tests
266
- const testEnv = env ;
267
- testEnv . PLATFORM = platform ;
268
- testEnv . APPIUM_APP = `./${ testAppName } ` ;
269
-
270
- if ( platform == 'ios' ) {
271
- testEnv . APPIUM_DERIVED_DATA = 'DerivedData' ;
272
- } else if ( platform == 'android' ) {
273
- execSync ( `adb devices -l` , { stdio : 'inherit' , cwd : e2eDir , env : env } ) ;
274
-
275
- execSync ( `adb logcat -c` , { stdio : 'inherit' , cwd : e2eDir , env : env } ) ;
276
-
277
- var adbLogStream = fs . createWriteStream ( `${ e2eDir } /adb.log` ) ;
278
- const adbLogProcess = spawn ( 'adb' , [ 'logcat' ] , { cwd : e2eDir , env : env , shell : false } ) ;
279
- adbLogProcess . stdout . pipe ( adbLogStream ) ;
280
- adbLogProcess . stderr . pipe ( adbLogStream ) ;
281
- adbLogProcess . on ( 'close' , ( ) => adbLogStream . close ( ) ) ;
282
- await newProcess ( 'adb logcat' , adbLogProcess ) ;
283
- }
284
-
285
- execSync ( `yarn test:e2e:runner --verbose` , { stdio : 'inherit' , cwd : e2eDir , env : testEnv } ) ;
286
- } finally {
287
- for ( const [ name , info ] of Object . entries ( processesToKill ) ) {
288
- console . log ( `Sending termination signal to process '${ name } ' (${ info . process . pid } )` ) ;
289
-
290
- // Send SIGTERM first to allow graceful shutdown.
291
- info . process . kill ( 15 ) ;
292
-
293
- // Also send SIGKILL after 10 seconds.
294
- const killTimeout = setTimeout ( ( ) => process . kill ( 9 ) , '10000' ) ;
295
-
296
- // Wait for the process to exit (either via SIGTERM or SIGKILL).
297
- const code = await info . complete ;
298
-
299
- // Successfully exited now, no need to kill (if it hasn't run yet).
300
- clearTimeout ( killTimeout ) ;
301
-
302
- console . log ( `Process '${ name } ' (${ info . process . pid } ) exited with code ${ code } ` ) ;
215
+ // Run e2e tests
216
+ if ( platform == 'ios' ) {
217
+ try {
218
+ execSync ( 'xcrun simctl list devices | grep -q "(Booted)"' ) ;
219
+ } catch ( error ) {
220
+ throw new Error ( 'No simulator is currently booted. Please boot a simulator before running this script.' ) ;
303
221
}
304
- }
305
- }
306
222
307
- async function waitForAppium ( ) {
308
- console . log ( 'Waiting for Appium server to start...' ) ;
309
- for ( let i = 0 ; i < 60 ; i ++ ) {
223
+ execFileSync ( 'xcrun' , [ 'simctl' , 'install' , 'booted' , testApp ] ) ;
224
+ } else if ( platform == 'android' ) {
310
225
try {
311
- await fetch ( 'http://127.0.0.1:4723/sessions' , { method : 'HEAD' } ) ;
312
- console . log ( 'Appium server started' ) ;
313
- return ;
226
+ execSync ( 'adb devices | grep -q "emulator"' ) ;
314
227
} catch ( error ) {
315
- console . log ( `Appium server hasn't started yet (${ error } )...` ) ;
316
- await sleep ( 1000 ) ;
228
+ throw new Error ( 'No Android emulator is currently running. Please start an emulator before running this script.' ) ;
317
229
}
230
+
231
+ execFileSync ( 'adb' , [ 'install' , '-r' , '-d' , testApp ] ) ;
318
232
}
319
- throw new Error ( 'Appium server failed to start' ) ;
320
- }
321
233
322
- async function sleep ( millis ) {
323
- return new Promise ( resolve => setTimeout ( resolve , millis ) ) ;
234
+ execSync (
235
+ `maestro test maestro \
236
+ --env=APP_ID="${ appId } " \
237
+ --env=SENTRY_AUTH_TOKEN="${ sentryAuthToken } " \
238
+ --debug-output maestro-logs \
239
+ --flatten-debug-output` ,
240
+ {
241
+ stdio : 'inherit' ,
242
+ cwd : e2eDir ,
243
+ } ,
244
+ ) ;
324
245
}
0 commit comments