feat(testing): add @nx/playwright plugin (#17975)
This commit is contained in:
parent
460e469617
commit
2128f8e3e2
@ -99,6 +99,8 @@ pnpm-lock.yaml @nrwl/nx-pipelines-reviewers
|
|||||||
/e2e/cypress/** @nrwl/nx-testing-tools-reviewers
|
/e2e/cypress/** @nrwl/nx-testing-tools-reviewers
|
||||||
/packages/jest/** @nrwl/nx-testing-tools-reviewers
|
/packages/jest/** @nrwl/nx-testing-tools-reviewers
|
||||||
/e2e/jest/** @nrwl/nx-testing-tools-reviewers
|
/e2e/jest/** @nrwl/nx-testing-tools-reviewers
|
||||||
|
/packages/playwright/** @nrwl/nx-testing-tools-reviewers
|
||||||
|
/e2e/playwright/** @nrwl/nx-testing-tools-reviewers
|
||||||
|
|
||||||
# Linter
|
# Linter
|
||||||
/docs/generated/packages/eslint-plugin/** @nrwl/nx-linter-reviewers @nrwl/nx-docs-reviewers
|
/docs/generated/packages/eslint-plugin/** @nrwl/nx-linter-reviewers @nrwl/nx-docs-reviewers
|
||||||
|
|||||||
13
e2e/playwright/jest.config.ts
Normal file
13
e2e/playwright/jest.config.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
export default {
|
||||||
|
transform: {
|
||||||
|
'^.+\\.[tj]sx?$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
|
||||||
|
},
|
||||||
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||||
|
maxWorkers: 1,
|
||||||
|
globals: {},
|
||||||
|
globalSetup: '../utils/global-setup.ts',
|
||||||
|
globalTeardown: '../utils/global-teardown.ts',
|
||||||
|
displayName: 'e2e-playwright',
|
||||||
|
preset: '../../jest.preset.js',
|
||||||
|
};
|
||||||
11
e2e/playwright/project.json
Normal file
11
e2e/playwright/project.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "e2e-playwright",
|
||||||
|
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"sourceRoot": "e2e/playwright",
|
||||||
|
"projectType": "application",
|
||||||
|
"targets": {
|
||||||
|
"e2e": {},
|
||||||
|
"run-e2e-tests": {}
|
||||||
|
},
|
||||||
|
"implicitDependencies": ["playwright"]
|
||||||
|
}
|
||||||
171
e2e/playwright/src/playwright.test.ts
Normal file
171
e2e/playwright/src/playwright.test.ts
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
import {
|
||||||
|
cleanupProject,
|
||||||
|
newProject,
|
||||||
|
uniq,
|
||||||
|
createFile,
|
||||||
|
runCLI,
|
||||||
|
packageInstall,
|
||||||
|
runCommand,
|
||||||
|
} from '@nx/e2e/utils';
|
||||||
|
|
||||||
|
const TEN_MINS_MS = 600_000;
|
||||||
|
describe('Playwright E2E Test runner', () => {
|
||||||
|
beforeAll(() => {
|
||||||
|
newProject({ name: uniq('playwright') });
|
||||||
|
packageInstall('@playwright/test', undefined, '^1.30.0', 'dev');
|
||||||
|
runCommand('npx playwright install --with-deps');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => cleanupProject());
|
||||||
|
|
||||||
|
it(
|
||||||
|
'should test example app',
|
||||||
|
() => {
|
||||||
|
//TODO: remove when generators are setup.Need to have basic workspace deps setup
|
||||||
|
runCLI(`g @nx/js:init`);
|
||||||
|
addSampleProject();
|
||||||
|
|
||||||
|
// NOTE: playwright throws errors if it detects running inside jest process. tmp remove and restore the env var for playwright to run
|
||||||
|
const results = runCLI(`e2e demo-e2e`);
|
||||||
|
expect(results).toContain('6 passed');
|
||||||
|
expect(results).toContain('Successfully ran target e2e for project');
|
||||||
|
},
|
||||||
|
TEN_MINS_MS
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: remove this when there are project generators
|
||||||
|
function addSampleProject() {
|
||||||
|
createFile(
|
||||||
|
'apps/demo-e2e/src/example.spec.ts',
|
||||||
|
`
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
|
test('has title', async ({ page }) => {
|
||||||
|
await page.goto('https://playwright.dev/');
|
||||||
|
|
||||||
|
// Expect a title "to contain" a substring.
|
||||||
|
await expect(page).toHaveTitle(/Playwright/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('get started link', async ({ page }) => {
|
||||||
|
await page.goto('https://playwright.dev/');
|
||||||
|
|
||||||
|
// Click the get started link.
|
||||||
|
await page.getByRole('link', { name: 'Get started' }).click();
|
||||||
|
|
||||||
|
// Expects the URL to contain intro.
|
||||||
|
await expect(page).toHaveURL(/.*intro/);
|
||||||
|
});
|
||||||
|
`
|
||||||
|
);
|
||||||
|
createFile(
|
||||||
|
'apps/demo-e2e/playwright.config.ts',
|
||||||
|
`
|
||||||
|
import { defineConfig, devices } from '@playwright/test';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read environment variables from file.
|
||||||
|
* https://github.com/motdotla/dotenv
|
||||||
|
*/
|
||||||
|
// require('dotenv').config();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See https://playwright.dev/docs/test-configuration.
|
||||||
|
*/
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: './src',
|
||||||
|
outputDir: '../../dist/playwright/apps/demo-e2e/output',
|
||||||
|
/* Run tests in files in parallel */
|
||||||
|
fullyParallel: true,
|
||||||
|
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||||
|
forbidOnly: !!process.env.CI,
|
||||||
|
/* Retry on CI only */
|
||||||
|
retries: process.env.CI ? 2 : 0,
|
||||||
|
/* Opt out of parallel tests on CI. */
|
||||||
|
workers: process.env.CI ? 1 : undefined,
|
||||||
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
|
reporter: [
|
||||||
|
[
|
||||||
|
'html',
|
||||||
|
{
|
||||||
|
outputFolder:
|
||||||
|
'../../dist/playwright/apps/demo-e2e/playwright-report',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||||
|
use: {
|
||||||
|
/* Base URL to use in actions like await page.goto('/'). */
|
||||||
|
// baseURL: 'http://127.0.0.1:3000',
|
||||||
|
|
||||||
|
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||||
|
trace: 'on-first-retry',
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Configure projects for major browsers */
|
||||||
|
projects: [
|
||||||
|
{
|
||||||
|
name: 'chromium',
|
||||||
|
use: { ...devices['Desktop Chrome'] },
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: 'firefox',
|
||||||
|
use: { ...devices['Desktop Firefox'] },
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: 'webkit',
|
||||||
|
use: { ...devices['Desktop Safari'] },
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Test against mobile viewports. */
|
||||||
|
// {
|
||||||
|
// name: 'Mobile Chrome',
|
||||||
|
// use: { ...devices['Pixel 5'] },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: 'Mobile Safari',
|
||||||
|
// use: { ...devices['iPhone 12'] },
|
||||||
|
// },
|
||||||
|
|
||||||
|
/* Test against branded browsers. */
|
||||||
|
// {
|
||||||
|
// name: 'Microsoft Edge',
|
||||||
|
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: 'Google Chrome',
|
||||||
|
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
|
||||||
|
// },
|
||||||
|
],
|
||||||
|
|
||||||
|
/* Run your local dev server before starting the tests */
|
||||||
|
// webServer: {
|
||||||
|
// command: 'npm run start',
|
||||||
|
// url: 'http://127.0.0.1:3000',
|
||||||
|
// reuseExistingServer: !process.env.CI,
|
||||||
|
// },
|
||||||
|
});
|
||||||
|
`
|
||||||
|
);
|
||||||
|
createFile(
|
||||||
|
'apps/demo-e2e/project.json',
|
||||||
|
JSON.stringify(
|
||||||
|
{
|
||||||
|
name: 'demo-e2e',
|
||||||
|
root: 'apps/demo-e2e',
|
||||||
|
sourceRoot: 'apps/demo-e2e/src',
|
||||||
|
targets: {
|
||||||
|
e2e: {
|
||||||
|
executor: '@nx/playwright:playwright',
|
||||||
|
options: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
13
e2e/playwright/tsconfig.json
Normal file
13
e2e/playwright/tsconfig.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"types": ["node", "jest"]
|
||||||
|
},
|
||||||
|
"include": [],
|
||||||
|
"files": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.spec.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
20
e2e/playwright/tsconfig.spec.json
Normal file
20
e2e/playwright/tsconfig.spec.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../dist/out-tsc",
|
||||||
|
"module": "commonjs",
|
||||||
|
"types": ["jest", "node"]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"**/*.test.ts",
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/*.spec.tsx",
|
||||||
|
"**/*.test.tsx",
|
||||||
|
"**/*.spec.js",
|
||||||
|
"**/*.test.js",
|
||||||
|
"**/*.spec.jsx",
|
||||||
|
"**/*.test.jsx",
|
||||||
|
"**/*.d.ts",
|
||||||
|
"jest.config.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -72,6 +72,7 @@ export function newProject({
|
|||||||
`@nx/next`,
|
`@nx/next`,
|
||||||
`@nx/node`,
|
`@nx/node`,
|
||||||
`@nx/plugin`,
|
`@nx/plugin`,
|
||||||
|
`@nx/playwright`,
|
||||||
`@nx/rollup`,
|
`@nx/rollup`,
|
||||||
`@nx/react`,
|
`@nx/react`,
|
||||||
`@nx/storybook`,
|
`@nx/storybook`,
|
||||||
|
|||||||
@ -122,6 +122,10 @@ export function getStrippedEnvironmentVariables() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key === 'JEST_WORKER_ID') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
const { getJestProjects } = require('@nx/jest');
|
import { getJestProjects } from '@nx/jest';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
projects: getJestProjects(),
|
projects: getJestProjects(),
|
||||||
|
|||||||
@ -124,6 +124,7 @@
|
|||||||
"@nrwl/next",
|
"@nrwl/next",
|
||||||
"@nx/node",
|
"@nx/node",
|
||||||
"@nrwl/node",
|
"@nrwl/node",
|
||||||
|
"@nx/playwright",
|
||||||
"@nx/plugin",
|
"@nx/plugin",
|
||||||
"@nrwl/nx-plugin",
|
"@nrwl/nx-plugin",
|
||||||
"@nx/react",
|
"@nx/react",
|
||||||
|
|||||||
25
packages/playwright/.eslintrc.json
Normal file
25
packages/playwright/.eslintrc.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"extends": ["../../.eslintrc.json"],
|
||||||
|
"ignorePatterns": ["!**/*"],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.ts", "*.tsx"],
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.js", "*.jsx"],
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["./package.json", "./executors.json"],
|
||||||
|
"parser": "jsonc-eslint-parser",
|
||||||
|
"rules": {
|
||||||
|
"@nx/nx-plugin-checks": "error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
11
packages/playwright/README.md
Normal file
11
packages/playwright/README.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<p style="text-align: center;"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx.png" width="600" alt="Nx - Smart, Fast and Extensible Build System"></p>
|
||||||
|
|
||||||
|
{{links}}
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
# Nx: Smart, Fast and Extensible Build System
|
||||||
|
|
||||||
|
Nx is a next generation build system with first class monorepo support and powerful integrations.
|
||||||
|
|
||||||
|
{{content}}
|
||||||
16
packages/playwright/executors.json
Normal file
16
packages/playwright/executors.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"builders": {
|
||||||
|
"playwright": {
|
||||||
|
"implementation": "./src/executors/playwright/compat",
|
||||||
|
"schema": "./src/executors/playwright/schema.json",
|
||||||
|
"description": "Run Playwright tests."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"executors": {
|
||||||
|
"playwright": {
|
||||||
|
"implementation": "./src/executors/playwright/playwright",
|
||||||
|
"schema": "./src/executors/playwright/schema.json",
|
||||||
|
"description": "Run Playwright tests."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
packages/playwright/jest.config.ts
Normal file
10
packages/playwright/jest.config.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
export default {
|
||||||
|
displayName: 'playwright',
|
||||||
|
preset: '../../jest.preset.js',
|
||||||
|
transform: {
|
||||||
|
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
|
||||||
|
},
|
||||||
|
moduleFileExtensions: ['ts', 'js', 'html'],
|
||||||
|
coverageDirectory: '../../coverage/packages/playwright',
|
||||||
|
};
|
||||||
43
packages/playwright/package.json
Normal file
43
packages/playwright/package.json
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"name": "@nx/playwright",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"type": "commonjs",
|
||||||
|
"homepage": "https://nx.dev",
|
||||||
|
"private": true,
|
||||||
|
"description": "The Nx Plugin for Playwright contains executors and generators allowing your workspace to use the powerful Playwright integration testing capabilities.",
|
||||||
|
"keywords": [
|
||||||
|
"Monorepo",
|
||||||
|
"Angular",
|
||||||
|
"React",
|
||||||
|
"Web",
|
||||||
|
"Node",
|
||||||
|
"Nest",
|
||||||
|
"Jest",
|
||||||
|
"Playwright",
|
||||||
|
"CLI"
|
||||||
|
],
|
||||||
|
"main": "./index",
|
||||||
|
"typings": "./index.d.ts",
|
||||||
|
"author": "Victor Savkin",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/nrwl/nx/issues"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/nrwl/nx.git",
|
||||||
|
"directory": "packages/playwright"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@nx/devkit": "file:../devkit"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@playwright/test": "^1.30.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@playwright/test": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"executors": "./executors.json"
|
||||||
|
}
|
||||||
50
packages/playwright/project.json
Normal file
50
packages/playwright/project.json
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"name": "playwright",
|
||||||
|
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"sourceRoot": "packages/playwright/src",
|
||||||
|
"projectType": "library",
|
||||||
|
"targets": {
|
||||||
|
"build": {
|
||||||
|
"executor": "nx:run-commands",
|
||||||
|
"outputs": ["{workspaceRoot}/build/packages/playwright"],
|
||||||
|
"options": {
|
||||||
|
"commands": ["node ./scripts/copy-readme.js playwright"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"build-base": {
|
||||||
|
"executor": "@nx/js:tsc",
|
||||||
|
"outputs": ["{options.outputPath}"],
|
||||||
|
"options": {
|
||||||
|
"outputPath": "build/packages/playwright",
|
||||||
|
"main": "packages/playwright/src/index.ts",
|
||||||
|
"tsConfig": "packages/playwright/tsconfig.lib.json",
|
||||||
|
"assets": [
|
||||||
|
"packages/playwright/*.md",
|
||||||
|
{
|
||||||
|
"input": "./packages/playwright/src",
|
||||||
|
"glob": "**/!(*.ts)",
|
||||||
|
"output": "./src"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"input": "./packages/playwright/src",
|
||||||
|
"glob": "**/*.d.ts",
|
||||||
|
"output": "./src"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"input": "./packages/playwright",
|
||||||
|
"glob": "generators.json",
|
||||||
|
"output": "."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"input": "./packages/playwright",
|
||||||
|
"glob": "executors.json",
|
||||||
|
"output": "."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": {},
|
||||||
|
"test": {}
|
||||||
|
},
|
||||||
|
"tags": []
|
||||||
|
}
|
||||||
4
packages/playwright/src/executors/playwright/compat.ts
Normal file
4
packages/playwright/src/executors/playwright/compat.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { convertNxExecutor } from '@nx/devkit';
|
||||||
|
import { playwrightExecutor } from './playwright';
|
||||||
|
|
||||||
|
export default convertNxExecutor(playwrightExecutor);
|
||||||
113
packages/playwright/src/executors/playwright/playwright.ts
Normal file
113
packages/playwright/src/executors/playwright/playwright.ts
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
import { fork } from 'child_process';
|
||||||
|
import { ExecutorContext, names } from '@nx/devkit';
|
||||||
|
import { join } from 'path';
|
||||||
|
|
||||||
|
export interface PlaywrightExecutorSchema {
|
||||||
|
/*
|
||||||
|
* if 'projects' is configured then that name needs to be provided instead of
|
||||||
|
* all, chromium, firefox, webkit
|
||||||
|
**/
|
||||||
|
browser?: 'all' | 'chromium' | 'firefox' | 'webkit' | string;
|
||||||
|
config?: string;
|
||||||
|
debug?: boolean;
|
||||||
|
forbidOnly?: boolean;
|
||||||
|
fullyParallel?: boolean;
|
||||||
|
grep?: string;
|
||||||
|
globalTimeout?: number;
|
||||||
|
grepInvert?: string;
|
||||||
|
headed?: boolean;
|
||||||
|
ignoreSnapshots?: boolean;
|
||||||
|
workers?: string;
|
||||||
|
list?: boolean;
|
||||||
|
maxFailures?: number | boolean;
|
||||||
|
noDeps?: boolean;
|
||||||
|
output?: string;
|
||||||
|
passWithNoTests?: boolean;
|
||||||
|
project?: string[];
|
||||||
|
quiet?: boolean;
|
||||||
|
repeatEach?: number;
|
||||||
|
reporter?:
|
||||||
|
| 'list'
|
||||||
|
| 'line'
|
||||||
|
| 'dot'
|
||||||
|
| 'json'
|
||||||
|
| 'junit'
|
||||||
|
| 'null'
|
||||||
|
| 'github'
|
||||||
|
| 'html'
|
||||||
|
| 'blob';
|
||||||
|
retries?: number;
|
||||||
|
shard?: string;
|
||||||
|
timeout?: number;
|
||||||
|
trace?:
|
||||||
|
| 'on'
|
||||||
|
| 'off'
|
||||||
|
| 'on-first-retry'
|
||||||
|
| 'on-all-retries'
|
||||||
|
| 'retain-on-failure';
|
||||||
|
updateSnapshots?: boolean;
|
||||||
|
ui?: boolean;
|
||||||
|
uiHost?: string;
|
||||||
|
uiPort?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function playwrightExecutor(
|
||||||
|
options: PlaywrightExecutorSchema,
|
||||||
|
context: ExecutorContext
|
||||||
|
) {
|
||||||
|
const projectRoot =
|
||||||
|
context.projectGraph?.nodes?.[context?.projectName]?.data?.root;
|
||||||
|
|
||||||
|
if (!projectRoot) {
|
||||||
|
throw new Error(
|
||||||
|
`Unable to find the Project Root for ${context.projectName}. Is it set in the project.json?`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const args = createArgs(options);
|
||||||
|
const p = runPlaywright(args, join(context.root, projectRoot));
|
||||||
|
|
||||||
|
return new Promise<{ success: boolean }>((resolve) => {
|
||||||
|
p.on('close', (code) => {
|
||||||
|
resolve({ success: code === 0 });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createArgs(opts: PlaywrightExecutorSchema): string[] {
|
||||||
|
const args: string[] = [];
|
||||||
|
|
||||||
|
for (const key in opts) {
|
||||||
|
const value = opts[key];
|
||||||
|
// NOTE: playwright doesn't accept pascalCase args, only kebab-case
|
||||||
|
const arg = names(key).fileName;
|
||||||
|
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
args.push(`--${arg}=${value.map((v) => v.trim()).join(',')}`);
|
||||||
|
} else if (typeof value === 'boolean') {
|
||||||
|
// NOTE: playwright don't accept --arg=false, instead just don't pass the arg.
|
||||||
|
if (value) {
|
||||||
|
args.push(`--${arg}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
args.push(`--${arg}=${value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
function runPlaywright(args: string[], cwd: string) {
|
||||||
|
try {
|
||||||
|
const cli = require.resolve('@playwright/test/cli');
|
||||||
|
|
||||||
|
return fork(cli, ['test', ...args], {
|
||||||
|
stdio: 'inherit',
|
||||||
|
cwd,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
throw new Error('Unable to run playwright. Is @playwright/test installed?');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default playwrightExecutor;
|
||||||
155
packages/playwright/src/executors/playwright/schema.json
Normal file
155
packages/playwright/src/executors/playwright/schema.json
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/schema",
|
||||||
|
"version": 2,
|
||||||
|
"title": "Playwright executor",
|
||||||
|
"description": "Run Playwright tests.",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"browser": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Browser to use for tests, one of 'all', 'chromium', 'firefox' or 'webkit'. If a playwright config is provided/discovered then the browserName value is expected from the configured 'projects'",
|
||||||
|
"x-priority": "important"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Configuration file, or a test directory with optional",
|
||||||
|
"x-completion-type": "file",
|
||||||
|
"x-completion-glob": "playwright?(*)@(.js|.cjs|.mjs|.ts|.cts|.mtx)",
|
||||||
|
"x-priority": "important"
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Run tests with Playwright Inspector. Shortcut for 'PWDEBUG=1' environment variable and '--timeout=0',--max-failures=1 --headed --workers=1' options"
|
||||||
|
},
|
||||||
|
"forbidOnly": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Fail if test.only is called"
|
||||||
|
},
|
||||||
|
"fullyParallel": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Run all tests in parallel"
|
||||||
|
},
|
||||||
|
"grep": {
|
||||||
|
"alias": "g",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Only run tests matching this regular expression"
|
||||||
|
},
|
||||||
|
"globalTimeout": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Maximum time this test suite can run in milliseconds"
|
||||||
|
},
|
||||||
|
"grepInvert": {
|
||||||
|
"alias": "gv",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Only run tests that do not match this regular expression"
|
||||||
|
},
|
||||||
|
"headed": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Run tests in headed browsers",
|
||||||
|
"x-priority": "important"
|
||||||
|
},
|
||||||
|
"ignoreSnapshots": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Ignore screenshot and snapshot expectations"
|
||||||
|
},
|
||||||
|
"workers": {
|
||||||
|
"alias": "j",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Number of concurrent workers or percentage of logical CPU cores, use 1 to run in a single worker"
|
||||||
|
},
|
||||||
|
"list": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Collect all the tests and report them, but do not run"
|
||||||
|
},
|
||||||
|
"maxFailures": {
|
||||||
|
"alias": "x",
|
||||||
|
"oneOf": [{ "type": "number" }, { "type": "boolean" }],
|
||||||
|
"description": "Stop after the first N failures"
|
||||||
|
},
|
||||||
|
"noDeps": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Do not run project dependencies"
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Folder for output artifacts"
|
||||||
|
},
|
||||||
|
"passWithNoTests": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Makes test run succeed even if no tests were found",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"project": {
|
||||||
|
"description": "Only run tests from the specified list of projects",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"quiet": {
|
||||||
|
"alias": "q",
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Suppress stdio"
|
||||||
|
},
|
||||||
|
"repeatEach": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Run each test N times"
|
||||||
|
},
|
||||||
|
"reporter": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"list",
|
||||||
|
"line",
|
||||||
|
"dot",
|
||||||
|
"json",
|
||||||
|
"junit",
|
||||||
|
"null",
|
||||||
|
"github",
|
||||||
|
"html",
|
||||||
|
"blob"
|
||||||
|
],
|
||||||
|
"description": "Reporter to use, comma-separated, can be 'list', 'line', 'dot', 'json', 'junit', 'null', 'github', 'html', 'blob'. To configure reporter options, use the playwright configuration."
|
||||||
|
},
|
||||||
|
"retries": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Maximum retry count for flaky tests, zero for no retries"
|
||||||
|
},
|
||||||
|
"shard": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Shard tests and execute only the selected shard, specify in the form 'current/all', 1-based, for example '3/5'"
|
||||||
|
},
|
||||||
|
"timeout": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Specify test timeout threshold in milliseconds, zero for unlimited"
|
||||||
|
},
|
||||||
|
"trace": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"on",
|
||||||
|
"off",
|
||||||
|
"on-first-retry",
|
||||||
|
"on-all-retries",
|
||||||
|
"retain-on-failure"
|
||||||
|
],
|
||||||
|
"description": "Force tracing mode, can be 'on', 'off', 'on-first-retry', 'on-all-retries', 'retain-on-failure'"
|
||||||
|
},
|
||||||
|
"updateSnapshots": {
|
||||||
|
"alias": "u",
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Update snapshots with actual results. Snapshots will be created if missing."
|
||||||
|
},
|
||||||
|
"ui": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Run tests in interactive UI mode"
|
||||||
|
},
|
||||||
|
"uiHost": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Host to serve UI on; specifying this option opens UI in a browser tab"
|
||||||
|
},
|
||||||
|
"uiPort": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Port to serve UI on, 0 for any free port; specifying this option opens UI in a browser tab"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": []
|
||||||
|
}
|
||||||
4
packages/playwright/src/index.ts
Normal file
4
packages/playwright/src/index.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export {
|
||||||
|
playwrightExecutor,
|
||||||
|
PlaywrightExecutorSchema,
|
||||||
|
} from './executors/playwright/playwright';
|
||||||
16
packages/playwright/tsconfig.json
Normal file
16
packages/playwright/tsconfig.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs"
|
||||||
|
},
|
||||||
|
"files": [],
|
||||||
|
"include": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.lib.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.spec.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
10
packages/playwright/tsconfig.lib.json
Normal file
10
packages/playwright/tsconfig.lib.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../dist/out-tsc",
|
||||||
|
"declaration": true,
|
||||||
|
"types": ["node"]
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts"],
|
||||||
|
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
|
||||||
|
}
|
||||||
14
packages/playwright/tsconfig.spec.json
Normal file
14
packages/playwright/tsconfig.spec.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../dist/out-tsc",
|
||||||
|
"module": "commonjs",
|
||||||
|
"types": ["jest", "node"]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"jest.config.ts",
|
||||||
|
"src/**/*.test.ts",
|
||||||
|
"src/**/*.spec.ts",
|
||||||
|
"src/**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -83,6 +83,7 @@
|
|||||||
"@nx/nx-dev/ui-references": ["nx-dev/ui-references/src/index.ts"],
|
"@nx/nx-dev/ui-references": ["nx-dev/ui-references/src/index.ts"],
|
||||||
"@nx/nx-dev/ui-sponsor-card": ["nx-dev/ui-sponsor-card/src/index.ts"],
|
"@nx/nx-dev/ui-sponsor-card": ["nx-dev/ui-sponsor-card/src/index.ts"],
|
||||||
"@nx/nx-dev/ui-theme": ["nx-dev/ui-theme/src/index.ts"],
|
"@nx/nx-dev/ui-theme": ["nx-dev/ui-theme/src/index.ts"],
|
||||||
|
"@nx/playwright": ["packages/playwright/src/index.ts"],
|
||||||
"@nx/plugin": ["packages/plugin"],
|
"@nx/plugin": ["packages/plugin"],
|
||||||
"@nx/plugin/*": ["packages/plugin/*"],
|
"@nx/plugin/*": ["packages/plugin/*"],
|
||||||
"@nx/react": ["packages/react"],
|
"@nx/react": ["packages/react"],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user