@nx/playwright 20.0.8 → 20.1.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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.0",
|
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.0",
|
39
|
+
"@nx/eslint": "20.1.0-beta.0",
|
40
|
+
"@nx/webpack": "20.1.0-beta.0",
|
41
|
+
"@nx/vite": "20.1.0-beta.0",
|
42
|
+
"@nx/js": "20.1.0-beta.0",
|
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,
|