feat(web): add playwright e2eTestRunner option (#18284)
This commit is contained in:
parent
e78575badc
commit
27923fd2d8
@ -79,7 +79,8 @@
|
|||||||
},
|
},
|
||||||
"e2eTestRunner": {
|
"e2eTestRunner": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["cypress", "none"],
|
"enum": ["cypress", "playwright", "none"],
|
||||||
|
"x-prompt": "Which E2E test runner would you like to use?",
|
||||||
"description": "Test runner to use for end to end (e2e) tests",
|
"description": "Test runner to use for end to end (e2e) tests",
|
||||||
"default": "cypress"
|
"default": "cypress"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -24,7 +24,8 @@
|
|||||||
"e2eTestRunner": {
|
"e2eTestRunner": {
|
||||||
"description": "Adds the specified e2e test runner",
|
"description": "Adds the specified e2e test runner",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["cypress", "none"],
|
"enum": ["cypress", "playwright", "none"],
|
||||||
|
"x-prompt": "Which E2E test runner would you like to use?",
|
||||||
"default": "cypress"
|
"default": "cypress"
|
||||||
},
|
},
|
||||||
"skipFormat": {
|
"skipFormat": {
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import {
|
|||||||
checkFilesExist,
|
checkFilesExist,
|
||||||
cleanupProject,
|
cleanupProject,
|
||||||
createFile,
|
createFile,
|
||||||
|
ensurePlaywrightBrowsersInstallation,
|
||||||
isNotWindows,
|
isNotWindows,
|
||||||
killPorts,
|
killPorts,
|
||||||
listFiles,
|
listFiles,
|
||||||
@ -98,6 +99,26 @@ describe('Web Components Applications', () => {
|
|||||||
);
|
);
|
||||||
}, 500000);
|
}, 500000);
|
||||||
|
|
||||||
|
it('should generate working playwright e2e app', async () => {
|
||||||
|
const appName = uniq('app');
|
||||||
|
runCLI(
|
||||||
|
`generate @nx/web:app ${appName} --bundler=webpack --e2eTestRunner=playwright --no-interactive`
|
||||||
|
);
|
||||||
|
|
||||||
|
const lintE2eResults = runCLI(`lint ${appName}-e2e`);
|
||||||
|
|
||||||
|
expect(lintE2eResults).toContain('All files pass linting.');
|
||||||
|
|
||||||
|
if (isNotWindows() && runCypressTests()) {
|
||||||
|
ensurePlaywrightBrowsersInstallation();
|
||||||
|
const e2eResults = runCLI(`e2e ${appName}-e2e`);
|
||||||
|
expect(e2eResults).toContain(
|
||||||
|
`Successfully ran target e2e for project ${appName}-e2e`
|
||||||
|
);
|
||||||
|
expect(await killPorts()).toBeTruthy();
|
||||||
|
}
|
||||||
|
}, 500000);
|
||||||
|
|
||||||
it('should remove previous output before building', async () => {
|
it('should remove previous output before building', async () => {
|
||||||
const appName = uniq('app');
|
const appName = uniq('app');
|
||||||
const libName = uniq('lib');
|
const libName = uniq('lib');
|
||||||
|
|||||||
@ -47,6 +47,7 @@
|
|||||||
// Installed by ensurePackage
|
// Installed by ensurePackage
|
||||||
"@nx/linter",
|
"@nx/linter",
|
||||||
"@nx/cypress",
|
"@nx/cypress",
|
||||||
|
"@nx/playwright",
|
||||||
"@nx/vite",
|
"@nx/vite",
|
||||||
"@nx/webpack",
|
"@nx/webpack",
|
||||||
"@nx/jest"
|
"@nx/jest"
|
||||||
|
|||||||
@ -8,6 +8,12 @@ import { Schema } from './schema';
|
|||||||
// need to mock cypress otherwise it'll use the nx installed version from package.json
|
// need to mock cypress otherwise it'll use the nx installed version from package.json
|
||||||
// which is v9 while we are testing for the new v10 version
|
// which is v9 while we are testing for the new v10 version
|
||||||
jest.mock('@nx/cypress/src/utils/cypress-version');
|
jest.mock('@nx/cypress/src/utils/cypress-version');
|
||||||
|
jest.mock('@nx/devkit', () => {
|
||||||
|
return {
|
||||||
|
...jest.requireActual('@nx/devkit'),
|
||||||
|
ensurePackage: jest.fn((pkg) => jest.requireActual(pkg)),
|
||||||
|
};
|
||||||
|
});
|
||||||
describe('app', () => {
|
describe('app', () => {
|
||||||
let tree: Tree;
|
let tree: Tree;
|
||||||
let mockedInstalledCypressVersion: jest.Mock<
|
let mockedInstalledCypressVersion: jest.Mock<
|
||||||
@ -135,6 +141,30 @@ describe('app', () => {
|
|||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should setup playwright e2e project', async () => {
|
||||||
|
await applicationGenerator(tree, {
|
||||||
|
name: 'cool-app',
|
||||||
|
e2eTestRunner: 'playwright',
|
||||||
|
unitTestRunner: 'none',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(readProjectConfiguration(tree, 'cool-app-e2e').targets.e2e)
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"executor": "@nx/playwright:playwright",
|
||||||
|
"options": {
|
||||||
|
"config": "apps/cool-app-e2e/playwright.config.ts",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"dist/.playwright/apps/cool-app-e2e",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
expect(
|
||||||
|
tree.exists('apps/cool-app-e2e/playwright.config.ts')
|
||||||
|
).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
it('should generate files if bundler is vite', async () => {
|
it('should generate files if bundler is vite', async () => {
|
||||||
await applicationGenerator(tree, {
|
await applicationGenerator(tree, {
|
||||||
name: 'myApp',
|
name: 'myApp',
|
||||||
|
|||||||
@ -241,10 +241,7 @@ export async function applicationGenerator(host: Tree, schema: Schema) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.linter === 'eslint') {
|
if (options.linter === 'eslint') {
|
||||||
const { lintProjectGenerator } = await ensurePackage(
|
const { lintProjectGenerator } = ensurePackage('@nx/linter', nxVersion);
|
||||||
'@nx/linter',
|
|
||||||
nxVersion
|
|
||||||
);
|
|
||||||
const lintTask = await lintProjectGenerator(host, {
|
const lintTask = await lintProjectGenerator(host, {
|
||||||
linter: options.linter,
|
linter: options.linter,
|
||||||
project: options.projectName,
|
project: options.projectName,
|
||||||
@ -260,7 +257,7 @@ export async function applicationGenerator(host: Tree, schema: Schema) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.e2eTestRunner === 'cypress') {
|
if (options.e2eTestRunner === 'cypress') {
|
||||||
const { cypressProjectGenerator } = await ensurePackage<
|
const { cypressProjectGenerator } = ensurePackage<
|
||||||
typeof import('@nx/cypress')
|
typeof import('@nx/cypress')
|
||||||
>('@nx/cypress', nxVersion);
|
>('@nx/cypress', nxVersion);
|
||||||
const cypressTask = await cypressProjectGenerator(host, {
|
const cypressTask = await cypressProjectGenerator(host, {
|
||||||
@ -271,11 +268,34 @@ export async function applicationGenerator(host: Tree, schema: Schema) {
|
|||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
tasks.push(cypressTask);
|
tasks.push(cypressTask);
|
||||||
|
} else if (options.e2eTestRunner === 'playwright') {
|
||||||
|
const { configurationGenerator: playwrightConfigGenerator } = ensurePackage<
|
||||||
|
typeof import('@nx/playwright')
|
||||||
|
>('@nx/playwright', nxVersion);
|
||||||
|
|
||||||
|
addProjectConfiguration(host, options.e2eProjectName, {
|
||||||
|
root: options.e2eProjectRoot,
|
||||||
|
sourceRoot: joinPathFragments(options.e2eProjectRoot, 'src'),
|
||||||
|
projectType: 'application',
|
||||||
|
targets: {},
|
||||||
|
implicitDependencies: [options.projectName],
|
||||||
|
});
|
||||||
|
const playwrightTask = await playwrightConfigGenerator(host, {
|
||||||
|
project: options.e2eProjectName,
|
||||||
|
skipFormat: true,
|
||||||
|
skipPackageJson: false,
|
||||||
|
directory: 'src',
|
||||||
|
js: false,
|
||||||
|
linter: options.linter,
|
||||||
|
setParserOptionsProject: options.setParserOptionsProject,
|
||||||
|
});
|
||||||
|
tasks.push(playwrightTask);
|
||||||
}
|
}
|
||||||
if (options.unitTestRunner === 'jest') {
|
if (options.unitTestRunner === 'jest') {
|
||||||
const { configurationGenerator } = await ensurePackage<
|
const { configurationGenerator } = ensurePackage<typeof import('@nx/jest')>(
|
||||||
typeof import('@nx/jest')
|
'@nx/jest',
|
||||||
>('@nx/jest', nxVersion);
|
nxVersion
|
||||||
|
);
|
||||||
const jestTask = await configurationGenerator(host, {
|
const jestTask = await configurationGenerator(host, {
|
||||||
project: options.projectName,
|
project: options.projectName,
|
||||||
skipSerializers: true,
|
skipSerializers: true,
|
||||||
|
|||||||
@ -11,7 +11,7 @@ export interface Schema {
|
|||||||
tags?: string;
|
tags?: string;
|
||||||
unitTestRunner?: 'jest' | 'vitest' | 'none';
|
unitTestRunner?: 'jest' | 'vitest' | 'none';
|
||||||
inSourceTests?: boolean;
|
inSourceTests?: boolean;
|
||||||
e2eTestRunner?: 'cypress' | 'none';
|
e2eTestRunner?: 'cypress' | 'playwright' | 'none';
|
||||||
linter?: Linter;
|
linter?: Linter;
|
||||||
standaloneConfig?: boolean;
|
standaloneConfig?: boolean;
|
||||||
setParserOptionsProject?: boolean;
|
setParserOptionsProject?: boolean;
|
||||||
|
|||||||
@ -82,7 +82,8 @@
|
|||||||
},
|
},
|
||||||
"e2eTestRunner": {
|
"e2eTestRunner": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["cypress", "none"],
|
"enum": ["cypress", "playwright", "none"],
|
||||||
|
"x-prompt": "Which E2E test runner would you like to use?",
|
||||||
"description": "Test runner to use for end to end (e2e) tests",
|
"description": "Test runner to use for end to end (e2e) tests",
|
||||||
"default": "cypress"
|
"default": "cypress"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
import {
|
import { addDependenciesToPackageJson, readJson, Tree } from '@nx/devkit';
|
||||||
addDependenciesToPackageJson,
|
|
||||||
NxJsonConfiguration,
|
|
||||||
readJson,
|
|
||||||
Tree,
|
|
||||||
updateJson,
|
|
||||||
} from '@nx/devkit';
|
|
||||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||||
|
|
||||||
import { nxVersion } from '../../utils/versions';
|
import { nxVersion } from '../../utils/versions';
|
||||||
|
|
||||||
import webInitGenerator from './init';
|
import webInitGenerator from './init';
|
||||||
|
jest.mock('@nx/devkit', () => {
|
||||||
|
return {
|
||||||
|
...jest.requireActual('@nx/devkit'),
|
||||||
|
ensurePackage: jest.fn((pkg) => jest.requireActual(pkg)),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
describe('init', () => {
|
describe('init', () => {
|
||||||
let tree: Tree;
|
let tree: Tree;
|
||||||
@ -45,4 +45,28 @@ describe('init', () => {
|
|||||||
});
|
});
|
||||||
expect(tree.exists('jest.config.js')).toBe(false);
|
expect(tree.exists('jest.config.js')).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should init playwright', async () => {
|
||||||
|
await webInitGenerator(tree, {
|
||||||
|
e2eTestRunner: 'playwright',
|
||||||
|
});
|
||||||
|
expect(readJson(tree, 'package.json').devDependencies).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
'@nx/playwright': expect.any(String),
|
||||||
|
'@playwright/test': expect.any(String),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should init cypress', async () => {
|
||||||
|
await webInitGenerator(tree, {
|
||||||
|
e2eTestRunner: 'cypress',
|
||||||
|
});
|
||||||
|
expect(readJson(tree, 'package.json').devDependencies).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
'@nx/cypress': expect.any(String),
|
||||||
|
cypress: expect.any(String),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -43,22 +43,31 @@ export async function webInitGenerator(tree: Tree, schema: Schema) {
|
|||||||
tasks.push(jsInitTask);
|
tasks.push(jsInitTask);
|
||||||
|
|
||||||
if (!schema.unitTestRunner || schema.unitTestRunner === 'jest') {
|
if (!schema.unitTestRunner || schema.unitTestRunner === 'jest') {
|
||||||
const { jestInitGenerator } = await ensurePackage('@nx/jest', nxVersion);
|
const { jestInitGenerator } = ensurePackage('@nx/jest', nxVersion);
|
||||||
const jestTask = await jestInitGenerator(tree, {
|
const jestTask = await jestInitGenerator(tree, {
|
||||||
skipPackageJson: schema.skipPackageJson,
|
skipPackageJson: schema.skipPackageJson,
|
||||||
});
|
});
|
||||||
tasks.push(jestTask);
|
tasks.push(jestTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!schema.e2eTestRunner || schema.e2eTestRunner === 'cypress') {
|
if (!schema.e2eTestRunner || schema.e2eTestRunner === 'cypress') {
|
||||||
const { cypressInitGenerator } = await ensurePackage(
|
const { cypressInitGenerator } = ensurePackage('@nx/cypress', nxVersion);
|
||||||
'@nx/cypress',
|
|
||||||
nxVersion
|
|
||||||
);
|
|
||||||
const cypressTask = await cypressInitGenerator(tree, {
|
const cypressTask = await cypressInitGenerator(tree, {
|
||||||
skipPackageJson: schema.skipPackageJson,
|
skipPackageJson: schema.skipPackageJson,
|
||||||
});
|
});
|
||||||
tasks.push(cypressTask);
|
tasks.push(cypressTask);
|
||||||
|
} else if (schema.e2eTestRunner === 'playwright') {
|
||||||
|
const { initGenerator: playwrightInitGenerator } = ensurePackage<
|
||||||
|
typeof import('@nx/playwright')
|
||||||
|
>('@nx/playwright', nxVersion);
|
||||||
|
|
||||||
|
const playwrightConfigTask = await playwrightInitGenerator(tree, {
|
||||||
|
skipFormat: true,
|
||||||
|
skipPackageJson: schema.skipPackageJson,
|
||||||
|
});
|
||||||
|
tasks.push(playwrightConfigTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!schema.skipPackageJson) {
|
if (!schema.skipPackageJson) {
|
||||||
const installTask = updateDependencies(tree, schema);
|
const installTask = updateDependencies(tree, schema);
|
||||||
tasks.push(installTask);
|
tasks.push(installTask);
|
||||||
|
|||||||
2
packages/web/src/generators/init/schema.d.ts
vendored
2
packages/web/src/generators/init/schema.d.ts
vendored
@ -1,7 +1,7 @@
|
|||||||
export interface Schema {
|
export interface Schema {
|
||||||
bundler?: 'webpack' | 'none' | 'vite';
|
bundler?: 'webpack' | 'none' | 'vite';
|
||||||
unitTestRunner?: 'jest' | 'vitest' | 'none';
|
unitTestRunner?: 'jest' | 'vitest' | 'none';
|
||||||
e2eTestRunner?: 'cypress' | 'none';
|
e2eTestRunner?: 'cypress' | 'playwright' | 'none';
|
||||||
skipFormat?: boolean;
|
skipFormat?: boolean;
|
||||||
skipPackageJson?: boolean;
|
skipPackageJson?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,8 @@
|
|||||||
"e2eTestRunner": {
|
"e2eTestRunner": {
|
||||||
"description": "Adds the specified e2e test runner",
|
"description": "Adds the specified e2e test runner",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["cypress", "none"],
|
"enum": ["cypress", "playwright", "none"],
|
||||||
|
"x-prompt": "Which E2E test runner would you like to use?",
|
||||||
"default": "cypress"
|
"default": "cypress"
|
||||||
},
|
},
|
||||||
"skipFormat": {
|
"skipFormat": {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user