2016-04-13 18:18:49 +03:00
|
|
|
/**
|
2018-09-12 01:27:47 +03:00
|
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
2016-04-13 18:18:49 +03:00
|
|
|
*
|
2018-02-17 05:24:55 +03:00
|
|
|
* This source code is licensed under the MIT license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree.
|
2018-05-11 23:32:37 +03:00
|
|
|
*
|
|
|
|
* @format
|
2016-04-13 18:18:49 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This script tests that React Native end to end installation/bootstrap works for different platforms
|
|
|
|
* Available arguments:
|
2017-03-15 17:43:20 +03:00
|
|
|
* --ios - 'react-native init' and check iOS app doesn't redbox
|
|
|
|
* --android - 'react-native init' and check Android app doesn't redbox
|
|
|
|
* --js - 'react-native init' and only check the packager returns a bundle
|
2016-04-13 18:18:49 +03:00
|
|
|
* --skip-cli-install - to skip react-native-cli global installation (for local debugging)
|
2018-02-06 23:36:07 +03:00
|
|
|
* --retries [num] - how many times to retry possible flaky commands: yarn add and running tests, default 1
|
2016-04-13 18:18:49 +03:00
|
|
|
*/
|
|
|
|
/*eslint-disable no-undef */
|
|
|
|
require('shelljs/global');
|
2016-04-25 17:15:25 +03:00
|
|
|
|
|
|
|
const spawn = require('child_process').spawn;
|
|
|
|
const argv = require('yargs').argv;
|
2016-04-13 18:18:49 +03:00
|
|
|
const path = require('path');
|
|
|
|
|
|
|
|
const SCRIPTS = __dirname;
|
|
|
|
const ROOT = path.normalize(path.join(__dirname, '..'));
|
2016-05-04 20:57:30 +03:00
|
|
|
const tryExecNTimes = require('./try-n-times');
|
2016-04-13 18:18:49 +03:00
|
|
|
|
2019-06-01 02:42:18 +03:00
|
|
|
const REACT_NATIVE_TEMP_DIR = exec(
|
|
|
|
'mktemp -d /tmp/react-native-XXXXXXXX',
|
|
|
|
).stdout.trim();
|
|
|
|
const REACT_NATIVE_APP_DIR = `${REACT_NATIVE_TEMP_DIR}/template`;
|
2016-04-25 17:15:25 +03:00
|
|
|
const numberOfRetries = argv.retries || 1;
|
2016-04-13 18:18:49 +03:00
|
|
|
let SERVER_PID;
|
|
|
|
let APPIUM_PID;
|
2016-04-25 17:15:25 +03:00
|
|
|
let exitCode;
|
2016-04-13 18:18:49 +03:00
|
|
|
|
2019-04-10 04:43:02 +03:00
|
|
|
function describe(message) {
|
|
|
|
echo(`\n\n>>>>> ${message}\n\n\n`);
|
2019-02-22 00:12:48 +03:00
|
|
|
}
|
|
|
|
|
2016-04-25 17:15:25 +03:00
|
|
|
try {
|
2016-10-31 22:52:30 +03:00
|
|
|
if (argv.android) {
|
2019-05-31 01:07:45 +03:00
|
|
|
describe('Compile Android binaries');
|
2018-05-11 23:32:37 +03:00
|
|
|
if (
|
|
|
|
exec(
|
|
|
|
'./gradlew :ReactAndroid:installArchives -Pjobs=1 -Dorg.gradle.jvmargs="-Xmx512m -XX:+HeapDumpOnOutOfMemoryError"',
|
|
|
|
).code
|
|
|
|
) {
|
2016-04-25 17:15:25 +03:00
|
|
|
echo('Failed to compile Android binaries');
|
|
|
|
exitCode = 1;
|
|
|
|
throw Error(exitCode);
|
|
|
|
}
|
2016-04-13 18:18:49 +03:00
|
|
|
}
|
|
|
|
|
2019-04-30 13:05:06 +03:00
|
|
|
if (argv.js) {
|
2019-05-31 01:07:45 +03:00
|
|
|
describe('Install Flow');
|
2019-04-30 13:05:06 +03:00
|
|
|
if (
|
|
|
|
tryExecNTimes(
|
|
|
|
() => {
|
|
|
|
return exec('npm install --save-dev flow-bin').code;
|
|
|
|
},
|
|
|
|
numberOfRetries,
|
|
|
|
() => exec('sleep 10s'),
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
echo('Failed to install Flow');
|
|
|
|
echo('Most common reason is npm registry connectivity, try again');
|
|
|
|
exitCode = 1;
|
|
|
|
throw Error(exitCode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-31 01:07:45 +03:00
|
|
|
describe('Create react-native package');
|
2019-05-21 15:41:23 +03:00
|
|
|
if (exec('npm pack').code) {
|
2016-04-25 17:15:25 +03:00
|
|
|
echo('Failed to pack react-native');
|
|
|
|
exitCode = 1;
|
|
|
|
throw Error(exitCode);
|
|
|
|
}
|
2016-04-13 18:18:49 +03:00
|
|
|
|
2019-06-01 02:42:18 +03:00
|
|
|
const REACT_NATIVE_PACKAGE = path.join(ROOT, 'react-native-*.tgz');
|
2019-04-10 04:43:02 +03:00
|
|
|
|
2019-06-01 02:42:18 +03:00
|
|
|
describe('Scaffold a basic React Native app from template');
|
|
|
|
exec(`rsync -a ${ROOT}/template ${REACT_NATIVE_TEMP_DIR}`);
|
|
|
|
cd(REACT_NATIVE_APP_DIR);
|
2019-05-04 00:34:57 +03:00
|
|
|
|
|
|
|
const METRO_CONFIG = path.join(ROOT, 'metro.config.js');
|
✅ Green CI: Fix JavaScript e2e tests, disable failing Android e2e test (#28392)
Summary:
Jobs now have a `run_disabled_tests` argument that allows for the selective execution of disabled tests. When working on re-enabling a failing test, the contributor just needs to set `run_disabled_tests` to `true` in the appropriate workflow in `.circleci/config.yml`.
Tests can be kept green by moving failing tests into the disabled section until a contributor can provide a fix, thus ensuring signal is maintained on master. For example, a failing end-to-end test might be disabled in order to allow the signal from unit tests to be provided, as opposed to flat out failing the entire job.
What was done in this PR:
* The failing `test_js_e2e` job has been fixed, and merged into the `test_js` job. An empty disabled tests section is added for future use.
* The failing `test_ios_e2e` job has been merged into `test_ios`, with all of its steps gated behind the `run_disabled_steps` argument.
* The failing Android end-to-end tests have been added to `test_android`, gated behind the `run_disabled_steps` argument
* The failing Podspecs test has been added back into `test_ios`, gated behind the `run_disabled_steps` argument
## Changelog
[Internal] [CI] - ✅ Green CI, disabled test infrastructure work
Pull Request resolved: https://github.com/facebook/react-native/pull/28392
Test Plan: Verified on Circle CI
Reviewed By: cpojer
Differential Revision: D20665512
Pulled By: hramos
fbshipit-source-id: 831738027f90f4b23313893d8342d7e654f34726
2020-03-26 16:49:03 +03:00
|
|
|
const RN_GET_POLYFILLS = path.join(ROOT, 'rn-get-polyfills.js');
|
|
|
|
const RN_POLYFILLS_PATH = 'Libraries/polyfills/';
|
|
|
|
exec(`mkdir -p ${RN_POLYFILLS_PATH}`);
|
|
|
|
|
2019-06-01 02:42:18 +03:00
|
|
|
cp(METRO_CONFIG, '.');
|
✅ Green CI: Fix JavaScript e2e tests, disable failing Android e2e test (#28392)
Summary:
Jobs now have a `run_disabled_tests` argument that allows for the selective execution of disabled tests. When working on re-enabling a failing test, the contributor just needs to set `run_disabled_tests` to `true` in the appropriate workflow in `.circleci/config.yml`.
Tests can be kept green by moving failing tests into the disabled section until a contributor can provide a fix, thus ensuring signal is maintained on master. For example, a failing end-to-end test might be disabled in order to allow the signal from unit tests to be provided, as opposed to flat out failing the entire job.
What was done in this PR:
* The failing `test_js_e2e` job has been fixed, and merged into the `test_js` job. An empty disabled tests section is added for future use.
* The failing `test_ios_e2e` job has been merged into `test_ios`, with all of its steps gated behind the `run_disabled_steps` argument.
* The failing Android end-to-end tests have been added to `test_android`, gated behind the `run_disabled_steps` argument
* The failing Podspecs test has been added back into `test_ios`, gated behind the `run_disabled_steps` argument
## Changelog
[Internal] [CI] - ✅ Green CI, disabled test infrastructure work
Pull Request resolved: https://github.com/facebook/react-native/pull/28392
Test Plan: Verified on Circle CI
Reviewed By: cpojer
Differential Revision: D20665512
Pulled By: hramos
fbshipit-source-id: 831738027f90f4b23313893d8342d7e654f34726
2020-03-26 16:49:03 +03:00
|
|
|
cp(RN_GET_POLYFILLS, '.');
|
|
|
|
exec(
|
|
|
|
`rsync -a ${ROOT}/${RN_POLYFILLS_PATH} ${REACT_NATIVE_APP_DIR}/${RN_POLYFILLS_PATH}`,
|
|
|
|
);
|
2019-06-01 02:42:18 +03:00
|
|
|
mv('_flowconfig', '.flowconfig');
|
|
|
|
mv('_watchmanconfig', '.watchmanconfig');
|
2019-05-04 00:34:57 +03:00
|
|
|
|
2019-05-31 01:07:45 +03:00
|
|
|
describe('Install React Native package');
|
2019-06-01 02:42:18 +03:00
|
|
|
exec(`npm install ${REACT_NATIVE_PACKAGE}`);
|
2019-05-31 01:07:45 +03:00
|
|
|
|
|
|
|
describe('Install node_modules');
|
2019-04-10 04:43:02 +03:00
|
|
|
if (
|
|
|
|
tryExecNTimes(
|
|
|
|
() => {
|
|
|
|
return exec('npm install').code;
|
|
|
|
},
|
|
|
|
numberOfRetries,
|
|
|
|
() => exec('sleep 10s'),
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
echo('Failed to execute npm install');
|
|
|
|
echo('Most common reason is npm registry connectivity, try again');
|
|
|
|
exitCode = 1;
|
|
|
|
throw Error(exitCode);
|
|
|
|
}
|
2019-06-01 02:42:18 +03:00
|
|
|
exec('rm -rf ./node_modules/react-native/template');
|
2016-04-25 17:15:25 +03:00
|
|
|
|
2016-10-31 22:52:30 +03:00
|
|
|
if (argv.android) {
|
2019-05-31 01:07:45 +03:00
|
|
|
describe('Install end-to-end framework');
|
2018-05-11 23:32:37 +03:00
|
|
|
if (
|
|
|
|
tryExecNTimes(
|
|
|
|
() =>
|
|
|
|
exec(
|
2019-03-18 17:34:26 +03:00
|
|
|
'yarn add --dev appium@1.11.1 mocha@2.4.5 wd@1.11.1 colors@1.0.3 pretty-data2@0.40.1',
|
2018-05-11 23:32:37 +03:00
|
|
|
{silent: true},
|
|
|
|
).code,
|
|
|
|
numberOfRetries,
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
echo('Failed to install appium');
|
|
|
|
echo('Most common reason is npm registry connectivity, try again');
|
|
|
|
exitCode = 1;
|
|
|
|
throw Error(exitCode);
|
2016-04-25 17:15:25 +03:00
|
|
|
}
|
|
|
|
cp(`${SCRIPTS}/android-e2e-test.js`, 'android-e2e-test.js');
|
|
|
|
cd('android');
|
2019-05-31 01:07:45 +03:00
|
|
|
describe('Download Maven deps');
|
2016-04-25 17:15:25 +03:00
|
|
|
exec('./gradlew :app:copyDownloadableDepsToLibs');
|
|
|
|
cd('..');
|
2019-03-18 17:34:26 +03:00
|
|
|
|
2019-05-31 01:07:45 +03:00
|
|
|
describe('Generate key');
|
2019-03-18 17:34:26 +03:00
|
|
|
exec('rm android/app/debug.keystore');
|
|
|
|
if (
|
|
|
|
exec(
|
|
|
|
'keytool -genkey -v -keystore android/app/debug.keystore -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000 -dname "CN=Android Debug,O=Android,C=US"',
|
|
|
|
).code
|
|
|
|
) {
|
|
|
|
echo('Key could not be generated');
|
|
|
|
exitCode = 1;
|
|
|
|
throw Error(exitCode);
|
|
|
|
}
|
2016-04-25 17:15:25 +03:00
|
|
|
|
2019-05-31 01:07:45 +03:00
|
|
|
describe(`Start appium server, ${APPIUM_PID}`);
|
2016-04-25 17:15:25 +03:00
|
|
|
const appiumProcess = spawn('node', ['./node_modules/.bin/appium']);
|
|
|
|
APPIUM_PID = appiumProcess.pid;
|
2017-03-15 17:43:20 +03:00
|
|
|
|
2019-05-31 01:07:45 +03:00
|
|
|
describe('Build the app');
|
2019-06-01 02:42:18 +03:00
|
|
|
if (exec('react-native run-android').code) {
|
2019-03-18 17:34:26 +03:00
|
|
|
echo('could not execute react-native run-android');
|
2016-04-25 17:15:25 +03:00
|
|
|
exitCode = 1;
|
|
|
|
throw Error(exitCode);
|
|
|
|
}
|
2017-03-15 17:43:20 +03:00
|
|
|
|
2019-05-31 01:07:45 +03:00
|
|
|
describe(`Start packager server, ${SERVER_PID}`);
|
2016-04-25 17:15:25 +03:00
|
|
|
// shelljs exec('', {async: true}) does not emit stdout events, so we rely on good old spawn
|
2018-02-06 23:36:07 +03:00
|
|
|
const packagerProcess = spawn('yarn', ['start', '--max-workers 1'], {
|
2018-05-11 23:32:37 +03:00
|
|
|
env: process.env,
|
2016-04-25 17:15:25 +03:00
|
|
|
});
|
|
|
|
SERVER_PID = packagerProcess.pid;
|
|
|
|
// wait a bit to allow packager to startup
|
2016-06-25 02:54:52 +03:00
|
|
|
exec('sleep 15s');
|
2019-04-10 04:43:02 +03:00
|
|
|
describe('Test: Android end-to-end test');
|
2018-05-11 23:32:37 +03:00
|
|
|
if (
|
2019-04-10 04:43:02 +03:00
|
|
|
tryExecNTimes(
|
|
|
|
() => {
|
|
|
|
return exec('node node_modules/.bin/_mocha android-e2e-test.js').code;
|
|
|
|
},
|
|
|
|
numberOfRetries,
|
|
|
|
() => exec('sleep 10s'),
|
|
|
|
)
|
2018-05-11 23:32:37 +03:00
|
|
|
) {
|
2018-06-11 02:53:22 +03:00
|
|
|
echo('Failed to run Android end-to-end tests');
|
2018-05-11 23:32:37 +03:00
|
|
|
echo('Most likely the code is broken');
|
|
|
|
exitCode = 1;
|
|
|
|
throw Error(exitCode);
|
2016-04-25 17:15:25 +03:00
|
|
|
}
|
2016-04-13 18:18:49 +03:00
|
|
|
}
|
2016-04-25 17:15:25 +03:00
|
|
|
|
2020-04-27 07:35:47 +03:00
|
|
|
if (argv.ios) {
|
2016-04-25 17:15:25 +03:00
|
|
|
cd('ios');
|
|
|
|
// shelljs exec('', {async: true}) does not emit stdout events, so we rely on good old spawn
|
2016-10-31 22:52:30 +03:00
|
|
|
const packagerEnv = Object.create(process.env);
|
2016-04-25 17:15:25 +03:00
|
|
|
packagerEnv.REACT_NATIVE_MAX_WORKERS = 1;
|
2019-05-31 01:07:45 +03:00
|
|
|
describe('Start packager server');
|
2019-05-04 00:34:57 +03:00
|
|
|
const packagerProcess = spawn('yarn', ['start'], {
|
2018-05-11 23:32:37 +03:00
|
|
|
stdio: 'inherit',
|
|
|
|
env: packagerEnv,
|
|
|
|
});
|
2016-04-25 17:15:25 +03:00
|
|
|
SERVER_PID = packagerProcess.pid;
|
|
|
|
exec('sleep 15s');
|
2020-04-27 07:35:47 +03:00
|
|
|
// prepare cache to reduce chances of possible red screen "Can't find variable __fbBatchedBridge..."
|
2018-05-11 23:32:37 +03:00
|
|
|
exec(
|
|
|
|
'response=$(curl --write-out %{http_code} --silent --output /dev/null localhost:8081/index.bundle?platform=ios&dev=true)',
|
|
|
|
);
|
2019-05-31 01:07:45 +03:00
|
|
|
echo(`Packager server up and running, ${SERVER_PID}`);
|
|
|
|
|
|
|
|
describe('Install CocoaPod dependencies');
|
2019-03-22 13:26:05 +03:00
|
|
|
exec('pod install');
|
2019-05-31 01:07:45 +03:00
|
|
|
|
2020-04-27 07:35:47 +03:00
|
|
|
describe('Test: iOS end-to-end test');
|
2018-05-11 23:32:37 +03:00
|
|
|
if (
|
2020-01-15 00:27:53 +03:00
|
|
|
// TODO: Get target OS and simulator from .tests.env
|
2019-04-10 04:43:02 +03:00
|
|
|
tryExecNTimes(
|
|
|
|
() => {
|
|
|
|
return exec(
|
2018-06-11 02:53:22 +03:00
|
|
|
[
|
2019-04-10 04:43:02 +03:00
|
|
|
'xcodebuild',
|
|
|
|
'-workspace',
|
2019-06-01 02:42:18 +03:00
|
|
|
'"HelloWorld.xcworkspace"',
|
2019-04-10 04:43:02 +03:00
|
|
|
'-destination',
|
2020-04-27 07:35:47 +03:00
|
|
|
'"platform=iOS Simulator,name=iPhone 8,OS=13.3"',
|
2019-04-10 04:43:02 +03:00
|
|
|
'-scheme',
|
2020-04-27 07:35:47 +03:00
|
|
|
'"HelloWorld"',
|
2019-04-10 04:43:02 +03:00
|
|
|
'-sdk',
|
2020-04-27 07:35:47 +03:00
|
|
|
'iphonesimulator',
|
2019-04-10 04:43:02 +03:00
|
|
|
'-UseModernBuildSystem=NO',
|
|
|
|
'test',
|
2018-06-11 02:53:22 +03:00
|
|
|
].join(' ') +
|
2019-04-10 04:43:02 +03:00
|
|
|
' | ' +
|
|
|
|
[
|
|
|
|
'xcpretty',
|
|
|
|
'--report',
|
|
|
|
'junit',
|
|
|
|
'--output',
|
2020-04-27 07:35:47 +03:00
|
|
|
'"~/react-native/reports/junit/iOS-e2e/results.xml"',
|
2019-04-10 04:43:02 +03:00
|
|
|
].join(' ') +
|
|
|
|
' && exit ${PIPESTATUS[0]}',
|
|
|
|
).code;
|
|
|
|
},
|
|
|
|
numberOfRetries,
|
|
|
|
() => exec('sleep 10s'),
|
|
|
|
)
|
2018-05-11 23:32:37 +03:00
|
|
|
) {
|
2020-04-27 07:35:47 +03:00
|
|
|
echo('Failed to run iOS end-to-end tests');
|
2018-05-11 23:32:37 +03:00
|
|
|
echo('Most likely the code is broken');
|
|
|
|
exitCode = 1;
|
|
|
|
throw Error(exitCode);
|
2016-04-25 17:15:25 +03:00
|
|
|
}
|
|
|
|
cd('..');
|
2016-04-13 18:18:49 +03:00
|
|
|
}
|
2016-04-25 17:15:25 +03:00
|
|
|
|
2016-10-31 22:52:30 +03:00
|
|
|
if (argv.js) {
|
2016-04-25 17:15:25 +03:00
|
|
|
// Check the packager produces a bundle (doesn't throw an error)
|
2019-04-10 04:43:02 +03:00
|
|
|
describe('Test: Verify packager can generate an Android bundle');
|
2018-05-11 23:32:37 +03:00
|
|
|
if (
|
|
|
|
exec(
|
✅ Green CI: Fix JavaScript e2e tests, disable failing Android e2e test (#28392)
Summary:
Jobs now have a `run_disabled_tests` argument that allows for the selective execution of disabled tests. When working on re-enabling a failing test, the contributor just needs to set `run_disabled_tests` to `true` in the appropriate workflow in `.circleci/config.yml`.
Tests can be kept green by moving failing tests into the disabled section until a contributor can provide a fix, thus ensuring signal is maintained on master. For example, a failing end-to-end test might be disabled in order to allow the signal from unit tests to be provided, as opposed to flat out failing the entire job.
What was done in this PR:
* The failing `test_js_e2e` job has been fixed, and merged into the `test_js` job. An empty disabled tests section is added for future use.
* The failing `test_ios_e2e` job has been merged into `test_ios`, with all of its steps gated behind the `run_disabled_steps` argument.
* The failing Android end-to-end tests have been added to `test_android`, gated behind the `run_disabled_steps` argument
* The failing Podspecs test has been added back into `test_ios`, gated behind the `run_disabled_steps` argument
## Changelog
[Internal] [CI] - ✅ Green CI, disabled test infrastructure work
Pull Request resolved: https://github.com/facebook/react-native/pull/28392
Test Plan: Verified on Circle CI
Reviewed By: cpojer
Differential Revision: D20665512
Pulled By: hramos
fbshipit-source-id: 831738027f90f4b23313893d8342d7e654f34726
2020-03-26 16:49:03 +03:00
|
|
|
'yarn react-native bundle --verbose --entry-file index.js --platform android --dev true --bundle-output android-bundle.js --max-workers 1',
|
2018-05-11 23:32:37 +03:00
|
|
|
).code
|
|
|
|
) {
|
2016-11-19 05:25:02 +03:00
|
|
|
echo('Could not build Android bundle');
|
2016-04-25 17:15:25 +03:00
|
|
|
exitCode = 1;
|
|
|
|
throw Error(exitCode);
|
|
|
|
}
|
2019-04-10 04:43:02 +03:00
|
|
|
describe('Test: Verify packager can generate an iOS bundle');
|
2018-05-11 23:32:37 +03:00
|
|
|
if (
|
|
|
|
exec(
|
2019-06-01 02:42:18 +03:00
|
|
|
'yarn react-native bundle --entry-file index.js --platform ios --dev true --bundle-output ios-bundle.js --max-workers 1',
|
2018-05-11 23:32:37 +03:00
|
|
|
).code
|
|
|
|
) {
|
2016-11-19 05:25:02 +03:00
|
|
|
echo('Could not build iOS bundle');
|
2016-04-25 17:15:25 +03:00
|
|
|
exitCode = 1;
|
|
|
|
throw Error(exitCode);
|
|
|
|
}
|
2019-04-10 04:43:02 +03:00
|
|
|
describe('Test: Flow check');
|
2019-06-01 02:42:18 +03:00
|
|
|
if (exec(`${ROOT}/node_modules/.bin/flow check`).code) {
|
2019-04-10 04:43:02 +03:00
|
|
|
echo('Flow check failed.');
|
|
|
|
exitCode = 1;
|
|
|
|
throw Error(exitCode);
|
|
|
|
}
|
2016-04-13 18:18:49 +03:00
|
|
|
}
|
2016-04-25 17:15:25 +03:00
|
|
|
exitCode = 0;
|
|
|
|
} finally {
|
2019-05-31 01:07:45 +03:00
|
|
|
describe('Clean up');
|
2016-04-25 17:15:25 +03:00
|
|
|
if (SERVER_PID) {
|
|
|
|
echo(`Killing packager ${SERVER_PID}`);
|
|
|
|
exec(`kill -9 ${SERVER_PID}`);
|
|
|
|
// this is quite drastic but packager starts a daemon that we can't kill by killing the parent process
|
|
|
|
// it will be fixed in April (quote David Aurelio), so until then we will kill the zombie by the port number
|
|
|
|
exec("lsof -i tcp:8081 | awk 'NR!=1 {print $2}' | xargs kill");
|
2016-04-13 18:18:49 +03:00
|
|
|
}
|
2016-04-25 17:15:25 +03:00
|
|
|
if (APPIUM_PID) {
|
|
|
|
echo(`Killing appium ${APPIUM_PID}`);
|
|
|
|
exec(`kill -9 ${APPIUM_PID}`);
|
2016-04-13 18:18:49 +03:00
|
|
|
}
|
|
|
|
}
|
2016-04-25 17:15:25 +03:00
|
|
|
exit(exitCode);
|
2016-04-13 18:18:49 +03:00
|
|
|
|
|
|
|
/*eslint-enable no-undef */
|