@nx/playwright 0.0.0-pr-22179-271588f

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.
Files changed (37) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +66 -0
  3. package/executors.json +9 -0
  4. package/generators.json +16 -0
  5. package/index.d.ts +3 -0
  6. package/index.js +9 -0
  7. package/migrations.json +16 -0
  8. package/package.json +66 -0
  9. package/plugin.d.ts +1 -0
  10. package/plugin.js +6 -0
  11. package/preset.d.ts +1 -0
  12. package/preset.js +4 -0
  13. package/src/executors/playwright/playwright.impl.d.ts +37 -0
  14. package/src/executors/playwright/playwright.impl.js +77 -0
  15. package/src/executors/playwright/schema.json +168 -0
  16. package/src/generators/configuration/configuration.d.ts +5 -0
  17. package/src/generators/configuration/configuration.js +153 -0
  18. package/src/generators/configuration/files/__directory__/example.spec.ts.template +8 -0
  19. package/src/generators/configuration/files/playwright.config.ts.template +75 -0
  20. package/src/generators/configuration/schema.d.ts +27 -0
  21. package/src/generators/configuration/schema.json +73 -0
  22. package/src/generators/init/init.d.ts +5 -0
  23. package/src/generators/init/init.js +51 -0
  24. package/src/generators/init/schema.d.ts +7 -0
  25. package/src/generators/init/schema.json +34 -0
  26. package/src/migrations/update-17-3-1/add-project-to-config.d.ts +2 -0
  27. package/src/migrations/update-17-3-1/add-project-to-config.js +95 -0
  28. package/src/migrations/update-18-1-0/remove-baseUrl-from-project-json.d.ts +2 -0
  29. package/src/migrations/update-18-1-0/remove-baseUrl-from-project-json.js +42 -0
  30. package/src/plugins/plugin.d.ts +7 -0
  31. package/src/plugins/plugin.js +205 -0
  32. package/src/utils/add-linter.d.ts +16 -0
  33. package/src/utils/add-linter.js +52 -0
  34. package/src/utils/preset.d.ts +30 -0
  35. package/src/utils/preset.js +60 -0
  36. package/src/utils/versions.d.ts +3 -0
  37. package/src/utils/versions.js +6 -0
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.configurationGeneratorInternal = exports.configurationGenerator = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const js_1 = require("@nx/js");
6
+ const versions_1 = require("@nx/js/src/utils/versions");
7
+ const child_process_1 = require("child_process");
8
+ const path = require("path");
9
+ const add_linter_1 = require("../../utils/add-linter");
10
+ const versions_2 = require("../../utils/versions");
11
+ const init_1 = require("../init/init");
12
+ function configurationGenerator(tree, options) {
13
+ return configurationGeneratorInternal(tree, { addPlugin: false, ...options });
14
+ }
15
+ exports.configurationGenerator = configurationGenerator;
16
+ async function configurationGeneratorInternal(tree, options) {
17
+ const nxJson = (0, devkit_1.readNxJson)(tree);
18
+ options.addPlugin ??=
19
+ process.env.NX_ADD_PLUGINS !== 'false' &&
20
+ nxJson.useInferencePlugins !== false;
21
+ const tasks = [];
22
+ tasks.push(await (0, init_1.initGenerator)(tree, {
23
+ skipFormat: true,
24
+ skipPackageJson: options.skipPackageJson,
25
+ addPlugin: options.addPlugin,
26
+ }));
27
+ const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.project);
28
+ const hasTsConfig = tree.exists((0, devkit_1.joinPathFragments)(projectConfig.root, 'tsconfig.json'));
29
+ const offsetFromProjectRoot = (0, devkit_1.offsetFromRoot)(projectConfig.root);
30
+ (0, devkit_1.generateFiles)(tree, path.join(__dirname, 'files'), projectConfig.root, {
31
+ offsetFromRoot: offsetFromProjectRoot,
32
+ projectRoot: projectConfig.root,
33
+ webServerCommand: options.webServerCommand ?? null,
34
+ webServerAddress: options.webServerAddress ?? null,
35
+ ...options,
36
+ });
37
+ if (!hasTsConfig) {
38
+ tree.write(`${projectConfig.root}/tsconfig.json`, JSON.stringify({
39
+ extends: (0, js_1.getRelativePathToRootTsConfig)(tree, projectConfig.root),
40
+ compilerOptions: {
41
+ allowJs: true,
42
+ outDir: `${offsetFromProjectRoot}dist/out-tsc`,
43
+ module: 'commonjs',
44
+ sourceMap: false,
45
+ },
46
+ include: [
47
+ '**/*.ts',
48
+ '**/*.js',
49
+ 'playwright.config.ts',
50
+ 'src/**/*.spec.ts',
51
+ 'src/**/*.spec.js',
52
+ 'src/**/*.test.ts',
53
+ 'src/**/*.test.js',
54
+ 'src/**/*.d.ts',
55
+ ],
56
+ }, null, 2));
57
+ }
58
+ const hasPlugin = (0, devkit_1.readNxJson)(tree).plugins?.some((p) => typeof p === 'string'
59
+ ? p === '@nx/playwright/plugin'
60
+ : p.plugin === '@nx/playwright/plugin');
61
+ if (!hasPlugin) {
62
+ addE2eTarget(tree, options);
63
+ setupE2ETargetDefaults(tree);
64
+ }
65
+ tasks.push(await (0, add_linter_1.addLinterToPlaywrightProject)(tree, {
66
+ project: options.project,
67
+ linter: options.linter,
68
+ skipPackageJson: options.skipPackageJson,
69
+ js: options.js,
70
+ directory: options.directory,
71
+ setParserOptionsProject: options.setParserOptionsProject,
72
+ rootProject: options.rootProject ?? projectConfig.root === '.',
73
+ addPlugin: options.addPlugin,
74
+ }));
75
+ if (options.js) {
76
+ const { ModuleKind } = (0, devkit_1.ensurePackage)('typescript', versions_1.typescriptVersion);
77
+ (0, devkit_1.toJS)(tree, { extension: '.cjs', module: ModuleKind.CommonJS });
78
+ }
79
+ recommendVsCodeExtensions(tree);
80
+ if (!options.skipPackageJson) {
81
+ tasks.push((0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
82
+ // required since used in playwright config
83
+ '@nx/devkit': versions_2.nxVersion,
84
+ }));
85
+ }
86
+ if (!options.skipInstall) {
87
+ tasks.push(getBrowsersInstallTask());
88
+ }
89
+ if (!options.skipFormat) {
90
+ await (0, devkit_1.formatFiles)(tree);
91
+ }
92
+ return (0, devkit_1.runTasksInSerial)(...tasks);
93
+ }
94
+ exports.configurationGeneratorInternal = configurationGeneratorInternal;
95
+ function getBrowsersInstallTask() {
96
+ return () => {
97
+ devkit_1.output.log({
98
+ title: 'Ensuring Playwright is installed.',
99
+ bodyLines: ['use --skipInstall to skip installation.'],
100
+ });
101
+ const pmc = (0, devkit_1.getPackageManagerCommand)();
102
+ (0, child_process_1.execSync)(`${pmc.exec} playwright install`, { cwd: devkit_1.workspaceRoot });
103
+ };
104
+ }
105
+ function recommendVsCodeExtensions(tree) {
106
+ if (tree.exists('.vscode/extensions.json')) {
107
+ (0, devkit_1.updateJson)(tree, '.vscode/extensions.json', (json) => {
108
+ json.recommendations ??= [];
109
+ const recs = new Set(json.recommendations);
110
+ recs.add('ms-playwright.playwright');
111
+ json.recommendations = Array.from(recs);
112
+ return json;
113
+ });
114
+ }
115
+ else {
116
+ (0, devkit_1.writeJson)(tree, '.vscode/extensions.json', {
117
+ recommendations: ['ms-playwright.playwright'],
118
+ });
119
+ }
120
+ }
121
+ function setupE2ETargetDefaults(tree) {
122
+ const nxJson = (0, devkit_1.readNxJson)(tree);
123
+ if (!nxJson.namedInputs) {
124
+ return;
125
+ }
126
+ // E2e targets depend on all their project's sources + production sources of dependencies
127
+ nxJson.targetDefaults ??= {};
128
+ const productionFileSet = !!nxJson.namedInputs?.production;
129
+ nxJson.targetDefaults.e2e ??= {};
130
+ nxJson.targetDefaults.e2e.cache ??= true;
131
+ nxJson.targetDefaults.e2e.inputs ??= [
132
+ 'default',
133
+ productionFileSet ? '^production' : '^default',
134
+ ];
135
+ (0, devkit_1.updateNxJson)(tree, nxJson);
136
+ }
137
+ function addE2eTarget(tree, options) {
138
+ const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.project);
139
+ if (projectConfig?.targets?.e2e) {
140
+ throw new Error(`Project ${options.project} already has an e2e target.
141
+ Rename or remove the existing e2e target.`);
142
+ }
143
+ projectConfig.targets ??= {};
144
+ projectConfig.targets.e2e = {
145
+ executor: '@nx/playwright:playwright',
146
+ outputs: [`{workspaceRoot}/dist/.playwright/${projectConfig.root}`],
147
+ options: {
148
+ config: `${projectConfig.root}/playwright.config.${options.js ? 'cjs' : 'ts'}`,
149
+ },
150
+ };
151
+ (0, devkit_1.updateProjectConfiguration)(tree, options.project, projectConfig);
152
+ }
153
+ exports.default = configurationGenerator;
@@ -0,0 +1,8 @@
1
+ import { test, expect } from '@playwright/test';
2
+
3
+ test('has title', async ({ page }) => {
4
+ await page.goto('/');
5
+
6
+ // Expect h1 to contain a substring.
7
+ expect(await page.locator('h1').innerText()).toContain('Welcome');
8
+ });
@@ -0,0 +1,75 @@
1
+ import { defineConfig, devices } from '@playwright/test';
2
+ import { nxE2EPreset } from '@nx/playwright/preset';
3
+ <% if(!webServerCommand || !webServerAddress) { %>// eslint-disable-next-line @typescript-eslint/no-unused-vars <% } %>
4
+ import { workspaceRoot } from '@nx/devkit';
5
+
6
+ // For CI, you may want to set BASE_URL to the deployed application.
7
+ const baseURL = process.env['BASE_URL'] || '<% if(webServerAddress) {%><%= webServerAddress %><% } else {%>http://localhost:3000<% } %>';
8
+
9
+ /**
10
+ * Read environment variables from file.
11
+ * https://github.com/motdotla/dotenv
12
+ */
13
+ // require('dotenv').config();
14
+
15
+ /**
16
+ * See https://playwright.dev/docs/test-configuration.
17
+ */
18
+ export default defineConfig({
19
+ ...nxE2EPreset(__filename, { testDir: './<%= directory %>' }),
20
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
21
+ use: {
22
+ baseURL,
23
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
24
+ trace: 'on-first-retry',
25
+ },
26
+ /* Run your local dev server before starting the tests */<% if(webServerCommand && webServerAddress) {%>
27
+ webServer: {
28
+ command: '<%= webServerCommand %>',
29
+ url: '<%= webServerAddress %>',
30
+ reuseExistingServer: !process.env.CI,
31
+ cwd: workspaceRoot
32
+ },<% } else {%>
33
+ // webServer: {
34
+ // command: 'npm run start',
35
+ // url: 'http://127.0.0.1:3000',
36
+ // reuseExistingServer: !process.env.CI,
37
+ // cwd: workspaceRoot,
38
+ // },<% } %>
39
+ projects: [
40
+ {
41
+ name: "chromium",
42
+ use: { ...devices["Desktop Chrome"] },
43
+ },
44
+
45
+ {
46
+ name: "firefox",
47
+ use: { ...devices["Desktop Firefox"] },
48
+ },
49
+
50
+ {
51
+ name: "webkit",
52
+ use: { ...devices["Desktop Safari"] },
53
+ },
54
+
55
+ // Uncomment for mobile browsers support
56
+ /* {
57
+ name: 'Mobile Chrome',
58
+ use: { ...devices['Pixel 5'] },
59
+ },
60
+ {
61
+ name: 'Mobile Safari',
62
+ use: { ...devices['iPhone 12'] },
63
+ }, */
64
+
65
+ // Uncomment for branded browsers
66
+ /* {
67
+ name: 'Microsoft Edge',
68
+ use: { ...devices['Desktop Edge'], channel: 'msedge' },
69
+ },
70
+ {
71
+ name: 'Google Chrome',
72
+ use: { ...devices['Desktop Chrome'], channel: 'chrome' },
73
+ } */
74
+ ],
75
+ });
@@ -0,0 +1,27 @@
1
+ import type { Linter } from '@nx/eslint';
2
+
3
+ export interface ConfigurationGeneratorSchema {
4
+ project: string;
5
+ /**
6
+ * this is relative to the projectRoot
7
+ **/
8
+ directory: string;
9
+ js: boolean; // default is false
10
+ skipFormat: boolean;
11
+ skipPackageJson: boolean;
12
+ skipInstall?: boolean;
13
+ linter: Linter;
14
+ setParserOptionsProject: boolean; // default is false
15
+ /**
16
+ * command to give playwright to run the web server
17
+ * @example: "npx nx serve my-fe-app"
18
+ **/
19
+ webServerCommand?: string;
20
+ /**
21
+ * address
22
+ * @example: "http://localhost:4200"
23
+ **/
24
+ webServerAddress?: string;
25
+ rootProject?: boolean;
26
+ addPlugin?: boolean;
27
+ }
@@ -0,0 +1,73 @@
1
+ {
2
+ "$schema": "https://json-schema.org/schema",
3
+ "$id": "NxPlaywrightConfiguration",
4
+ "description": "Add a Playwright configuration.",
5
+ "title": "Add a Playwright configuration",
6
+ "type": "object",
7
+ "properties": {
8
+ "project": {
9
+ "type": "string",
10
+ "description": "The project to add a Playwright configuration to.",
11
+ "$default": {
12
+ "$source": "projectName"
13
+ },
14
+ "x-priority": "important",
15
+ "x-prompt": "What is the name of the project to set up Playwright for?"
16
+ },
17
+ "directory": {
18
+ "type": "string",
19
+ "description": "A directory where the project is placed relative from the project root.",
20
+ "x-priority": "important",
21
+ "default": "e2e"
22
+ },
23
+ "js": {
24
+ "type": "boolean",
25
+ "description": "Generate JavaScript files rather than TypeScript files.",
26
+ "default": false
27
+ },
28
+ "webServerCommand": {
29
+ "type": "string",
30
+ "description": "The command to start the web server."
31
+ },
32
+ "webServerAddress": {
33
+ "type": "string",
34
+ "description": "The address of the web server."
35
+ },
36
+ "linter": {
37
+ "description": "The tool to use for running lint checks.",
38
+ "type": "string",
39
+ "enum": ["eslint", "none"],
40
+ "default": "eslint"
41
+ },
42
+ "setParserOptionsProject": {
43
+ "type": "boolean",
44
+ "description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
45
+ "default": false
46
+ },
47
+ "skipFormat": {
48
+ "description": "Skip formatting files.",
49
+ "type": "boolean",
50
+ "default": false,
51
+ "x-priority": "internal"
52
+ },
53
+ "skipPackageJson": {
54
+ "type": "boolean",
55
+ "default": false,
56
+ "description": "Do not add dependencies to `package.json`.",
57
+ "x-priority": "internal"
58
+ },
59
+ "rootProject": {
60
+ "description": "Create a application at the root of the workspace",
61
+ "type": "boolean",
62
+ "default": false,
63
+ "hidden": true,
64
+ "x-priority": "internal"
65
+ },
66
+ "skipInstall": {
67
+ "type": "boolean",
68
+ "description": "Skip running `playwright install`. This is to ensure that playwright browsers are installed.",
69
+ "default": false
70
+ }
71
+ },
72
+ "required": ["project"]
73
+ }
@@ -0,0 +1,5 @@
1
+ import { GeneratorCallback, Tree } from '@nx/devkit';
2
+ import { InitGeneratorSchema } from './schema';
3
+ export declare function initGenerator(tree: Tree, options: InitGeneratorSchema): Promise<GeneratorCallback>;
4
+ export declare function initGeneratorInternal(tree: Tree, options: InitGeneratorSchema): Promise<GeneratorCallback>;
5
+ export default initGenerator;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initGeneratorInternal = exports.initGenerator = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const update_package_scripts_1 = require("@nx/devkit/src/utils/update-package-scripts");
6
+ const plugin_1 = require("../../plugins/plugin");
7
+ const versions_1 = require("../../utils/versions");
8
+ function initGenerator(tree, options) {
9
+ return initGeneratorInternal(tree, { addPlugin: false, ...options });
10
+ }
11
+ exports.initGenerator = initGenerator;
12
+ async function initGeneratorInternal(tree, options) {
13
+ const tasks = [];
14
+ const nxJson = (0, devkit_1.readNxJson)(tree);
15
+ const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
16
+ nxJson.useInferencePlugins !== false;
17
+ options.addPlugin ??= addPluginDefault;
18
+ if (!options.skipPackageJson) {
19
+ tasks.push((0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
20
+ '@nx/playwright': versions_1.nxVersion,
21
+ '@playwright/test': versions_1.playwrightVersion,
22
+ }, undefined, options.keepExistingVersions));
23
+ }
24
+ if (options.addPlugin) {
25
+ addPlugin(tree);
26
+ }
27
+ if (options.updatePackageScripts) {
28
+ await (0, update_package_scripts_1.updatePackageScripts)(tree, plugin_1.createNodes);
29
+ }
30
+ if (!options.skipFormat) {
31
+ await (0, devkit_1.formatFiles)(tree);
32
+ }
33
+ return (0, devkit_1.runTasksInSerial)(...tasks);
34
+ }
35
+ exports.initGeneratorInternal = initGeneratorInternal;
36
+ function addPlugin(tree) {
37
+ const nxJson = (0, devkit_1.readNxJson)(tree);
38
+ nxJson.plugins ??= [];
39
+ if (!nxJson.plugins.some((p) => typeof p === 'string'
40
+ ? p === '@nx/playwright/plugin'
41
+ : p.plugin === '@nx/playwright/plugin')) {
42
+ nxJson.plugins.push({
43
+ plugin: '@nx/playwright/plugin',
44
+ options: {
45
+ targetName: 'e2e',
46
+ },
47
+ });
48
+ (0, devkit_1.updateNxJson)(tree, nxJson);
49
+ }
50
+ }
51
+ exports.default = initGenerator;
@@ -0,0 +1,7 @@
1
+ export interface InitGeneratorSchema {
2
+ skipFormat?: boolean;
3
+ skipPackageJson?: boolean;
4
+ keepExistingVersions?: boolean;
5
+ updatePackageScripts?: boolean;
6
+ addPlugin?: boolean;
7
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "$schema": "https://json-schema.org/schema",
3
+ "$id": "NxPlaywrightInit",
4
+ "title": "Playwright Init Generator",
5
+ "description": "Initializes a Playwright project in the current workspace.",
6
+ "type": "object",
7
+ "properties": {
8
+ "skipFormat": {
9
+ "description": "Skip formatting files.",
10
+ "type": "boolean",
11
+ "default": false,
12
+ "x-priority": "internal"
13
+ },
14
+ "skipPackageJson": {
15
+ "type": "boolean",
16
+ "default": false,
17
+ "description": "Do not add dependencies to `package.json`.",
18
+ "x-priority": "internal"
19
+ },
20
+ "keepExistingVersions": {
21
+ "type": "boolean",
22
+ "x-priority": "internal",
23
+ "description": "Keep existing dependencies versions",
24
+ "default": false
25
+ },
26
+ "updatePackageScripts": {
27
+ "type": "boolean",
28
+ "x-priority": "internal",
29
+ "description": "Update `package.json` scripts with inferred targets",
30
+ "default": false
31
+ }
32
+ },
33
+ "required": []
34
+ }
@@ -0,0 +1,2 @@
1
+ import { Tree } from '@nx/devkit';
2
+ export default function update(tree: Tree): Promise<void>;
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const devkit_1 = require("@nx/devkit");
4
+ const ts = require("typescript");
5
+ const tsquery_1 = require("@phenomnomnominal/tsquery");
6
+ async function update(tree) {
7
+ const projects = (0, devkit_1.getProjects)(tree);
8
+ projects.forEach((project) => {
9
+ // Check if the project contains playwright config
10
+ const configPath = (0, devkit_1.joinPathFragments)(project.root, 'playwright.config.ts');
11
+ if (tree.exists(configPath)) {
12
+ addProjectIfExists(tree, (0, devkit_1.joinPathFragments)(configPath));
13
+ }
14
+ });
15
+ }
16
+ exports.default = update;
17
+ function addProjectIfExists(tree, configFilePath) {
18
+ const configFileContent = tree.read(configFilePath, 'utf-8');
19
+ const sourceFile = tsquery_1.tsquery.ast(configFileContent);
20
+ const printer = ts.createPrinter();
21
+ const updatedStatements = updateOrCreateImportStatement(sourceFile, '@playwright/test', ['devices']);
22
+ const exportAssignment = tsquery_1.tsquery.query(sourceFile, 'ExportAssignment')[0];
23
+ if (!exportAssignment) {
24
+ // No export found in the file
25
+ return;
26
+ }
27
+ const exportAssignemntObject = exportAssignment.expression;
28
+ if (!(ts.isCallExpression(exportAssignemntObject) &&
29
+ exportAssignemntObject.getText(sourceFile).startsWith('defineConfig') &&
30
+ exportAssignemntObject.arguments.length > 0)) {
31
+ // Export is not a call expression with defineConfig ex. export default defineConfig({ ... })
32
+ return;
33
+ }
34
+ let firstArgument = exportAssignemntObject.arguments[0];
35
+ if (!ts.isObjectLiteralExpression(firstArgument)) {
36
+ // First argument is not an object literal ex. defineConfig('foo')
37
+ return;
38
+ }
39
+ const projectProperty = tsquery_1.tsquery.query(exportAssignemntObject, 'PropertyAssignment > Identifier[name="projects"]')[0];
40
+ if (projectProperty) {
41
+ // Projects property already exists in the config
42
+ return;
43
+ }
44
+ // Add projects property to the config
45
+ const projectsArray = ts.factory.createArrayLiteralExpression([
46
+ createProperty('chromium', 'Desktop Chrome'),
47
+ createProperty('firefox', 'Desktop Firefox'),
48
+ createProperty('webkit', 'Desktop Safari'),
49
+ ], true);
50
+ const newProjectsProperty = ts.factory.createPropertyAssignment('projects', projectsArray);
51
+ const newObj = ts.factory.createObjectLiteralExpression([
52
+ ...firstArgument.properties,
53
+ newProjectsProperty,
54
+ ]);
55
+ const newCallExpression = ts.factory.updateCallExpression(exportAssignemntObject, exportAssignemntObject.expression, exportAssignemntObject.typeArguments, [newObj]);
56
+ const newExportAssignment = ts.factory.updateExportAssignment(exportAssignment, exportAssignment.modifiers, newCallExpression);
57
+ const transformedStatements = updatedStatements.map((statement) => {
58
+ return statement === exportAssignment ? newExportAssignment : statement;
59
+ });
60
+ const transformedSourceFile = ts.factory.updateSourceFile(sourceFile, transformedStatements);
61
+ const updatedConfigFileContent = printer.printFile(transformedSourceFile);
62
+ tree.write(configFilePath, updatedConfigFileContent);
63
+ }
64
+ function createProperty(name, device) {
65
+ return ts.factory.createObjectLiteralExpression([
66
+ ts.factory.createPropertyAssignment('name', ts.factory.createStringLiteral(name)),
67
+ ts.factory.createPropertyAssignment('use', ts.factory.createObjectLiteralExpression([
68
+ ts.factory.createSpreadAssignment(ts.factory.createElementAccessExpression(ts.factory.createIdentifier('devices'), ts.factory.createStringLiteral(device))),
69
+ ])),
70
+ ]);
71
+ }
72
+ function updateOrCreateImportStatement(sourceFile, moduleName, importNames) {
73
+ let importDeclarationFound = false;
74
+ const newStatements = sourceFile.statements.map((statement) => {
75
+ if (ts.isImportDeclaration(statement) &&
76
+ statement.moduleSpecifier.getText(sourceFile) === `'${moduleName}'`) {
77
+ importDeclarationFound = true;
78
+ const existingSpecifiers = statement.importClause?.namedBindings &&
79
+ ts.isNamedImports(statement.importClause.namedBindings)
80
+ ? statement.importClause.namedBindings.elements.map((e) => e.name.text)
81
+ : [];
82
+ // Merge with new import names, avoiding duplicates
83
+ const mergedImportNames = Array.from(new Set([...existingSpecifiers, ...importNames]));
84
+ // Create new import specifiers
85
+ const importSpecifiers = mergedImportNames.map((name) => ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier(name)));
86
+ return ts.factory.updateImportDeclaration(statement, statement.modifiers, ts.factory.createImportClause(false, undefined, ts.factory.createNamedImports(importSpecifiers)), statement.moduleSpecifier, undefined);
87
+ }
88
+ return statement;
89
+ });
90
+ if (!importDeclarationFound) {
91
+ const importDeclaration = ts.factory.createImportDeclaration(undefined, ts.factory.createImportClause(false, undefined, ts.factory.createNamedImports(importNames.map((name) => ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier(name))))), ts.factory.createStringLiteral(moduleName));
92
+ newStatements.push(importDeclaration);
93
+ }
94
+ return newStatements;
95
+ }
@@ -0,0 +1,2 @@
1
+ import { type Tree } from '@nx/devkit';
2
+ export default function (tree: Tree): Promise<void>;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const devkit_1 = require("@nx/devkit");
4
+ const executor_options_utils_1 = require("@nx/devkit/src/generators/executor-options-utils");
5
+ async function default_1(tree) {
6
+ (0, executor_options_utils_1.forEachExecutorOptions)(tree, '@nx/playwright:playwright', (options, projectName, targetName, configurationName) => {
7
+ if (options?.['baseUrl']) {
8
+ const project = (0, devkit_1.readProjectConfiguration)(tree, projectName);
9
+ if (configurationName) {
10
+ delete project.targets[targetName].configurations[configurationName]['baseUrl'];
11
+ }
12
+ else {
13
+ delete project.targets[targetName].options['baseUrl'];
14
+ }
15
+ (0, devkit_1.updateProjectConfiguration)(tree, projectName, project);
16
+ }
17
+ });
18
+ const nxJson = (0, devkit_1.readNxJson)(tree);
19
+ for (const [targetNameOrExecutor, target] of Object.entries(nxJson.targetDefaults)) {
20
+ if (targetNameOrExecutor === '@nx/playwright:playwright' ||
21
+ (target.executor && target.executor === '@nx/playwright:playwright')) {
22
+ let updated = false;
23
+ if (target.options?.['baseUrl']) {
24
+ delete nxJson.targetDefaults[targetNameOrExecutor].options['baseUrl'];
25
+ updated = true;
26
+ }
27
+ if (target.configurations) {
28
+ for (const [configurationName, configuration] of Object.entries(target.configurations)) {
29
+ if (configuration['baseUrl']) {
30
+ delete nxJson.targetDefaults[targetNameOrExecutor].configurations[configurationName]['baseUrl'];
31
+ updated = true;
32
+ }
33
+ }
34
+ }
35
+ if (updated) {
36
+ (0, devkit_1.updateNxJson)(tree, nxJson);
37
+ }
38
+ }
39
+ }
40
+ await (0, devkit_1.formatFiles)(tree);
41
+ }
42
+ exports.default = default_1;
@@ -0,0 +1,7 @@
1
+ import { CreateDependencies, CreateNodes } from '@nx/devkit';
2
+ export interface PlaywrightPluginOptions {
3
+ targetName?: string;
4
+ ciTargetName?: string;
5
+ }
6
+ export declare const createDependencies: CreateDependencies;
7
+ export declare const createNodes: CreateNodes<PlaywrightPluginOptions>;