From 1e032fb9e515ddcec6f97e79ca920fd8dc27bdb1 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Thu, 16 Jan 2025 13:10:34 -0500 Subject: [PATCH] fix(misc): update e2e config generators to align with new TS solution setup (#29638) This PR updates the `@nx/detox:app` generator to match the new TS solution setup. The `@nx/cypress:configuration` and `@nx/cypress:configuration` generators are also updated so that they can be run on existing projects and generator the correct tsconfig files. The Playwright/Cypress example can be seen as follows: ```shell # Skip e2e nx g @nx/react:app apps/demo --bundler vite --e2eTestRunner none # now configure e2e nx g @nx/playwright --project demo ``` Now if you add this line to `apps/demo/e2e/example.spec.ts`: ``` const x: number = 'a'; ``` And run `nx typecheck demo`, it will pass. This happens because the `e2e/**/*.ts` pattern is missing. Thus, we need to ensure that a `tsconfig.e2e.json` project is added for the Playwright spec files. Same thing with Cypress. The Detox generator does not support adding configuration to existing project, so we don't quite get the same problem. The fix for Detox is just to make sure the tsconfig content is not following the old (integrated) version, but the updated TS solution version. ## Current Behavior Detox TS setup is incorrect. Running Cypress and Playwright configuration generator on existing projects generate invalid setup, such that spec files are not typechecked. ## Expected Behavior E2E generators should all generate correct TS setup. ## Related Issue(s) Fixes # --- .../src/generators/base-setup/base-setup.ts | 19 ++- .../configuration/configuration.spec.ts | 72 +++++++++ .../application/application.spec.ts | 152 +++++++++++++++++- .../src/generators/application/application.ts | 27 ++++ .../tsconfig.e2e.json.template} | 0 .../tsconfig.json.template} | 0 .../application/lib/add-linting.spec.ts | 3 + .../application/lib/create-files.ts | 44 ++++- .../application/lib/normalize-options.spec.ts | 3 + .../application/lib/normalize-options.ts | 3 + .../configuration/configuration.spec.ts | 114 +++++++++++++ .../generators/configuration/configuration.ts | 41 ++++- .../files/playwright.config.ts.template | 3 +- .../application/application.spec.ts | 1 - .../application.impl.spec.ts.snap | 2 - .../__snapshots__/application.spec.ts.snap | 1 - .../__snapshots__/application.spec.ts.snap | 3 - 17 files changed, 464 insertions(+), 24 deletions(-) rename packages/detox/src/generators/application/files/{app/tsconfig.e2e.json => non-ts-solution/tsconfig.e2e.json.template} (100%) rename packages/detox/src/generators/application/files/{app/tsconfig.json => non-ts-solution/tsconfig.json.template} (100%) create mode 100644 packages/playwright/src/generators/configuration/configuration.spec.ts diff --git a/packages/cypress/src/generators/base-setup/base-setup.ts b/packages/cypress/src/generators/base-setup/base-setup.ts index d41cc62e3a..b3c15d1e7f 100644 --- a/packages/cypress/src/generators/base-setup/base-setup.ts +++ b/packages/cypress/src/generators/base-setup/base-setup.ts @@ -37,14 +37,25 @@ export function addBaseCypressSetup( } const opts = normalizeOptions(tree, projectConfig, options); + const isUsingTsSolutionConfig = isUsingTsSolutionSetup(tree); const templateVars = { ...opts, jsx: !!opts.jsx, offsetFromRoot: offsetFromRoot(projectConfig.root), offsetFromProjectRoot: opts.hasTsConfig ? opts.offsetFromProjectRoot : '', - tsConfigPath: opts.hasTsConfig - ? `${opts.offsetFromProjectRoot}tsconfig.json` - : getRelativePathToRootTsConfig(tree, projectConfig.root), + tsConfigPath: + // TS solution setup should always extend from tsconfig.base.json to use shared compilerOptions, the project's tsconfig.json will not have compilerOptions. + isUsingTsSolutionConfig + ? getRelativePathToRootTsConfig( + tree, + opts.hasTsConfig + ? joinPathFragments(projectConfig.root, options.directory) + : // If an existing tsconfig.json file does not exist, then cypress tsconfig will be moved to the project root. + projectConfig.root + ) + : opts.hasTsConfig + ? `${opts.offsetFromProjectRoot}tsconfig.json` + : getRelativePathToRootTsConfig(tree, projectConfig.root), linter: isEslintInstalled(tree) ? 'eslint' : 'none', ext: '', }; @@ -58,7 +69,7 @@ export function addBaseCypressSetup( generateFiles( tree, - isUsingTsSolutionSetup(tree) + isUsingTsSolutionConfig ? join(__dirname, 'files/tsconfig/ts-solution') : join(__dirname, 'files/tsconfig/non-ts-solution'), projectConfig.root, diff --git a/packages/cypress/src/generators/configuration/configuration.spec.ts b/packages/cypress/src/generators/configuration/configuration.spec.ts index a7a12a0cb8..b4ed915e55 100644 --- a/packages/cypress/src/generators/configuration/configuration.spec.ts +++ b/packages/cypress/src/generators/configuration/configuration.spec.ts @@ -8,6 +8,7 @@ import { Tree, updateJson, updateProjectConfiguration, + writeJson, } from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import cypressE2EConfigurationGenerator from './configuration'; @@ -555,6 +556,77 @@ export default defineConfig({ " `); }); + + describe('TS Solution Setup', () => { + beforeEach(() => { + updateJson(tree, 'package.json', (json) => { + json.workspaces = ['packages/*', 'apps/*']; + return json; + }); + writeJson(tree, 'tsconfig.base.json', { + compilerOptions: { + composite: true, + declaration: true, + }, + }); + writeJson(tree, 'tsconfig.json', { + extends: './tsconfig.base.json', + files: [], + references: [], + }); + }); + + it('should handle existing tsconfig.json files', async () => { + addProject(tree, { name: 'my-lib', type: 'libs' }); + writeJson(tree, 'libs/my-lib/tsconfig.json', { + include: [], + files: [], + references: [], + }); + + await cypressE2EConfigurationGenerator(tree, { + project: 'my-lib', + baseUrl: 'http://localhost:4200', + js: true, + }); + + expect(tree.read('libs/my-lib/tsconfig.json', 'utf-8')) + .toMatchInlineSnapshot(` + "{ + "include": [], + "files": [], + "references": [ + { + "path": "./src/tsconfig.json" + } + ] + } + " + `); + expect(tree.read('libs/my-lib/src/tsconfig.json', 'utf-8')) + .toMatchInlineSnapshot(` + "{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "out-tsc/cypress", + "allowJs": true, + "types": ["cypress", "node"], + "sourceMap": false + }, + "include": [ + "**/*.ts", + "**/*.js", + "../cypress.config.ts", + "../**/*.cy.ts", + "../**/*.cy.js", + "../**/*.d.ts" + ], + "exclude": ["out-tsc", "test-output"] + } + " + `); + }); + }); }); }); diff --git a/packages/detox/src/generators/application/application.spec.ts b/packages/detox/src/generators/application/application.spec.ts index d0318e695e..bdc3e77254 100644 --- a/packages/detox/src/generators/application/application.spec.ts +++ b/packages/detox/src/generators/application/application.spec.ts @@ -5,6 +5,8 @@ import { readJson, readProjectConfiguration, Tree, + updateJson, + writeJson, } from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { Linter } from '@nx/eslint/src/generators/utils/linter'; @@ -396,8 +398,38 @@ describe('detox application generator', () => { addPlugin: true, }); - const tsConfig = readJson(tree, 'my-app-e2e/tsconfig.json'); - expect(tsConfig.extends).toEqual('../tsconfig.base.json'); + expect(readJson(tree, 'my-app-e2e/tsconfig.json')).toMatchInlineSnapshot(` + { + "extends": "../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.e2e.json", + }, + ], + } + `); + expect(readJson(tree, 'my-app-e2e/tsconfig.e2e.json')) + .toMatchInlineSnapshot(` + { + "compilerOptions": { + "allowJs": true, + "outDir": "../dist/out-tsc", + "sourceMap": false, + "types": [ + "node", + "jest", + "detox", + ], + }, + "extends": "./tsconfig.json", + "include": [ + "src/**/*.ts", + "src/**/*.js", + ], + } + `); }); it('should support a root tsconfig.json instead of tsconfig.base.json', async () => { @@ -411,8 +443,120 @@ describe('detox application generator', () => { addPlugin: true, }); - const tsConfig = readJson(tree, 'my-app-e2e/tsconfig.json'); - expect(tsConfig.extends).toEqual('../tsconfig.json'); + expect(readJson(tree, 'my-app-e2e/tsconfig.json')).toMatchInlineSnapshot(` + { + "extends": "../tsconfig.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.e2e.json", + }, + ], + } + `); + expect(readJson(tree, 'my-app-e2e/tsconfig.e2e.json')) + .toMatchInlineSnapshot(` + { + "compilerOptions": { + "allowJs": true, + "outDir": "../dist/out-tsc", + "sourceMap": false, + "types": [ + "node", + "jest", + "detox", + ], + }, + "extends": "./tsconfig.json", + "include": [ + "src/**/*.ts", + "src/**/*.js", + ], + } + `); + }); + }); + + describe('TS Solution Setup', () => { + beforeEach(() => { + updateJson(tree, 'package.json', (json) => { + json.workspaces = ['packages/*', 'apps/*']; + return json; + }); + writeJson(tree, 'tsconfig.base.json', { + compilerOptions: { + composite: true, + declaration: true, + }, + }); + writeJson(tree, 'tsconfig.json', { + extends: './tsconfig.base.json', + files: [], + references: [], + }); + }); + + it('should create tsconfig.json and update project references', async () => { + writeJson(tree, 'apps/my-app/package.json', { + name: 'my-app', + }); + + await detoxApplicationGenerator(tree, { + e2eDirectory: 'apps/my-app-e2e', + appProject: 'my-app', + linter: Linter.None, + framework: 'react-native', + addPlugin: true, + }); + + expect(tree.read('tsconfig.json', 'utf-8')).toMatchInlineSnapshot(` + "{ + "extends": "./tsconfig.base.json", + "files": [], + "references": [ + { + "path": "./apps/my-app-e2e" + } + ] + } + " + `); + expect(tree.read('apps/my-app-e2e/package.json', 'utf-8')) + .toMatchInlineSnapshot(` + "{ + "name": "my-app-e2e", + "version": "0.0.1", + "private": true, + "nx": { + "sourceRoot": "apps/my-app-e2e/src", + "projectType": "application", + "implicitDependencies": [ + "my-app" + ] + } + } + " + `); + expect(tree.read('apps/my-app-e2e/tsconfig.json', 'utf-8')) + .toMatchInlineSnapshot(` + "{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "sourceMap": false, + "outDir": "out-tsc/detox", + "allowJs": true, + "types": ["node", "jest", "detox"], + "rootDir": "src", + "module": "esnext", + "moduleResolution": "bundler", + "tsBuildInfoFile": "out-tsc/detox/tsconfig.tsbuildinfo" + }, + "include": ["src/**/*.ts", "src/**/*.js"], + "exclude": ["out-tsc", "dist", "test-output"] + } + " + `); }); }); }); diff --git a/packages/detox/src/generators/application/application.ts b/packages/detox/src/generators/application/application.ts index 9b42fdf537..eb392ab29d 100644 --- a/packages/detox/src/generators/application/application.ts +++ b/packages/detox/src/generators/application/application.ts @@ -9,6 +9,11 @@ import { createFiles } from './lib/create-files'; import { normalizeOptions } from './lib/normalize-options'; import { Schema } from './schema'; import { ensureDependencies } from './lib/ensure-dependencies'; +import { + addProjectToTsSolutionWorkspace, + updateTsconfigFiles, +} from '@nx/js/src/utils/typescript/ts-solution-setup'; +import { sortPackageJsonFields } from '@nx/js/src/utils/package-json/sort-fields'; export async function detoxApplicationGenerator(host: Tree, schema: Schema) { return await detoxApplicationGeneratorInternal(host, { @@ -38,6 +43,28 @@ export async function detoxApplicationGeneratorInternal( const lintingTask = await addLinting(host, options); const depsTask = ensureDependencies(host, options); + updateTsconfigFiles( + host, + options.e2eProjectRoot, + 'tsconfig.json', + { + module: 'esnext', + moduleResolution: 'bundler', + outDir: 'out-tsc/detox', + allowJs: true, + types: ['node', 'jest', 'detox'], + }, + options.linter === 'eslint' + ? ['eslint.config.js', 'eslint.config.cjs', 'eslint.config.mjs'] + : undefined + ); + + if (options.isUsingTsSolutionConfig) { + addProjectToTsSolutionWorkspace(host, options.e2eProjectRoot); + } + + sortPackageJsonFields(host, options.e2eProjectRoot); + if (!options.skipFormat) { await formatFiles(host); } diff --git a/packages/detox/src/generators/application/files/app/tsconfig.e2e.json b/packages/detox/src/generators/application/files/non-ts-solution/tsconfig.e2e.json.template similarity index 100% rename from packages/detox/src/generators/application/files/app/tsconfig.e2e.json rename to packages/detox/src/generators/application/files/non-ts-solution/tsconfig.e2e.json.template diff --git a/packages/detox/src/generators/application/files/app/tsconfig.json b/packages/detox/src/generators/application/files/non-ts-solution/tsconfig.json.template similarity index 100% rename from packages/detox/src/generators/application/files/app/tsconfig.json rename to packages/detox/src/generators/application/files/non-ts-solution/tsconfig.json.template diff --git a/packages/detox/src/generators/application/lib/add-linting.spec.ts b/packages/detox/src/generators/application/lib/add-linting.spec.ts index 114f716b90..5c2ece3576 100644 --- a/packages/detox/src/generators/application/lib/add-linting.spec.ts +++ b/packages/detox/src/generators/application/lib/add-linting.spec.ts @@ -20,6 +20,7 @@ describe('Add Linting', () => { appExpoName: 'MyApp', appRoot: 'apps/my-app', linter: Linter.EsLint, + isUsingTsSolutionConfig: false, framework: 'react-native', }); }); @@ -36,6 +37,7 @@ describe('Add Linting', () => { appExpoName: 'MyApp', appRoot: 'apps/my-app', linter: Linter.EsLint, + isUsingTsSolutionConfig: false, framework: 'react-native', }); @@ -54,6 +56,7 @@ describe('Add Linting', () => { appExpoName: 'MyApp', appRoot: 'apps/my-app', linter: Linter.None, + isUsingTsSolutionConfig: false, framework: 'react-native', }); const project = readProjectConfiguration(tree, 'my-app-e2e'); diff --git a/packages/detox/src/generators/application/lib/create-files.ts b/packages/detox/src/generators/application/lib/create-files.ts index 5bbffa8f98..0eee321dec 100644 --- a/packages/detox/src/generators/application/lib/create-files.ts +++ b/packages/detox/src/generators/application/lib/create-files.ts @@ -2,24 +2,56 @@ import { detectPackageManager, generateFiles, getPackageManagerCommand, - offsetFromRoot, + offsetFromRoot as _offsetFromRoot, toJS, Tree, + writeJson, + joinPathFragments, } from '@nx/devkit'; import { getRelativePathToRootTsConfig } from '@nx/js'; import { join } from 'path'; import { NormalizedSchema } from './normalize-options'; export function createFiles(host: Tree, options: NormalizedSchema) { + const offsetFromRoot = _offsetFromRoot(options.e2eProjectRoot); + const rootTsConfigPath = getRelativePathToRootTsConfig( + host, + options.e2eProjectRoot + ); generateFiles(host, join(__dirname, '../files/app'), options.e2eProjectRoot, { ...options, exec: getPackageManagerCommand(detectPackageManager(host.root)).exec, - offsetFromRoot: offsetFromRoot(options.e2eProjectRoot), - rootTsConfigPath: getRelativePathToRootTsConfig( - host, - options.e2eProjectRoot - ), + offsetFromRoot, + rootTsConfigPath, }); + if (options.isUsingTsSolutionConfig) { + writeJson( + host, + joinPathFragments(options.e2eProjectRoot, 'tsconfig.json'), + { + extends: `${offsetFromRoot}tsconfig.base.json`, + compilerOptions: { + sourceMap: false, + outDir: 'out-tsc/detox', + allowJs: true, + types: ['node', 'jest', 'detox'], + }, + include: ['src/**/*.ts', 'src/**/*.js'], + exclude: ['out-tsc', 'test-output'], + } + ); + } else { + generateFiles( + host, + join(__dirname, '../files/non-ts-solution'), + options.e2eProjectRoot, + { + ...options, + offsetFromRoot, + rootTsConfigPath, + } + ); + } if (options.js) { toJS(host); } diff --git a/packages/detox/src/generators/application/lib/normalize-options.spec.ts b/packages/detox/src/generators/application/lib/normalize-options.spec.ts index 8a36daf82a..e1d7832669 100644 --- a/packages/detox/src/generators/application/lib/normalize-options.spec.ts +++ b/packages/detox/src/generators/application/lib/normalize-options.spec.ts @@ -37,6 +37,7 @@ describe('Normalize Options', () => { appDisplayName: 'MyApp', appExpoName: 'MyApp', appRoot: 'apps/my-app', + isUsingTsSolutionConfig: false, linter: Linter.EsLint, }); }); @@ -66,6 +67,7 @@ describe('Normalize Options', () => { e2eProjectName: 'my-app-e2e', e2eProjectRoot: 'apps/my-app-e2e', framework: 'react-native', + isUsingTsSolutionConfig: false, }); }); @@ -94,6 +96,7 @@ describe('Normalize Options', () => { e2eDirectory: 'directory', e2eProjectName: 'directory-my-app-e2e', framework: 'react-native', + isUsingTsSolutionConfig: false, }); }); }); diff --git a/packages/detox/src/generators/application/lib/normalize-options.ts b/packages/detox/src/generators/application/lib/normalize-options.ts index f6739a2169..3c77232e03 100644 --- a/packages/detox/src/generators/application/lib/normalize-options.ts +++ b/packages/detox/src/generators/application/lib/normalize-options.ts @@ -4,6 +4,7 @@ import { ensureProjectName, } from '@nx/devkit/src/generators/project-name-and-root-utils'; import { Schema } from '../schema'; +import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup'; export interface NormalizedSchema extends Schema { appFileName: string; // the file name of app to be tested in kebab case @@ -12,6 +13,7 @@ export interface NormalizedSchema extends Schema { appRoot: string; // the root path of e2e project. e.g. apps/app-directory/app e2eProjectName: string; // the name of e2e project e2eProjectRoot: string; // the root path of e2e project. e.g. apps/e2e-directory/e2e-app + isUsingTsSolutionConfig?: boolean; } export async function normalizeOptions( @@ -45,5 +47,6 @@ export async function normalizeOptions( e2eName: e2eProjectName, e2eProjectName, e2eProjectRoot, + isUsingTsSolutionConfig: isUsingTsSolutionSetup(host), }; } diff --git a/packages/playwright/src/generators/configuration/configuration.spec.ts b/packages/playwright/src/generators/configuration/configuration.spec.ts new file mode 100644 index 0000000000..f4e52ac228 --- /dev/null +++ b/packages/playwright/src/generators/configuration/configuration.spec.ts @@ -0,0 +1,114 @@ +import 'nx/src/internal-testing-utils/mock-project-graph'; + +import { Tree, updateJson, writeJson } from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import configGenerator from './configuration'; + +describe('Playwright e2e configuration', () => { + let tree: Tree; + beforeEach(() => { + tree = createTreeWithEmptyWorkspace(); + }); + + afterAll(() => { + jest.resetAllMocks(); + }); + + describe('TS Solution Setup', () => { + beforeEach(() => { + updateJson(tree, 'package.json', (json) => { + json.workspaces = ['packages/*', 'apps/*']; + return json; + }); + writeJson(tree, 'tsconfig.base.json', { + compilerOptions: { + composite: true, + declaration: true, + }, + }); + writeJson(tree, 'tsconfig.json', { + extends: './tsconfig.base.json', + files: [], + references: [], + }); + }); + + it('should create tsconfig.json if it does not exist yet (default case for app generators)', async () => { + writeJson(tree, 'apps/myapp-e2e/package.json', { + name: '@proj/myapp-e2e', + }); + + await configGenerator(tree, { + project: '@proj/myapp-e2e', + }); + + expect(tree.read('apps/myapp-e2e/tsconfig.json', 'utf-8')) + .toMatchInlineSnapshot(` + "{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "allowJs": true, + "outDir": "out-tsc/playwright", + "sourceMap": false + }, + "include": [ + "**/*.ts", + "**/*.js", + "playwright.config.ts", + "src/**/*.spec.ts", + "src/**/*.spec.js", + "src/**/*.test.ts", + "src/**/*.test.js", + "src/**/*.d.ts" + ], + "exclude": ["out-tsc", "test-output"] + } + " + `); + expect(tree.exists('apps/myapp/tsconfig.e2e.json')).toBeFalsy(); + }); + + it('should use tsconfig.e2e.json if tsconfig.json already exists', async () => { + writeJson(tree, 'apps/myapp/package.json', { + name: '@proj/myapp', + }); + writeJson(tree, 'apps/myapp/tsconfig.json', { + include: [], + files: [], + references: [], + }); + + await configGenerator(tree, { + project: '@proj/myapp', + }); + + expect(tree.read('apps/myapp/tsconfig.json', 'utf-8')) + .toMatchInlineSnapshot(` + "{ + "include": [], + "files": [], + "references": [ + { + "path": "./tsconfig.e2e.json" + } + ] + } + " + `); + expect(tree.read('apps/myapp/tsconfig.e2e.json', 'utf-8')) + .toMatchInlineSnapshot(` + "{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "allowJs": true, + "outDir": "out-tsc/playwright", + "sourceMap": false + }, + "include": ["e2e/**/*.ts", "e2e/**/*.js", "playwright.config.ts"], + "exclude": ["out-tsc", "test-output"] + } + " + `); + }); + }); +}); diff --git a/packages/playwright/src/generators/configuration/configuration.ts b/packages/playwright/src/generators/configuration/configuration.ts index 7b5ab7c65e..bbdfa4f0a7 100644 --- a/packages/playwright/src/generators/configuration/configuration.ts +++ b/packages/playwright/src/generators/configuration/configuration.ts @@ -74,7 +74,46 @@ export async function configurationGeneratorInternal( const isTsSolutionSetup = isUsingTsSolutionSetup(tree); const tsconfigPath = joinPathFragments(projectConfig.root, 'tsconfig.json'); - if (!tree.exists(tsconfigPath)) { + if (tree.exists(tsconfigPath)) { + if (isTsSolutionSetup) { + const tsconfig: any = { + extends: getRelativePathToRootTsConfig(tree, projectConfig.root), + compilerOptions: { + allowJs: true, + outDir: 'out-tsc/playwright', + sourceMap: false, + }, + include: [ + joinPathFragments(options.directory, '**/*.ts'), + joinPathFragments(options.directory, '**/*.js'), + 'playwright.config.ts', + ], + exclude: ['out-tsc', 'test-output'], + }; + + // skip eslint from typechecking since it extends from root file that is outside rootDir + if (options.linter === 'eslint') { + tsconfig.exclude.push( + 'eslint.config.js', + 'eslint.config.mjs', + 'eslint.config.cjs' + ); + } + + writeJson( + tree, + joinPathFragments(projectConfig.root, 'tsconfig.e2e.json'), + tsconfig + ); + + updateJson(tree, tsconfigPath, (json) => { + // add the project tsconfig to the workspace root tsconfig.json references + json.references ??= []; + json.references.push({ path: './tsconfig.e2e.json' }); + return json; + }); + } + } else { const tsconfig: any = { extends: getRelativePathToRootTsConfig(tree, projectConfig.root), compilerOptions: { diff --git a/packages/playwright/src/generators/configuration/files/playwright.config.ts.template b/packages/playwright/src/generators/configuration/files/playwright.config.ts.template index 5b72109d6d..4fe960bed7 100644 --- a/packages/playwright/src/generators/configuration/files/playwright.config.ts.template +++ b/packages/playwright/src/generators/configuration/files/playwright.config.ts.template @@ -1,7 +1,6 @@ import { defineConfig, devices } from '@playwright/test'; import { nxE2EPreset } from '@nx/playwright/preset'; -<% if(!webServerCommand || !webServerAddress) { %>// eslint-disable-next-line @typescript-eslint/no-unused-vars <% } %> -import { workspaceRoot } from '@nx/devkit'; +<% if (webServerCommand && webServerAddress) { %>import { workspaceRoot } from '@nx/devkit';<% } %> // For CI, you may want to set BASE_URL to the deployed application. const baseURL = process.env['BASE_URL'] || '<% if(webServerAddress) {%><%= webServerAddress %><% } else {%>http://localhost:3000<% } %>'; diff --git a/packages/react/src/generators/application/application.spec.ts b/packages/react/src/generators/application/application.spec.ts index 41939096b5..aaa13e44e0 100644 --- a/packages/react/src/generators/application/application.spec.ts +++ b/packages/react/src/generators/application/application.spec.ts @@ -134,7 +134,6 @@ describe('app', () => { const snapshot = ` "import { defineConfig, devices } from '@playwright/test'; import { nxE2EPreset } from '@nx/playwright/preset'; - import { workspaceRoot } from '@nx/devkit'; // For CI, you may want to set BASE_URL to the deployed application. diff --git a/packages/remix/src/generators/application/__snapshots__/application.impl.spec.ts.snap b/packages/remix/src/generators/application/__snapshots__/application.impl.spec.ts.snap index 7aa583a3a9..8b808f47da 100644 --- a/packages/remix/src/generators/application/__snapshots__/application.impl.spec.ts.snap +++ b/packages/remix/src/generators/application/__snapshots__/application.impl.spec.ts.snap @@ -156,7 +156,6 @@ export default defineConfig({ exports[`Remix Application Integrated Repo --e2eTestRunner should generate a playwright e2e application for the app 1`] = ` "import { defineConfig, devices } from '@playwright/test'; import { nxE2EPreset } from '@nx/playwright/preset'; - import { workspaceRoot } from '@nx/devkit'; // For CI, you may want to set BASE_URL to the deployed application. @@ -678,7 +677,6 @@ exports[`Remix Application Standalone Project Repo should create the application exports[`Remix Application Standalone Project Repo should generate a playwright e2e application for the app 1`] = ` "import { defineConfig, devices } from '@playwright/test'; import { nxE2EPreset } from '@nx/playwright/preset'; - import { workspaceRoot } from '@nx/devkit'; // For CI, you may want to set BASE_URL to the deployed application. diff --git a/packages/vue/src/generators/application/__snapshots__/application.spec.ts.snap b/packages/vue/src/generators/application/__snapshots__/application.spec.ts.snap index 11698da728..17512f4489 100644 --- a/packages/vue/src/generators/application/__snapshots__/application.spec.ts.snap +++ b/packages/vue/src/generators/application/__snapshots__/application.spec.ts.snap @@ -327,7 +327,6 @@ describe('App', () => { exports[`application generator should set up project correctly with given options 5`] = ` "import { defineConfig, devices } from '@playwright/test'; import { nxE2EPreset } from '@nx/playwright/preset'; - import { workspaceRoot } from '@nx/devkit'; // For CI, you may want to set BASE_URL to the deployed application. diff --git a/packages/web/src/generators/application/__snapshots__/application.spec.ts.snap b/packages/web/src/generators/application/__snapshots__/application.spec.ts.snap index 0a8df963bc..f1269df4c0 100644 --- a/packages/web/src/generators/application/__snapshots__/application.spec.ts.snap +++ b/packages/web/src/generators/application/__snapshots__/application.spec.ts.snap @@ -3,7 +3,6 @@ exports[`app not nested should generate files if bundler is vite 1`] = ` "import { defineConfig, devices } from '@playwright/test'; import { nxE2EPreset } from '@nx/playwright/preset'; - import { workspaceRoot } from '@nx/devkit'; // For CI, you may want to set BASE_URL to the deployed application. @@ -76,7 +75,6 @@ export default defineConfig({ exports[`app not nested should setup playwright e2e project correctly for webpack 1`] = ` "import { defineConfig, devices } from '@playwright/test'; import { nxE2EPreset } from '@nx/playwright/preset'; - import { workspaceRoot } from '@nx/devkit'; // For CI, you may want to set BASE_URL to the deployed application. @@ -149,7 +147,6 @@ export default defineConfig({ exports[`app not nested should use serve target and port if bundler=vite, e2eTestRunner=playwright, addPlugin=false 1`] = ` "import { defineConfig, devices } from '@playwright/test'; import { nxE2EPreset } from '@nx/playwright/preset'; - import { workspaceRoot } from '@nx/devkit'; // For CI, you may want to set BASE_URL to the deployed application.