react-native-macos/scripts/test-e2e-local.js

206 строки
6.0 KiB
JavaScript
Исходник Обычный вид История

infra(e2e): rework local E2E script (#34513) Summary: This is a long time coming effort to improve the situation around the local e2e script that in the release crew: the current bash-based script is quirky at best, and what you end up generating as a sample project is not really a true sample project. This is where this PR comes in: it migrates the flow from `./scripts/test-manual-e2e.sh` to `yarn test-e2e-local <options>`. Here's the current shape of the options: ```sh Options: --help Show help [boolean] --version Show version number [boolean] -t, --target [choices: "RNTester", "RNTestProject"] [default: "RNTester"] -p, --platform [choices: "iOS", "Android"] [default: "iOS"] -h, --hermes [boolean] [default: true] ``` The idea is to change it so that you can just run the script, and it will do that one specific thing "well", without the tester needing to do anything aside from actually testing the app once it's open. Some of the key changes: * tries to stick to the patterns of the other established *.js based scripts, in terms of tooling and approach (and even refactor parts that can be shared with other scripts) - like the android artifacts generation * no need to start the android emulator on the side * no need to start Metro on the side * RNTester iOS will open up on the simulator (no Xcode open that then you need to press) Things that still need work: * see the #fixme and #todo in comments * because we rely on exec, the output sent back is not formatted/shaped correctly so it's a bit more noisy/chaotic - but can't handle it right now because the package we use doesn't allow it - see https://github.com/shelljs/shelljs/issues/86 ## Changelog <!-- Help reviewers and the release process by writing your own changelog entry. For an example, see: https://reactnative.dev/contributing/changelogs-in-pull-requests --> [Internal] [Changed] - Migrate bash E2E local testing script to new JS based command Pull Request resolved: https://github.com/facebook/react-native/pull/34513 Test Plan: To test the script, you can run it passing the options showed above; this is the current situation: * RNTester iOS Hermes ✅ * RNTester Android Hermes ✅ * RNTester iOS JSC ✅ * RNTester Android JSC ✅ * RNTestProject Android Hermes ✅ * RNTestProject iOS Hermes ✅ * RNTestProject Android JSC ✅ * RNTestProject iOS JSC ✅ Reviewed By: cortinico Differential Revision: D39814692 Pulled By: cortinico fbshipit-source-id: d4791798aaad764c6a3757269b7636f847ccf2ca
2022-10-04 14:56:44 +03:00
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
'use strict';
/*
* This script is a re-interpretation of the old test-manual.e2e.sh script.
* the idea is to provide a better DX for the manual testing.
* It's using Javascript over Bash for consistency with the rest of the recent scripts
* and to make it more accessible for other devs to play around with.
*/
const {exec, exit, pushd, popd, pwd, cd} = require('shelljs');
const yargs = require('yargs');
const fs = require('fs');
const path = require('path');
const os = require('os');
const {
launchAndroidEmulator,
isPackagerRunning,
launchPackagerInSeparateWindow,
} = require('./testing-utils');
const {
generateAndroidArtifacts,
saveFilesToRestore,
} = require('./release-utils');
const argv = yargs
.option('t', {
alias: 'target',
default: 'RNTester',
choices: ['RNTester', 'RNTestProject'],
})
.option('p', {
alias: 'platform',
default: 'iOS',
choices: ['iOS', 'Android'],
})
.option('h', {
alias: 'hermes',
type: 'boolean',
default: true,
}).argv;
/*
* see the test-local-e2e.js script for clean up process
*/
// command order: we ask the user to select if they want to test RN tester
// or RNTestProject
// if they select RN tester, we ask if iOS or Android, and then we run the tests
// if they select RNTestProject, we run the RNTestProject test
// let's check if Metro is already running, if it is let's kill it and start fresh
if (isPackagerRunning() === 'running') {
exec("lsof -i :8081 | grep LISTEN | /usr/bin/awk '{print $2}' | xargs kill");
}
if (argv.target === 'RNTester') {
// FIXME: make sure that the commands retains colors
// (--ansi) doesn't always work
// see also https://github.com/shelljs/shelljs/issues/86
if (argv.platform === 'iOS') {
console.info(
`We're going to test the ${
argv.hermes ? 'Hermes' : 'JSC'
} version of RNTester iOS`,
);
exec(
`cd packages/rn-tester && USE_HERMES=${
argv.hermes ? 1 : 0
} bundle exec pod install --ansi`,
);
// if everything succeeded so far, we can launch Metro and the app
// start the Metro server in a separate window
launchPackagerInSeparateWindow();
// launch the app on iOS simulator
pushd('packages/rn-tester');
exec('npx react-native run-ios --scheme RNTester');
popd();
} else {
// we do the android path here
launchAndroidEmulator();
console.info(
`We're going to test the ${
argv.hermes ? 'Hermes' : 'JSC'
} version of RNTester Android`,
);
exec(
`./gradlew :packages:rn-tester:android:app:${
argv.hermes ? 'installHermesDebug' : 'installJscDebug'
} --quiet`,
);
// launch the app on Android simulator
// TODO: we should find a way to make it work like for iOS, via npx react-native run-android
// currently, that fails with an error.
// if everything succeeded so far, we can launch Metro and the app
// start the Metro server in a separate window
launchPackagerInSeparateWindow();
// just to make sure that the Android up won't have troubles finding the Metro server
exec('adb reverse tcp:8081 tcp:8081');
// launch the app
exec(
'adb shell am start -n com.facebook.react.uiapp/com.facebook.react.uiapp.RNTesterActivity',
);
}
} else {
console.info("We're going to test a fresh new RN project");
// create the local npm package to feed the CLI
// base setup required (specular to publish-npm.js)
const tmpPublishingFolder = fs.mkdtempSync(
path.join(os.tmpdir(), 'rn-publish-'),
);
console.info(`The temp publishing folder is ${tmpPublishingFolder}`);
saveFilesToRestore(tmpPublishingFolder);
// we need to add the unique timestamp to avoid npm/yarn to use some local caches
const baseVersion = require('../package.json').version;
const dateIdentifier = new Date()
.toISOString()
.slice(0, -8)
.replace(/[-:]/g, '')
.replace(/[T]/g, '-');
const releaseVersion = `${baseVersion}-${dateIdentifier}`;
// this is needed to generate the Android artifacts correctly
exec(`node scripts/set-rn-version.js --to-version ${releaseVersion}`).code;
// Generate native files (Android only for now)
generateAndroidArtifacts(releaseVersion, tmpPublishingFolder);
// create locally the node module
exec('npm pack');
const localNodeTGZPath = `${pwd()}/react-native-${releaseVersion}.tgz`;
exec(`node scripts/set-rn-template-version.js "file:${localNodeTGZPath}"`);
const repoRoot = pwd();
pushd('/tmp/');
// need to avoid the pod install step because it will fail! (see above)
exec(
`node ${repoRoot}/cli.js init RNTestProject --template ${repoRoot} --skip-install`,
);
cd('RNTestProject');
exec('yarn install');
if (argv.platform === 'iOS') {
// if we want iOS, we need to do pod install - but with a trick
cd('ios');
exec('bundle install');
// TODO: we should be able to also use HERMES_ENGINE_TARBALL_PATH
// if we can make RNTester step generate it already so that it gets reused
// need to discern if it's main branch or release branch
if (baseVersion === '1000.0.0') {
// main branch
exec(`USE_HERMES=${argv.hermes ? 1 : 0} bundle exec pod install --ansi`);
} else {
// TODO: to test this, I need to apply changes on top of a release branch
// a release branch
// copy over the .hermesversion file from react-native core into the RNTestProject
exec(`cp -f ${repoRoot}/sdks/.hermesversion .`);
exec(
`CI=true USE_HERMES=${
argv.hermes ? 1 : 0
} bundle exec pod install --ansi`,
);
}
cd('..');
exec('yarn ios');
} else {
// android
exec('yarn android');
}
popd();
// just cleaning up the temp folder, the rest is done by the test clean script
exec(`rm -rf ${tmpPublishingFolder}`);
}
exit(0);