feat(detox): add detox config for expo apps (#11104)

This commit is contained in:
Emily Xiong 2022-07-18 15:39:25 -04:00 committed by GitHub
parent d657f912d9
commit 38a2d95d9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 248 additions and 55 deletions

View File

@ -59,6 +59,12 @@
"$default": { "$source": "argv", "index": 0 }, "$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for the E2E project?" "x-prompt": "What name would you like to use for the E2E project?"
}, },
"framework": {
"type": "string",
"description": "App framework to test",
"enum": ["react-native", "expo"],
"x-prompt": "What app framework should detox test?"
},
"directory": { "directory": {
"type": "string", "type": "string",
"description": "A directory where the project is placed." "description": "A directory where the project is placed."
@ -85,7 +91,7 @@
"default": false "default": false
} }
}, },
"required": ["name", "project"], "required": ["name", "project", "framework"],
"presets": [] "presets": []
}, },
"aliases": ["app"], "aliases": ["app"],

View File

@ -37,7 +37,7 @@ export function runCliBuild(
join(workspaceRoot, './node_modules/detox/local-cli/cli.js'), join(workspaceRoot, './node_modules/detox/local-cli/cli.js'),
['build', ...createDetoxBuildOptions(options)], ['build', ...createDetoxBuildOptions(options)],
{ {
cwd: projectRoot, cwd: join(workspaceRoot, projectRoot),
} }
); );

View File

@ -58,7 +58,7 @@ function runCliTest(
join(workspaceRoot, './node_modules/detox/local-cli/cli.js'), join(workspaceRoot, './node_modules/detox/local-cli/cli.js'),
['test', ...createDetoxTestOptions(options)], ['test', ...createDetoxTestOptions(options)],
{ {
cwd: projectRoot, cwd: join(workspaceRoot, projectRoot),
} }
); );

View File

@ -27,6 +27,7 @@ describe('detox application generator', () => {
name: 'my-app-e2e', name: 'my-app-e2e',
project: 'my-app', project: 'my-app',
linter: Linter.None, linter: Linter.None,
framework: 'react-native',
}); });
}); });
@ -60,6 +61,7 @@ describe('detox application generator', () => {
directory: 'my-dir', directory: 'my-dir',
project: 'my-dir-my-app', project: 'my-dir-my-app',
linter: Linter.None, linter: Linter.None,
framework: 'react-native',
}); });
}); });
@ -94,6 +96,7 @@ describe('detox application generator', () => {
name: 'my-dir/my-app-e2e', name: 'my-dir/my-app-e2e',
project: 'my-dir-my-app', project: 'my-dir-my-app',
linter: Linter.None, linter: Linter.None,
framework: 'react-native',
}); });
}); });
@ -128,6 +131,7 @@ describe('detox application generator', () => {
name: 'my-app-e2e', name: 'my-app-e2e',
project: 'my-app', project: 'my-app',
linter: Linter.None, linter: Linter.None,
framework: 'react-native',
}); });
const tsConfig = readJson(tree, 'apps/my-app-e2e/tsconfig.json'); const tsConfig = readJson(tree, 'apps/my-app-e2e/tsconfig.json');
@ -141,6 +145,7 @@ describe('detox application generator', () => {
name: 'my-app-e2e', name: 'my-app-e2e',
project: 'my-app', project: 'my-app',
linter: Linter.None, linter: Linter.None,
framework: 'react-native',
}); });
const tsConfig = readJson(tree, 'apps/my-app-e2e/tsconfig.json'); const tsConfig = readJson(tree, 'apps/my-app-e2e/tsconfig.json');

View File

@ -12,6 +12,18 @@
"build": "cd ../<%= appFileName %>/ios && xcodebuild -workspace <%= appClassName %>.xcworkspace -scheme <%= appClassName %> -configuration Release -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 13' -derivedDataPath ./build -quiet", "build": "cd ../<%= appFileName %>/ios && xcodebuild -workspace <%= appClassName %>.xcworkspace -scheme <%= appClassName %> -configuration Release -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 13' -derivedDataPath ./build -quiet",
"binaryPath": "../<%= appFileName %>/ios/build/Build/Products/Release-iphonesimulator/<%= appClassName %>.app" "binaryPath": "../<%= appFileName %>/ios/build/Build/Products/Release-iphonesimulator/<%= appClassName %>.app"
}, },
<% if (framework === 'expo') { %>
"ios.eas": {
"type": "ios.app",
"build": "<%= exec %> nx run <%= appFileName %>:download --platform ios --distribution simulator --output=<%= projectDirectory %>/<%= appFileName %>/dist/",
"binaryPath": "../<%= appFileName %>/dist/<%= appDisplayName %>.app"
},
"ios.local": {
"type": "ios.app",
"build": "<%= exec %> nx run <%= appFileName %>:build --platform ios --profile preview --wait --local --no-interactive --output=<%= projectDirectory %>/<%= appFileName %>/dist/",
"binaryPath": "../<%= appFileName %>/dist/<%= appDisplayName %>.app"
},
<% } %>
"android.debug": { "android.debug": {
"type": "android.apk", "type": "android.apk",
"build": "cd ../<%= appFileName %>/android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug", "build": "cd ../<%= appFileName %>/android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug",
@ -21,7 +33,19 @@
"type": "android.apk", "type": "android.apk",
"build": "cd ../<%= appFileName %>/android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release", "build": "cd ../<%= appFileName %>/android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release",
"binaryPath": "../<%= appFileName %>/android/app/build/outputs/apk/release/app-release.apk" "binaryPath": "../<%= appFileName %>/android/app/build/outputs/apk/release/app-release.apk"
} },
<% if (framework === 'expo') { %>
"android.eas": {
"type": "ios.app",
"build": "<%= exec %> nx run <%= appFileName %>:download --platform android --output=<%= projectDirectory %>/<%= appFileName %>/dist/",
"binaryPath": "../<%= appFileName %>/dist/<%= appDisplayName %>.apk"
},
"android.local": {
"type": "ios.app",
"build": "<%= exec %> nx run <%= appFileName %>:build --platform android --profile preview --wait --local --no-interactive --output=<%= projectDirectory %>/<%= appFileName %>/dist/",
"binaryPath": "../<%= appFileName %>/dist/<%= appDisplayName %>.apk"
},
<% } %>
}, },
"devices": { "devices": {
"simulator": { "simulator": {
@ -46,6 +70,16 @@
"device": "simulator", "device": "simulator",
"app": "ios.debug" "app": "ios.debug"
}, },
<% if (framework === 'expo') { %>
"ios.sim.eas": {
"device": "simulator",
"app": "ios.eas"
},
"ios.sim.local": {
"device": "simulator",
"app": "ios.local"
},
<% } %>
"android.emu.release": { "android.emu.release": {
"device": "emulator", "device": "emulator",
"app": "android.release" "app": "android.release"
@ -53,6 +87,16 @@
"android.emu.debug": { "android.emu.debug": {
"device": "emulator", "device": "emulator",
"app": "android.debug" "app": "android.debug"
} },
<% if (framework === 'expo') { %>
"android.sim.eas": {
"device": "simulator",
"app": "android.eas"
},
"android.sim.local": {
"device": "simulator",
"app": "android.local"
},
<% } %>
} }
} }

View File

@ -12,11 +12,14 @@ describe('Add Linting', () => {
addProject(tree, { addProject(tree, {
name: 'my-app-e2e', name: 'my-app-e2e',
projectName: 'my-app-e2e', projectName: 'my-app-e2e',
projectDirectory: 'apps',
projectRoot: 'apps/my-app-e2e', projectRoot: 'apps/my-app-e2e',
project: 'my-app', project: 'my-app',
appFileName: 'my-app', appFileName: 'my-app',
appClassName: 'MyApp', appClassName: 'MyApp',
appDisplayName: 'MyApp',
linter: Linter.EsLint, linter: Linter.EsLint,
framework: 'react-native',
}); });
}); });
@ -24,11 +27,14 @@ describe('Add Linting', () => {
addLinting(tree, { addLinting(tree, {
name: 'my-app-e2e', name: 'my-app-e2e',
projectName: 'my-app-e2e', projectName: 'my-app-e2e',
projectDirectory: 'apps',
projectRoot: 'apps/my-app-e2e', projectRoot: 'apps/my-app-e2e',
project: 'my-app', project: 'my-app',
appFileName: 'my-app', appFileName: 'my-app',
appClassName: 'MyApp', appClassName: 'MyApp',
appDisplayName: 'MyApp',
linter: Linter.EsLint, linter: Linter.EsLint,
framework: 'react-native',
}); });
const project = readProjectConfiguration(tree, 'my-app-e2e'); const project = readProjectConfiguration(tree, 'my-app-e2e');
@ -40,11 +46,14 @@ describe('Add Linting', () => {
addLinting(tree, { addLinting(tree, {
name: 'my-app-e2e', name: 'my-app-e2e',
projectName: 'my-app-e2e', projectName: 'my-app-e2e',
projectDirectory: 'apps',
projectRoot: 'apps/my-app-e2e', projectRoot: 'apps/my-app-e2e',
project: 'my-app', project: 'my-app',
appFileName: 'my-app', appFileName: 'my-app',
appClassName: 'MyApp', appClassName: 'MyApp',
appDisplayName: 'MyApp',
linter: Linter.TsLint, linter: Linter.TsLint,
framework: 'react-native',
}); });
const project = readProjectConfiguration(tree, 'my-app-e2e'); const project = readProjectConfiguration(tree, 'my-app-e2e');
@ -58,11 +67,14 @@ describe('Add Linting', () => {
addLinting(tree, { addLinting(tree, {
name: 'my-app-e2e', name: 'my-app-e2e',
projectName: 'my-app-e2e', projectName: 'my-app-e2e',
projectDirectory: 'apps',
projectRoot: 'apps/my-app-e2e', projectRoot: 'apps/my-app-e2e',
project: 'my-app', project: 'my-app',
appFileName: 'my-app', appFileName: 'my-app',
appClassName: 'MyApp', appClassName: 'MyApp',
appDisplayName: 'MyApp',
linter: Linter.None, linter: Linter.None,
framework: 'react-native',
}); });
const project = readProjectConfiguration(tree, 'my-app-e2e'); const project = readProjectConfiguration(tree, 'my-app-e2e');

View File

@ -39,7 +39,7 @@ export async function addLinting(host: Tree, options: NormalizedSchema) {
() => reactEslintJson () => reactEslintJson
); );
const installTask = await addDependenciesToPackageJson( const installTask = addDependenciesToPackageJson(
host, host,
extraEslintDependencies.dependencies, extraEslintDependencies.dependencies,
extraEslintDependencies.devDependencies extraEslintDependencies.devDependencies

View File

@ -31,11 +31,14 @@ describe('Add Project', () => {
addProject(tree, { addProject(tree, {
name: 'my-app-e2e', name: 'my-app-e2e',
projectName: 'my-app-e2e', projectName: 'my-app-e2e',
projectDirectory: 'apps',
projectRoot: 'apps/my-app-e2e', projectRoot: 'apps/my-app-e2e',
project: 'my-app', project: 'my-app',
appFileName: 'my-app', appFileName: 'my-app',
appClassName: 'MyApp', appClassName: 'MyApp',
appDisplayName: 'MyApp',
linter: Linter.EsLint, linter: Linter.EsLint,
framework: 'react-native',
}); });
}); });
@ -76,11 +79,14 @@ describe('Add Project', () => {
addProject(tree, { addProject(tree, {
name: 'my-dir-my-app-e2e', name: 'my-dir-my-app-e2e',
projectName: 'my-dir-my-app-e2e', projectName: 'my-dir-my-app-e2e',
projectDirectory: 'apps',
projectRoot: 'apps/my-dir/my-app-e2e', projectRoot: 'apps/my-dir/my-app-e2e',
project: 'my-dir-my-app', project: 'my-dir-my-app',
appFileName: 'my-app', appFileName: 'my-app',
appClassName: 'MyApp', appClassName: 'MyApp',
appDisplayName: 'MyApp',
linter: Linter.EsLint, linter: Linter.EsLint,
framework: 'react-native',
}); });
}); });

View File

@ -3,6 +3,12 @@ import {
TargetConfiguration, TargetConfiguration,
Tree, Tree,
} from '@nrwl/devkit'; } from '@nrwl/devkit';
import {
expoBuildTarget,
expoTestTarget,
reactNativeBuildTarget,
reactNativeTestTarget,
} from './get-targets';
import { NormalizedSchema } from './normalize-options'; import { NormalizedSchema } from './normalize-options';
export function addProject(host: Tree, options: NormalizedSchema) { export function addProject(host: Tree, options: NormalizedSchema) {
@ -17,59 +23,35 @@ export function addProject(host: Tree, options: NormalizedSchema) {
} }
function getTargets(options: NormalizedSchema) { function getTargets(options: NormalizedSchema) {
const architect: { [key: string]: TargetConfiguration } = {}; const targets: { [key: string]: TargetConfiguration } = {};
architect['build-ios'] = { targets['build-ios'] = {
executor: '@nrwl/detox:build', executor: '@nrwl/detox:build',
options: { ...(options.framework === 'react-native'
detoxConfiguration: 'ios.sim.debug', ? reactNativeBuildTarget('ios')
}, : expoBuildTarget('ios')),
configurations: {
production: {
detoxConfiguration: 'ios.sim.release',
},
},
}; };
architect['test-ios'] = { targets['test-ios'] = {
executor: '@nrwl/detox:test', executor: '@nrwl/detox:test',
options: { ...(options.framework === 'react-native'
detoxConfiguration: 'ios.sim.debug', ? reactNativeTestTarget('ios', options.name)
buildTarget: `${options.name}:build-ios`, : expoTestTarget('ios', options.name)),
},
configurations: {
production: {
detoxConfiguration: 'ios.sim.release',
buildTarget: `${options.name}:build-ios:prod`,
},
},
}; };
architect['build-android'] = { targets['build-android'] = {
executor: '@nrwl/detox:build', executor: '@nrwl/detox:build',
options: { ...(options.framework === 'react-native'
detoxConfiguration: 'android.emu.debug', ? reactNativeBuildTarget('android')
}, : expoBuildTarget('android')),
configurations: {
production: {
detoxConfiguration: 'android.emu.release',
},
},
}; };
architect['test-android'] = { targets['test-android'] = {
executor: '@nrwl/detox:test', executor: '@nrwl/detox:test',
options: { ...(options.framework === 'react-native'
detoxConfiguration: 'android.emu.debug', ? reactNativeTestTarget('android', options.name)
buildTarget: `${options.name}:build-android`, : expoTestTarget('android', options.name)),
},
configurations: {
production: {
detoxConfiguration: 'android.emu.release',
buildTarget: `${options.name}:build-android:prod`,
},
},
}; };
return architect; return targets;
} }

View File

@ -14,11 +14,14 @@ describe('Create Files', () => {
createFiles(tree, { createFiles(tree, {
name: 'my-app-e2e', name: 'my-app-e2e',
projectName: 'my-app-e2e', projectName: 'my-app-e2e',
projectDirectory: 'apps',
projectRoot: 'apps/my-app-e2e', projectRoot: 'apps/my-app-e2e',
project: 'my-app', project: 'my-app',
appFileName: 'my-app', appFileName: 'my-app',
appClassName: 'MyApp', appClassName: 'MyApp',
appDisplayName: 'MyApp',
linter: Linter.EsLint, linter: Linter.EsLint,
framework: 'react-native',
}); });
expect(tree.exists('apps/my-app-e2e/.detoxrc.json')).toBeTruthy(); expect(tree.exists('apps/my-app-e2e/.detoxrc.json')).toBeTruthy();

View File

@ -1,4 +1,11 @@
import { generateFiles, offsetFromRoot, toJS, Tree } from '@nrwl/devkit'; import {
detectPackageManager,
generateFiles,
getPackageManagerCommand,
offsetFromRoot,
toJS,
Tree,
} from '@nrwl/devkit';
import { getRelativePathToRootTsConfig } from '@nrwl/workspace/src/utilities/typescript'; import { getRelativePathToRootTsConfig } from '@nrwl/workspace/src/utilities/typescript';
import { join } from 'path'; import { join } from 'path';
import { NormalizedSchema } from './normalize-options'; import { NormalizedSchema } from './normalize-options';
@ -6,6 +13,7 @@ import { NormalizedSchema } from './normalize-options';
export function createFiles(host: Tree, options: NormalizedSchema) { export function createFiles(host: Tree, options: NormalizedSchema) {
generateFiles(host, join(__dirname, '../files/app'), options.projectRoot, { generateFiles(host, join(__dirname, '../files/app'), options.projectRoot, {
...options, ...options,
exec: getPackageManagerCommand(detectPackageManager(host.root)).exec,
offsetFromRoot: offsetFromRoot(options.projectRoot), offsetFromRoot: offsetFromRoot(options.projectRoot),
rootTsConfigPath: getRelativePathToRootTsConfig(host, options.projectRoot), rootTsConfigPath: getRelativePathToRootTsConfig(host, options.projectRoot),
}); });

View File

@ -0,0 +1,69 @@
export function reactNativeBuildTarget(platform: 'ios' | 'android') {
return {
options: {
detoxConfiguration: `${platform}.sim.debug`,
},
configurations: {
production: {
detoxConfiguration: `${platform}.sim.release`,
},
},
};
}
export function expoBuildTarget(platform: string) {
return {
options: {
detoxConfiguration: `${platform}.sim.debug`,
},
configurations: {
local: {
detoxConfiguration: `${platform}.sim.local`,
},
bare: {
detoxConfiguration: `${platform}.sim.debug`,
},
production: {
detoxConfiguration: `${platform}.sim.release`,
},
},
};
}
export function reactNativeTestTarget(platform: string, name: string) {
return {
options: {
detoxConfiguration: `${platform}.sim.debug`,
buildTarget: `${name}:build-ios`,
},
configurations: {
production: {
detoxConfiguration: `${platform}.sim.release`,
buildTarget: `${name}:build-ios:production`,
},
},
};
}
export function expoTestTarget(platform: string, name: string) {
return {
options: {
detoxConfiguration: `${platform}.sim.eas`,
buildTarget: `${name}:build-ios`,
},
configurations: {
local: {
detoxConfiguration: `${platform}.sim.local`,
buildTarget: `${name}:build-ios:local`,
},
bare: {
detoxConfiguration: `${platform}.sim.debug`,
buildTarget: `${name}:build-ios:bare`,
},
production: {
detoxConfiguration: `${platform}.sim.release`,
buildTarget: `${name}:build-ios:production`,
},
},
};
}

View File

@ -17,18 +17,22 @@ describe('Normalize Options', () => {
targets: {}, targets: {},
}); });
const schema: Schema = { const schema: Schema = {
framework: 'react-native',
name: 'my-app-e2e', name: 'my-app-e2e',
project: 'my-app', project: 'my-app',
linter: Linter.EsLint, linter: Linter.EsLint,
}; };
const options = normalizeOptions(appTree, schema); const options = normalizeOptions(appTree, schema);
expect(options).toEqual({ expect(options).toEqual({
framework: 'react-native',
name: 'my-app-e2e', name: 'my-app-e2e',
projectName: 'my-app-e2e', projectName: 'my-app-e2e',
projectDirectory: 'apps',
projectRoot: 'apps/my-app-e2e', projectRoot: 'apps/my-app-e2e',
project: 'my-app', project: 'my-app',
appFileName: 'my-app', appFileName: 'my-app',
appClassName: 'MyApp', appClassName: 'MyApp',
appDisplayName: 'MyApp',
linter: Linter.EsLint, linter: Linter.EsLint,
}); });
}); });
@ -39,17 +43,47 @@ describe('Normalize Options', () => {
targets: {}, targets: {},
}); });
const schema: Schema = { const schema: Schema = {
framework: 'react-native',
name: 'myAppE2e', name: 'myAppE2e',
project: 'myApp', project: 'myApp',
}; };
const options = normalizeOptions(appTree, schema); const options = normalizeOptions(appTree, schema);
expect(options).toEqual({ expect(options).toEqual({
appClassName: 'MyApp', appClassName: 'MyApp',
appDisplayName: 'MyApp',
appFileName: 'my-app', appFileName: 'my-app',
name: 'my-app-e2e', name: 'my-app-e2e',
project: 'myApp', project: 'myApp',
projectName: 'my-app-e2e', projectName: 'my-app-e2e',
projectDirectory: 'apps',
projectRoot: 'apps/my-app-e2e', projectRoot: 'apps/my-app-e2e',
framework: 'react-native',
});
});
it('should normalize options with display name', () => {
addProjectConfiguration(appTree, 'my-app', {
root: 'apps/my-app',
targets: {},
});
const schema: Schema = {
framework: 'react-native',
name: 'myAppE2e',
project: 'myApp',
displayName: 'app display name',
};
const options = normalizeOptions(appTree, schema);
expect(options).toEqual({
displayName: 'app display name',
appClassName: 'MyApp',
appDisplayName: 'AppDisplayName',
appFileName: 'my-app',
name: 'my-app-e2e',
project: 'myApp',
projectName: 'my-app-e2e',
projectDirectory: 'apps',
projectRoot: 'apps/my-app-e2e',
framework: 'react-native',
}); });
}); });
@ -59,6 +93,7 @@ describe('Normalize Options', () => {
targets: {}, targets: {},
}); });
const schema: Schema = { const schema: Schema = {
framework: 'react-native',
name: 'my-app-e2e', name: 'my-app-e2e',
project: 'my-app', project: 'my-app',
directory: 'directory', directory: 'directory',
@ -67,11 +102,14 @@ describe('Normalize Options', () => {
expect(options).toEqual({ expect(options).toEqual({
project: 'my-app', project: 'my-app',
appClassName: 'MyApp', appClassName: 'MyApp',
appDisplayName: 'MyApp',
appFileName: 'my-app', appFileName: 'my-app',
projectDirectory: 'apps/directory',
projectRoot: 'apps/directory/my-app-e2e', projectRoot: 'apps/directory/my-app-e2e',
name: 'my-app-e2e', name: 'my-app-e2e',
directory: 'directory', directory: 'directory',
projectName: 'directory-my-app-e2e', projectName: 'directory-my-app-e2e',
framework: 'react-native',
}); });
}); });
@ -81,6 +119,7 @@ describe('Normalize Options', () => {
targets: {}, targets: {},
}); });
const schema: Schema = { const schema: Schema = {
framework: 'react-native',
name: 'directory/my-app-e2e', name: 'directory/my-app-e2e',
project: 'my-app', project: 'my-app',
}; };
@ -88,10 +127,13 @@ describe('Normalize Options', () => {
expect(options).toEqual({ expect(options).toEqual({
project: 'my-app', project: 'my-app',
appClassName: 'MyApp', appClassName: 'MyApp',
appDisplayName: 'MyApp',
appFileName: 'my-app', appFileName: 'my-app',
projectRoot: 'apps/directory/my-app-e2e', projectRoot: 'apps/directory/my-app-e2e',
projectDirectory: 'apps',
name: 'directory/my-app-e2e', name: 'directory/my-app-e2e',
projectName: 'directory-my-app-e2e', projectName: 'directory-my-app-e2e',
framework: 'react-native',
}); });
}); });
}); });

View File

@ -9,7 +9,9 @@ import { Schema } from '../schema';
export interface NormalizedSchema extends Schema { export interface NormalizedSchema extends Schema {
appFileName: string; // the file name of app to be tested appFileName: string; // the file name of app to be tested
appClassName: string; // the class name of app to be tested appClassName: string; // the class name of app to be tested
appDisplayName: string; // the display name of the app to be tested
projectName: string; // the name of e2e project projectName: string; // the name of e2e project
projectDirectory: string; // the directory of e2e project
projectRoot: string; // the root path of e2e project projectRoot: string; // the root path of e2e project
} }
@ -31,9 +33,10 @@ export function normalizeOptions(
const projectName = ( const projectName = (
directoryFileName ? `${directoryFileName}-${fileName}` : fileName directoryFileName ? `${directoryFileName}-${fileName}` : fileName
).replace(new RegExp('/', 'g'), '-'); ).replace(new RegExp('/', 'g'), '-');
const projectRoot = directoryFileName const projectDirectory = directoryFileName
? joinPathFragments(appsDir, directoryFileName, fileName) ? joinPathFragments(appsDir, directoryFileName)
: joinPathFragments(appsDir, fileName); : appsDir;
const projectRoot = joinPathFragments(projectDirectory, fileName);
const { fileName: appFileName, className: appClassName } = names( const { fileName: appFileName, className: appClassName } = names(
options.project options.project
@ -43,8 +46,12 @@ export function normalizeOptions(
...options, ...options,
appFileName, appFileName,
appClassName, appClassName,
appDisplayName: options.displayName
? names(options.displayName).className
: appClassName,
name: fileName, name: fileName,
projectName, projectName,
projectDirectory,
projectRoot, projectRoot,
}; };
} }

View File

@ -1,11 +1,13 @@
import { Linter } from '@nrwl/linter'; import { Linter } from '@nrwl/linter';
export interface Schema { export interface Schema {
project: string; project: string; // name of the project app to be tested
name: string; displayName?: string; // display name of the mobile app
name: string; // name of the e2e app
directory?: string; directory?: string;
linter?: Linter; linter?: Linter;
js?: boolean; js?: boolean;
skipFormat?: boolean; skipFormat?: boolean;
setParserOptionsProject?: boolean; setParserOptionsProject?: boolean;
framework: 'react-native' | 'expo';
} }

View File

@ -21,6 +21,12 @@
}, },
"x-prompt": "What name would you like to use for the E2E project?" "x-prompt": "What name would you like to use for the E2E project?"
}, },
"framework": {
"type": "string",
"description": "App framework to test",
"enum": ["react-native", "expo"],
"x-prompt": "What app framework should detox test?"
},
"directory": { "directory": {
"type": "string", "type": "string",
"description": "A directory where the project is placed." "description": "A directory where the project is placed."
@ -47,5 +53,5 @@
"default": false "default": false
} }
}, },
"required": ["name", "project"] "required": ["name", "project", "framework"]
} }

View File

@ -14,5 +14,6 @@ export async function addDetox(host: Tree, options: NormalizedSchema) {
name: `${options.name}-e2e`, name: `${options.name}-e2e`,
directory: options.directory, directory: options.directory,
project: options.projectName, project: options.projectName,
framework: 'react-native',
}); });
} }