@nx/playwright 20.0.10 → 20.1.0-beta.1
Sign up to get free protection for your applications and to get access to all the features.
- package/package.json +6 -6
- package/src/generators/configuration/configuration.d.ts +2 -2
- package/src/generators/configuration/configuration.js +93 -15
- package/src/generators/configuration/schema.d.ts +13 -6
- package/src/generators/configuration/schema.json +6 -6
- package/src/generators/init/init.js +0 -2
- package/src/plugins/plugin.js +81 -45
- package/src/utils/preset.js +9 -3
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@nx/playwright",
|
3
|
-
"version": "20.0.
|
3
|
+
"version": "20.1.0-beta.1",
|
4
4
|
"type": "commonjs",
|
5
5
|
"homepage": "https://nx.dev",
|
6
6
|
"private": false,
|
@@ -35,11 +35,11 @@
|
|
35
35
|
},
|
36
36
|
"dependencies": {
|
37
37
|
"@phenomnomnominal/tsquery": "~5.0.1",
|
38
|
-
"@nx/devkit": "20.0.
|
39
|
-
"@nx/eslint": "20.0.
|
40
|
-
"@nx/webpack": "20.0.
|
41
|
-
"@nx/vite": "20.0.
|
42
|
-
"@nx/js": "20.0.
|
38
|
+
"@nx/devkit": "20.1.0-beta.1",
|
39
|
+
"@nx/eslint": "20.1.0-beta.1",
|
40
|
+
"@nx/webpack": "20.1.0-beta.1",
|
41
|
+
"@nx/vite": "20.1.0-beta.1",
|
42
|
+
"@nx/js": "20.1.0-beta.1",
|
43
43
|
"tslib": "^2.3.0",
|
44
44
|
"minimatch": "9.0.3"
|
45
45
|
},
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { GeneratorCallback, Tree } from '@nx/devkit';
|
2
|
-
import { ConfigurationGeneratorSchema } from './schema';
|
2
|
+
import type { ConfigurationGeneratorSchema } from './schema';
|
3
3
|
export declare function configurationGenerator(tree: Tree, options: ConfigurationGeneratorSchema): Promise<GeneratorCallback>;
|
4
|
-
export declare function configurationGeneratorInternal(tree: Tree,
|
4
|
+
export declare function configurationGeneratorInternal(tree: Tree, rawOptions: ConfigurationGeneratorSchema): Promise<GeneratorCallback>;
|
5
5
|
export default configurationGenerator;
|
@@ -3,23 +3,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.configurationGenerator = configurationGenerator;
|
4
4
|
exports.configurationGeneratorInternal = configurationGeneratorInternal;
|
5
5
|
const devkit_1 = require("@nx/devkit");
|
6
|
+
const project_name_and_root_utils_1 = require("@nx/devkit/src/generators/project-name-and-root-utils");
|
7
|
+
const prompt_1 = require("@nx/devkit/src/generators/prompt");
|
6
8
|
const js_1 = require("@nx/js");
|
9
|
+
const package_manager_workspaces_1 = require("@nx/js/src/utils/package-manager-workspaces");
|
10
|
+
const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescript");
|
7
11
|
const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
|
8
|
-
const versions_1 = require("@nx/js/src/utils/versions");
|
9
12
|
const child_process_1 = require("child_process");
|
10
13
|
const path = require("path");
|
11
14
|
const add_linter_1 = require("../../utils/add-linter");
|
12
|
-
const
|
15
|
+
const versions_1 = require("../../utils/versions");
|
13
16
|
const init_1 = require("../init/init");
|
14
17
|
function configurationGenerator(tree, options) {
|
15
18
|
return configurationGeneratorInternal(tree, { addPlugin: false, ...options });
|
16
19
|
}
|
17
|
-
async function configurationGeneratorInternal(tree,
|
18
|
-
|
19
|
-
const nxJson = (0, devkit_1.readNxJson)(tree);
|
20
|
-
options.addPlugin ??=
|
21
|
-
process.env.NX_ADD_PLUGINS !== 'false' &&
|
22
|
-
nxJson.useInferencePlugins !== false;
|
20
|
+
async function configurationGeneratorInternal(tree, rawOptions) {
|
21
|
+
const options = await normalizeOptions(tree, rawOptions);
|
23
22
|
const tasks = [];
|
24
23
|
tasks.push(await (0, init_1.initGenerator)(tree, {
|
25
24
|
skipFormat: true,
|
@@ -27,7 +26,6 @@ async function configurationGeneratorInternal(tree, options) {
|
|
27
26
|
addPlugin: options.addPlugin,
|
28
27
|
}));
|
29
28
|
const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.project);
|
30
|
-
const hasTsConfig = tree.exists((0, devkit_1.joinPathFragments)(projectConfig.root, 'tsconfig.json'));
|
31
29
|
const offsetFromProjectRoot = (0, devkit_1.offsetFromRoot)(projectConfig.root);
|
32
30
|
(0, devkit_1.generateFiles)(tree, path.join(__dirname, 'files'), projectConfig.root, {
|
33
31
|
offsetFromRoot: offsetFromProjectRoot,
|
@@ -36,13 +34,14 @@ async function configurationGeneratorInternal(tree, options) {
|
|
36
34
|
webServerAddress: options.webServerAddress ?? null,
|
37
35
|
...options,
|
38
36
|
});
|
39
|
-
|
40
|
-
|
37
|
+
const isTsSolutionSetup = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree);
|
38
|
+
const tsconfigPath = (0, devkit_1.joinPathFragments)(projectConfig.root, 'tsconfig.json');
|
39
|
+
if (!tree.exists(tsconfigPath)) {
|
40
|
+
const tsconfig = {
|
41
41
|
extends: (0, js_1.getRelativePathToRootTsConfig)(tree, projectConfig.root),
|
42
42
|
compilerOptions: {
|
43
43
|
allowJs: true,
|
44
44
|
outDir: `${offsetFromProjectRoot}dist/out-tsc`,
|
45
|
-
module: 'commonjs',
|
46
45
|
sourceMap: false,
|
47
46
|
},
|
48
47
|
include: [
|
@@ -55,7 +54,37 @@ async function configurationGeneratorInternal(tree, options) {
|
|
55
54
|
'src/**/*.test.js',
|
56
55
|
'src/**/*.d.ts',
|
57
56
|
],
|
58
|
-
}
|
57
|
+
};
|
58
|
+
if (isTsSolutionSetup) {
|
59
|
+
tsconfig.compilerOptions.outDir = 'dist';
|
60
|
+
tsconfig.compilerOptions.tsBuildInfoFile = 'dist/tsconfig.tsbuildinfo';
|
61
|
+
if (!options.rootProject) {
|
62
|
+
// add the project tsconfog to the workspace root tsconfig.json references
|
63
|
+
(0, devkit_1.updateJson)(tree, 'tsconfig.json', (json) => {
|
64
|
+
json.references ??= [];
|
65
|
+
json.references.push({ path: './' + projectConfig.root });
|
66
|
+
return json;
|
67
|
+
});
|
68
|
+
}
|
69
|
+
}
|
70
|
+
else {
|
71
|
+
tsconfig.compilerOptions.outDir = `${offsetFromProjectRoot}dist/out-tsc`;
|
72
|
+
tsconfig.compilerOptions.module = 'commonjs';
|
73
|
+
}
|
74
|
+
(0, devkit_1.writeJson)(tree, tsconfigPath, tsconfig);
|
75
|
+
}
|
76
|
+
if (isTsSolutionSetup) {
|
77
|
+
const packageJsonPath = (0, devkit_1.joinPathFragments)(projectConfig.root, 'package.json');
|
78
|
+
if (!tree.exists(packageJsonPath)) {
|
79
|
+
const importPath = (0, project_name_and_root_utils_1.resolveImportPath)(tree, projectConfig.name, projectConfig.root);
|
80
|
+
const packageJson = {
|
81
|
+
name: importPath,
|
82
|
+
version: '0.0.1',
|
83
|
+
private: true,
|
84
|
+
};
|
85
|
+
(0, devkit_1.writeJson)(tree, packageJsonPath, packageJson);
|
86
|
+
}
|
87
|
+
ignoreTestOutput(tree);
|
59
88
|
}
|
60
89
|
const hasPlugin = (0, devkit_1.readNxJson)(tree).plugins?.some((p) => typeof p === 'string'
|
61
90
|
? p === '@nx/playwright/plugin'
|
@@ -75,14 +104,14 @@ async function configurationGeneratorInternal(tree, options) {
|
|
75
104
|
addPlugin: options.addPlugin,
|
76
105
|
}));
|
77
106
|
if (options.js) {
|
78
|
-
const { ModuleKind } = (0,
|
107
|
+
const { ModuleKind } = (0, ensure_typescript_1.ensureTypescript)();
|
79
108
|
(0, devkit_1.toJS)(tree, { extension: '.cjs', module: ModuleKind.CommonJS });
|
80
109
|
}
|
81
110
|
recommendVsCodeExtensions(tree);
|
82
111
|
if (!options.skipPackageJson) {
|
83
112
|
tasks.push((0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
|
84
113
|
// required since used in playwright config
|
85
|
-
'@nx/devkit':
|
114
|
+
'@nx/devkit': versions_1.nxVersion,
|
86
115
|
}));
|
87
116
|
}
|
88
117
|
if (!options.skipInstall) {
|
@@ -91,8 +120,46 @@ async function configurationGeneratorInternal(tree, options) {
|
|
91
120
|
if (!options.skipFormat) {
|
92
121
|
await (0, devkit_1.formatFiles)(tree);
|
93
122
|
}
|
123
|
+
if (isTsSolutionSetup) {
|
124
|
+
const projectPackageManagerWorkspaceState = (0, package_manager_workspaces_1.getProjectPackageManagerWorkspaceState)(tree, projectConfig.root);
|
125
|
+
if (projectPackageManagerWorkspaceState !== 'included') {
|
126
|
+
tasks.push((0, package_manager_workspaces_1.getProjectPackageManagerWorkspaceStateWarningTask)(projectPackageManagerWorkspaceState, tree.root));
|
127
|
+
}
|
128
|
+
}
|
94
129
|
return (0, devkit_1.runTasksInSerial)(...tasks);
|
95
130
|
}
|
131
|
+
async function normalizeOptions(tree, options) {
|
132
|
+
const nxJson = (0, devkit_1.readNxJson)(tree);
|
133
|
+
const addPlugin = options.addPlugin ??
|
134
|
+
(process.env.NX_ADD_PLUGINS !== 'false' &&
|
135
|
+
nxJson.useInferencePlugins !== false);
|
136
|
+
const isTsSolutionSetup = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree);
|
137
|
+
let linter = options.linter;
|
138
|
+
if (isTsSolutionSetup) {
|
139
|
+
linter ??= await (0, prompt_1.promptWhenInteractive)({
|
140
|
+
type: 'select',
|
141
|
+
name: 'linter',
|
142
|
+
message: `Which linter would you like to use?`,
|
143
|
+
choices: [{ name: 'none' }, { name: 'eslint' }],
|
144
|
+
initial: 0,
|
145
|
+
}, { linter: 'none' }).then(({ linter }) => linter);
|
146
|
+
}
|
147
|
+
else {
|
148
|
+
linter ??= await (0, prompt_1.promptWhenInteractive)({
|
149
|
+
type: 'select',
|
150
|
+
name: 'linter',
|
151
|
+
message: `Which linter would you like to use?`,
|
152
|
+
choices: [{ name: 'eslint' }, { name: 'none' }],
|
153
|
+
initial: 0,
|
154
|
+
}, { linter: 'eslint' }).then(({ linter }) => linter);
|
155
|
+
}
|
156
|
+
return {
|
157
|
+
...options,
|
158
|
+
addPlugin,
|
159
|
+
linter,
|
160
|
+
directory: options.directory ?? 'e2e',
|
161
|
+
};
|
162
|
+
}
|
96
163
|
function getBrowsersInstallTask() {
|
97
164
|
return () => {
|
98
165
|
devkit_1.output.log({
|
@@ -154,4 +221,15 @@ Rename or remove the existing e2e target.`);
|
|
154
221
|
};
|
155
222
|
(0, devkit_1.updateProjectConfiguration)(tree, options.project, projectConfig);
|
156
223
|
}
|
224
|
+
function ignoreTestOutput(tree) {
|
225
|
+
if (!tree.exists('.gitignore')) {
|
226
|
+
devkit_1.logger.warn(`Couldn't find a root .gitignore file to update.`);
|
227
|
+
}
|
228
|
+
let content = tree.read('.gitignore', 'utf-8');
|
229
|
+
if (/^test-output$/gm.test(content)) {
|
230
|
+
return;
|
231
|
+
}
|
232
|
+
content = `${content}\ntest-output\n`;
|
233
|
+
tree.write('.gitignore', content);
|
234
|
+
}
|
157
235
|
exports.default = configurationGenerator;
|
@@ -5,13 +5,13 @@ export interface ConfigurationGeneratorSchema {
|
|
5
5
|
/**
|
6
6
|
* this is relative to the projectRoot
|
7
7
|
**/
|
8
|
-
directory
|
9
|
-
js
|
10
|
-
skipFormat
|
11
|
-
skipPackageJson
|
8
|
+
directory?: string;
|
9
|
+
js?: boolean; // default is false
|
10
|
+
skipFormat?: boolean;
|
11
|
+
skipPackageJson?: boolean;
|
12
12
|
skipInstall?: boolean;
|
13
|
-
linter
|
14
|
-
setParserOptionsProject
|
13
|
+
linter?: Linter | LinterType;
|
14
|
+
setParserOptionsProject?: boolean; // default is false
|
15
15
|
/**
|
16
16
|
* command to give playwright to run the web server
|
17
17
|
* @example: "npx nx serve my-fe-app"
|
@@ -25,3 +25,10 @@ export interface ConfigurationGeneratorSchema {
|
|
25
25
|
rootProject?: boolean;
|
26
26
|
addPlugin?: boolean;
|
27
27
|
}
|
28
|
+
|
29
|
+
export interface NormalizedGeneratorOptions
|
30
|
+
extends ConfigurationGeneratorSchema {
|
31
|
+
addPlugin: boolean;
|
32
|
+
directory: string;
|
33
|
+
linter: Linter | LinterType;
|
34
|
+
}
|
@@ -20,6 +20,12 @@
|
|
20
20
|
"x-priority": "important",
|
21
21
|
"default": "e2e"
|
22
22
|
},
|
23
|
+
"linter": {
|
24
|
+
"description": "The tool to use for running lint checks.",
|
25
|
+
"type": "string",
|
26
|
+
"enum": ["none", "eslint"],
|
27
|
+
"x-priority": "important"
|
28
|
+
},
|
23
29
|
"js": {
|
24
30
|
"type": "boolean",
|
25
31
|
"description": "Generate JavaScript files rather than TypeScript files.",
|
@@ -33,12 +39,6 @@
|
|
33
39
|
"type": "string",
|
34
40
|
"description": "The address of the web server."
|
35
41
|
},
|
36
|
-
"linter": {
|
37
|
-
"description": "The tool to use for running lint checks.",
|
38
|
-
"type": "string",
|
39
|
-
"enum": ["eslint", "none"],
|
40
|
-
"default": "eslint"
|
41
|
-
},
|
42
42
|
"setParserOptionsProject": {
|
43
43
|
"type": "boolean",
|
44
44
|
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
@@ -4,14 +4,12 @@ exports.initGenerator = initGenerator;
|
|
4
4
|
exports.initGeneratorInternal = initGeneratorInternal;
|
5
5
|
const devkit_1 = require("@nx/devkit");
|
6
6
|
const add_plugin_1 = require("@nx/devkit/src/utils/add-plugin");
|
7
|
-
const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
|
8
7
|
const plugin_1 = require("../../plugins/plugin");
|
9
8
|
const versions_1 = require("../../utils/versions");
|
10
9
|
function initGenerator(tree, options) {
|
11
10
|
return initGeneratorInternal(tree, { addPlugin: false, ...options });
|
12
11
|
}
|
13
12
|
async function initGeneratorInternal(tree, options) {
|
14
|
-
(0, ts_solution_setup_1.assertNotUsingTsSolutionSetup)(tree, 'playwright', 'init');
|
15
13
|
const tasks = [];
|
16
14
|
const nxJson = (0, devkit_1.readNxJson)(tree);
|
17
15
|
const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
|
package/src/plugins/plugin.js
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.createNodes = exports.createNodesV2 = void 0;
|
4
|
-
const
|
5
|
-
const
|
4
|
+
const node_fs_1 = require("node:fs");
|
5
|
+
const node_path_1 = require("node:path");
|
6
6
|
const devkit_1 = require("@nx/devkit");
|
7
7
|
const get_named_inputs_1 = require("@nx/devkit/src/utils/get-named-inputs");
|
8
8
|
const calculate_hash_for_create_nodes_1 = require("@nx/devkit/src/utils/calculate-hash-for-create-nodes");
|
@@ -14,7 +14,7 @@ const config_utils_1 = require("@nx/devkit/src/utils/config-utils");
|
|
14
14
|
const file_hasher_1 = require("nx/src/hasher/file-hasher");
|
15
15
|
const pmc = (0, devkit_1.getPackageManagerCommand)();
|
16
16
|
function readTargetsCache(cachePath) {
|
17
|
-
return (0,
|
17
|
+
return (0, node_fs_1.existsSync)(cachePath) ? (0, devkit_1.readJsonFile)(cachePath) : {};
|
18
18
|
}
|
19
19
|
function writeTargetsToCache(cachePath, results) {
|
20
20
|
(0, devkit_1.writeJsonFile)(cachePath, results);
|
@@ -24,7 +24,7 @@ exports.createNodesV2 = [
|
|
24
24
|
playwrightConfigGlob,
|
25
25
|
async (configFilePaths, options, context) => {
|
26
26
|
const optionsHash = (0, file_hasher_1.hashObject)(options);
|
27
|
-
const cachePath = (0,
|
27
|
+
const cachePath = (0, node_path_1.join)(cache_directory_1.workspaceDataDirectory, `playwright-${optionsHash}.hash`);
|
28
28
|
const targetsCache = readTargetsCache(cachePath);
|
29
29
|
try {
|
30
30
|
return await (0, devkit_1.createNodesFromFiles)((configFile, options, context) => createNodesInternal(configFile, options, context, targetsCache), configFilePaths, options, context);
|
@@ -46,9 +46,9 @@ exports.createNodes = [
|
|
46
46
|
},
|
47
47
|
];
|
48
48
|
async function createNodesInternal(configFilePath, options, context, targetsCache) {
|
49
|
-
const projectRoot = (0,
|
49
|
+
const projectRoot = (0, node_path_1.dirname)(configFilePath);
|
50
50
|
// Do not create a project if package.json and project.json isn't there.
|
51
|
-
const siblingFiles = (0,
|
51
|
+
const siblingFiles = (0, node_fs_1.readdirSync)((0, node_path_1.join)(context.workspaceRoot, projectRoot));
|
52
52
|
if (!siblingFiles.includes('package.json') &&
|
53
53
|
!siblingFiles.includes('project.json')) {
|
54
54
|
return {};
|
@@ -72,10 +72,12 @@ async function buildPlaywrightTargets(configFilePath, projectRoot, options, cont
|
|
72
72
|
// but we're just reading the config so let's delete the variable they are using to detect this.
|
73
73
|
// See: https://github.com/microsoft/playwright/pull/11218/files
|
74
74
|
delete process['__pw_initiator__'];
|
75
|
-
const playwrightConfig = await (0, config_utils_1.loadConfigFile)((0,
|
75
|
+
const playwrightConfig = await (0, config_utils_1.loadConfigFile)((0, node_path_1.join)(context.workspaceRoot, configFilePath));
|
76
76
|
const namedInputs = (0, get_named_inputs_1.getNamedInputs)(projectRoot, context);
|
77
77
|
const targets = {};
|
78
78
|
let metadata;
|
79
|
+
const testOutput = getTestOutput(playwrightConfig);
|
80
|
+
const reporterOutputs = getReporterOutputs(playwrightConfig);
|
79
81
|
const baseTargetConfig = {
|
80
82
|
command: 'playwright test',
|
81
83
|
options: {
|
@@ -104,7 +106,7 @@ async function buildPlaywrightTargets(configFilePath, projectRoot, options, cont
|
|
104
106
|
: ['default', '^default']),
|
105
107
|
{ externalDependencies: ['@playwright/test'] },
|
106
108
|
],
|
107
|
-
outputs:
|
109
|
+
outputs: getTargetOutputs(testOutput, reporterOutputs, projectRoot),
|
108
110
|
};
|
109
111
|
if (options.ciTargetName) {
|
110
112
|
const ciBaseTargetConfig = {
|
@@ -116,7 +118,7 @@ async function buildPlaywrightTargets(configFilePath, projectRoot, options, cont
|
|
116
118
|
: ['default', '^default']),
|
117
119
|
{ externalDependencies: ['@playwright/test'] },
|
118
120
|
],
|
119
|
-
outputs:
|
121
|
+
outputs: getTargetOutputs(testOutput, reporterOutputs, projectRoot),
|
120
122
|
};
|
121
123
|
const groupName = 'E2E (CI)';
|
122
124
|
metadata = { targetGroups: { [groupName]: [] } };
|
@@ -128,12 +130,20 @@ async function buildPlaywrightTargets(configFilePath, projectRoot, options, cont
|
|
128
130
|
playwrightConfig.testMatch ??= '**/*.@(spec|test).?(c|m)[jt]s?(x)';
|
129
131
|
const dependsOn = [];
|
130
132
|
await forEachTestFile((testFile) => {
|
131
|
-
const
|
133
|
+
const outputSubfolder = (0, node_path_1.relative)(projectRoot, testFile)
|
134
|
+
.replace(/[\/\\]/g, '-')
|
135
|
+
.replace(/\./g, '-');
|
136
|
+
const relativeSpecFilePath = (0, devkit_1.normalizePath)((0, node_path_1.relative)(projectRoot, testFile));
|
132
137
|
const targetName = `${options.ciTargetName}--${relativeSpecFilePath}`;
|
133
138
|
ciTargetGroup.push(targetName);
|
134
139
|
targets[targetName] = {
|
135
140
|
...ciBaseTargetConfig,
|
136
|
-
|
141
|
+
options: {
|
142
|
+
...ciBaseTargetConfig.options,
|
143
|
+
env: getOutputEnvVars(reporterOutputs, outputSubfolder),
|
144
|
+
},
|
145
|
+
outputs: getTargetOutputs(testOutput, reporterOutputs, projectRoot, outputSubfolder),
|
146
|
+
command: `${baseTargetConfig.command} ${relativeSpecFilePath} --output=${(0, node_path_1.join)(testOutput, outputSubfolder)}`,
|
137
147
|
metadata: {
|
138
148
|
technologies: ['playwright'],
|
139
149
|
description: `Runs Playwright Tests in ${relativeSpecFilePath} in CI`,
|
@@ -214,58 +224,84 @@ function createMatcher(pattern) {
|
|
214
224
|
};
|
215
225
|
}
|
216
226
|
}
|
217
|
-
function
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
227
|
+
function normalizeOptions(options) {
|
228
|
+
return {
|
229
|
+
...options,
|
230
|
+
targetName: options.targetName ?? 'e2e',
|
231
|
+
ciTargetName: options.ciTargetName ?? 'e2e-ci',
|
232
|
+
};
|
233
|
+
}
|
234
|
+
function getTestOutput(playwrightConfig) {
|
235
|
+
const { outputDir } = playwrightConfig;
|
236
|
+
if (outputDir) {
|
237
|
+
return outputDir;
|
238
|
+
}
|
239
|
+
else {
|
240
|
+
return './test-results';
|
225
241
|
}
|
242
|
+
}
|
243
|
+
function getReporterOutputs(playwrightConfig) {
|
226
244
|
const outputs = [];
|
227
|
-
const { reporter
|
245
|
+
const { reporter } = playwrightConfig;
|
228
246
|
if (reporter) {
|
229
|
-
const DEFAULT_REPORTER_OUTPUT =
|
230
|
-
if (reporter === 'html'
|
231
|
-
|
232
|
-
|
247
|
+
const DEFAULT_REPORTER_OUTPUT = 'playwright-report';
|
248
|
+
if (reporter === 'html') {
|
249
|
+
outputs.push([reporter, DEFAULT_REPORTER_OUTPUT]);
|
250
|
+
}
|
251
|
+
else if (reporter === 'json') {
|
252
|
+
outputs.push([reporter, DEFAULT_REPORTER_OUTPUT]);
|
233
253
|
}
|
234
254
|
else if (Array.isArray(reporter)) {
|
235
255
|
for (const r of reporter) {
|
236
|
-
const [, opts] = r;
|
256
|
+
const [reporter, opts] = r;
|
237
257
|
// There are a few different ways to specify an output file or directory
|
238
258
|
// depending on the reporter. This is a best effort to find the output.
|
239
|
-
if (
|
240
|
-
outputs.push(
|
241
|
-
}
|
242
|
-
else if (opts.outputFile) {
|
243
|
-
outputs.push(getOutput(opts.outputFile));
|
259
|
+
if (opts?.outputFile) {
|
260
|
+
outputs.push([reporter, opts.outputFile]);
|
244
261
|
}
|
245
|
-
else if (opts
|
246
|
-
outputs.push(
|
262
|
+
else if (opts?.outputDir) {
|
263
|
+
outputs.push([reporter, opts.outputDir]);
|
247
264
|
}
|
248
|
-
else if (opts
|
249
|
-
outputs.push(
|
265
|
+
else if (opts?.outputFolder) {
|
266
|
+
outputs.push([reporter, opts.outputFolder]);
|
250
267
|
}
|
251
268
|
else {
|
252
|
-
outputs.push(DEFAULT_REPORTER_OUTPUT);
|
269
|
+
outputs.push([reporter, DEFAULT_REPORTER_OUTPUT]);
|
253
270
|
}
|
254
271
|
}
|
255
272
|
}
|
256
273
|
}
|
257
|
-
|
258
|
-
|
274
|
+
return outputs;
|
275
|
+
}
|
276
|
+
function getTargetOutputs(testOutput, reporterOutputs, projectRoot, scope) {
|
277
|
+
const outputs = new Set();
|
278
|
+
outputs.add(normalizeOutput(projectRoot, scope ? (0, node_path_1.join)(testOutput, scope) : testOutput));
|
279
|
+
for (const [, output] of reporterOutputs) {
|
280
|
+
outputs.add(normalizeOutput(projectRoot, scope ? (0, node_path_1.join)(output, scope) : output));
|
281
|
+
}
|
282
|
+
return Array.from(outputs);
|
283
|
+
}
|
284
|
+
function normalizeOutput(projectRoot, path) {
|
285
|
+
if (path.startsWith('..')) {
|
286
|
+
return (0, node_path_1.join)('{workspaceRoot}', (0, node_path_1.join)(projectRoot, path));
|
259
287
|
}
|
260
288
|
else {
|
261
|
-
|
289
|
+
return (0, node_path_1.join)('{projectRoot}', path);
|
262
290
|
}
|
263
|
-
return outputs;
|
264
291
|
}
|
265
|
-
function
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
292
|
+
function getOutputEnvVars(reporterOutputs, outputSubfolder) {
|
293
|
+
const env = {};
|
294
|
+
for (let [reporter, output] of reporterOutputs) {
|
295
|
+
if (outputSubfolder) {
|
296
|
+
const isFile = (0, node_path_1.parse)(output).ext !== '';
|
297
|
+
const envVarName = `PLAYWRIGHT_${reporter.toUpperCase()}_OUTPUT_${isFile ? 'FILE' : 'DIR'}`;
|
298
|
+
env[envVarName] = (0, node_path_1.join)(output, outputSubfolder);
|
299
|
+
// Also set PLAYWRIGHT_HTML_REPORT for Playwright prior to 1.45.0.
|
300
|
+
// HTML prior to this version did not follow the pattern of "PLAYWRIGHT_<REPORTER>_OUTPUT_<FILE|DIR>".
|
301
|
+
if (reporter === 'html') {
|
302
|
+
env['PLAYWRIGHT_HTML_REPORT'] = env[envVarName];
|
303
|
+
}
|
304
|
+
}
|
305
|
+
}
|
306
|
+
return env;
|
271
307
|
}
|
package/src/utils/preset.js
CHANGED
@@ -2,9 +2,10 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.nxE2EPreset = nxE2EPreset;
|
4
4
|
const devkit_1 = require("@nx/devkit");
|
5
|
+
const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
|
6
|
+
const test_1 = require("@playwright/test");
|
5
7
|
const node_fs_1 = require("node:fs");
|
6
8
|
const node_path_1 = require("node:path");
|
7
|
-
const test_1 = require("@playwright/test");
|
8
9
|
/**
|
9
10
|
* nx E2E Preset for Playwright
|
10
11
|
* @description
|
@@ -33,8 +34,13 @@ function nxE2EPreset(pathToConfig, options) {
|
|
33
34
|
: (0, node_path_1.dirname)(pathToConfig);
|
34
35
|
const projectPath = (0, node_path_1.relative)(devkit_1.workspaceRoot, normalizedPath);
|
35
36
|
const offset = (0, node_path_1.relative)(normalizedPath, devkit_1.workspaceRoot);
|
36
|
-
const
|
37
|
-
const
|
37
|
+
const isTsSolutionSetup = (0, ts_solution_setup_1.isUsingTsSolutionSetup)();
|
38
|
+
const testResultOuputDir = isTsSolutionSetup
|
39
|
+
? 'test-output/playwright/output'
|
40
|
+
: (0, node_path_1.join)(offset, 'dist', '.playwright', projectPath, 'test-output');
|
41
|
+
const reporterOutputDir = isTsSolutionSetup
|
42
|
+
? 'test-output/playwright/report'
|
43
|
+
: (0, node_path_1.join)(offset, 'dist', '.playwright', projectPath, 'playwright-report');
|
38
44
|
return (0, test_1.defineConfig)({
|
39
45
|
testDir: options?.testDir ?? './src',
|
40
46
|
outputDir: testResultOuputDir,
|