Skip to content

Commit 495ff4a

Browse files
committed
feat: find project root in mono repositories
1 parent 3c66faf commit 495ff4a

11 files changed

+270
-91
lines changed

README.md

+9-9
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,15 @@ Usage
4444
Default glob: **/test?(s)/**/?(*.)+(spec|test).js.
4545
4646
Options
47-
--plaform, -p Platform on which to run the test suite on. One of: 'ios', 'android'.
48-
--simulator, -s iOS simulator to run the test suite on.
49-
--emulator, -e Android emulator or virtual device (AVD) to run the test suite on.
50-
--metroPort, -p Port on which Metro's server should listen to. [Default: 8081]
51-
--cwd Current directory. [Default: process.cwd()]
52-
--rn React Native version to use. [Default: 0.63.4]
53-
--runner Test runner to use. One of: 'zora', 'mocha'. [Default: 'zora']
54-
--require Path to the module to load before the test suite. If not absolute, cwd is used to resolve the path.
55-
--removeTestApp Removes the test app directory after running the test suite. [Default: false]
47+
--plaform, -p Platform on which to run the test suite on. One of: 'ios', 'android'.
48+
--simulator, -s iOS simulator to run the test suite on.
49+
--emulator, -e Android emulator or virtual device (AVD) to run the test suite on.
50+
--metroPort, -p Port on which Metro's server should listen to. [Default: 8081]
51+
--cwd Current directory. [Default: process.cwd()]
52+
--rn React Native version to use. [Default: 0.63.4]
53+
--runner Test runner to use. One of: 'zora', 'mocha'. [Default: 'zora']
54+
--require Path to the module to load before the test suite. If not absolute, cwd is used to resolve the path.
55+
--removeNativeTestApp Removes the natuve test app directory after running the test suite. [Default: false]
5656
5757
Examples
5858
# Run tests on iPhone 11 simulator with iOS version 14.1 runtime

cli/create-test-app.js renamed to cli/create-native-test-app.js

+15-15
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,16 @@ const applyPatches = async (cwd, loader, appPath, patches) => {
4545
module.exports = async ({
4646
cwd,
4747
rn: reactNativeVersion = '0.63.4',
48-
testAppPath = path.join(os.homedir(), '.npm', 'rn-test-app'),
48+
nativeTestAppRoot = path.join(os.homedir(), '.npm', 'rn-test-app'),
4949
nativeModules = [],
5050
patches = [],
5151
} = {}) => {
5252
const loader = ora();
5353

54-
const removeTestApp = async () => {
55-
loader.start(`Removing test app at ${testAppPath}`);
54+
const removeNativeTestApp = async () => {
55+
loader.start(`Removing test app at ${nativeTestAppRoot}`);
5656
try {
57-
await rmdir(testAppPath, { recursive: true });
57+
await rmdir(nativeTestAppRoot, { recursive: true });
5858
loader.succeed();
5959
} catch (error) {
6060
loader.fail();
@@ -65,23 +65,23 @@ module.exports = async ({
6565
let appPkg = null;
6666

6767
try {
68-
appPkg = await readPkg({ cwd: testAppPath });
68+
appPkg = await readPkg({ cwd: nativeTestAppRoot });
6969
} catch (error) {
7070
// Test app not installed
7171
}
7272

7373
if (appPkg && semver.neq(reactNativeVersion, appPkg.dependencies['react-native'])) {
74-
await removeTestApp();
74+
await removeNativeTestApp();
7575
appPkg = null;
7676
}
7777

7878
if (appPkg) {
7979
const modulesToInstall = getNativeModulesToInstall(appPkg, nativeModules);
8080

81-
await installNativeModules(loader, testAppPath, modulesToInstall);
82-
await applyPatches(cwd, loader, testAppPath, patches);
81+
await installNativeModules(loader, nativeTestAppRoot, modulesToInstall);
82+
await applyPatches(cwd, loader, nativeTestAppRoot, patches);
8383

84-
return { testAppPath, removeTestApp };
84+
return { nativeTestAppRoot, removeNativeTestApp };
8585
}
8686

8787
try {
@@ -94,22 +94,22 @@ module.exports = async ({
9494
await execa('npm', ['install', `react-native@${reactNativeVersion}`], { cwd: reactNativeCliPkgPath });
9595
loader.succeed();
9696

97-
loader.start(`Initializing test app with React Native ${reactNativeVersion} at ${testAppPath}`);
97+
loader.start(`Initializing test app with React Native ${reactNativeVersion} at ${nativeTestAppRoot}`);
9898
await execa('npx', [
99-
'react-native', 'init', 'Test', '--npm', '--version', reactNativeVersion, '--directory', testAppPath, '--title', 'Test',
99+
'react-native', 'init', 'Test', '--npm', '--version', reactNativeVersion, '--directory', nativeTestAppRoot, '--title', 'Test',
100100
], { cwd: reactNativeCliPkgPath });
101101
loader.succeed();
102102

103-
await installNativeModules(loader, testAppPath, nativeModules);
104-
await applyPatches(cwd, loader, testAppPath, patches);
103+
await installNativeModules(loader, nativeTestAppRoot, nativeModules);
104+
await applyPatches(cwd, loader, nativeTestAppRoot, patches);
105105
});
106106
} catch (error) {
107107
loader.fail();
108108

109-
await removeTestApp();
109+
await removeNativeTestApp();
110110

111111
throw error;
112112
}
113113

114-
return { testAppPath, removeTestApp };
114+
return { nativeTestAppRoot, removeNativeTestApp };
115115
};

cli/index.js

+16-16
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const { lilconfigSync: loadConfigFile } = require('lilconfig');
99
const runIOS = require('./run-ios');
1010
const runAndroid = require('./run-android');
1111
const runMetroServer = require('./metro-server');
12-
const createTestApp = require('./create-test-app');
12+
const createNativeTestApp = require('./create-native-test-app');
1313
const createTestRunner = require('./test-runners');
1414

1515
const fileConfigExplorer = loadConfigFile('rn-test', { stopDir: process.cwd() });
@@ -22,15 +22,15 @@ Usage
2222
Default glob: **/test?(s)/**/?(*.)+(spec|test).js.
2323
2424
Options
25-
--plaform, -p Platform on which to run the test suite on. One of: 'ios', 'android'.
26-
--simulator, -s iOS simulator to run the test suite on.
27-
--emulator, -e Android emulator or virtual device (AVD) to run the test suite on.
28-
--metroPort, -p Port on which Metro's server should listen to. [Default: 8081]
29-
--cwd Current directory. [Default: process.cwd()]
30-
--rn React Native version to use. [Default: 0.63.4]
31-
--runner Test runner to use. One of: 'zora', 'mocha'. [Default: 'zora']
32-
--require Path to the module to load before the test suite. If not absolute, cwd is used to resolve the path.
33-
--removeTestApp Removes the test app directory after running the test suite. [Default: false]
25+
--plaform, -p Platform on which to run the test suite on. One of: 'ios', 'android'.
26+
--simulator, -s iOS simulator to run the test suite on.
27+
--emulator, -e Android emulator or virtual device (AVD) to run the test suite on.
28+
--metroPort, -p Port on which Metro's server should listen to. [Default: 8081]
29+
--cwd Current directory. [Default: process.cwd()]
30+
--rn React Native version to use. [Default: 0.63.4]
31+
--runner Test runner to use. One of: 'zora', 'mocha'. [Default: 'zora']
32+
--require Path to the module to load before the test suite. If not absolute, cwd is used to resolve the path.
33+
--removeNativeTestApp Removes the natuve test app directory after running the test suite. [Default: false]
3434
3535
Examples
3636
# Run tests on iPhone 11 simulator with iOS version 14.1 runtime
@@ -122,10 +122,10 @@ if (!semver.valid(options.rn)) {
122122
process.exit(2);
123123
}
124124

125-
const runNativePlatform = (options) => {
125+
const runNativeTestApp = (options) => {
126126
options = {
127-
projectPath: path.join(options.testAppPath, options.platform),
128127
...options,
128+
nativeTestAppRoot: path.join(options.nativeTestAppRoot, options.platform),
129129
};
130130

131131
switch (options.platform) {
@@ -141,21 +141,21 @@ const runNativePlatform = (options) => {
141141
const runTests = async (options, testFileGlobs) => {
142142
try {
143143
const testRunner = createTestRunner(options, testFileGlobs);
144-
const { testAppPath, removeTestApp } = await createTestApp(options);
144+
const { nativeTestAppRoot, removeNativeTestApp } = await createNativeTestApp(options);
145145

146146
await runMetroServer({
147147
cwd: options.cwd,
148148
port: options.metroPort,
149-
testAppPath,
149+
nativeTestAppRoot,
150150
testRunner,
151151
});
152152

153-
const shutdownNativePlatform = await runNativePlatform({ ...options, testAppPath });
153+
const shutdownNativePlatform = await runNativeTestApp({ ...options, nativeTestAppRoot });
154154

155155
await testRunner.reporter.waitForTests();
156156
await shutdownNativePlatform();
157157

158-
options.removeTestApp && await removeTestApp();
158+
options.removeNativeTestApp && await removeNativeTestApp();
159159

160160
process.exit(testRunner.reporter.didPass() ? 0 : 1);
161161
} catch (error) {

cli/metro-server.js

+14-10
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const path = require('path');
1111
const { promisify } = require('util');
1212
const ora = require('ora');
1313
const isCI = require('is-ci');
14+
const { findMonoRepoRoot } = require('./utils');
1415

1516
const INTERNAL_CALLSITES_REGEX = new RegExp(
1617
[
@@ -25,8 +26,8 @@ const INTERNAL_CALLSITES_REGEX = new RegExp(
2526
].join('|'),
2627
);
2728

28-
const getTestAppDependencies = (testAppPath) => {
29-
const testAppModulesPath = path.join(testAppPath, 'node_modules');
29+
const getTestAppDependencies = (nativeTestAppRoot) => {
30+
const testAppModulesPath = path.join(nativeTestAppRoot, 'node_modules');
3031
const reactNativePath = path.join(testAppModulesPath, 'react-native');
3132

3233
return {
@@ -70,7 +71,8 @@ const createResolveModule = (testRunner, testAppModulesPath) => (context, module
7071
};
7172

7273
const getMetroConfig = ({
73-
testAppPath,
74+
cwd,
75+
nativeTestAppRoot,
7476
port,
7577
testRunner,
7678
}) => {
@@ -86,8 +88,9 @@ const getMetroConfig = ({
8688
minifierPath,
8789
assetRegistryPath,
8890
},
89-
} = getTestAppDependencies(testAppPath);
90-
const projectRoot = path.join(__dirname, '..');
91+
} = getTestAppDependencies(nativeTestAppRoot);
92+
const jsAppRoot = path.join(__dirname, '..');
93+
const monoRepoRoot = findMonoRepoRoot(cwd);
9194

9295
const resolveModule = createResolveModule(testRunner, testAppModulesPath);
9396
const testRunnerConfigFilePath = testRunner.writeConfigFile();
@@ -147,11 +150,12 @@ const getMetroConfig = ({
147150
},
148151
}),
149152
},
150-
projectRoot,
153+
projectRoot: jsAppRoot,
151154
watchFolders: [
152-
process.cwd(),
153-
testAppPath,
154-
projectRoot,
155+
cwd,
156+
monoRepoRoot,
157+
jsAppRoot,
158+
nativeTestAppRoot,
155159
path.dirname(testSuiteFilePath),
156160
path.dirname(testRunnerConfigFilePath),
157161
...testDirectoryPaths,
@@ -170,7 +174,7 @@ const runServer = async (options) => {
170174
reactNativeModules: {
171175
cliServerApi: { createDevServerMiddleware },
172176
},
173-
} = getTestAppDependencies(options.testAppPath);
177+
} = getTestAppDependencies(options.nativeTestAppRoot);
174178

175179
const defaultConfig = await getDefaultConfig();
176180
const config = mergeConfig(defaultConfig, getMetroConfig(options));

cli/run-android.js

+9-9
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,15 @@ const uninstallApp = async ({ packageName }) => {
9696
}
9797
};
9898

99-
const buildApk = async ({ projectPath, metroPort }) => {
99+
const buildApk = async ({ nativeTestAppRoot, metroPort }) => {
100100
const gradle = process.platform === 'win32' ? 'gradlew.bat' : './gradlew';
101101
const buildProcess = execa(
102102
`${gradle}`,
103103
// -PreactNativeDevServerPort works great!
104104
// https://github.com/facebook/react-native/pull/23616
105105
// https://github.com/react-native-community/cli/pull/421/files
106106
['assembleDebug', `-PreactNativeDevServerPort=${metroPort}`],
107-
{ cwd: projectPath },
107+
{ cwd: nativeTestAppRoot },
108108
);
109109
const loader = ora();
110110

@@ -261,9 +261,9 @@ const bootHeadlessEmulator = async ({ emulator }) => {
261261
]);
262262
};
263263

264-
const getProjectSettings = ({ projectPath }) => {
264+
const getProjectSettings = ({ nativeTestAppRoot }) => {
265265
const manifestPath = path.join(
266-
projectPath,
266+
nativeTestAppRoot,
267267
'app',
268268
'src',
269269
'main',
@@ -275,7 +275,7 @@ const getProjectSettings = ({ projectPath }) => {
275275
const [, packageName] = packageNameMatchResult;
276276

277277
const buildDirectory = path.join(
278-
projectPath,
278+
nativeTestAppRoot,
279279
'app',
280280
'build',
281281
'outputs',
@@ -284,7 +284,7 @@ const getProjectSettings = ({ projectPath }) => {
284284
);
285285

286286
const stringsPath = path.join(
287-
projectPath,
287+
nativeTestAppRoot,
288288
'app',
289289
'src',
290290
'main',
@@ -308,16 +308,16 @@ const getProjectSettings = ({ projectPath }) => {
308308
};
309309
};
310310

311-
module.exports = async ({ emulator, projectPath, metroPort }) => {
311+
module.exports = async ({ emulator, nativeTestAppRoot, metroPort }) => {
312312
const { apkFilePath, mainActivity, packageName } = getProjectSettings({
313-
projectPath,
313+
nativeTestAppRoot,
314314
});
315315
const {
316316
emulatorId,
317317
shutdown: shutdownEmulator,
318318
} = await bootHeadlessEmulator({ emulator });
319319

320-
await buildApk({ projectPath, metroPort });
320+
await buildApk({ nativeTestAppRoot, metroPort });
321321
await installApp({ emulatorId, apkFilePath });
322322
await launchApp({ mainActivity, packageName });
323323

cli/run-ios.js

+10-10
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ const findSimulatorByName = (querySimulatorName) => {
110110
};
111111
};
112112

113-
const getProjectSettings = ({ projectPath }) => {
113+
const getProjectSettings = ({ nativeTestAppRoot }) => {
114114
const xcodebuildArgs = [
115115
'-workspace',
116116
'Test.xcworkspace',
@@ -125,7 +125,7 @@ const getProjectSettings = ({ projectPath }) => {
125125
];
126126

127127
const { stdout } = execa.sync('xcodebuild', xcodebuildArgs, {
128-
cwd: projectPath,
128+
cwd: nativeTestAppRoot,
129129
});
130130
const projectSettings = JSON.parse(stdout);
131131

@@ -147,7 +147,7 @@ const getProjectSettings = ({ projectPath }) => {
147147
}
148148
};
149149

150-
const buildApp = async ({ projectPath, simulator, metroPort }) => {
150+
const buildApp = async ({ nativeTestAppRoot, simulator, metroPort }) => {
151151
const xcodebuildArgs = [
152152
'-workspace',
153153
'Test.xcworkspace',
@@ -163,7 +163,7 @@ const buildApp = async ({ projectPath, simulator, metroPort }) => {
163163
const loader = ora();
164164

165165
const buildProcess = execa('xcodebuild', xcodebuildArgs, {
166-
cwd: projectPath,
166+
cwd: nativeTestAppRoot,
167167
env: {
168168
...process.env,
169169
RCT_NO_LAUNCH_PACKAGER: true,
@@ -296,10 +296,10 @@ const terminateApp = async ({ simulator, bundleId }) => {
296296
}
297297
};
298298

299-
const runPodInstall = async ({ projectPath }) => {
299+
const runPodInstall = async ({ nativeTestAppRoot }) => {
300300
const loader = ora();
301301
const process = execa('pod', ['install'], {
302-
cwd: projectPath,
302+
cwd: nativeTestAppRoot,
303303
});
304304

305305
loader.start('Installing Pods');
@@ -315,7 +315,7 @@ const runPodInstall = async ({ projectPath }) => {
315315

316316
module.exports = async ({
317317
simulator: inputSimulator,
318-
projectPath,
318+
nativeTestAppRoot,
319319
metroPort,
320320
}) => {
321321
if (isUUID.v4(inputSimulator)) {
@@ -340,10 +340,10 @@ module.exports = async ({
340340
await bootHeadlessSimulator(simulator);
341341
}
342342

343-
await runPodInstall({ projectPath });
344-
await buildApp({ projectPath, simulator, metroPort });
343+
await runPodInstall({ nativeTestAppRoot });
344+
await buildApp({ nativeTestAppRoot, simulator, metroPort });
345345

346-
const { binaryFilePath, bundleId } = getProjectSettings({ projectPath });
346+
const { binaryFilePath, bundleId } = getProjectSettings({ nativeTestAppRoot });
347347

348348
await installApp({ simulator, binaryFilePath, bundleId });
349349
await launchApp({ simulator, bundleId });

0 commit comments

Comments
 (0)