From 40b39b2e64d4ffa5948065c4cabf92d64d70b5fe Mon Sep 17 00:00:00 2001 From: Victor Savkin Date: Wed, 7 Dec 2022 13:21:51 -0500 Subject: [PATCH] fix(core): remove leading ./ when normalizing root project outputs --- .../3-task-running.md | 2 +- .../4-task-pipelines.md | 2 +- .../shared/angular-tutorial/3-task-running.md | 2 +- .../4-workspace-optimization.md | 2 +- docs/shared/mental-model/large-tasks.json | 2 +- e2e/jest/src/jest-root.test.ts | 2 - e2e/nx-run/src/affected-graph.test.ts | 2 +- graph/ui-graph/project.json | 2 +- .../__snapshots__/application.spec.ts.snap | 4 +- .../application.v14.spec.ts.snap | 4 +- .../__snapshots__/jest-project.spec.ts.snap | 2 +- .../jest-project/jest-project.spec.ts | 2 +- .../jest-project/lib/update-workspace.ts | 2 +- .../workspace-rules-project.spec.ts | 2 +- .../src/generators/library/library.spec.ts | 2 +- .../src/generators/library/library.spec.ts | 2 +- .../src/generators/plugin/plugin.spec.ts | 2 +- packages/nx/src/tasks-runner/utils.spec.ts | 51 ++++++++++++++++++- packages/nx/src/tasks-runner/utils.ts | 41 ++++++++++----- .../__snapshots__/configuration.spec.ts.snap | 4 +- .../vite/src/generators/vitest/vitest.spec.ts | 2 +- .../test-files/react-project.config.json | 2 +- .../utils/test-files/web-project.config.json | 2 +- 23 files changed, 101 insertions(+), 39 deletions(-) diff --git a/docs/shared/angular-standalone-tutorial/3-task-running.md b/docs/shared/angular-standalone-tutorial/3-task-running.md index 9308dc35df..a198de5f00 100644 --- a/docs/shared/angular-standalone-tutorial/3-task-running.md +++ b/docs/shared/angular-standalone-tutorial/3-task-running.md @@ -40,7 +40,7 @@ Here's the `project.json` file for your `shared-ui` project: }, "test": { "executor": "@nrwl/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "outputs": ["{workspaceRoot}/coverage/{projectName}"], "options": { "jestConfig": "shared/ui/jest.config.ts", "passWithNoTests": true diff --git a/docs/shared/angular-standalone-tutorial/4-task-pipelines.md b/docs/shared/angular-standalone-tutorial/4-task-pipelines.md index a353636f00..1d2da6d4a8 100644 --- a/docs/shared/angular-standalone-tutorial/4-task-pipelines.md +++ b/docs/shared/angular-standalone-tutorial/4-task-pipelines.md @@ -157,7 +157,7 @@ Here are the outputs defined for the `shared-ui` project: }, "test": { "executor": "@nrwl/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "outputs": ["{workspaceRoot}/coverage/{projectName}"], "options": { "jestConfig": "shared/ui/jest.config.ts", "passWithNoTests": true diff --git a/docs/shared/angular-tutorial/3-task-running.md b/docs/shared/angular-tutorial/3-task-running.md index 0e17671761..b40b682f0b 100644 --- a/docs/shared/angular-tutorial/3-task-running.md +++ b/docs/shared/angular-tutorial/3-task-running.md @@ -24,7 +24,7 @@ Here's the `project.json` file for your `common-ui` project: "targets": { "test": { "executor": "@nrwl/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "outputs": ["{workspaceRoot}/coverage/{projectName}"], "options": { "jestConfig": "libs/common-ui/jest.config.ts", "passWithNoTests": true diff --git a/docs/shared/angular-tutorial/4-workspace-optimization.md b/docs/shared/angular-tutorial/4-workspace-optimization.md index 34ce0f38b6..3857ef1cae 100644 --- a/docs/shared/angular-tutorial/4-workspace-optimization.md +++ b/docs/shared/angular-tutorial/4-workspace-optimization.md @@ -89,7 +89,7 @@ Outputs are defined for every target in your workspace: }, "test": { "executor": "@nrwl/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "outputs": ["{workspaceRoot}/coverage/{projectName}"], "options": { "jestConfig": "libs/products/jest.config.ts", "passWithNoTests": true diff --git a/docs/shared/mental-model/large-tasks.json b/docs/shared/mental-model/large-tasks.json index bcc560ad68..3e0b8c9f5d 100644 --- a/docs/shared/mental-model/large-tasks.json +++ b/docs/shared/mental-model/large-tasks.json @@ -14215,7 +14215,7 @@ }, "test": { "executor": "@nrwl/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "outputs": ["{workspaceRoot}/coverage/{projectName}"], "options": { "jestConfig": "graph/ui-graph/jest.config.ts", "passWithNoTests": true diff --git a/e2e/jest/src/jest-root.test.ts b/e2e/jest/src/jest-root.test.ts index 6cb9cb9fdc..8ed7d4bf50 100644 --- a/e2e/jest/src/jest-root.test.ts +++ b/e2e/jest/src/jest-root.test.ts @@ -11,9 +11,7 @@ describe('Jest root projects', () => { it('should test root level app projects', async () => { runCLI(`generate @nrwl/angular:app ${myapp} --rootProject=true`); - const rootProjectTestResults = await runCLIAsync(`test ${myapp}`); - expect(rootProjectTestResults.combinedOutput).toContain( 'Test Suites: 1 passed, 1 total' ); diff --git a/e2e/nx-run/src/affected-graph.test.ts b/e2e/nx-run/src/affected-graph.test.ts index 12d850f331..6ca280541b 100644 --- a/e2e/nx-run/src/affected-graph.test.ts +++ b/e2e/nx-run/src/affected-graph.test.ts @@ -331,7 +331,7 @@ describe('Nx Affected and Graph Tests', () => { target: 'test', }, command: `${runNx} run ${myapp}:test`, - outputs: [`coverage/apps/${myapp}`], + outputs: [`coverage/${myapp}`], }); compareTwoArrays(resWithTarget.projects, [myapp]); diff --git a/graph/ui-graph/project.json b/graph/ui-graph/project.json index 337605e726..16b8de874f 100644 --- a/graph/ui-graph/project.json +++ b/graph/ui-graph/project.json @@ -14,7 +14,7 @@ }, "test": { "executor": "@nrwl/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "outputs": ["{workspaceRoot}/coverage/{projectName}"], "options": { "jestConfig": "graph/ui-graph/jest.config.ts", "passWithNoTests": true diff --git a/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap b/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap index 88db8145f4..df90a05b61 100644 --- a/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap +++ b/packages/angular/src/generators/application/__snapshots__/application.spec.ts.snap @@ -214,7 +214,7 @@ Object { "passWithNoTests": true, }, "outputs": Array [ - "{workspaceRoot}/coverage/{projectRoot}", + "{workspaceRoot}/coverage/{projectName}", ], }, }, @@ -385,7 +385,7 @@ Object { "passWithNoTests": true, }, "outputs": Array [ - "{workspaceRoot}/coverage/{projectRoot}", + "{workspaceRoot}/coverage/{projectName}", ], }, }, diff --git a/packages/angular/src/generators/application/__snapshots__/application.v14.spec.ts.snap b/packages/angular/src/generators/application/__snapshots__/application.v14.spec.ts.snap index dfc1c380a6..b633804f28 100644 --- a/packages/angular/src/generators/application/__snapshots__/application.v14.spec.ts.snap +++ b/packages/angular/src/generators/application/__snapshots__/application.v14.spec.ts.snap @@ -222,7 +222,7 @@ Object { "passWithNoTests": true, }, "outputs": Array [ - "{workspaceRoot}/coverage/{projectRoot}", + "{workspaceRoot}/coverage/{projectName}", ], }, }, @@ -393,7 +393,7 @@ Object { "passWithNoTests": true, }, "outputs": Array [ - "{workspaceRoot}/coverage/{projectRoot}", + "{workspaceRoot}/coverage/{projectName}", ], }, }, diff --git a/packages/jest/src/generators/jest-project/__snapshots__/jest-project.spec.ts.snap b/packages/jest/src/generators/jest-project/__snapshots__/jest-project.spec.ts.snap index 7fc44e6639..247e599eda 100644 --- a/packages/jest/src/generators/jest-project/__snapshots__/jest-project.spec.ts.snap +++ b/packages/jest/src/generators/jest-project/__snapshots__/jest-project.spec.ts.snap @@ -117,7 +117,7 @@ Object { "passWithNoTests": true, }, "outputs": Array [ - "{workspaceRoot}/coverage/{projectRoot}", + "{workspaceRoot}/coverage/{projectName}", ], } `; diff --git a/packages/jest/src/generators/jest-project/jest-project.spec.ts b/packages/jest/src/generators/jest-project/jest-project.spec.ts index 1a4a8ba243..45c7fe5c0c 100644 --- a/packages/jest/src/generators/jest-project/jest-project.spec.ts +++ b/packages/jest/src/generators/jest-project/jest-project.spec.ts @@ -74,7 +74,7 @@ describe('jestProject', () => { const lib1 = readProjectConfiguration(tree, 'lib1'); expect(lib1.targets.test).toEqual({ executor: '@nrwl/jest:jest', - outputs: ['{workspaceRoot}/coverage/{projectRoot}'], + outputs: ['{workspaceRoot}/coverage/{projectName}'], options: { jestConfig: 'libs/lib1/jest.config.ts', passWithNoTests: true, diff --git a/packages/jest/src/generators/jest-project/lib/update-workspace.ts b/packages/jest/src/generators/jest-project/lib/update-workspace.ts index e48be6b3ff..bb9d5e9682 100644 --- a/packages/jest/src/generators/jest-project/lib/update-workspace.ts +++ b/packages/jest/src/generators/jest-project/lib/update-workspace.ts @@ -12,7 +12,7 @@ export function updateWorkspace(tree: Tree, options: JestProjectSchema) { projectConfig.targets.test = { executor: '@nrwl/jest:jest', outputs: [ - joinPathFragments('{workspaceRoot}', 'coverage', '{projectRoot}'), + joinPathFragments('{workspaceRoot}', 'coverage', '{projectName}'), ], options: { jestConfig: joinPathFragments( diff --git a/packages/linter/src/generators/workspace-rules-project/workspace-rules-project.spec.ts b/packages/linter/src/generators/workspace-rules-project/workspace-rules-project.spec.ts index f787445623..281c966c8f 100644 --- a/packages/linter/src/generators/workspace-rules-project/workspace-rules-project.spec.ts +++ b/packages/linter/src/generators/workspace-rules-project/workspace-rules-project.spec.ts @@ -87,7 +87,7 @@ describe('@nrwl/linter:workspace-rules-project', () => { "passWithNoTests": true, }, "outputs": Array [ - "{workspaceRoot}/coverage/{projectRoot}", + "{workspaceRoot}/coverage/{projectName}", ], }, }, diff --git a/packages/nest/src/generators/library/library.spec.ts b/packages/nest/src/generators/library/library.spec.ts index 0c47e31b7e..77c29c84d8 100644 --- a/packages/nest/src/generators/library/library.spec.ts +++ b/packages/nest/src/generators/library/library.spec.ts @@ -34,7 +34,7 @@ describe('lib', () => { }); expect(workspaceJson.projects[libFileName].architect.test).toEqual({ builder: '@nrwl/jest:jest', - outputs: [`{workspaceRoot}/coverage/{projectRoot}`], + outputs: [`{workspaceRoot}/coverage/{projectName}`], options: { jestConfig: `libs/${libFileName}/jest.config.ts`, passWithNoTests: true, diff --git a/packages/node/src/generators/library/library.spec.ts b/packages/node/src/generators/library/library.spec.ts index 40cf7e2059..5720fba319 100644 --- a/packages/node/src/generators/library/library.spec.ts +++ b/packages/node/src/generators/library/library.spec.ts @@ -38,7 +38,7 @@ describe('lib', () => { }); expect(workspaceJson.projects['my-lib'].architect.test).toEqual({ builder: '@nrwl/jest:jest', - outputs: ['{workspaceRoot}/coverage/{projectRoot}'], + outputs: ['{workspaceRoot}/coverage/{projectName}'], options: { jestConfig: 'libs/my-lib/jest.config.ts', passWithNoTests: true, diff --git a/packages/nx-plugin/src/generators/plugin/plugin.spec.ts b/packages/nx-plugin/src/generators/plugin/plugin.spec.ts index 376ff77348..ff175e4f2c 100644 --- a/packages/nx-plugin/src/generators/plugin/plugin.spec.ts +++ b/packages/nx-plugin/src/generators/plugin/plugin.spec.ts @@ -80,7 +80,7 @@ describe('NxPlugin Plugin Generator', () => { }); expect(project.targets.test).toEqual({ executor: '@nrwl/jest:jest', - outputs: ['{workspaceRoot}/coverage/{projectRoot}'], + outputs: ['{workspaceRoot}/coverage/{projectName}'], options: { jestConfig: 'libs/my-plugin/jest.config.ts', passWithNoTests: true, diff --git a/packages/nx/src/tasks-runner/utils.spec.ts b/packages/nx/src/tasks-runner/utils.spec.ts index a919088266..3e60d05d06 100644 --- a/packages/nx/src/tasks-runner/utils.spec.ts +++ b/packages/nx/src/tasks-runner/utils.spec.ts @@ -56,7 +56,7 @@ describe('utils', () => { ).toEqual(['one', 'myapp/two', 'myapp/three']); }); - it('should interpolate {projectRoot} when it is not in front', () => { + it('should interpolate {projectRoot} when it is not at the beginning', () => { expect( getOutputsForTargetAndConfiguration( task, @@ -67,6 +67,55 @@ describe('utils', () => { ).toEqual(['dist/myapp']); }); + it('should throw when {workspaceRoot} is used not at the beginning', () => { + expect(() => + getOutputsForTargetAndConfiguration( + task, + getNode({ + outputs: ['test/{workspaceRoot}/dist'], + }) + ) + ).toThrow(); + }); + + it('should interpolate {projectRoot} = . by removing the slash after it', () => { + const data = { + name: 'myapp', + type: 'app', + data: { + root: '.', + targets: { + build: { + outputs: ['{projectRoot}/dist'], + }, + }, + files: [], + }, + }; + expect(getOutputsForTargetAndConfiguration(task, data as any)).toEqual([ + 'dist', + ]); + }); + + it('should throw when {projectRoot} is used not at the beginning and the value is .', () => { + const data = { + name: 'myapp', + type: 'app', + data: { + root: '.', + targets: { + build: { + outputs: ['test/{projectRoot}'], + }, + }, + files: [], + }, + }; + expect(() => + getOutputsForTargetAndConfiguration(task, data as any) + ).toThrow(); + }); + it('should support interpolation based on options', () => { expect( getOutputsForTargetAndConfiguration( diff --git a/packages/nx/src/tasks-runner/utils.ts b/packages/nx/src/tasks-runner/utils.ts index cfcf57d878..a8a0d00565 100644 --- a/packages/nx/src/tasks-runner/utils.ts +++ b/packages/nx/src/tasks-runner/utils.ts @@ -1,4 +1,3 @@ -import { flatten } from 'flat'; import { output } from '../utils/output'; import { Workspaces } from '../config/workspaces'; import { mergeNpmScriptsWithTargets } from '../utils/project-graph-utils'; @@ -183,19 +182,35 @@ export function getOutputsForTargetAndConfiguration( } export function interpolate(template: string, data: any): string { - return template - .replace('{workspaceRoot}/', '') - .replace(/{([\s\S]+?)}/g, (match: string) => { - let value = data; - let path = match.slice(1, -1).trim().split('.'); - for (let idx = 0; idx < path.length; idx++) { - if (!value[path[idx]]) { - return match; - } - value = value[path[idx]]; + if (template.includes('{workspaceRoot}', 1)) { + throw new Error( + `Output '${template}' is invalid. {workspaceRoot} can only be used at the beginning of the expression.` + ); + } + + if (data.projectRoot == '.' && template.includes('{projectRoot}', 1)) { + throw new Error( + `Output '${template}' is invalid. When {projectRoot} is '.', it can only be used at the beginning of the expression.` + ); + } + + let res = template.replace('{workspaceRoot}/', ''); + + if (data.projectRoot == '.') { + res = template.replace('{projectRoot}/', ''); + } + + return res.replace(/{([\s\S]+?)}/g, (match: string) => { + let value = data; + let path = match.slice(1, -1).trim().split('.'); + for (let idx = 0; idx < path.length; idx++) { + if (!value[path[idx]]) { + return match; } - return value; - }); + value = value[path[idx]]; + } + return value; + }); } export function getExecutorNameForTask( diff --git a/packages/vite/src/generators/configuration/__snapshots__/configuration.spec.ts.snap b/packages/vite/src/generators/configuration/__snapshots__/configuration.spec.ts.snap index d05470eba0..4227cc6bc8 100644 --- a/packages/vite/src/generators/configuration/__snapshots__/configuration.spec.ts.snap +++ b/packages/vite/src/generators/configuration/__snapshots__/configuration.spec.ts.snap @@ -71,7 +71,7 @@ exports[`@nrwl/vite:configuration transform React app to use Vite should transfo \\"test\\": { \\"builder\\": \\"@nrwl/jest:jest\\", \\"outputs\\": [ - \\"{workspaceRoot}/coverage/{projectRoot}\\" + \\"{workspaceRoot}/coverage/{projectName}\\" ], \\"options\\": { \\"jestConfig\\": \\"apps/my-test-react-app/jest.config.ts\\", @@ -148,7 +148,7 @@ exports[`@nrwl/vite:configuration transform Web app to use Vite should transform \\"test\\": { \\"builder\\": \\"@nrwl/jest:jest\\", \\"outputs\\": [ - \\"{workspaceRoot}/coverage/{projectRoot}\\" + \\"{workspaceRoot}/coverage/{projectName}\\" ], \\"options\\": { \\"jestConfig\\": \\"apps/my-test-web-app/jest.config.ts\\", diff --git a/packages/vite/src/generators/vitest/vitest.spec.ts b/packages/vite/src/generators/vitest/vitest.spec.ts index bb12b3d4f2..db484cdd7d 100644 --- a/packages/vite/src/generators/vitest/vitest.spec.ts +++ b/packages/vite/src/generators/vitest/vitest.spec.ts @@ -28,7 +28,7 @@ describe('vitest generator', () => { "passWithNoTests": true, }, "outputs": Array [ - "{workspaceRoot}/coverage/{projectRoot}", + "{workspaceRoot}/coverage/{projectName}", ], } `); diff --git a/packages/vite/src/utils/test-files/react-project.config.json b/packages/vite/src/utils/test-files/react-project.config.json index c638b08d35..15f57c9bd2 100644 --- a/packages/vite/src/utils/test-files/react-project.config.json +++ b/packages/vite/src/utils/test-files/react-project.config.json @@ -74,7 +74,7 @@ }, "test": { "executor": "@nrwl/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "outputs": ["{workspaceRoot}/coverage/{projectName}"], "options": { "jestConfig": "apps/my-test-react-app/jest.config.ts", "passWithNoTests": true diff --git a/packages/vite/src/utils/test-files/web-project.config.json b/packages/vite/src/utils/test-files/web-project.config.json index 1ec3768466..0fdbc208fa 100644 --- a/packages/vite/src/utils/test-files/web-project.config.json +++ b/packages/vite/src/utils/test-files/web-project.config.json @@ -62,7 +62,7 @@ }, "test": { "executor": "@nrwl/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "outputs": ["{workspaceRoot}/coverage/{projectName}"], "options": { "jestConfig": "apps/my-test-web-app/jest.config.ts", "passWithNoTests": true