Skip to content

Commit 4b70d1b

Browse files
authored
feat(testing): add support for the ts solution config setup to the playwright plugin (#28636)
<!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior <!-- This is the behavior we have today --> ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
1 parent f357b4e commit 4b70d1b

File tree

12 files changed

+291
-175
lines changed

12 files changed

+291
-175
lines changed

docs/generated/packages/playwright/generators/configuration.json

+6-6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@
2121
"x-priority": "important",
2222
"default": "e2e"
2323
},
24+
"linter": {
25+
"description": "The tool to use for running lint checks.",
26+
"type": "string",
27+
"enum": ["none", "eslint"],
28+
"x-priority": "important"
29+
},
2430
"js": {
2531
"type": "boolean",
2632
"description": "Generate JavaScript files rather than TypeScript files.",
@@ -34,12 +40,6 @@
3440
"type": "string",
3541
"description": "The address of the web server."
3642
},
37-
"linter": {
38-
"description": "The tool to use for running lint checks.",
39-
"type": "string",
40-
"enum": ["eslint", "none"],
41-
"default": "eslint"
42-
},
4343
"setParserOptionsProject": {
4444
"type": "boolean",
4545
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",

packages/devkit/src/generators/project-name-and-root-utils.ts

+22-14
Original file line numberDiff line numberDiff line change
@@ -90,20 +90,8 @@ export async function determineProjectNameAndRootOptions(
9090

9191
let importPath: string | undefined = undefined;
9292
if (options.projectType === 'library') {
93-
importPath = options.importPath;
94-
95-
if (!importPath) {
96-
if (name.startsWith('@')) {
97-
importPath = name;
98-
} else {
99-
const npmScope = getNpmScope(tree);
100-
importPath =
101-
projectRoot === '.'
102-
? readJson<{ name?: string }>(tree, 'package.json').name ??
103-
getImportPath(npmScope, name)
104-
: getImportPath(npmScope, name);
105-
}
106-
}
93+
importPath =
94+
options.importPath ?? resolveImportPath(tree, name, projectRoot);
10795
}
10896

10997
return {
@@ -117,6 +105,26 @@ export async function determineProjectNameAndRootOptions(
117105
};
118106
}
119107

108+
export function resolveImportPath(
109+
tree: Tree,
110+
projectName: string,
111+
projectRoot: string
112+
): string {
113+
let importPath: string;
114+
if (projectName.startsWith('@')) {
115+
importPath = projectName;
116+
} else {
117+
const npmScope = getNpmScope(tree);
118+
importPath =
119+
projectRoot === '.'
120+
? readJson<{ name?: string }>(tree, 'package.json').name ??
121+
getImportPath(npmScope, projectName)
122+
: getImportPath(npmScope, projectName);
123+
}
124+
125+
return importPath;
126+
}
127+
120128
export async function ensureProjectName(
121129
tree: Tree,
122130
options: Omit<ProjectGenerationOptions, 'projectType'>,
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { prompt } from 'enquirer';
2+
import { isCI } from 'nx/src/devkit-internals';
3+
4+
export async function promptWhenInteractive<T>(
5+
questions: Parameters<typeof prompt>[0],
6+
defaultValue: T
7+
): Promise<T> {
8+
if (!isInteractive()) {
9+
return defaultValue;
10+
}
11+
12+
return await prompt(questions);
13+
}
14+
15+
function isInteractive(): boolean {
16+
return (
17+
!isCI() && !!process.stdout.isTTY && process.env.NX_INTERACTIVE === 'true'
18+
);
19+
}

packages/js/src/generators/library/library.ts

+5-22
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,17 @@ import {
2626
determineProjectNameAndRootOptions,
2727
ensureProjectName,
2828
} from '@nx/devkit/src/generators/project-name-and-root-utils';
29-
29+
import { promptWhenInteractive } from '@nx/devkit/src/generators/prompt';
3030
import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils';
3131
import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
32-
import { prompt } from 'enquirer';
3332
import { findMatchingProjects } from 'nx/src/utils/find-matching-projects';
34-
import { isCI } from 'nx/src/utils/is-ci';
3533
import { type PackageJson } from 'nx/src/utils/package-json';
3634
import { join } from 'path';
3735
import type { CompilerOptions } from 'typescript';
38-
import { getProjectPackageManagerWorkspaceState } from '../../utils/package-manager-workspaces';
36+
import {
37+
getProjectPackageManagerWorkspaceState,
38+
getProjectPackageManagerWorkspaceStateWarningTask,
39+
} from '../../utils/package-manager-workspaces';
3940
import { addSwcConfig } from '../../utils/swc/add-swc-config';
4041
import { getSwcDependencies } from '../../utils/swc/add-swc-dependencies';
4142
import { getNeededCompilerOptionOverrides } from '../../utils/typescript/configuration';
@@ -63,7 +64,6 @@ import type {
6364
LibraryGeneratorSchema,
6465
NormalizedLibraryGeneratorOptions,
6566
} from './schema';
66-
import { getProjectPackageManagerWorkspaceStateWarningTask } from './utils/package-manager-workspaces';
6767
import {
6868
ensureProjectIsExcludedFromPluginRegistrations,
6969
ensureProjectIsIncludedInPluginRegistrations,
@@ -680,23 +680,6 @@ function replaceJestConfig(
680680
});
681681
}
682682

683-
function isNonInteractive(): boolean {
684-
return (
685-
isCI() || !process.stdout.isTTY || process.env.NX_INTERACTIVE !== 'true'
686-
);
687-
}
688-
689-
async function promptWhenInteractive<T>(
690-
questions: Parameters<typeof prompt>[0],
691-
defaultValue: T
692-
): Promise<T> {
693-
if (isNonInteractive()) {
694-
return defaultValue;
695-
}
696-
697-
return await prompt(questions);
698-
}
699-
700683
async function normalizeOptions(
701684
tree: Tree,
702685
options: LibraryGeneratorSchema

packages/js/src/generators/library/utils/package-manager-workspaces.ts

-58
This file was deleted.

packages/js/src/utils/package-manager-workspaces.ts

+52
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import {
22
detectPackageManager,
3+
getPackageManagerVersion,
34
isWorkspacesEnabled,
5+
output,
46
readJson,
7+
type GeneratorCallback,
58
type Tree,
69
} from '@nx/devkit';
710
import { minimatch } from 'minimatch';
811
import { join } from 'node:path/posix';
912
import { getGlobPatternsFromPackageManagerWorkspaces } from 'nx/src/plugins/package-json';
13+
import { lt } from 'semver';
1014

1115
export type ProjectPackageManagerWorkspaceState =
1216
| 'included'
@@ -35,3 +39,51 @@ export function getProjectPackageManagerWorkspaceState(
3539
export function isUsingPackageManagerWorkspaces(tree: Tree): boolean {
3640
return isWorkspacesEnabled(detectPackageManager(tree.root), tree.root);
3741
}
42+
43+
export function getProjectPackageManagerWorkspaceStateWarningTask(
44+
projectPackageManagerWorkspaceState: ProjectPackageManagerWorkspaceState,
45+
workspaceRoot: string
46+
): GeneratorCallback {
47+
return (): void => {
48+
if (projectPackageManagerWorkspaceState !== 'excluded') {
49+
return;
50+
}
51+
52+
const packageManager = detectPackageManager(workspaceRoot);
53+
let adviseMessage =
54+
'updating the "workspaces" option in the workspace root "package.json" file with the project root or pattern that includes it';
55+
let packageManagerWorkspaceSetupDocs: string;
56+
if (packageManager === 'pnpm') {
57+
adviseMessage =
58+
'updating the "pnpm-workspace.yaml" file with the project root or pattern that includes it';
59+
packageManagerWorkspaceSetupDocs =
60+
'https://pnpm.io/workspaces and https://pnpm.io/pnpm-workspace_yaml';
61+
} else if (packageManager === 'yarn') {
62+
const yarnVersion = getPackageManagerVersion(
63+
packageManager,
64+
workspaceRoot
65+
);
66+
if (lt(yarnVersion, '2.0.0')) {
67+
packageManagerWorkspaceSetupDocs =
68+
'https://classic.yarnpkg.com/lang/en/docs/workspaces/';
69+
} else {
70+
packageManagerWorkspaceSetupDocs =
71+
'https://yarnpkg.com/features/workspaces';
72+
}
73+
} else if (packageManager === 'npm') {
74+
packageManagerWorkspaceSetupDocs =
75+
'https://docs.npmjs.com/cli/v10/using-npm/workspaces';
76+
} else if (packageManager === 'bun') {
77+
packageManagerWorkspaceSetupDocs =
78+
'https://bun.sh/docs/install/workspaces';
79+
}
80+
81+
output.warn({
82+
title: `The project is not included in the package manager workspaces configuration`,
83+
bodyLines: [
84+
`Please add the project to the package manager workspaces configuration by ${adviseMessage}.`,
85+
`Read more about the ${packageManager} workspaces feature and how to set it up at ${packageManagerWorkspaceSetupDocs}.`,
86+
],
87+
});
88+
};
89+
}

packages/nx/src/devkit-internals.ts

+1
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@ export { LoadedNxPlugin } from './project-graph/plugins/internal-api';
3030
export * from './project-graph/error-types';
3131
export { registerTsProject } from './plugins/js/utils/register';
3232
export { interpolate } from './tasks-runner/utils';
33+
export { isCI } from './utils/is-ci';

0 commit comments

Comments
 (0)