Skip to content

Commit

Permalink
feat(react): add playwright to e2eTestRunner option (#18200)
Browse files Browse the repository at this point in the history
  • Loading branch information
xiongemi committed Aug 3, 2023
1 parent f1a90bf commit 24b1ab5
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 42 deletions.
3 changes: 2 additions & 1 deletion docs/generated/packages/react/generators/application.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,9 @@
},
"e2eTestRunner": {
"type": "string",
"enum": ["cypress", "none"],
"enum": ["cypress", "playwright", "none"],
"description": "Test runner to use for end to end (E2E) tests.",
"x-prompt": "Which E2E test runner would you like to use?",
"default": "cypress"
},
"tags": {
Expand Down
2 changes: 1 addition & 1 deletion docs/generated/packages/react/generators/init.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"e2eTestRunner": {
"description": "Adds the specified E2E test runner.",
"type": "string",
"enum": ["cypress", "none"],
"enum": ["cypress", "playwright", "none"],
"default": "cypress"
},
"skipFormat": {
Expand Down
1 change: 1 addition & 0 deletions packages/react/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"react",
// These are installed by ensurePackage so missing in package.json
"@nx/cypress",
"@nx/playwright",
"@nx/jest",
"@nx/rollup",
"@nx/storybook",
Expand Down
60 changes: 56 additions & 4 deletions packages/react/src/generators/application/application.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,24 @@ describe('app', () => {
},
].forEach(hasJsonValue);
});

it('should setup playwright', async () => {
await applicationGenerator(appTree, {
...schema,
directory: 'myDir',
e2eTestRunner: 'playwright',
});

expect(
appTree.exists('apps/my-dir/my-app-e2e/playwright.config.ts')
).toBeTruthy();
expect(
appTree.exists('apps/my-dir/my-app-e2e/src/example.spec.ts')
).toBeTruthy();
expect(
readProjectConfiguration(appTree, 'my-app-e2e')?.targets?.e2e?.executor
).toEqual('@nx/playwright:playwright');
});
});

it('should create Nx specific template', async () => {
Expand Down Expand Up @@ -332,7 +350,7 @@ describe('app', () => {
);
});

it('should setup the nrwl web build builder', async () => {
it('should setup the nx web build builder', async () => {
await applicationGenerator(appTree, {
...schema,
name: 'my-app',
Expand Down Expand Up @@ -372,7 +390,7 @@ describe('app', () => {
});
});

it('should setup the nrwl vite builder if bundler is vite', async () => {
it('should setup the nx vite builder if bundler is vite', async () => {
await applicationGenerator(appTree, {
...schema,
name: 'my-app',
Expand All @@ -394,7 +412,7 @@ describe('app', () => {
).toBeFalsy();
});

it('should setup the nrwl web dev server builder', async () => {
it('should setup the nx web dev server builder', async () => {
await applicationGenerator(appTree, {
...schema,
name: 'my-app',
Expand All @@ -414,7 +432,7 @@ describe('app', () => {
});
});

it('should setup the nrwl vite dev server builder if bundler is vite', async () => {
it('should setup the nx vite dev server builder if bundler is vite', async () => {
await applicationGenerator(appTree, {
...schema,
name: 'my-app',
Expand Down Expand Up @@ -486,6 +504,25 @@ describe('app', () => {
});
});

describe('--e2e-test-runner playwright', () => {
it('should setup playwright', async () => {
await applicationGenerator(appTree, {
...schema,
e2eTestRunner: 'playwright',
});

expect(
appTree.exists('apps/my-app-e2e/playwright.config.ts')
).toBeTruthy();
expect(
appTree.exists('apps/my-app-e2e/src/example.spec.ts')
).toBeTruthy();
expect(
readProjectConfiguration(appTree, 'my-app-e2e')?.targets?.e2e?.executor
).toEqual('@nx/playwright:playwright');
});
});

describe('--pascalCaseFiles', () => {
it('should use upper case app file', async () => {
await applicationGenerator(appTree, { ...schema, pascalCaseFiles: true });
Expand Down Expand Up @@ -950,6 +987,21 @@ describe('app', () => {
]
).toEqual('dist/my-app2');
});

it('should setup playwright', async () => {
await applicationGenerator(appTree, {
...schema,
name: 'my-app3',
rootProject: true,
e2eTestRunner: 'playwright',
});

expect(appTree.exists('e2e/playwright.config.ts')).toBeTruthy();
expect(appTree.exists('e2e/src/example.spec.ts')).toBeTruthy();
expect(
readProjectConfiguration(appTree, 'e2e')?.targets?.e2e?.executor
).toEqual('@nx/playwright:playwright');
});
});

describe('setup React app with --bundler=vite', () => {
Expand Down
8 changes: 4 additions & 4 deletions packages/react/src/generators/application/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { createApplicationFiles } from './lib/create-application-files';
import { updateSpecConfig } from './lib/update-jest-config';
import { normalizeOptions } from './lib/normalize-options';
import { addProject, maybeJs } from './lib/add-project';
import { addCypress } from './lib/add-cypress';
import { addJest } from './lib/add-jest';
import { addRouting } from './lib/add-routing';
import { setDefaults } from './lib/set-defaults';
Expand Down Expand Up @@ -39,6 +38,7 @@ import { extractTsConfigBase } from '../../utils/create-ts-config';
import { addSwcDependencies } from '@nx/js/src/utils/swc/add-swc-dependencies';
import * as chalk from 'chalk';
import { showPossibleWarnings } from './lib/show-possible-warnings';
import { addE2e } from './lib/add-e2e';

async function addLinting(host: Tree, options: NormalizedSchema) {
const tasks: GeneratorCallback[] = [];
Expand Down Expand Up @@ -70,7 +70,7 @@ async function addLinting(host: Tree, options: NormalizedSchema) {
);

if (!options.skipPackageJson) {
const installTask = await addDependenciesToPackageJson(
const installTask = addDependenciesToPackageJson(
host,
extraEslintDependencies.dependencies,
extraEslintDependencies.devDependencies
Expand Down Expand Up @@ -189,8 +189,8 @@ export async function applicationGenerator(
const lintTask = await addLinting(host, options);
tasks.push(lintTask);

const cypressTask = await addCypress(host, options);
tasks.push(cypressTask);
const e2eTask = await addE2e(host, options);
tasks.push(e2eTask);

if (options.unitTestRunner === 'jest') {
const jestTask = await addJest(host, options);
Expand Down
28 changes: 0 additions & 28 deletions packages/react/src/generators/application/lib/add-cypress.ts

This file was deleted.

63 changes: 63 additions & 0 deletions packages/react/src/generators/application/lib/add-e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import type { GeneratorCallback, Tree } from '@nx/devkit';
import {
addProjectConfiguration,
ensurePackage,
getPackageManagerCommand,
joinPathFragments,
readProjectConfiguration,
} from '@nx/devkit';
import { webStaticServeGenerator } from '@nx/web';

import { nxVersion } from '../../../utils/versions';
import { NormalizedSchema } from '../schema';

export async function addE2e(
tree: Tree,
options: NormalizedSchema
): Promise<GeneratorCallback> {
switch (options.e2eTestRunner) {
case 'cypress':
webStaticServeGenerator(tree, {
buildTarget: `${options.projectName}:build`,
targetName: 'serve-static',
});

const { cypressProjectGenerator } = ensurePackage<
typeof import('@nx/cypress')
>('@nx/cypress', nxVersion);

return await cypressProjectGenerator(tree, {
...options,
name: options.e2eProjectName,
directory: options.directory,
project: options.projectName,
bundler: options.bundler === 'rspack' ? 'webpack' : options.bundler,
skipFormat: true,
});
case 'playwright':
const { configurationGenerator } = ensurePackage<
typeof import('@nx/playwright')
>('@nx/playwright', nxVersion);
addProjectConfiguration(tree, options.e2eProjectName, {
root: options.e2eProjectRoot,
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
targets: {},
implicitDependencies: [options.projectName],
});
return configurationGenerator(tree, {
project: options.e2eProjectName,
skipFormat: true,
skipPackageJson: options.skipPackageJson,
directory: 'src',
js: false,
linter: options.linter,
setParserOptionsProject: options.setParserOptionsProject,
webServerCommand: `${getPackageManagerCommand().exec} nx serve ${
options.name
}`,
});
case 'none':
default:
return () => {};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { assertValidStyle } from '../../../utils/assertion';
import {
extractLayoutDirectory,
getWorkspaceLayout,
joinPathFragments,
names,
normalizePath,
Tree,
Expand Down Expand Up @@ -36,6 +37,9 @@ export function normalizeOptions<T extends Schema = Schema>(
const appProjectRoot = options.rootProject
? '.'
: normalizePath(`${appsDir}/${appDirectory}`);
const e2eProjectRoot = options.rootProject
? 'e2e'
: joinPathFragments(appsDir, `${appDirectory}-e2e`);

const parsedTags = options.tags
? options.tags.split(',').map((s) => s.trim())
Expand All @@ -59,6 +63,7 @@ export function normalizeOptions<T extends Schema = Schema>(
projectName: appProjectName,
appProjectRoot,
e2eProjectName,
e2eProjectRoot,
parsedTags,
fileName,
styledModule,
Expand Down
3 changes: 2 additions & 1 deletion packages/react/src/generators/application/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export interface Schema {
tags?: string;
unitTestRunner?: 'jest' | 'vitest' | 'none';
inSourceTests?: boolean;
e2eTestRunner: 'cypress' | 'none';
e2eTestRunner: 'cypress' | 'playwright' | 'none';
linter: Linter;
pascalCaseFiles?: boolean;
classComponent?: boolean;
Expand All @@ -32,6 +32,7 @@ export interface NormalizedSchema<T extends Schema = Schema> extends T {
projectName: string;
appProjectRoot: string;
e2eProjectName: string;
e2eProjectRoot: string;
parsedTags: string[];
fileName: string;
styledModule: null | SupportedStyles;
Expand Down
3 changes: 2 additions & 1 deletion packages/react/src/generators/application/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@
},
"e2eTestRunner": {
"type": "string",
"enum": ["cypress", "none"],
"enum": ["cypress", "playwright", "none"],
"description": "Test runner to use for end to end (E2E) tests.",
"x-prompt": "Which E2E test runner would you like to use?",
"default": "cypress"
},
"tags": {
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/generators/init/schema.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export interface InitSchema {
unitTestRunner?: 'jest' | 'vitest' | 'none';
e2eTestRunner?: 'cypress' | 'none';
e2eTestRunner?: 'cypress' | 'playwright' | 'none';
skipFormat?: boolean;
skipPackageJson?: boolean;
skipHelperLibs?: boolean;
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/generators/init/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"e2eTestRunner": {
"description": "Adds the specified E2E test runner.",
"type": "string",
"enum": ["cypress", "none"],
"enum": ["cypress", "playwright", "none"],
"default": "cypress"
},
"skipFormat": {
Expand Down

1 comment on commit 24b1ab5

@vercel
Copy link

@vercel vercel bot commented on 24b1ab5 Aug 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nx-dev – ./

nx-dev-git-master-nrwl.vercel.app
nx-dev-nrwl.vercel.app
nx-five.vercel.app
nx.dev

Please sign in to comment.