chore(repo): split e2e-workspace to two applications (#7240)
This commit is contained in:
parent
508ff79296
commit
a01a5c9d34
@ -390,7 +390,7 @@ workflows:
|
|||||||
run-unit-tests: 'false'
|
run-unit-tests: 'false'
|
||||||
run-linting: 'false'
|
run-linting: 'false'
|
||||||
e2e-test-filter: 'MACOS-Tests'
|
e2e-test-filter: 'MACOS-Tests'
|
||||||
exclude-projects: 'e2e-next,e2e-gatsby,e2e-workspace,e2e-react,e2e-web,e2e-angular-extensions,e2e-angular-core,e2e-cli,e2e-nx-plugin,e2e-storybook,e2e-cypress,e2e-node,e2e-linter,e2e-jest'
|
exclude-projects: 'e2e-next,e2e-gatsby,e2e-workspace-create,e2e-workspace-integrations,e2e-workspace-core,e2e-react,e2e-web,e2e-angular-extensions,e2e-angular-core,e2e-cli,e2e-nx-plugin,e2e-storybook,e2e-cypress,e2e-node,e2e-linter,e2e-jest'
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
ignore: master
|
ignore: master
|
||||||
@ -426,7 +426,7 @@ workflows:
|
|||||||
run-linting: 'false'
|
run-linting: 'false'
|
||||||
e2e-test-filter: 'MACOS-Tests'
|
e2e-test-filter: 'MACOS-Tests'
|
||||||
run-cypress-tests: 'true'
|
run-cypress-tests: 'true'
|
||||||
exclude-projects: 'e2e-next,e2e-gatsby,e2e-workspace,e2e-react,e2e-web,e2e-angular-extensions,e2e-angular-core,e2e-cli,e2e-nx-plugin,e2e-storybook,e2e-cypress,e2e-node,e2e-linter,e2e-jest'
|
exclude-projects: 'e2e-next,e2e-gatsby,e2e-workspace-create,e2e-workspace-integrations,e2e-workspace-core,e2e-react,e2e-web,e2e-angular-extensions,e2e-angular-core,e2e-cli,e2e-nx-plugin,e2e-storybook,e2e-cypress,e2e-node,e2e-linter,e2e-jest'
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
only: master
|
only: master
|
||||||
|
|||||||
8
.github/workflows/e2e-matrix.yml
vendored
8
.github/workflows/e2e-matrix.yml
vendored
@ -45,7 +45,7 @@ jobs:
|
|||||||
- e2e-node
|
- e2e-node
|
||||||
- e2e-web
|
- e2e-web
|
||||||
- e2e-storybook
|
- e2e-storybook
|
||||||
- e2e-workspace
|
- e2e-workspace-integrations,e2e-workspace-core,e2e-workspace-create
|
||||||
- e2e-react-native,e2e-detox
|
- e2e-react-native,e2e-detox
|
||||||
exclude:
|
exclude:
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
@ -64,7 +64,11 @@ jobs:
|
|||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
package_manager: pnpm
|
package_manager: pnpm
|
||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
packages: e2e-workspace
|
packages: e2e-workspace-core
|
||||||
|
- os: macos-latest
|
||||||
|
packages: e2e-workspace-integrations
|
||||||
|
- os: macos-latest
|
||||||
|
packages: e2e-workspace-create
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
node_version: '14'
|
node_version: '14'
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
|
|||||||
@ -188,9 +188,19 @@
|
|||||||
"data": { "tags": [], "root": "e2e/storybook", "files": [] }
|
"data": { "tags": [], "root": "e2e/storybook", "files": [] }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "e2e-workspace",
|
"name": "e2e-workspace-integrations",
|
||||||
"type": "app",
|
"type": "app",
|
||||||
"data": { "tags": [], "root": "e2e/workspace", "files": [] }
|
"data": { "tags": [], "root": "e2e/workspace-integrations", "files": [] }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "e2e-workspace-core",
|
||||||
|
"type": "app",
|
||||||
|
"data": { "tags": [], "root": "e2e/workspace-core", "files": [] }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "e2e-workspace-create",
|
||||||
|
"type": "app",
|
||||||
|
"data": { "tags": [], "root": "e2e/workspace-create", "files": [] }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "jest",
|
"name": "jest",
|
||||||
@ -510,17 +520,61 @@
|
|||||||
{ "source": "e2e-storybook", "target": "storybook", "type": "implicit" },
|
{ "source": "e2e-storybook", "target": "storybook", "type": "implicit" },
|
||||||
{ "source": "e2e-storybook", "target": "e2e-utils", "type": "static" }
|
{ "source": "e2e-storybook", "target": "e2e-utils", "type": "static" }
|
||||||
],
|
],
|
||||||
"e2e-workspace": [
|
"e2e-workspace-integrations": [
|
||||||
{
|
{
|
||||||
"source": "e2e-workspace",
|
"source": "e2e-workspace-integrations",
|
||||||
|
"target": "angular",
|
||||||
|
"type": "implicit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "e2e-workspace-integrations",
|
||||||
|
"target": "react",
|
||||||
|
"type": "implicit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "e2e-workspace-integrations",
|
||||||
|
"target": "e2e-utils",
|
||||||
|
"type": "static"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "e2e-workspace-integrations",
|
||||||
|
"target": "devkit",
|
||||||
|
"type": "static"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "e2e-workspace-integrations",
|
||||||
|
"target": "workspace",
|
||||||
|
"type": "static"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"e2e-workspace-create": [
|
||||||
|
{
|
||||||
|
"source": "e2e-workspace-create",
|
||||||
"target": "create-nx-workspace",
|
"target": "create-nx-workspace",
|
||||||
"type": "implicit"
|
"type": "implicit"
|
||||||
},
|
},
|
||||||
{ "source": "e2e-workspace", "target": "angular", "type": "implicit" },
|
{
|
||||||
{ "source": "e2e-workspace", "target": "react", "type": "implicit" },
|
"source": "e2e-workspace-create",
|
||||||
{ "source": "e2e-workspace", "target": "e2e-utils", "type": "static" },
|
"target": "e2e-utils",
|
||||||
{ "source": "e2e-workspace", "target": "devkit", "type": "static" },
|
"type": "static"
|
||||||
{ "source": "e2e-workspace", "target": "workspace", "type": "static" }
|
},
|
||||||
|
{
|
||||||
|
"source": "e2e-workspace-create",
|
||||||
|
"target": "workspace",
|
||||||
|
"type": "static"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"e2e-workspace-core": [
|
||||||
|
{
|
||||||
|
"source": "e2e-workspace-core",
|
||||||
|
"target": "e2e-utils",
|
||||||
|
"type": "static"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "e2e-workspace-core",
|
||||||
|
"target": "workspace",
|
||||||
|
"type": "static"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"jest": [
|
"jest": [
|
||||||
{ "source": "jest", "target": "devkit", "type": "static" },
|
{ "source": "jest", "target": "devkit", "type": "static" },
|
||||||
|
|||||||
@ -230,6 +230,72 @@ describe('Linter', () => {
|
|||||||
expect(lintOutput).toContain(knownLintErrorMessage);
|
expect(lintOutput).toContain(knownLintErrorMessage);
|
||||||
}, 1000000);
|
}, 1000000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('lint plugin should ensure module boundaries', () => {
|
||||||
|
const proj = newProject();
|
||||||
|
const myapp = uniq('myapp');
|
||||||
|
const myapp2 = uniq('myapp2');
|
||||||
|
const mylib = uniq('mylib');
|
||||||
|
const lazylib = uniq('lazylib');
|
||||||
|
const invalidtaglib = uniq('invalidtaglib');
|
||||||
|
const validtaglib = uniq('validtaglib');
|
||||||
|
|
||||||
|
runCLI(`generate @nrwl/angular:app ${myapp} --tags=validtag`);
|
||||||
|
runCLI(`generate @nrwl/angular:app ${myapp2}`);
|
||||||
|
runCLI(`generate @nrwl/angular:lib ${mylib}`);
|
||||||
|
runCLI(`generate @nrwl/angular:lib ${lazylib}`);
|
||||||
|
runCLI(`generate @nrwl/angular:lib ${invalidtaglib} --tags=invalidtag`);
|
||||||
|
runCLI(`generate @nrwl/angular:lib ${validtaglib} --tags=validtag`);
|
||||||
|
|
||||||
|
const eslint = readJson('.eslintrc.json');
|
||||||
|
eslint.overrides[0].rules[
|
||||||
|
'@nrwl/nx/enforce-module-boundaries'
|
||||||
|
][1].depConstraints = [
|
||||||
|
{ sourceTag: 'validtag', onlyDependOnLibsWithTags: ['validtag'] },
|
||||||
|
...eslint.overrides[0].rules['@nrwl/nx/enforce-module-boundaries'][1]
|
||||||
|
.depConstraints,
|
||||||
|
];
|
||||||
|
updateFile('.eslintrc.json', JSON.stringify(eslint, null, 2));
|
||||||
|
|
||||||
|
const tsConfig = readJson('tsconfig.base.json');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* apps do not add themselves to the tsconfig file.
|
||||||
|
*
|
||||||
|
* Let's add it so that we can trigger the lint failure
|
||||||
|
*/
|
||||||
|
tsConfig.compilerOptions.paths[`@${proj}/${myapp2}`] = [
|
||||||
|
`apps/${myapp2}/src/main.ts`,
|
||||||
|
];
|
||||||
|
|
||||||
|
tsConfig.compilerOptions.paths[`@secondScope/${lazylib}`] =
|
||||||
|
tsConfig.compilerOptions.paths[`@${proj}/${lazylib}`];
|
||||||
|
delete tsConfig.compilerOptions.paths[`@${proj}/${lazylib}`];
|
||||||
|
updateFile('tsconfig.base.json', JSON.stringify(tsConfig, null, 2));
|
||||||
|
|
||||||
|
updateFile(
|
||||||
|
`apps/${myapp}/src/main.ts`,
|
||||||
|
`
|
||||||
|
import '../../../libs/${mylib}';
|
||||||
|
import '@secondScope/${lazylib}';
|
||||||
|
import '@${proj}/${myapp2}';
|
||||||
|
import '@${proj}/${invalidtaglib}';
|
||||||
|
import '@${proj}/${validtaglib}';
|
||||||
|
|
||||||
|
const s = {loadChildren: '@${proj}/${lazylib}'};
|
||||||
|
`
|
||||||
|
);
|
||||||
|
|
||||||
|
const out = runCLI(`lint ${myapp}`, { silenceError: true });
|
||||||
|
expect(out).toContain(
|
||||||
|
'Libraries cannot be imported by a relative or absolute path, and must begin with a npm scope'
|
||||||
|
);
|
||||||
|
// expect(out).toContain('Imports of lazy-loaded libraries are forbidden');
|
||||||
|
expect(out).toContain('Imports of apps are forbidden');
|
||||||
|
expect(out).toContain(
|
||||||
|
'A project tagged with "validtag" can only depend on libs tagged with "validtag"'
|
||||||
|
);
|
||||||
|
}, 1000000);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -6,5 +6,5 @@ module.exports = {
|
|||||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||||
maxWorkers: 1,
|
maxWorkers: 1,
|
||||||
globals: { 'ts-jest': { tsconfig: '<rootDir>/tsconfig.spec.json' } },
|
globals: { 'ts-jest': { tsconfig: '<rootDir>/tsconfig.spec.json' } },
|
||||||
displayName: 'e2e-workspace',
|
displayName: 'e2e-workspace-core',
|
||||||
};
|
};
|
||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"root": "e2e/workspace",
|
"root": "e2e/workspace-core",
|
||||||
"sourceRoot": "e2e/workspace",
|
"sourceRoot": "e2e/workspace-core",
|
||||||
"projectType": "application",
|
"projectType": "application",
|
||||||
"targets": {
|
"targets": {
|
||||||
"e2e": {
|
"e2e": {
|
||||||
@ -14,7 +14,7 @@
|
|||||||
"command": "yarn e2e-build-package-publish"
|
"command": "yarn e2e-build-package-publish"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "nx run-e2e-tests e2e-workspace"
|
"command": "nx run-e2e-tests e2e-workspace-core"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parallel": false
|
"parallel": false
|
||||||
@ -23,12 +23,12 @@
|
|||||||
"run-e2e-tests": {
|
"run-e2e-tests": {
|
||||||
"executor": "@nrwl/jest:jest",
|
"executor": "@nrwl/jest:jest",
|
||||||
"options": {
|
"options": {
|
||||||
"jestConfig": "e2e/workspace/jest.config.js",
|
"jestConfig": "e2e/workspace-core/jest.config.js",
|
||||||
"passWithNoTests": true,
|
"passWithNoTests": true,
|
||||||
"runInBand": true
|
"runInBand": true
|
||||||
},
|
},
|
||||||
"outputs": ["coverage/e2e/workspace"]
|
"outputs": ["coverage/e2e/workspace-core"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"implicitDependencies": ["create-nx-workspace", "angular", "react"]
|
"implicitDependencies": []
|
||||||
}
|
}
|
||||||
@ -1,251 +1,23 @@
|
|||||||
import * as path from 'path';
|
import { NxJsonConfiguration } from '@nrwl/devkit';
|
||||||
import {
|
import {
|
||||||
checkFilesExist,
|
checkFilesExist,
|
||||||
exists,
|
exists,
|
||||||
isNotWindows,
|
|
||||||
newProject,
|
newProject,
|
||||||
readFile,
|
readFile,
|
||||||
readJson,
|
readJson,
|
||||||
removeProject,
|
|
||||||
renameFile,
|
renameFile,
|
||||||
runCLI,
|
runCLI,
|
||||||
runCLIAsync,
|
|
||||||
tmpProjPath,
|
tmpProjPath,
|
||||||
uniq,
|
uniq,
|
||||||
updateFile,
|
updateFile,
|
||||||
workspaceConfigName,
|
workspaceConfigName,
|
||||||
} from '@nrwl/e2e/utils';
|
} from '@nrwl/e2e/utils';
|
||||||
import type { NxJsonConfiguration } from '@nrwl/devkit';
|
|
||||||
import { classify } from '@nrwl/workspace/src/utils/strings';
|
|
||||||
|
|
||||||
let proj: string;
|
let proj;
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
proj = newProject();
|
proj = newProject();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('lint', () => {
|
|
||||||
it('lint should ensure module boundaries', () => {
|
|
||||||
const myapp = uniq('myapp');
|
|
||||||
const myapp2 = uniq('myapp2');
|
|
||||||
const mylib = uniq('mylib');
|
|
||||||
const lazylib = uniq('lazylib');
|
|
||||||
const invalidtaglib = uniq('invalidtaglib');
|
|
||||||
const validtaglib = uniq('validtaglib');
|
|
||||||
|
|
||||||
runCLI(`generate @nrwl/angular:app ${myapp} --tags=validtag`);
|
|
||||||
runCLI(`generate @nrwl/angular:app ${myapp2}`);
|
|
||||||
runCLI(`generate @nrwl/angular:lib ${mylib}`);
|
|
||||||
runCLI(`generate @nrwl/angular:lib ${lazylib}`);
|
|
||||||
runCLI(`generate @nrwl/angular:lib ${invalidtaglib} --tags=invalidtag`);
|
|
||||||
runCLI(`generate @nrwl/angular:lib ${validtaglib} --tags=validtag`);
|
|
||||||
|
|
||||||
const eslint = readJson('.eslintrc.json');
|
|
||||||
eslint.overrides[0].rules[
|
|
||||||
'@nrwl/nx/enforce-module-boundaries'
|
|
||||||
][1].depConstraints = [
|
|
||||||
{ sourceTag: 'validtag', onlyDependOnLibsWithTags: ['validtag'] },
|
|
||||||
...eslint.overrides[0].rules['@nrwl/nx/enforce-module-boundaries'][1]
|
|
||||||
.depConstraints,
|
|
||||||
];
|
|
||||||
updateFile('.eslintrc.json', JSON.stringify(eslint, null, 2));
|
|
||||||
|
|
||||||
const tsConfig = readJson('tsconfig.base.json');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* apps do not add themselves to the tsconfig file.
|
|
||||||
*
|
|
||||||
* Let's add it so that we can trigger the lint failure
|
|
||||||
*/
|
|
||||||
tsConfig.compilerOptions.paths[`@${proj}/${myapp2}`] = [
|
|
||||||
`apps/${myapp2}/src/main.ts`,
|
|
||||||
];
|
|
||||||
|
|
||||||
tsConfig.compilerOptions.paths[`@secondScope/${lazylib}`] =
|
|
||||||
tsConfig.compilerOptions.paths[`@${proj}/${lazylib}`];
|
|
||||||
delete tsConfig.compilerOptions.paths[`@${proj}/${lazylib}`];
|
|
||||||
updateFile('tsconfig.base.json', JSON.stringify(tsConfig, null, 2));
|
|
||||||
|
|
||||||
updateFile(
|
|
||||||
`apps/${myapp}/src/main.ts`,
|
|
||||||
`
|
|
||||||
import '../../../libs/${mylib}';
|
|
||||||
import '@secondScope/${lazylib}';
|
|
||||||
import '@${proj}/${myapp2}';
|
|
||||||
import '@${proj}/${invalidtaglib}';
|
|
||||||
import '@${proj}/${validtaglib}';
|
|
||||||
|
|
||||||
const s = {loadChildren: '@${proj}/${lazylib}'};
|
|
||||||
`
|
|
||||||
);
|
|
||||||
|
|
||||||
const out = runCLI(`lint ${myapp}`, { silenceError: true });
|
|
||||||
expect(out).toContain(
|
|
||||||
'Libraries cannot be imported by a relative or absolute path, and must begin with a npm scope'
|
|
||||||
);
|
|
||||||
// expect(out).toContain('Imports of lazy-loaded libraries are forbidden');
|
|
||||||
expect(out).toContain('Imports of apps are forbidden');
|
|
||||||
expect(out).toContain(
|
|
||||||
'A project tagged with "validtag" can only depend on libs tagged with "validtag"'
|
|
||||||
);
|
|
||||||
}, 1000000);
|
|
||||||
|
|
||||||
describe('nx workspace-lint', () => {
|
|
||||||
it('should identify issues with the workspace', () => {
|
|
||||||
const appBefore = uniq('before');
|
|
||||||
const appAfter = uniq('after');
|
|
||||||
|
|
||||||
runCLI(`generate @nrwl/angular:app ${appBefore}`);
|
|
||||||
renameFile(`apps/${appBefore}`, `apps/${appAfter}`);
|
|
||||||
|
|
||||||
const stdout = runCLI('workspace-lint', { silenceError: true });
|
|
||||||
expect(stdout).toContain(
|
|
||||||
`- Cannot find project '${appBefore}' in 'apps/${appBefore}'`
|
|
||||||
);
|
|
||||||
expect(stdout).toContain(
|
|
||||||
'The following file(s) do not belong to any projects:'
|
|
||||||
);
|
|
||||||
expect(stdout).toContain(`- apps/${appAfter}/jest.config.js`);
|
|
||||||
expect(stdout).toContain(`- apps/${appAfter}/src/app/app.component.css`);
|
|
||||||
expect(stdout).toContain(`- apps/${appAfter}/src/app/app.component.html`);
|
|
||||||
expect(stdout).toContain(
|
|
||||||
`- apps/${appAfter}/src/app/app.component.spec.ts`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('format', () => {
|
|
||||||
it('should check and reformat the code', async () => {
|
|
||||||
if (isNotWindows()) {
|
|
||||||
const myapp = uniq('myapp');
|
|
||||||
const mylib = uniq('mylib');
|
|
||||||
|
|
||||||
runCLI(`generate @nrwl/angular:app ${myapp}`);
|
|
||||||
runCLI(`generate @nrwl/angular:lib ${mylib}`);
|
|
||||||
updateFile(
|
|
||||||
`apps/${myapp}/src/main.ts`,
|
|
||||||
`
|
|
||||||
const x = 1111;
|
|
||||||
`
|
|
||||||
);
|
|
||||||
|
|
||||||
updateFile(
|
|
||||||
`apps/${myapp}/src/app/app.module.ts`,
|
|
||||||
`
|
|
||||||
const y = 1111;
|
|
||||||
`
|
|
||||||
);
|
|
||||||
|
|
||||||
updateFile(
|
|
||||||
`apps/${myapp}/src/app/app.component.ts`,
|
|
||||||
`
|
|
||||||
const z = 1111;
|
|
||||||
`
|
|
||||||
);
|
|
||||||
|
|
||||||
updateFile(
|
|
||||||
`libs/${mylib}/index.ts`,
|
|
||||||
`
|
|
||||||
const x = 1111;
|
|
||||||
`
|
|
||||||
);
|
|
||||||
updateFile(
|
|
||||||
`libs/${mylib}/src/${mylib}.module.ts`,
|
|
||||||
`
|
|
||||||
const y = 1111;
|
|
||||||
`
|
|
||||||
);
|
|
||||||
|
|
||||||
updateFile(
|
|
||||||
`README.md`,
|
|
||||||
`
|
|
||||||
my new readme;
|
|
||||||
`
|
|
||||||
);
|
|
||||||
|
|
||||||
let stdout = runCLI(
|
|
||||||
`format:check --files="libs/${mylib}/index.ts,package.json" --libs-and-apps`,
|
|
||||||
{ silenceError: true }
|
|
||||||
);
|
|
||||||
expect(stdout).toContain(path.normalize(`libs/${mylib}/index.ts`));
|
|
||||||
expect(stdout).toContain(
|
|
||||||
path.normalize(`libs/${mylib}/src/${mylib}.module.ts`)
|
|
||||||
);
|
|
||||||
expect(stdout).not.toContain(path.normalize(`README.md`)); // It will be contained only in case of exception, that we fallback to all
|
|
||||||
|
|
||||||
stdout = runCLI(`format:check --all`, { silenceError: true });
|
|
||||||
expect(stdout).toContain(path.normalize(`apps/${myapp}/src/main.ts`));
|
|
||||||
expect(stdout).toContain(
|
|
||||||
path.normalize(`apps/${myapp}/src/app/app.module.ts`)
|
|
||||||
);
|
|
||||||
expect(stdout).toContain(
|
|
||||||
path.normalize(`apps/${myapp}/src/app/app.component.ts`)
|
|
||||||
);
|
|
||||||
|
|
||||||
stdout = runCLI(`format:check --projects=${myapp}`, {
|
|
||||||
silenceError: true,
|
|
||||||
});
|
|
||||||
expect(stdout).toContain(path.normalize(`apps/${myapp}/src/main.ts`));
|
|
||||||
expect(stdout).toContain(
|
|
||||||
path.normalize(`apps/${myapp}/src/app/app.module.ts`)
|
|
||||||
);
|
|
||||||
expect(stdout).toContain(
|
|
||||||
path.normalize(`apps/${myapp}/src/app/app.component.ts`)
|
|
||||||
);
|
|
||||||
expect(stdout).not.toContain(path.normalize(`libs/${mylib}/index.ts`));
|
|
||||||
expect(stdout).not.toContain(
|
|
||||||
path.normalize(`libs/${mylib}/src/${mylib}.module.ts`)
|
|
||||||
);
|
|
||||||
expect(stdout).not.toContain(path.normalize(`README.md`));
|
|
||||||
|
|
||||||
stdout = runCLI(`format:check --projects=${myapp},${mylib}`, {
|
|
||||||
silenceError: true,
|
|
||||||
});
|
|
||||||
expect(stdout).toContain(path.normalize(`apps/${myapp}/src/main.ts`));
|
|
||||||
expect(stdout).toContain(
|
|
||||||
path.normalize(`apps/${myapp}/src/app/app.module.ts`)
|
|
||||||
);
|
|
||||||
expect(stdout).toContain(
|
|
||||||
path.normalize(`apps/${myapp}/src/app/app.component.ts`)
|
|
||||||
);
|
|
||||||
expect(stdout).toContain(path.normalize(`libs/${mylib}/index.ts`));
|
|
||||||
expect(stdout).toContain(
|
|
||||||
path.normalize(`libs/${mylib}/src/${mylib}.module.ts`)
|
|
||||||
);
|
|
||||||
expect(stdout).not.toContain(path.normalize(`README.md`));
|
|
||||||
|
|
||||||
const { stderr } = await runCLIAsync(
|
|
||||||
`format:check --projects=${myapp},${mylib} --all`,
|
|
||||||
{
|
|
||||||
silenceError: true,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
expect(stderr).toContain(
|
|
||||||
'Arguments all and projects are mutually exclusive'
|
|
||||||
);
|
|
||||||
|
|
||||||
runCLI(
|
|
||||||
`format:write --files="apps/${myapp}/src/app/app.module.ts,apps/${myapp}/src/app/app.component.ts"`
|
|
||||||
);
|
|
||||||
|
|
||||||
stdout = runCLI('format:check --all', { silenceError: true });
|
|
||||||
expect(stdout).toContain(path.normalize(`apps/${myapp}/src/main.ts`));
|
|
||||||
expect(stdout).not.toContain(
|
|
||||||
path.normalize(`apps/${myapp}/src/app/app.module.ts`)
|
|
||||||
);
|
|
||||||
expect(stdout).not.toContain(
|
|
||||||
path.normalize(`apps/${myapp}/src/app/app.component.ts`)
|
|
||||||
);
|
|
||||||
|
|
||||||
runCLI('format:write --all');
|
|
||||||
expect(runCLI('format:check --all')).not.toContain(
|
|
||||||
path.normalize(`apps/${myapp}/src/main.ts`)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}, 90000);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('workspace-generator', () => {
|
describe('workspace-generator', () => {
|
||||||
let custom: string;
|
let custom: string;
|
||||||
let failing: string;
|
let failing: string;
|
||||||
@ -399,329 +171,31 @@ describe('workspace-generator', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('dep-graph', () => {
|
describe('workspace-lint', () => {
|
||||||
let proj: string;
|
it('should identify issues with the workspace', () => {
|
||||||
let myapp: string;
|
const appBefore = uniq('before');
|
||||||
let myapp2: string;
|
const appAfter = uniq('after');
|
||||||
let myapp3: string;
|
|
||||||
let myappE2e: string;
|
|
||||||
let myapp2E2e: string;
|
|
||||||
let myapp3E2e: string;
|
|
||||||
let mylib: string;
|
|
||||||
let mylib2: string;
|
|
||||||
beforeAll(() => {
|
|
||||||
proj = newProject();
|
|
||||||
myapp = uniq('myapp');
|
|
||||||
myapp2 = uniq('myapp2');
|
|
||||||
myapp3 = uniq('myapp3');
|
|
||||||
myappE2e = `${myapp}-e2e`;
|
|
||||||
myapp2E2e = `${myapp2}-e2e`;
|
|
||||||
myapp3E2e = `${myapp3}-e2e`;
|
|
||||||
mylib = uniq('mylib');
|
|
||||||
mylib2 = uniq('mylib2');
|
|
||||||
|
|
||||||
runCLI(`generate @nrwl/angular:app ${myapp}`);
|
runCLI(`generate @nrwl/angular:app ${appBefore}`);
|
||||||
runCLI(`generate @nrwl/angular:app ${myapp2}`);
|
renameFile(`apps/${appBefore}`, `apps/${appAfter}`);
|
||||||
runCLI(`generate @nrwl/angular:app ${myapp3}`);
|
|
||||||
runCLI(`generate @nrwl/angular:lib ${mylib}`);
|
|
||||||
runCLI(`generate @nrwl/angular:lib ${mylib2}`);
|
|
||||||
|
|
||||||
updateFile(
|
const stdout = runCLI('workspace-lint', { silenceError: true });
|
||||||
`apps/${myapp}/src/main.ts`,
|
expect(stdout).toContain(
|
||||||
`
|
`- Cannot find project '${appBefore}' in 'apps/${appBefore}'`
|
||||||
import '@${proj}/${mylib}';
|
|
||||||
|
|
||||||
const s = {loadChildren: '@${proj}/${mylib2}'};
|
|
||||||
`
|
|
||||||
);
|
);
|
||||||
|
expect(stdout).toContain(
|
||||||
updateFile(
|
'The following file(s) do not belong to any projects:'
|
||||||
`apps/${myapp2}/src/app/app.component.spec.ts`,
|
|
||||||
`import '@${proj}/${mylib}';`
|
|
||||||
);
|
);
|
||||||
|
expect(stdout).toContain(`- apps/${appAfter}/jest.config.js`);
|
||||||
updateFile(
|
expect(stdout).toContain(`- apps/${appAfter}/src/app/app.component.css`);
|
||||||
`libs/${mylib}/src/mylib.module.spec.ts`,
|
expect(stdout).toContain(`- apps/${appAfter}/src/app/app.component.html`);
|
||||||
`import '@${proj}/${mylib2}';`
|
expect(stdout).toContain(
|
||||||
|
`- apps/${appAfter}/src/app/app.component.spec.ts`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('dep-graph should output json to file', () => {
|
|
||||||
runCLI(`dep-graph --file=project-graph.json`);
|
|
||||||
|
|
||||||
expect(() => checkFilesExist('project-graph.json')).not.toThrow();
|
|
||||||
|
|
||||||
const jsonFileContents = readJson('project-graph.json');
|
|
||||||
|
|
||||||
expect(jsonFileContents.graph.dependencies).toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
[myapp3E2e]: [
|
|
||||||
{
|
|
||||||
source: myapp3E2e,
|
|
||||||
target: myapp3,
|
|
||||||
type: 'implicit',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[myapp2]: [
|
|
||||||
{
|
|
||||||
source: myapp2,
|
|
||||||
target: mylib,
|
|
||||||
type: 'static',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[myapp2E2e]: [
|
|
||||||
{
|
|
||||||
source: myapp2E2e,
|
|
||||||
target: myapp2,
|
|
||||||
type: 'implicit',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[mylib]: [
|
|
||||||
{
|
|
||||||
source: mylib,
|
|
||||||
target: mylib2,
|
|
||||||
type: 'static',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[mylib2]: [],
|
|
||||||
[myapp]: [
|
|
||||||
{
|
|
||||||
source: myapp,
|
|
||||||
target: mylib,
|
|
||||||
type: 'static',
|
|
||||||
},
|
|
||||||
{ source: myapp, target: mylib2, type: 'static' },
|
|
||||||
],
|
|
||||||
[myappE2e]: [
|
|
||||||
{
|
|
||||||
source: myappE2e,
|
|
||||||
target: myapp,
|
|
||||||
type: 'implicit',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[myapp3]: [],
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
runCLI(
|
|
||||||
`affected:dep-graph --files="libs/${mylib}/src/index.ts" --file="project-graph.json"`
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(() => checkFilesExist('project-graph.json')).not.toThrow();
|
|
||||||
|
|
||||||
const jsonFileContents2 = readJson('project-graph.json');
|
|
||||||
|
|
||||||
expect(jsonFileContents2.criticalPath).toContain(myapp);
|
|
||||||
expect(jsonFileContents2.criticalPath).toContain(myapp2);
|
|
||||||
expect(jsonFileContents2.criticalPath).toContain(mylib);
|
|
||||||
expect(jsonFileContents2.criticalPath).not.toContain(mylib2);
|
|
||||||
}, 1000000);
|
|
||||||
|
|
||||||
it('dep-graph should focus requested project', () => {
|
|
||||||
runCLI(`dep-graph --focus=${myapp} --file=project-graph.json`);
|
|
||||||
|
|
||||||
expect(() => checkFilesExist('project-graph.json')).not.toThrow();
|
|
||||||
|
|
||||||
const jsonFileContents = readJson('project-graph.json');
|
|
||||||
const projectNames = Object.keys(jsonFileContents.graph.nodes);
|
|
||||||
|
|
||||||
expect(projectNames).toContain(myapp);
|
|
||||||
expect(projectNames).toContain(mylib);
|
|
||||||
expect(projectNames).toContain(mylib2);
|
|
||||||
expect(projectNames).toContain(myappE2e);
|
|
||||||
|
|
||||||
expect(projectNames).not.toContain(myapp2);
|
|
||||||
expect(projectNames).not.toContain(myapp3);
|
|
||||||
expect(projectNames).not.toContain(myapp2E2e);
|
|
||||||
expect(projectNames).not.toContain(myapp3E2e);
|
|
||||||
}, 1000000);
|
|
||||||
|
|
||||||
it('dep-graph should exclude requested projects', () => {
|
|
||||||
runCLI(
|
|
||||||
`dep-graph --exclude=${myappE2e},${myapp2E2e},${myapp3E2e} --file=project-graph.json`
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(() => checkFilesExist('project-graph.json')).not.toThrow();
|
|
||||||
|
|
||||||
const jsonFileContents = readJson('project-graph.json');
|
|
||||||
const projectNames = Object.keys(jsonFileContents.graph.nodes);
|
|
||||||
|
|
||||||
expect(projectNames).toContain(myapp);
|
|
||||||
expect(projectNames).toContain(mylib);
|
|
||||||
expect(projectNames).toContain(mylib2);
|
|
||||||
expect(projectNames).toContain(myapp2);
|
|
||||||
expect(projectNames).toContain(myapp3);
|
|
||||||
|
|
||||||
expect(projectNames).not.toContain(myappE2e);
|
|
||||||
expect(projectNames).not.toContain(myapp2E2e);
|
|
||||||
expect(projectNames).not.toContain(myapp3E2e);
|
|
||||||
}, 1000000);
|
|
||||||
|
|
||||||
it('dep-graph should exclude requested projects that were included by a focus', () => {
|
|
||||||
runCLI(
|
|
||||||
`dep-graph --focus=${myapp} --exclude=${myappE2e} --file=project-graph.json`
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(() => checkFilesExist('project-graph.json')).not.toThrow();
|
|
||||||
|
|
||||||
const jsonFileContents = readJson('project-graph.json');
|
|
||||||
const projectNames = Object.keys(jsonFileContents.graph.nodes);
|
|
||||||
|
|
||||||
expect(projectNames).toContain(myapp);
|
|
||||||
expect(projectNames).toContain(mylib);
|
|
||||||
expect(projectNames).toContain(mylib2);
|
|
||||||
|
|
||||||
expect(projectNames).not.toContain(myappE2e);
|
|
||||||
expect(projectNames).not.toContain(myapp2);
|
|
||||||
expect(projectNames).not.toContain(myapp3);
|
|
||||||
expect(projectNames).not.toContain(myapp2E2e);
|
|
||||||
expect(projectNames).not.toContain(myapp3E2e);
|
|
||||||
}, 1000000);
|
|
||||||
|
|
||||||
it('dep-graph should output a deployable static website in an html file accompanied by a folder with static assets', () => {
|
|
||||||
runCLI(`dep-graph --file=project-graph.html`);
|
|
||||||
|
|
||||||
expect(() => checkFilesExist('project-graph.html')).not.toThrow();
|
|
||||||
expect(() => checkFilesExist('static/styles.css')).not.toThrow();
|
|
||||||
expect(() => checkFilesExist('static/runtime.esm.js')).not.toThrow();
|
|
||||||
expect(() => checkFilesExist('static/polyfills.esm.js')).not.toThrow();
|
|
||||||
expect(() => checkFilesExist('static/main.esm.js')).not.toThrow();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Move Angular Project', () => {
|
describe('move project', () => {
|
||||||
let proj: string;
|
|
||||||
let app1: string;
|
|
||||||
let app2: string;
|
|
||||||
let newPath: string;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
proj = newProject();
|
|
||||||
app1 = uniq('app1');
|
|
||||||
app2 = uniq('app2');
|
|
||||||
newPath = `subfolder/${app2}`;
|
|
||||||
runCLI(`generate @nrwl/angular:app ${app1}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => removeProject({ onlyOnCI: true }));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries moving an app from ${app1} -> subfolder/${app2}
|
|
||||||
*/
|
|
||||||
it('should work for apps', () => {
|
|
||||||
const moveOutput = runCLI(
|
|
||||||
`generate @nrwl/angular:move --project ${app1} ${newPath}`
|
|
||||||
);
|
|
||||||
|
|
||||||
// just check the output
|
|
||||||
expect(moveOutput).toContain(`DELETE apps/${app1}`);
|
|
||||||
expect(moveOutput).toContain(`CREATE apps/${newPath}/.browserslistrc`);
|
|
||||||
expect(moveOutput).toContain(`CREATE apps/${newPath}/jest.config.js`);
|
|
||||||
expect(moveOutput).toContain(`CREATE apps/${newPath}/tsconfig.app.json`);
|
|
||||||
expect(moveOutput).toContain(`CREATE apps/${newPath}/tsconfig.json`);
|
|
||||||
expect(moveOutput).toContain(`CREATE apps/${newPath}/tsconfig.spec.json`);
|
|
||||||
expect(moveOutput).toContain(`CREATE apps/${newPath}/.eslintrc.json`);
|
|
||||||
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/favicon.ico`);
|
|
||||||
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/index.html`);
|
|
||||||
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/main.ts`);
|
|
||||||
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/polyfills.ts`);
|
|
||||||
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/styles.css`);
|
|
||||||
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/test-setup.ts`);
|
|
||||||
expect(moveOutput).toContain(
|
|
||||||
`CREATE apps/${newPath}/src/app/app.component.html`
|
|
||||||
);
|
|
||||||
expect(moveOutput).toContain(
|
|
||||||
`CREATE apps/${newPath}/src/app/app.module.ts`
|
|
||||||
);
|
|
||||||
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/assets/.gitkeep`);
|
|
||||||
expect(moveOutput).toContain(
|
|
||||||
`CREATE apps/${newPath}/src/environments/environment.prod.ts`
|
|
||||||
);
|
|
||||||
expect(moveOutput).toContain(
|
|
||||||
`CREATE apps/${newPath}/src/environments/environment.ts`
|
|
||||||
);
|
|
||||||
expect(moveOutput).toContain(`UPDATE nx.json`);
|
|
||||||
expect(moveOutput).toContain(`UPDATE workspace.json`);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries moving an e2e project from ${app1} -> ${newPath}
|
|
||||||
*/
|
|
||||||
it('should work for e2e projects', () => {
|
|
||||||
const moveOutput = runCLI(
|
|
||||||
`generate @nrwl/angular:move --projectName=${app1}-e2e --destination=${newPath}-e2e`
|
|
||||||
);
|
|
||||||
|
|
||||||
// just check that the cypress.json is updated correctly
|
|
||||||
const cypressJsonPath = `apps/${newPath}-e2e/cypress.json`;
|
|
||||||
expect(moveOutput).toContain(`CREATE ${cypressJsonPath}`);
|
|
||||||
checkFilesExist(cypressJsonPath);
|
|
||||||
const cypressJson = readJson(cypressJsonPath);
|
|
||||||
expect(cypressJson.videosFolder).toEqual(
|
|
||||||
`../../../dist/cypress/apps/${newPath}-e2e/videos`
|
|
||||||
);
|
|
||||||
expect(cypressJson.screenshotsFolder).toEqual(
|
|
||||||
`../../../dist/cypress/apps/${newPath}-e2e/screenshots`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries moving a library from ${lib} -> shared/${lib}
|
|
||||||
*/
|
|
||||||
it('should work for libraries', () => {
|
|
||||||
const lib1 = uniq('mylib');
|
|
||||||
const lib2 = uniq('mylib');
|
|
||||||
runCLI(`generate @nrwl/angular:lib ${lib1}`);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a library which imports the module from the other lib
|
|
||||||
*/
|
|
||||||
|
|
||||||
runCLI(`generate @nrwl/angular:lib ${lib2}`);
|
|
||||||
|
|
||||||
updateFile(
|
|
||||||
`libs/${lib2}/src/lib/${lib2}.module.ts`,
|
|
||||||
`import { ${classify(lib1)}Module } from '@${proj}/${lib1}';
|
|
||||||
|
|
||||||
export class ExtendedModule extends ${classify(lib1)}Module { }`
|
|
||||||
);
|
|
||||||
|
|
||||||
const moveOutput = runCLI(
|
|
||||||
`generate @nrwl/angular:move --projectName=${lib1} --destination=shared/${lib1}`
|
|
||||||
);
|
|
||||||
|
|
||||||
const newPath = `libs/shared/${lib1}`;
|
|
||||||
const newModule = `Shared${classify(lib1)}Module`;
|
|
||||||
|
|
||||||
const testSetupPath = `${newPath}/src/test-setup.ts`;
|
|
||||||
expect(moveOutput).toContain(`CREATE ${testSetupPath}`);
|
|
||||||
checkFilesExist(testSetupPath);
|
|
||||||
|
|
||||||
const modulePath = `${newPath}/src/lib/shared-${lib1}.module.ts`;
|
|
||||||
expect(moveOutput).toContain(`CREATE ${modulePath}`);
|
|
||||||
checkFilesExist(modulePath);
|
|
||||||
const moduleFile = readFile(modulePath);
|
|
||||||
expect(moduleFile).toContain(`export class ${newModule}`);
|
|
||||||
|
|
||||||
const indexPath = `${newPath}/src/index.ts`;
|
|
||||||
expect(moveOutput).toContain(`CREATE ${indexPath}`);
|
|
||||||
checkFilesExist(indexPath);
|
|
||||||
const index = readFile(indexPath);
|
|
||||||
expect(index).toContain(`export * from './lib/shared-${lib1}.module'`);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check that the import in lib2 has been updated
|
|
||||||
*/
|
|
||||||
const lib2FilePath = `libs/${lib2}/src/lib/${lib2}.module.ts`;
|
|
||||||
const lib2File = readFile(lib2FilePath);
|
|
||||||
expect(lib2File).toContain(
|
|
||||||
`import { ${newModule} } from '@${proj}/shared-${lib1}';`
|
|
||||||
);
|
|
||||||
expect(lib2File).toContain(`extends ${newModule}`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Move Project', () => {
|
|
||||||
/**
|
/**
|
||||||
* Tries moving a library from ${lib}/data-access -> shared/${lib}/data-access
|
* Tries moving a library from ${lib}/data-access -> shared/${lib}/data-access
|
||||||
*/
|
*/
|
||||||
@ -1138,7 +612,7 @@ describe('Move Project', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Remove Project', () => {
|
describe('remove project', () => {
|
||||||
/**
|
/**
|
||||||
* Tries creating then deleting a lib
|
* Tries creating then deleting a lib
|
||||||
*/
|
*/
|
||||||
@ -13,20 +13,20 @@ describe('Run Commands', () => {
|
|||||||
afterAll(() => removeProject({ onlyOnCI: true }));
|
afterAll(() => removeProject({ onlyOnCI: true }));
|
||||||
|
|
||||||
it('should not override environment variables already set when setting a custom env file path', async () => {
|
it('should not override environment variables already set when setting a custom env file path', async () => {
|
||||||
const nodeapp = uniq('nodeapp');
|
const mylib = uniq('lib');
|
||||||
updateFile(
|
updateFile(
|
||||||
`.env`,
|
`.env`,
|
||||||
'SHARED_VAR=shared-root-value\nROOT_ONLY=root-only-value'
|
'SHARED_VAR=shared-root-value\nROOT_ONLY=root-only-value'
|
||||||
);
|
);
|
||||||
runCLI(`generate @nrwl/express:app ${nodeapp}`);
|
runCLI(`generate @nrwl/workspace:lib ${mylib}`);
|
||||||
updateFile(
|
updateFile(
|
||||||
`apps/${nodeapp}/.custom.env`,
|
`apps/${mylib}/.custom.env`,
|
||||||
'SHARED_VAR=shared-nested-value\nNESTED_ONLY=nested-only-value'
|
'SHARED_VAR=shared-nested-value\nNESTED_ONLY=nested-only-value'
|
||||||
);
|
);
|
||||||
|
|
||||||
const envFile = `apps/${nodeapp}/.custom.env`;
|
const envFile = `apps/${mylib}/.custom.env`;
|
||||||
runCLI(
|
runCLI(
|
||||||
`generate @nrwl/workspace:run-commands echoEnvVariables --command=echo --envFile=${envFile} --project=${nodeapp}`
|
`generate @nrwl/workspace:run-commands echoEnvVariables --command=echo --envFile=${envFile} --project=${mylib}`
|
||||||
);
|
);
|
||||||
|
|
||||||
const command =
|
const command =
|
||||||
@ -35,11 +35,11 @@ describe('Run Commands', () => {
|
|||||||
: `$SHARED_VAR $ROOT_ONLY $NESTED_ONLY`;
|
: `$SHARED_VAR $ROOT_ONLY $NESTED_ONLY`;
|
||||||
const config = readJson(workspaceConfigName());
|
const config = readJson(workspaceConfigName());
|
||||||
config.projects[
|
config.projects[
|
||||||
nodeapp
|
mylib
|
||||||
].targets.echoEnvVariables.options.command += ` ${command}`;
|
].targets.echoEnvVariables.options.command += ` ${command}`;
|
||||||
updateFile(workspaceConfigName(), JSON.stringify(config, null, 2));
|
updateFile(workspaceConfigName(), JSON.stringify(config, null, 2));
|
||||||
|
|
||||||
const result = runCLI('echoEnvVariables');
|
const result = runCLI(`run ${mylib}:echoEnvVariables`);
|
||||||
expect(result).toContain('shared-root-value');
|
expect(result).toContain('shared-root-value');
|
||||||
expect(result).not.toContain('shared-nested-value');
|
expect(result).not.toContain('shared-nested-value');
|
||||||
expect(result).toContain('root-only-value');
|
expect(result).toContain('root-only-value');
|
||||||
@ -47,12 +47,12 @@ describe('Run Commands', () => {
|
|||||||
}, 120000);
|
}, 120000);
|
||||||
|
|
||||||
it('should pass options', async () => {
|
it('should pass options', async () => {
|
||||||
const myapp = uniq('myapp1');
|
const mylib = uniq('lib');
|
||||||
|
|
||||||
runCLI(`generate @nrwl/web:app ${myapp}`);
|
runCLI(`generate @nrwl/workspace:lib ${mylib}`);
|
||||||
|
|
||||||
const config = readJson(workspaceConfigName());
|
const config = readJson(workspaceConfigName());
|
||||||
config.projects[myapp].targets.echo = {
|
config.projects[mylib].targets.echo = {
|
||||||
executor: '@nrwl/workspace:run-commands',
|
executor: '@nrwl/workspace:run-commands',
|
||||||
options: {
|
options: {
|
||||||
command: 'echo',
|
command: 'echo',
|
||||||
@ -64,19 +64,19 @@ describe('Run Commands', () => {
|
|||||||
};
|
};
|
||||||
updateFile(workspaceConfigName(), JSON.stringify(config));
|
updateFile(workspaceConfigName(), JSON.stringify(config));
|
||||||
|
|
||||||
const result = runCLI(`run ${myapp}:echo`, { silent: true });
|
const result = runCLI(`run ${mylib}:echo`, { silent: true });
|
||||||
expect(result).toContain(
|
expect(result).toContain(
|
||||||
'--var1=a --var2=b --var-hyphen=c --varCamelCase=d'
|
'--var1=a --var2=b --var-hyphen=c --varCamelCase=d'
|
||||||
);
|
);
|
||||||
}, 120000);
|
}, 120000);
|
||||||
|
|
||||||
it('should interpolate provided arguments', async () => {
|
it('should interpolate provided arguments', async () => {
|
||||||
const myapp = uniq('myapp1');
|
const mylib = uniq('lib');
|
||||||
|
|
||||||
runCLI(`generate @nrwl/web:app ${myapp}`);
|
runCLI(`generate @nrwl/workspace:lib ${mylib}`);
|
||||||
|
|
||||||
const config = readJson(workspaceConfigName());
|
const config = readJson(workspaceConfigName());
|
||||||
config.projects[myapp].targets.echo = {
|
config.projects[mylib].targets.echo = {
|
||||||
executor: '@nrwl/workspace:run-commands',
|
executor: '@nrwl/workspace:run-commands',
|
||||||
options: {
|
options: {
|
||||||
commands: [
|
commands: [
|
||||||
@ -92,7 +92,7 @@ describe('Run Commands', () => {
|
|||||||
updateFile(workspaceConfigName(), JSON.stringify(config));
|
updateFile(workspaceConfigName(), JSON.stringify(config));
|
||||||
|
|
||||||
const result = runCLI(
|
const result = runCLI(
|
||||||
`run ${myapp}:echo --var1=a --var2=b --var-hyphen=c --varCamelCase=d`
|
`run ${mylib}:echo --var1=a --var2=b --var-hyphen=c --varCamelCase=d`
|
||||||
);
|
);
|
||||||
expect(result).toContain('var1: a');
|
expect(result).toContain('var1: a');
|
||||||
expect(result).toContain('var2: b');
|
expect(result).toContain('var2: b');
|
||||||
@ -100,7 +100,7 @@ describe('Run Commands', () => {
|
|||||||
expect(result).toContain('camel: d');
|
expect(result).toContain('camel: d');
|
||||||
|
|
||||||
const resultArgs = runCLI(
|
const resultArgs = runCLI(
|
||||||
`run ${myapp}:echo --args="--var1=a --var2=b --var-hyphen=c --varCamelCase=d"`
|
`run ${mylib}:echo --args="--var1=a --var2=b --var-hyphen=c --varCamelCase=d"`
|
||||||
);
|
);
|
||||||
expect(resultArgs).toContain('var1: a');
|
expect(resultArgs).toContain('var1: a');
|
||||||
expect(resultArgs).toContain('var2: b');
|
expect(resultArgs).toContain('var2: b');
|
||||||
@ -109,12 +109,12 @@ describe('Run Commands', () => {
|
|||||||
}, 120000);
|
}, 120000);
|
||||||
|
|
||||||
it('should fail when a process exits non-zero', () => {
|
it('should fail when a process exits non-zero', () => {
|
||||||
const myapp = uniq('myapp1');
|
const mylib = uniq('lib');
|
||||||
|
|
||||||
runCLI(`generate @nrwl/web:app ${myapp}`);
|
runCLI(`generate @nrwl/workspace:lib ${mylib}`);
|
||||||
|
|
||||||
const config = readJson(workspaceConfigName());
|
const config = readJson(workspaceConfigName());
|
||||||
config.projects[myapp].targets.error = {
|
config.projects[mylib].targets.error = {
|
||||||
executor: '@nrwl/workspace:run-commands',
|
executor: '@nrwl/workspace:run-commands',
|
||||||
options: {
|
options: {
|
||||||
command: `exit 1`,
|
command: `exit 1`,
|
||||||
@ -123,7 +123,7 @@ describe('Run Commands', () => {
|
|||||||
updateFile(workspaceConfigName(), JSON.stringify(config));
|
updateFile(workspaceConfigName(), JSON.stringify(config));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
runCLI(`run ${myapp}:error`);
|
runCLI(`run ${mylib}:error`);
|
||||||
fail('Should error if process errors');
|
fail('Should error if process errors');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.stderr.toString()).toContain(
|
expect(e.stderr.toString()).toContain(
|
||||||
@ -133,17 +133,17 @@ describe('Run Commands', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('run command should not break if output property is missing in options and arguments', () => {
|
it('run command should not break if output property is missing in options and arguments', () => {
|
||||||
const myapp = uniq('myapp');
|
const mylib = uniq('mylib');
|
||||||
|
|
||||||
runCLI(`generate @nrwl/web:app ${myapp}`);
|
runCLI(`generate @nrwl/workspace:lib ${mylib}`);
|
||||||
const workspaceJson = readJson(`workspace.json`);
|
const workspaceJson = readJson(`workspace.json`);
|
||||||
workspaceJson.projects[myapp].targets.lint.outputs = [
|
workspaceJson.projects[mylib].targets.lint.outputs = [
|
||||||
'{options.outputFile}',
|
'{options.outputFile}',
|
||||||
];
|
];
|
||||||
updateFile('workspace.json', JSON.stringify(workspaceJson, null, 2));
|
updateFile('workspace.json', JSON.stringify(workspaceJson, null, 2));
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
runCLI(`run ${myapp}:lint --format=json`, {
|
runCLI(`run ${mylib}:lint --format=json`, {
|
||||||
silenceError: true,
|
silenceError: true,
|
||||||
})
|
})
|
||||||
).not.toThrow();
|
).not.toThrow();
|
||||||
10
e2e/workspace-create/jest.config.js
Normal file
10
e2e/workspace-create/jest.config.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module.exports = {
|
||||||
|
preset: '../../jest.preset.js',
|
||||||
|
transform: {
|
||||||
|
'^.+\\.[tj]sx?$': 'ts-jest',
|
||||||
|
},
|
||||||
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||||
|
maxWorkers: 1,
|
||||||
|
globals: { 'ts-jest': { tsconfig: '<rootDir>/tsconfig.spec.json' } },
|
||||||
|
displayName: 'e2e-workspace-create',
|
||||||
|
};
|
||||||
34
e2e/workspace-create/project.json
Normal file
34
e2e/workspace-create/project.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"root": "e2e/workspace-create",
|
||||||
|
"sourceRoot": "e2e/workspace-create",
|
||||||
|
"projectType": "application",
|
||||||
|
"targets": {
|
||||||
|
"e2e": {
|
||||||
|
"executor": "@nrwl/workspace:run-commands",
|
||||||
|
"options": {
|
||||||
|
"commands": [
|
||||||
|
{
|
||||||
|
"command": "yarn e2e-start-local-registry"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "yarn e2e-build-package-publish"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "nx run-e2e-tests e2e-workspace-create"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parallel": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"run-e2e-tests": {
|
||||||
|
"executor": "@nrwl/jest:jest",
|
||||||
|
"options": {
|
||||||
|
"jestConfig": "e2e/workspace-create/jest.config.js",
|
||||||
|
"passWithNoTests": true,
|
||||||
|
"runInBand": true
|
||||||
|
},
|
||||||
|
"outputs": ["coverage/e2e/workspace-create"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"implicitDependencies": ["create-nx-workspace"]
|
||||||
|
}
|
||||||
13
e2e/workspace-create/tsconfig.json
Normal file
13
e2e/workspace-create/tsconfig.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"types": ["node", "jest"]
|
||||||
|
},
|
||||||
|
"include": [],
|
||||||
|
"files": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.spec.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
16
e2e/workspace-create/tsconfig.spec.json
Normal file
16
e2e/workspace-create/tsconfig.spec.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../dist/out-tsc",
|
||||||
|
"module": "commonjs",
|
||||||
|
"types": ["jest", "node"]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"**/*.test.ts",
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/*.spec.tsx",
|
||||||
|
"**/*.spec.js",
|
||||||
|
"**/*.spec.jsx",
|
||||||
|
"**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
10
e2e/workspace-integrations/jest.config.js
Normal file
10
e2e/workspace-integrations/jest.config.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module.exports = {
|
||||||
|
preset: '../../jest.preset.js',
|
||||||
|
transform: {
|
||||||
|
'^.+\\.[tj]sx?$': 'ts-jest',
|
||||||
|
},
|
||||||
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||||
|
maxWorkers: 1,
|
||||||
|
globals: { 'ts-jest': { tsconfig: '<rootDir>/tsconfig.spec.json' } },
|
||||||
|
displayName: 'e2e-workspace-integrations',
|
||||||
|
};
|
||||||
34
e2e/workspace-integrations/project.json
Normal file
34
e2e/workspace-integrations/project.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"root": "e2e/workspace-integrations",
|
||||||
|
"sourceRoot": "e2e/workspace-integrations",
|
||||||
|
"projectType": "application",
|
||||||
|
"targets": {
|
||||||
|
"e2e": {
|
||||||
|
"executor": "@nrwl/workspace:run-commands",
|
||||||
|
"options": {
|
||||||
|
"commands": [
|
||||||
|
{
|
||||||
|
"command": "yarn e2e-start-local-registry"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "yarn e2e-build-package-publish"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "nx run-e2e-tests e2e-workspace-integrations"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parallel": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"run-e2e-tests": {
|
||||||
|
"executor": "@nrwl/jest:jest",
|
||||||
|
"options": {
|
||||||
|
"jestConfig": "e2e/workspace-integrations/jest.config.js",
|
||||||
|
"passWithNoTests": true,
|
||||||
|
"runInBand": true
|
||||||
|
},
|
||||||
|
"outputs": ["coverage/e2e/workspace-integrations"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"implicitDependencies": ["angular", "react"]
|
||||||
|
}
|
||||||
56
e2e/workspace-integrations/src/custom-layout.test.ts
Normal file
56
e2e/workspace-integrations/src/custom-layout.test.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import {
|
||||||
|
checkFilesExist,
|
||||||
|
readFile,
|
||||||
|
readJson,
|
||||||
|
runCLI,
|
||||||
|
runCLIAsync,
|
||||||
|
runCreateWorkspace,
|
||||||
|
uniq,
|
||||||
|
packageInstall,
|
||||||
|
removeProject,
|
||||||
|
getSelectedPackageManager,
|
||||||
|
} from '@nrwl/e2e/utils';
|
||||||
|
|
||||||
|
describe('custom workspace layout', () => {
|
||||||
|
afterAll(() => removeProject({ onlyOnCI: true }));
|
||||||
|
|
||||||
|
it('should work', async () => {
|
||||||
|
// TODO (meeroslav): what is the purpose of this test?
|
||||||
|
// const proj = uniq('custom-layout-proj');
|
||||||
|
// const packageManager = getSelectedPackageManager();
|
||||||
|
// runCreateWorkspace(proj, { preset: 'npm', packageManager });
|
||||||
|
// packageInstall('@nrwl/react @nrwl/angular @nrwl/express');
|
||||||
|
// const nxJson = readJson('nx.json');
|
||||||
|
// expect(nxJson.extends).toEqual('@nrwl/workspace/presets/npm.json');
|
||||||
|
// const reactApp = uniq('reactapp');
|
||||||
|
// const reactLib = uniq('reactlib');
|
||||||
|
// const ngApp = uniq('ngapp');
|
||||||
|
// const ngLib = uniq('nglib');
|
||||||
|
// const expressApp = uniq('expessapp');
|
||||||
|
// const expressLib = uniq('expresslib');
|
||||||
|
// runCLI(`generate @nrwl/react:app ${reactApp} --no-interactive`);
|
||||||
|
// runCLI(`generate @nrwl/react:lib ${reactLib} --no-interactive`);
|
||||||
|
// runCLI(`generate @nrwl/angular:app ${ngApp} --no-interactive`);
|
||||||
|
// runCLI(`generate @nrwl/angular:lib ${ngLib} --no-interactive`);
|
||||||
|
// runCLI(`generate @nrwl/express:app ${expressApp} --no-interactive`);
|
||||||
|
// runCLI(`generate @nrwl/express:lib ${expressLib} --no-interactive`);
|
||||||
|
// checkFilesExist(
|
||||||
|
// `packages/${reactLib}/src/index.ts`,
|
||||||
|
// `packages/${reactApp}/src/main.tsx`,
|
||||||
|
// `packages/${reactApp}-e2e/cypress.json`,
|
||||||
|
// `packages/${ngLib}/src/index.ts`,
|
||||||
|
// `packages/${ngApp}/src/main.ts`,
|
||||||
|
// `packages/${ngApp}-e2e/cypress.json`,
|
||||||
|
// `packages/${expressLib}/src/index.ts`,
|
||||||
|
// `packages/${expressApp}/src/main.ts`
|
||||||
|
// );
|
||||||
|
// const workspaceJson = readFile('workspace.json');
|
||||||
|
// expect(workspaceJson).not.toContain('apps/');
|
||||||
|
// expect(workspaceJson).not.toContain('libs/');
|
||||||
|
// const libTestResults = await runCLIAsync(`test ${expressLib}`);
|
||||||
|
// expect(libTestResults.stdout).toContain(`nx run ${expressLib}:test`);
|
||||||
|
// const appBuildResults = await runCLIAsync(`build ${expressApp}`);
|
||||||
|
// expect(appBuildResults.stdout).toContain(`nx run ${expressApp}:build`);
|
||||||
|
// checkFilesExist(`dist/packages/${expressApp}/main.js`);
|
||||||
|
}, 1000000);
|
||||||
|
});
|
||||||
476
e2e/workspace-integrations/src/workspace-aux-commands.test.ts
Normal file
476
e2e/workspace-integrations/src/workspace-aux-commands.test.ts
Normal file
@ -0,0 +1,476 @@
|
|||||||
|
import * as path from 'path';
|
||||||
|
import {
|
||||||
|
checkFilesExist,
|
||||||
|
exists,
|
||||||
|
isNotWindows,
|
||||||
|
newProject,
|
||||||
|
readFile,
|
||||||
|
readJson,
|
||||||
|
removeProject,
|
||||||
|
runCLI,
|
||||||
|
runCLIAsync,
|
||||||
|
tmpProjPath,
|
||||||
|
uniq,
|
||||||
|
updateFile,
|
||||||
|
} from '@nrwl/e2e/utils';
|
||||||
|
import type { NxJsonConfiguration } from '@nrwl/devkit';
|
||||||
|
import { classify } from '@nrwl/workspace/src/utils/strings';
|
||||||
|
|
||||||
|
let proj: string;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
proj = newProject();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('format', () => {
|
||||||
|
it('should check and reformat the code', async () => {
|
||||||
|
if (isNotWindows()) {
|
||||||
|
const myapp = uniq('myapp');
|
||||||
|
const mylib = uniq('mylib');
|
||||||
|
|
||||||
|
runCLI(`generate @nrwl/angular:app ${myapp}`);
|
||||||
|
runCLI(`generate @nrwl/angular:lib ${mylib}`);
|
||||||
|
updateFile(
|
||||||
|
`apps/${myapp}/src/main.ts`,
|
||||||
|
`
|
||||||
|
const x = 1111;
|
||||||
|
`
|
||||||
|
);
|
||||||
|
|
||||||
|
updateFile(
|
||||||
|
`apps/${myapp}/src/app/app.module.ts`,
|
||||||
|
`
|
||||||
|
const y = 1111;
|
||||||
|
`
|
||||||
|
);
|
||||||
|
|
||||||
|
updateFile(
|
||||||
|
`apps/${myapp}/src/app/app.component.ts`,
|
||||||
|
`
|
||||||
|
const z = 1111;
|
||||||
|
`
|
||||||
|
);
|
||||||
|
|
||||||
|
updateFile(
|
||||||
|
`libs/${mylib}/index.ts`,
|
||||||
|
`
|
||||||
|
const x = 1111;
|
||||||
|
`
|
||||||
|
);
|
||||||
|
updateFile(
|
||||||
|
`libs/${mylib}/src/${mylib}.module.ts`,
|
||||||
|
`
|
||||||
|
const y = 1111;
|
||||||
|
`
|
||||||
|
);
|
||||||
|
|
||||||
|
updateFile(
|
||||||
|
`README.md`,
|
||||||
|
`
|
||||||
|
my new readme;
|
||||||
|
`
|
||||||
|
);
|
||||||
|
|
||||||
|
let stdout = runCLI(
|
||||||
|
`format:check --files="libs/${mylib}/index.ts,package.json" --libs-and-apps`,
|
||||||
|
{ silenceError: true }
|
||||||
|
);
|
||||||
|
expect(stdout).toContain(path.normalize(`libs/${mylib}/index.ts`));
|
||||||
|
expect(stdout).toContain(
|
||||||
|
path.normalize(`libs/${mylib}/src/${mylib}.module.ts`)
|
||||||
|
);
|
||||||
|
expect(stdout).not.toContain(path.normalize(`README.md`)); // It will be contained only in case of exception, that we fallback to all
|
||||||
|
|
||||||
|
stdout = runCLI(`format:check --all`, { silenceError: true });
|
||||||
|
expect(stdout).toContain(path.normalize(`apps/${myapp}/src/main.ts`));
|
||||||
|
expect(stdout).toContain(
|
||||||
|
path.normalize(`apps/${myapp}/src/app/app.module.ts`)
|
||||||
|
);
|
||||||
|
expect(stdout).toContain(
|
||||||
|
path.normalize(`apps/${myapp}/src/app/app.component.ts`)
|
||||||
|
);
|
||||||
|
|
||||||
|
stdout = runCLI(`format:check --projects=${myapp}`, {
|
||||||
|
silenceError: true,
|
||||||
|
});
|
||||||
|
expect(stdout).toContain(path.normalize(`apps/${myapp}/src/main.ts`));
|
||||||
|
expect(stdout).toContain(
|
||||||
|
path.normalize(`apps/${myapp}/src/app/app.module.ts`)
|
||||||
|
);
|
||||||
|
expect(stdout).toContain(
|
||||||
|
path.normalize(`apps/${myapp}/src/app/app.component.ts`)
|
||||||
|
);
|
||||||
|
expect(stdout).not.toContain(path.normalize(`libs/${mylib}/index.ts`));
|
||||||
|
expect(stdout).not.toContain(
|
||||||
|
path.normalize(`libs/${mylib}/src/${mylib}.module.ts`)
|
||||||
|
);
|
||||||
|
expect(stdout).not.toContain(path.normalize(`README.md`));
|
||||||
|
|
||||||
|
stdout = runCLI(`format:check --projects=${myapp},${mylib}`, {
|
||||||
|
silenceError: true,
|
||||||
|
});
|
||||||
|
expect(stdout).toContain(path.normalize(`apps/${myapp}/src/main.ts`));
|
||||||
|
expect(stdout).toContain(
|
||||||
|
path.normalize(`apps/${myapp}/src/app/app.module.ts`)
|
||||||
|
);
|
||||||
|
expect(stdout).toContain(
|
||||||
|
path.normalize(`apps/${myapp}/src/app/app.component.ts`)
|
||||||
|
);
|
||||||
|
expect(stdout).toContain(path.normalize(`libs/${mylib}/index.ts`));
|
||||||
|
expect(stdout).toContain(
|
||||||
|
path.normalize(`libs/${mylib}/src/${mylib}.module.ts`)
|
||||||
|
);
|
||||||
|
expect(stdout).not.toContain(path.normalize(`README.md`));
|
||||||
|
|
||||||
|
const { stderr } = await runCLIAsync(
|
||||||
|
`format:check --projects=${myapp},${mylib} --all`,
|
||||||
|
{
|
||||||
|
silenceError: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
expect(stderr).toContain(
|
||||||
|
'Arguments all and projects are mutually exclusive'
|
||||||
|
);
|
||||||
|
|
||||||
|
runCLI(
|
||||||
|
`format:write --files="apps/${myapp}/src/app/app.module.ts,apps/${myapp}/src/app/app.component.ts"`
|
||||||
|
);
|
||||||
|
|
||||||
|
stdout = runCLI('format:check --all', { silenceError: true });
|
||||||
|
expect(stdout).toContain(path.normalize(`apps/${myapp}/src/main.ts`));
|
||||||
|
expect(stdout).not.toContain(
|
||||||
|
path.normalize(`apps/${myapp}/src/app/app.module.ts`)
|
||||||
|
);
|
||||||
|
expect(stdout).not.toContain(
|
||||||
|
path.normalize(`apps/${myapp}/src/app/app.component.ts`)
|
||||||
|
);
|
||||||
|
|
||||||
|
runCLI('format:write --all');
|
||||||
|
expect(runCLI('format:check --all')).not.toContain(
|
||||||
|
path.normalize(`apps/${myapp}/src/main.ts`)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, 90000);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('dep-graph', () => {
|
||||||
|
let proj: string;
|
||||||
|
let myapp: string;
|
||||||
|
let myapp2: string;
|
||||||
|
let myapp3: string;
|
||||||
|
let myappE2e: string;
|
||||||
|
let myapp2E2e: string;
|
||||||
|
let myapp3E2e: string;
|
||||||
|
let mylib: string;
|
||||||
|
let mylib2: string;
|
||||||
|
beforeAll(() => {
|
||||||
|
proj = newProject();
|
||||||
|
myapp = uniq('myapp');
|
||||||
|
myapp2 = uniq('myapp2');
|
||||||
|
myapp3 = uniq('myapp3');
|
||||||
|
myappE2e = `${myapp}-e2e`;
|
||||||
|
myapp2E2e = `${myapp2}-e2e`;
|
||||||
|
myapp3E2e = `${myapp3}-e2e`;
|
||||||
|
mylib = uniq('mylib');
|
||||||
|
mylib2 = uniq('mylib2');
|
||||||
|
|
||||||
|
runCLI(`generate @nrwl/angular:app ${myapp}`);
|
||||||
|
runCLI(`generate @nrwl/angular:app ${myapp2}`);
|
||||||
|
runCLI(`generate @nrwl/angular:app ${myapp3}`);
|
||||||
|
runCLI(`generate @nrwl/angular:lib ${mylib}`);
|
||||||
|
runCLI(`generate @nrwl/angular:lib ${mylib2}`);
|
||||||
|
|
||||||
|
updateFile(
|
||||||
|
`apps/${myapp}/src/main.ts`,
|
||||||
|
`
|
||||||
|
import '@${proj}/${mylib}';
|
||||||
|
|
||||||
|
const s = {loadChildren: '@${proj}/${mylib2}'};
|
||||||
|
`
|
||||||
|
);
|
||||||
|
|
||||||
|
updateFile(
|
||||||
|
`apps/${myapp2}/src/app/app.component.spec.ts`,
|
||||||
|
`import '@${proj}/${mylib}';`
|
||||||
|
);
|
||||||
|
|
||||||
|
updateFile(
|
||||||
|
`libs/${mylib}/src/mylib.module.spec.ts`,
|
||||||
|
`import '@${proj}/${mylib2}';`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('dep-graph should output json to file', () => {
|
||||||
|
runCLI(`dep-graph --file=project-graph.json`);
|
||||||
|
|
||||||
|
expect(() => checkFilesExist('project-graph.json')).not.toThrow();
|
||||||
|
|
||||||
|
const jsonFileContents = readJson('project-graph.json');
|
||||||
|
|
||||||
|
expect(jsonFileContents.graph.dependencies).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
[myapp3E2e]: [
|
||||||
|
{
|
||||||
|
source: myapp3E2e,
|
||||||
|
target: myapp3,
|
||||||
|
type: 'implicit',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[myapp2]: [
|
||||||
|
{
|
||||||
|
source: myapp2,
|
||||||
|
target: mylib,
|
||||||
|
type: 'static',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[myapp2E2e]: [
|
||||||
|
{
|
||||||
|
source: myapp2E2e,
|
||||||
|
target: myapp2,
|
||||||
|
type: 'implicit',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[mylib]: [
|
||||||
|
{
|
||||||
|
source: mylib,
|
||||||
|
target: mylib2,
|
||||||
|
type: 'static',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[mylib2]: [],
|
||||||
|
[myapp]: [
|
||||||
|
{
|
||||||
|
source: myapp,
|
||||||
|
target: mylib,
|
||||||
|
type: 'static',
|
||||||
|
},
|
||||||
|
{ source: myapp, target: mylib2, type: 'static' },
|
||||||
|
],
|
||||||
|
[myappE2e]: [
|
||||||
|
{
|
||||||
|
source: myappE2e,
|
||||||
|
target: myapp,
|
||||||
|
type: 'implicit',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[myapp3]: [],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
runCLI(
|
||||||
|
`affected:dep-graph --files="libs/${mylib}/src/index.ts" --file="project-graph.json"`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(() => checkFilesExist('project-graph.json')).not.toThrow();
|
||||||
|
|
||||||
|
const jsonFileContents2 = readJson('project-graph.json');
|
||||||
|
|
||||||
|
expect(jsonFileContents2.criticalPath).toContain(myapp);
|
||||||
|
expect(jsonFileContents2.criticalPath).toContain(myapp2);
|
||||||
|
expect(jsonFileContents2.criticalPath).toContain(mylib);
|
||||||
|
expect(jsonFileContents2.criticalPath).not.toContain(mylib2);
|
||||||
|
}, 1000000);
|
||||||
|
|
||||||
|
it('dep-graph should focus requested project', () => {
|
||||||
|
runCLI(`dep-graph --focus=${myapp} --file=project-graph.json`);
|
||||||
|
|
||||||
|
expect(() => checkFilesExist('project-graph.json')).not.toThrow();
|
||||||
|
|
||||||
|
const jsonFileContents = readJson('project-graph.json');
|
||||||
|
const projectNames = Object.keys(jsonFileContents.graph.nodes);
|
||||||
|
|
||||||
|
expect(projectNames).toContain(myapp);
|
||||||
|
expect(projectNames).toContain(mylib);
|
||||||
|
expect(projectNames).toContain(mylib2);
|
||||||
|
expect(projectNames).toContain(myappE2e);
|
||||||
|
|
||||||
|
expect(projectNames).not.toContain(myapp2);
|
||||||
|
expect(projectNames).not.toContain(myapp3);
|
||||||
|
expect(projectNames).not.toContain(myapp2E2e);
|
||||||
|
expect(projectNames).not.toContain(myapp3E2e);
|
||||||
|
}, 1000000);
|
||||||
|
|
||||||
|
it('dep-graph should exclude requested projects', () => {
|
||||||
|
runCLI(
|
||||||
|
`dep-graph --exclude=${myappE2e},${myapp2E2e},${myapp3E2e} --file=project-graph.json`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(() => checkFilesExist('project-graph.json')).not.toThrow();
|
||||||
|
|
||||||
|
const jsonFileContents = readJson('project-graph.json');
|
||||||
|
const projectNames = Object.keys(jsonFileContents.graph.nodes);
|
||||||
|
|
||||||
|
expect(projectNames).toContain(myapp);
|
||||||
|
expect(projectNames).toContain(mylib);
|
||||||
|
expect(projectNames).toContain(mylib2);
|
||||||
|
expect(projectNames).toContain(myapp2);
|
||||||
|
expect(projectNames).toContain(myapp3);
|
||||||
|
|
||||||
|
expect(projectNames).not.toContain(myappE2e);
|
||||||
|
expect(projectNames).not.toContain(myapp2E2e);
|
||||||
|
expect(projectNames).not.toContain(myapp3E2e);
|
||||||
|
}, 1000000);
|
||||||
|
|
||||||
|
it('dep-graph should exclude requested projects that were included by a focus', () => {
|
||||||
|
runCLI(
|
||||||
|
`dep-graph --focus=${myapp} --exclude=${myappE2e} --file=project-graph.json`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(() => checkFilesExist('project-graph.json')).not.toThrow();
|
||||||
|
|
||||||
|
const jsonFileContents = readJson('project-graph.json');
|
||||||
|
const projectNames = Object.keys(jsonFileContents.graph.nodes);
|
||||||
|
|
||||||
|
expect(projectNames).toContain(myapp);
|
||||||
|
expect(projectNames).toContain(mylib);
|
||||||
|
expect(projectNames).toContain(mylib2);
|
||||||
|
|
||||||
|
expect(projectNames).not.toContain(myappE2e);
|
||||||
|
expect(projectNames).not.toContain(myapp2);
|
||||||
|
expect(projectNames).not.toContain(myapp3);
|
||||||
|
expect(projectNames).not.toContain(myapp2E2e);
|
||||||
|
expect(projectNames).not.toContain(myapp3E2e);
|
||||||
|
}, 1000000);
|
||||||
|
|
||||||
|
it('dep-graph should output a deployable static website in an html file accompanied by a folder with static assets', () => {
|
||||||
|
runCLI(`dep-graph --file=project-graph.html`);
|
||||||
|
|
||||||
|
expect(() => checkFilesExist('project-graph.html')).not.toThrow();
|
||||||
|
expect(() => checkFilesExist('static/styles.css')).not.toThrow();
|
||||||
|
expect(() => checkFilesExist('static/runtime.esm.js')).not.toThrow();
|
||||||
|
expect(() => checkFilesExist('static/polyfills.esm.js')).not.toThrow();
|
||||||
|
expect(() => checkFilesExist('static/main.esm.js')).not.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Move Angular Project', () => {
|
||||||
|
let proj: string;
|
||||||
|
let app1: string;
|
||||||
|
let app2: string;
|
||||||
|
let newPath: string;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
proj = newProject();
|
||||||
|
app1 = uniq('app1');
|
||||||
|
app2 = uniq('app2');
|
||||||
|
newPath = `subfolder/${app2}`;
|
||||||
|
runCLI(`generate @nrwl/angular:app ${app1}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => removeProject({ onlyOnCI: true }));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries moving an app from ${app1} -> subfolder/${app2}
|
||||||
|
*/
|
||||||
|
it('should work for apps', () => {
|
||||||
|
const moveOutput = runCLI(
|
||||||
|
`generate @nrwl/angular:move --project ${app1} ${newPath}`
|
||||||
|
);
|
||||||
|
|
||||||
|
// just check the output
|
||||||
|
expect(moveOutput).toContain(`DELETE apps/${app1}`);
|
||||||
|
expect(moveOutput).toContain(`CREATE apps/${newPath}/.browserslistrc`);
|
||||||
|
expect(moveOutput).toContain(`CREATE apps/${newPath}/jest.config.js`);
|
||||||
|
expect(moveOutput).toContain(`CREATE apps/${newPath}/tsconfig.app.json`);
|
||||||
|
expect(moveOutput).toContain(`CREATE apps/${newPath}/tsconfig.json`);
|
||||||
|
expect(moveOutput).toContain(`CREATE apps/${newPath}/tsconfig.spec.json`);
|
||||||
|
expect(moveOutput).toContain(`CREATE apps/${newPath}/.eslintrc.json`);
|
||||||
|
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/favicon.ico`);
|
||||||
|
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/index.html`);
|
||||||
|
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/main.ts`);
|
||||||
|
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/polyfills.ts`);
|
||||||
|
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/styles.css`);
|
||||||
|
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/test-setup.ts`);
|
||||||
|
expect(moveOutput).toContain(
|
||||||
|
`CREATE apps/${newPath}/src/app/app.component.html`
|
||||||
|
);
|
||||||
|
expect(moveOutput).toContain(
|
||||||
|
`CREATE apps/${newPath}/src/app/app.module.ts`
|
||||||
|
);
|
||||||
|
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/assets/.gitkeep`);
|
||||||
|
expect(moveOutput).toContain(
|
||||||
|
`CREATE apps/${newPath}/src/environments/environment.prod.ts`
|
||||||
|
);
|
||||||
|
expect(moveOutput).toContain(
|
||||||
|
`CREATE apps/${newPath}/src/environments/environment.ts`
|
||||||
|
);
|
||||||
|
expect(moveOutput).toContain(`UPDATE nx.json`);
|
||||||
|
expect(moveOutput).toContain(`UPDATE workspace.json`);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries moving an e2e project from ${app1} -> ${newPath}
|
||||||
|
*/
|
||||||
|
it('should work for e2e projects', () => {
|
||||||
|
const moveOutput = runCLI(
|
||||||
|
`generate @nrwl/angular:move --projectName=${app1}-e2e --destination=${newPath}-e2e`
|
||||||
|
);
|
||||||
|
|
||||||
|
// just check that the cypress.json is updated correctly
|
||||||
|
const cypressJsonPath = `apps/${newPath}-e2e/cypress.json`;
|
||||||
|
expect(moveOutput).toContain(`CREATE ${cypressJsonPath}`);
|
||||||
|
checkFilesExist(cypressJsonPath);
|
||||||
|
const cypressJson = readJson(cypressJsonPath);
|
||||||
|
expect(cypressJson.videosFolder).toEqual(
|
||||||
|
`../../../dist/cypress/apps/${newPath}-e2e/videos`
|
||||||
|
);
|
||||||
|
expect(cypressJson.screenshotsFolder).toEqual(
|
||||||
|
`../../../dist/cypress/apps/${newPath}-e2e/screenshots`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries moving a library from ${lib} -> shared/${lib}
|
||||||
|
*/
|
||||||
|
it('should work for libraries', () => {
|
||||||
|
const lib1 = uniq('mylib');
|
||||||
|
const lib2 = uniq('mylib');
|
||||||
|
runCLI(`generate @nrwl/angular:lib ${lib1}`);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a library which imports the module from the other lib
|
||||||
|
*/
|
||||||
|
|
||||||
|
runCLI(`generate @nrwl/angular:lib ${lib2}`);
|
||||||
|
|
||||||
|
updateFile(
|
||||||
|
`libs/${lib2}/src/lib/${lib2}.module.ts`,
|
||||||
|
`import { ${classify(lib1)}Module } from '@${proj}/${lib1}';
|
||||||
|
|
||||||
|
export class ExtendedModule extends ${classify(lib1)}Module { }`
|
||||||
|
);
|
||||||
|
|
||||||
|
const moveOutput = runCLI(
|
||||||
|
`generate @nrwl/angular:move --projectName=${lib1} --destination=shared/${lib1}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const newPath = `libs/shared/${lib1}`;
|
||||||
|
const newModule = `Shared${classify(lib1)}Module`;
|
||||||
|
|
||||||
|
const testSetupPath = `${newPath}/src/test-setup.ts`;
|
||||||
|
expect(moveOutput).toContain(`CREATE ${testSetupPath}`);
|
||||||
|
checkFilesExist(testSetupPath);
|
||||||
|
|
||||||
|
const modulePath = `${newPath}/src/lib/shared-${lib1}.module.ts`;
|
||||||
|
expect(moveOutput).toContain(`CREATE ${modulePath}`);
|
||||||
|
checkFilesExist(modulePath);
|
||||||
|
const moduleFile = readFile(modulePath);
|
||||||
|
expect(moduleFile).toContain(`export class ${newModule}`);
|
||||||
|
|
||||||
|
const indexPath = `${newPath}/src/index.ts`;
|
||||||
|
expect(moveOutput).toContain(`CREATE ${indexPath}`);
|
||||||
|
checkFilesExist(indexPath);
|
||||||
|
const index = readFile(indexPath);
|
||||||
|
expect(index).toContain(`export * from './lib/shared-${lib1}.module'`);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that the import in lib2 has been updated
|
||||||
|
*/
|
||||||
|
const lib2FilePath = `libs/${lib2}/src/lib/${lib2}.module.ts`;
|
||||||
|
const lib2File = readFile(lib2FilePath);
|
||||||
|
expect(lib2File).toContain(
|
||||||
|
`import { ${newModule} } from '@${proj}/shared-${lib1}';`
|
||||||
|
);
|
||||||
|
expect(lib2File).toContain(`extends ${newModule}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
13
e2e/workspace-integrations/tsconfig.json
Normal file
13
e2e/workspace-integrations/tsconfig.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"types": ["node", "jest"]
|
||||||
|
},
|
||||||
|
"include": [],
|
||||||
|
"files": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.spec.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
16
e2e/workspace-integrations/tsconfig.spec.json
Normal file
16
e2e/workspace-integrations/tsconfig.spec.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../dist/out-tsc",
|
||||||
|
"module": "commonjs",
|
||||||
|
"types": ["jest", "node"]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"**/*.test.ts",
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/*.spec.tsx",
|
||||||
|
"**/*.spec.js",
|
||||||
|
"**/*.spec.jsx",
|
||||||
|
"**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -1,69 +0,0 @@
|
|||||||
import {
|
|
||||||
checkFilesExist,
|
|
||||||
readFile,
|
|
||||||
readJson,
|
|
||||||
runCLI,
|
|
||||||
runCLIAsync,
|
|
||||||
runCreateWorkspace,
|
|
||||||
uniq,
|
|
||||||
packageInstall,
|
|
||||||
removeProject,
|
|
||||||
getSelectedPackageManager,
|
|
||||||
} from '@nrwl/e2e/utils';
|
|
||||||
|
|
||||||
describe('custom workspace layout', () => {
|
|
||||||
afterAll(() => removeProject({ onlyOnCI: true }));
|
|
||||||
|
|
||||||
it('should work', async () => {
|
|
||||||
const proj = uniq('custom-layout-proj');
|
|
||||||
const packageManager = getSelectedPackageManager();
|
|
||||||
runCreateWorkspace(proj, { preset: 'npm', packageManager });
|
|
||||||
packageInstall('@nrwl/react @nrwl/angular @nrwl/express');
|
|
||||||
|
|
||||||
const nxJson = readJson('nx.json');
|
|
||||||
expect(nxJson.extends).toEqual('@nrwl/workspace/presets/npm.json');
|
|
||||||
|
|
||||||
const reactApp = uniq('reactapp');
|
|
||||||
const reactLib = uniq('reactlib');
|
|
||||||
|
|
||||||
const ngApp = uniq('ngapp');
|
|
||||||
const ngLib = uniq('nglib');
|
|
||||||
|
|
||||||
const expressApp = uniq('expessapp');
|
|
||||||
const expressLib = uniq('expresslib');
|
|
||||||
|
|
||||||
runCLI(`generate @nrwl/react:app ${reactApp} --no-interactive`);
|
|
||||||
runCLI(`generate @nrwl/react:lib ${reactLib} --no-interactive`);
|
|
||||||
|
|
||||||
runCLI(`generate @nrwl/angular:app ${ngApp} --no-interactive`);
|
|
||||||
runCLI(`generate @nrwl/angular:lib ${ngLib} --no-interactive`);
|
|
||||||
|
|
||||||
runCLI(`generate @nrwl/express:app ${expressApp} --no-interactive`);
|
|
||||||
runCLI(`generate @nrwl/express:lib ${expressLib} --no-interactive`);
|
|
||||||
|
|
||||||
checkFilesExist(
|
|
||||||
`packages/${reactLib}/src/index.ts`,
|
|
||||||
`packages/${reactApp}/src/main.tsx`,
|
|
||||||
`packages/${reactApp}-e2e/cypress.json`,
|
|
||||||
|
|
||||||
`packages/${ngLib}/src/index.ts`,
|
|
||||||
`packages/${ngApp}/src/main.ts`,
|
|
||||||
`packages/${ngApp}-e2e/cypress.json`,
|
|
||||||
|
|
||||||
`packages/${expressLib}/src/index.ts`,
|
|
||||||
`packages/${expressApp}/src/main.ts`
|
|
||||||
);
|
|
||||||
|
|
||||||
const workspaceJson = readFile('workspace.json');
|
|
||||||
expect(workspaceJson).not.toContain('apps/');
|
|
||||||
expect(workspaceJson).not.toContain('libs/');
|
|
||||||
|
|
||||||
const libTestResults = await runCLIAsync(`test ${expressLib}`);
|
|
||||||
expect(libTestResults.stdout).toContain(`nx run ${expressLib}:test`);
|
|
||||||
|
|
||||||
const appBuildResults = await runCLIAsync(`build ${expressApp}`);
|
|
||||||
expect(appBuildResults.stdout).toContain(`nx run ${expressApp}:build`);
|
|
||||||
|
|
||||||
checkFilesExist(`dist/packages/${expressApp}/main.js`);
|
|
||||||
}, 1000000);
|
|
||||||
});
|
|
||||||
@ -37,7 +37,9 @@
|
|||||||
"e2e-storybook": "e2e/storybook",
|
"e2e-storybook": "e2e/storybook",
|
||||||
"e2e-utils": "e2e/utils",
|
"e2e-utils": "e2e/utils",
|
||||||
"e2e-web": "e2e/web",
|
"e2e-web": "e2e/web",
|
||||||
"e2e-workspace": "e2e/workspace",
|
"e2e-workspace-core": "e2e/workspace-core",
|
||||||
|
"e2e-workspace-create": "e2e/workspace-create",
|
||||||
|
"e2e-workspace-integrations": "e2e/workspace-integrations",
|
||||||
"eslint-plugin-nx": "packages/eslint-plugin-nx",
|
"eslint-plugin-nx": "packages/eslint-plugin-nx",
|
||||||
"express": "packages/express",
|
"express": "packages/express",
|
||||||
"gatsby": "packages/gatsby",
|
"gatsby": "packages/gatsby",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user