cleanup(angular): consolidate and improve e2e-angular-core tests (#15726)
This commit is contained in:
parent
db20f655d9
commit
9dbc90d45e
@ -1,79 +0,0 @@
|
||||
import {
|
||||
cleanupProject,
|
||||
newProject,
|
||||
runCLI,
|
||||
uniq,
|
||||
updateFile,
|
||||
} from '@nrwl/e2e/utils';
|
||||
import * as path from 'path';
|
||||
|
||||
describe('Angular Package', () => {
|
||||
describe('linting', () => {
|
||||
beforeAll(() => newProject());
|
||||
afterAll(() => cleanupProject());
|
||||
|
||||
it('should support eslint and pass linting on the standard generated code', async () => {
|
||||
const myapp = uniq('myapp');
|
||||
runCLI(
|
||||
`generate @nrwl/angular:app ${myapp} --linter=eslint --no-interactive`
|
||||
);
|
||||
expect(runCLI(`lint ${myapp}`)).toContain('All files pass linting.');
|
||||
|
||||
const mylib = uniq('mylib');
|
||||
runCLI(
|
||||
`generate @nrwl/angular:lib ${mylib} --linter=eslint --no-interactive`
|
||||
);
|
||||
expect(runCLI(`lint ${mylib}`)).toContain('All files pass linting.');
|
||||
});
|
||||
|
||||
it('should support eslint and successfully lint external HTML files and inline templates', async () => {
|
||||
const myapp = uniq('myapp');
|
||||
|
||||
runCLI(
|
||||
`generate @nrwl/angular:app ${myapp} --linter=eslint --no-interactive`
|
||||
);
|
||||
|
||||
const templateWhichFailsBananaInBoxLintCheck = `<div ([foo])="bar"></div>`;
|
||||
const wrappedAsInlineTemplate = `
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'inline-template-component',
|
||||
template: \`
|
||||
${templateWhichFailsBananaInBoxLintCheck}
|
||||
\`,
|
||||
})
|
||||
export class InlineTemplateComponent {}
|
||||
`;
|
||||
|
||||
// External HTML template file
|
||||
updateFile(
|
||||
`apps/${myapp}/src/app/app.component.html`,
|
||||
templateWhichFailsBananaInBoxLintCheck
|
||||
);
|
||||
|
||||
// Inline template within component.ts file
|
||||
updateFile(
|
||||
`apps/${myapp}/src/app/inline-template.component.ts`,
|
||||
wrappedAsInlineTemplate
|
||||
);
|
||||
|
||||
const appLintStdOut = runCLI(`lint ${myapp}`, { silenceError: true });
|
||||
expect(appLintStdOut).toContain(
|
||||
path.normalize(`apps/${myapp}/src/app/app.component.html`)
|
||||
);
|
||||
expect(appLintStdOut).toContain(`1:6`);
|
||||
expect(appLintStdOut).toContain(`Invalid binding syntax`);
|
||||
expect(appLintStdOut).toContain(
|
||||
path.normalize(`apps/${myapp}/src/app/inline-template.component.ts`)
|
||||
);
|
||||
|
||||
expect(appLintStdOut).toContain(`5:21`);
|
||||
expect(appLintStdOut).toContain(
|
||||
`The selector should start with one of these prefixes`
|
||||
);
|
||||
expect(appLintStdOut).toContain(`7:18`);
|
||||
expect(appLintStdOut).toContain(`Invalid binding syntax`);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,151 +1,169 @@
|
||||
import {
|
||||
checkFilesExist,
|
||||
cleanupProject,
|
||||
expectTestsPass,
|
||||
newProject,
|
||||
removeFile,
|
||||
runCLI,
|
||||
runCLIAsync,
|
||||
uniq,
|
||||
updateFile,
|
||||
} from '@nrwl/e2e/utils';
|
||||
|
||||
describe('Angular Config', () => {
|
||||
beforeAll(() => newProject());
|
||||
describe('angular.json v1 config', () => {
|
||||
const app1 = uniq('app1');
|
||||
|
||||
beforeAll(() => {
|
||||
newProject();
|
||||
runCLI(`generate @nrwl/angular:app ${app1} --no-interactive`);
|
||||
// reset workspace to use v1 config
|
||||
updateFile(`angular.json`, angularV1Json(app1));
|
||||
removeFile(`apps/${app1}/project.json`);
|
||||
removeFile(`apps/${app1}-e2e/project.json`);
|
||||
});
|
||||
afterAll(() => cleanupProject());
|
||||
|
||||
it('should upgrade the config correctly', async () => {
|
||||
const myapp = uniq('myapp');
|
||||
runCLI(`generate @nrwl/angular:app ${myapp} --no-interactive`);
|
||||
it('should support projects in angular.json v1 config', async () => {
|
||||
expect(runCLI(`build ${app1}`)).toContain('Successfully ran target build');
|
||||
expect(runCLI(`test ${app1} --no-watch`)).toContain(
|
||||
'Successfully ran target test'
|
||||
);
|
||||
}, 1000000);
|
||||
|
||||
// update the angular.json, first reset to v1 config
|
||||
updateFile(`angular.json`, angularV1Json(myapp));
|
||||
it('should generate new app with project.json and keep the existing in angular.json', async () => {
|
||||
// create new app
|
||||
const app2 = uniq('app2');
|
||||
runCLI(`generate @nrwl/angular:app ${app2} --no-interactive`);
|
||||
|
||||
const myapp2 = uniq('myapp');
|
||||
runCLI(`generate @nrwl/angular:app ${myapp2} --no-interactive`);
|
||||
expectTestsPass(await runCLIAsync(`test ${myapp2} --no-watch`));
|
||||
// should generate project.json for new projects
|
||||
checkFilesExist(`apps/${app2}/project.json`);
|
||||
// check it works correctly
|
||||
expect(runCLI(`build ${app2}`)).toContain('Successfully ran target build');
|
||||
expect(runCLI(`test ${app2} --no-watch`)).toContain(
|
||||
'Successfully ran target test'
|
||||
);
|
||||
// check existing app in angular.json still works
|
||||
expect(runCLI(`build ${app1}`)).toContain('Successfully ran target build');
|
||||
expect(runCLI(`test ${app1} --no-watch`)).toContain(
|
||||
'Successfully ran target test'
|
||||
);
|
||||
}, 1000000);
|
||||
});
|
||||
|
||||
const angularV1Json = (appName: string) => `{
|
||||
"version": 1,
|
||||
"projects": {
|
||||
"${appName}": {
|
||||
"projectType": "application",
|
||||
"root": "apps/${appName}",
|
||||
"sourceRoot": "apps/${appName}/src",
|
||||
"prefix": "v1anuglar",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"options": {
|
||||
"outputPath": "dist/apps/${appName}",
|
||||
"index": "apps/${appName}/src/index.html",
|
||||
"main": "apps/${appName}/src/main.ts",
|
||||
"polyfills": "apps/${appName}/src/polyfills.ts",
|
||||
"tsConfig": "apps/${appName}/tsconfig.app.json",
|
||||
"assets": ["apps/${appName}/src/favicon.ico", "apps/${appName}/src/assets"],
|
||||
"styles": ["apps/${appName}/src/styles.css"],
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "500kb",
|
||||
"maximumError": "1mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "2kb",
|
||||
"maximumError": "4kb"
|
||||
}
|
||||
],
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "apps/${appName}/src/environments/environment.ts",
|
||||
"with": "apps/${appName}/src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"outputHashing": "all"
|
||||
},
|
||||
"development": {
|
||||
"buildOptimizer": false,
|
||||
"optimization": false,
|
||||
"vendorChunk": true,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true,
|
||||
"namedChunks": true
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "production"
|
||||
"version": 1,
|
||||
"projects": {
|
||||
"${appName}": {
|
||||
"projectType": "application",
|
||||
"root": "apps/${appName}",
|
||||
"sourceRoot": "apps/${appName}/src",
|
||||
"prefix": "v1angular",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"options": {
|
||||
"outputPath": "dist/apps/${appName}",
|
||||
"index": "apps/${appName}/src/index.html",
|
||||
"main": "apps/${appName}/src/main.ts",
|
||||
"polyfills": ["zone.js"],
|
||||
"tsConfig": "apps/${appName}/tsconfig.app.json",
|
||||
"assets": ["apps/${appName}/src/favicon.ico", "apps/${appName}/src/assets"],
|
||||
"styles": ["apps/${appName}/src/styles.css"],
|
||||
"scripts": []
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "${appName}:build:production"
|
||||
},
|
||||
"development": {
|
||||
"browserTarget": "${appName}:build:development"
|
||||
}
|
||||
"configurations": {
|
||||
"production": {
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "500kb",
|
||||
"maximumError": "1mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "2kb",
|
||||
"maximumError": "4kb"
|
||||
}
|
||||
],
|
||||
"outputHashing": "all"
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "${appName}:build"
|
||||
"development": {
|
||||
"buildOptimizer": false,
|
||||
"optimization": false,
|
||||
"vendorChunk": true,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true,
|
||||
"namedChunks": true
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@nrwl/linter:eslint",
|
||||
"options": {
|
||||
"lintFilePatterns": [
|
||||
"apps/${appName}/src/**/*.ts",
|
||||
"apps/${appName}/src/**/*.html"
|
||||
]
|
||||
"defaultConfiguration": "production"
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "${appName}:build:production"
|
||||
},
|
||||
"development": {
|
||||
"browserTarget": "${appName}:build:development"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@nrwl/jest:jest",
|
||||
"outputs": ["coverage/apps/${appName}"],
|
||||
"options": {
|
||||
"jestConfig": "apps/${appName}/jest.config.ts",
|
||||
"passWithNoTests": true
|
||||
}
|
||||
"defaultConfiguration": "development"
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "${appName}:build"
|
||||
}
|
||||
},
|
||||
"tags": []
|
||||
"lint": {
|
||||
"builder": "@nrwl/linter:eslint",
|
||||
"options": {
|
||||
"lintFilePatterns": [
|
||||
"apps/${appName}/src/**/*.ts",
|
||||
"apps/${appName}/src/**/*.html"
|
||||
]
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@nrwl/jest:jest",
|
||||
"outputs": ["coverage/apps/${appName}"],
|
||||
"options": {
|
||||
"jestConfig": "apps/${appName}/jest.config.ts",
|
||||
"passWithNoTests": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"${appName}-e2e": {
|
||||
"root": "apps/${appName}-e2e",
|
||||
"sourceRoot": "apps/${appName}-e2e/src",
|
||||
"projectType": "application",
|
||||
"architect": {
|
||||
"e2e": {
|
||||
"builder": "@nrwl/cypress:cypress",
|
||||
"options": {
|
||||
"cypressConfig": "apps/${appName}-e2e/cypress.json",
|
||||
"devServerTarget": "${appName}:serve:development"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "${appName}:serve:production"
|
||||
}
|
||||
}
|
||||
"tags": []
|
||||
},
|
||||
"${appName}-e2e": {
|
||||
"root": "apps/${appName}-e2e",
|
||||
"sourceRoot": "apps/${appName}-e2e/src",
|
||||
"projectType": "application",
|
||||
"architect": {
|
||||
"e2e": {
|
||||
"builder": "@nrwl/cypress:cypress",
|
||||
"options": {
|
||||
"cypressConfig": "apps/${appName}-e2e/cypress.json",
|
||||
"devServerTarget": "${appName}:serve:development",
|
||||
"testingType": "e2e"
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@nrwl/linter:eslint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["apps/${appName}-e2e/**/*.{js,ts}"]
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "${appName}:serve:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [],
|
||||
"implicitDependencies": ["${appName}"]
|
||||
}
|
||||
"lint": {
|
||||
"builder": "@nrwl/linter:eslint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["apps/${appName}-e2e/**/*.{js,ts}"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [],
|
||||
"implicitDependencies": ["${appName}"]
|
||||
}
|
||||
}
|
||||
`;
|
||||
}
|
||||
`;
|
||||
|
||||
@ -1,61 +1,58 @@
|
||||
import { names } from '@nrwl/devkit';
|
||||
import {
|
||||
cleanupProject,
|
||||
killPort,
|
||||
killProcessAndPorts,
|
||||
newProject,
|
||||
promisifiedTreeKill,
|
||||
readProjectConfig,
|
||||
runCLI,
|
||||
runCommandUntil,
|
||||
uniq,
|
||||
updateFile,
|
||||
updateProjectConfig,
|
||||
} from '@nrwl/e2e/utils';
|
||||
import { ChildProcess } from 'child_process';
|
||||
|
||||
import { names } from '@nrwl/devkit';
|
||||
|
||||
describe('Angular Projects', () => {
|
||||
describe('Angular Module Federation', () => {
|
||||
let proj: string;
|
||||
let oldValue;
|
||||
let oldVerboseLoggingValue: string;
|
||||
|
||||
beforeAll(() => {
|
||||
proj = newProject();
|
||||
oldValue = process.env.NX_E2E_VERBOSE_LOGGING;
|
||||
oldVerboseLoggingValue = process.env.NX_E2E_VERBOSE_LOGGING;
|
||||
process.env.NX_E2E_VERBOSE_LOGGING = 'true';
|
||||
});
|
||||
afterAll(() => {
|
||||
cleanupProject();
|
||||
process.env.NX_E2E_VERBOSE_LOGGING = oldValue;
|
||||
process.env.NX_E2E_VERBOSE_LOGGING = oldVerboseLoggingValue;
|
||||
});
|
||||
|
||||
it('should serve the host and remote apps successfully, even with a shared library with a secondary entry point between them', async () => {
|
||||
// ACT + ASSERT
|
||||
const port1 = 4200;
|
||||
const port2 = 4206;
|
||||
it('should generate valid host and remote apps', async () => {
|
||||
const hostApp = uniq('app');
|
||||
const remoteApp1 = uniq('remote');
|
||||
const sharedLib = uniq('shared-lib');
|
||||
const secondaryEntry = uniq('secondary');
|
||||
const hostPort = 4300;
|
||||
const remotePort = 4301;
|
||||
|
||||
// generate host app
|
||||
runCLI(
|
||||
`generate @nrwl/angular:host ${hostApp} --style=css --no-interactive`
|
||||
);
|
||||
|
||||
// generate remote apps
|
||||
// generate remote app
|
||||
runCLI(
|
||||
`generate @nrwl/angular:remote ${remoteApp1} --host=${hostApp} --port=${port2} --style=css --no-interactive`
|
||||
`generate @nrwl/angular:remote ${remoteApp1} --host=${hostApp} --port=${remotePort} --style=css --no-interactive`
|
||||
);
|
||||
|
||||
// generate a shared lib
|
||||
// check default generated host is built successfully
|
||||
const buildOutput = runCLI(`build ${hostApp}`);
|
||||
expect(buildOutput).toContain('Successfully ran target build');
|
||||
|
||||
// generate a shared lib with a seconary entry point
|
||||
runCLI(
|
||||
`generate @nrwl/angular:library ${sharedLib} --buildable --no-interactive`
|
||||
);
|
||||
runCLI(
|
||||
`generate @nrwl/angular:library-secondary-entry-point --library=${sharedLib} --name=${secondaryEntry} --no-interactive`
|
||||
);
|
||||
|
||||
// update the files to use shared library
|
||||
// update host & remote files to use shared library
|
||||
updateFile(
|
||||
`apps/${hostApp}/src/app/app.module.ts`,
|
||||
`import { NgModule } from '@angular/core';
|
||||
@ -123,169 +120,79 @@ describe('Angular Projects', () => {
|
||||
`
|
||||
);
|
||||
|
||||
let process: ChildProcess;
|
||||
|
||||
try {
|
||||
process = await runCommandUntil(
|
||||
`serve ${hostApp} --dev-remotes=${remoteApp1}`,
|
||||
(output) => {
|
||||
return (
|
||||
output.includes(`listening on localhost:${port2}`) &&
|
||||
output.includes(`listening on localhost:${port1}`)
|
||||
);
|
||||
}
|
||||
);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
// port and process cleanup
|
||||
try {
|
||||
if (process && process.pid) {
|
||||
await promisifiedTreeKill(process.pid, 'SIGKILL');
|
||||
}
|
||||
await killPort(port1);
|
||||
await killPort(port2);
|
||||
} catch (err) {
|
||||
expect(err).toBeFalsy();
|
||||
}
|
||||
}, 300000);
|
||||
|
||||
it('should build the host app successfully', async () => {
|
||||
// ARRANGE
|
||||
const hostApp = uniq('app');
|
||||
const remoteApp1 = uniq('remote');
|
||||
|
||||
// generate host app
|
||||
runCLI(`generate @nrwl/angular:host ${hostApp} --no-interactive`);
|
||||
|
||||
// generate remote apps
|
||||
runCLI(
|
||||
`generate @nrwl/angular:remote ${remoteApp1} --host=${hostApp} --no-interactive`
|
||||
);
|
||||
|
||||
// ACT
|
||||
const buildOutput = runCLI(`build ${hostApp}`);
|
||||
|
||||
// ASSERT
|
||||
expect(buildOutput).toContain('Successfully ran target build');
|
||||
}, 300000);
|
||||
|
||||
it('should serve a ssr remote app successfully', async () => {
|
||||
// ARRANGE
|
||||
const remoteApp1 = uniq('remote');
|
||||
// generate remote apps
|
||||
runCLI(
|
||||
`generate @nrwl/angular:remote ${remoteApp1} --ssr --no-interactive`
|
||||
);
|
||||
|
||||
const port = 4301;
|
||||
|
||||
let process = await runCommandUntil(
|
||||
`serve-ssr ${remoteApp1} --port=${port}`,
|
||||
(output) => {
|
||||
return (
|
||||
output.includes(`Browser application bundle generation complete.`) &&
|
||||
output.includes(`Server application bundle generation complete.`) &&
|
||||
output.includes(
|
||||
`Angular Universal Live Development Server is listening`
|
||||
)
|
||||
);
|
||||
}
|
||||
const process = await runCommandUntil(
|
||||
`serve ${hostApp} --port=${hostPort} --dev-remotes=${remoteApp1}`,
|
||||
(output) =>
|
||||
output.includes(`listening on localhost:${remotePort}`) &&
|
||||
output.includes(`listening on localhost:${hostPort}`)
|
||||
);
|
||||
|
||||
// port and process cleanup
|
||||
try {
|
||||
if (process && process.pid) {
|
||||
await promisifiedTreeKill(process.pid, 'SIGKILL');
|
||||
}
|
||||
await killPort(port);
|
||||
} catch (err) {
|
||||
expect(err).toBeFalsy();
|
||||
}
|
||||
}, 10_000_000);
|
||||
await killProcessAndPorts(process.pid, hostPort, remotePort);
|
||||
}, 300000);
|
||||
|
||||
it('should convert apps to MF successfully', async () => {
|
||||
const app1 = uniq('app1');
|
||||
const app2 = uniq('app2');
|
||||
const app1Port = 4400;
|
||||
const app2Port = 4401;
|
||||
|
||||
// generate apps
|
||||
runCLI(
|
||||
`generate @nrwl/angular:application ${app1} --routing --no-interactive`
|
||||
);
|
||||
runCLI(`generate @nrwl/angular:application ${app2} --no-interactive`);
|
||||
|
||||
// convert apps
|
||||
runCLI(
|
||||
`generate @nrwl/angular:setup-mf ${app1} --mfType=host --port=${app1Port} --no-interactive`
|
||||
);
|
||||
runCLI(
|
||||
`generate @nrwl/angular:setup-mf ${app2} --mfType=remote --host=${app1} --port=${app2Port} --no-interactive`
|
||||
);
|
||||
|
||||
const process = await runCommandUntil(
|
||||
`serve ${app1} --dev-remotes=${app2}`,
|
||||
(output) =>
|
||||
output.includes(`listening on localhost:${app1Port}`) &&
|
||||
output.includes(`listening on localhost:${app2Port}`)
|
||||
);
|
||||
|
||||
// port and process cleanup
|
||||
await killProcessAndPorts(process.pid, app1Port, app2Port);
|
||||
}, 20_000_000);
|
||||
|
||||
// TODO(colum): enable when this issue is resolved https://github.com/module-federation/universe/issues/604
|
||||
xit('should scaffold a ssr MF setup successfully', async () => {
|
||||
// ARRANGE
|
||||
const remoteApp1 = uniq('remote1');
|
||||
const remoteApp2 = uniq('remote2');
|
||||
const hostApp = uniq('host1');
|
||||
xit('should scaffold MF + SSR setup successfully', async () => {
|
||||
const host = uniq('host');
|
||||
const remote1 = uniq('remote1');
|
||||
const remote2 = uniq('remote2');
|
||||
|
||||
// generate remote apps
|
||||
runCLI(
|
||||
`generate @nrwl/angular:host ${hostApp} --ssr --remotes=${remoteApp1},${remoteApp2} --no-interactive`
|
||||
`generate @nrwl/angular:host ${host} --ssr --remotes=${remote1},${remote2} --no-interactive`
|
||||
);
|
||||
|
||||
// ports
|
||||
const remoteApp1Port =
|
||||
readProjectConfig(remoteApp1).targets.serve.options.port;
|
||||
const remoteApp2Port =
|
||||
readProjectConfig(remoteApp2).targets.serve.options.port;
|
||||
const hostPort = 4500;
|
||||
const remote1Port = readProjectConfig(remote1).targets.serve.options.port;
|
||||
const remote2Port = readProjectConfig(remote2).targets.serve.options.port;
|
||||
|
||||
const port = 4401;
|
||||
|
||||
let process = await runCommandUntil(
|
||||
`serve-ssr ${hostApp} --port=${port}`,
|
||||
(output) => {
|
||||
return (
|
||||
output.includes(
|
||||
`Node Express server listening on http://localhost:${remoteApp1Port}`
|
||||
) &&
|
||||
output.includes(
|
||||
`Node Express server listening on http://localhost:${remoteApp2Port}`
|
||||
) &&
|
||||
output.includes(
|
||||
`Angular Universal Live Development Server is listening`
|
||||
)
|
||||
);
|
||||
}
|
||||
const process = await runCommandUntil(
|
||||
`serve-ssr ${host} --port=${hostPort}`,
|
||||
(output) =>
|
||||
output.includes(
|
||||
`Node Express server listening on http://localhost:${remote1Port}`
|
||||
) &&
|
||||
output.includes(
|
||||
`Node Express server listening on http://localhost:${remote2Port}`
|
||||
) &&
|
||||
output.includes(
|
||||
`Angular Universal Live Development Server is listening`
|
||||
)
|
||||
);
|
||||
|
||||
// port and process cleanup
|
||||
try {
|
||||
if (process && process.pid) {
|
||||
await promisifiedTreeKill(process.pid, 'SIGKILL');
|
||||
}
|
||||
await killPort(port);
|
||||
await killPort(remoteApp1Port);
|
||||
await killPort(remoteApp2Port);
|
||||
} catch (err) {
|
||||
expect(err).toBeFalsy();
|
||||
}
|
||||
await killProcessAndPorts(process.pid, hostPort, remote1Port, remote2Port);
|
||||
}, 20_000_000);
|
||||
|
||||
it('Custom Webpack Config for SSR - should serve the app correctly', async () => {
|
||||
// ARRANGE
|
||||
const ssrApp = uniq('app');
|
||||
|
||||
runCLI(`generate @nrwl/angular:app ${ssrApp} --no-interactive`);
|
||||
runCLI(`generate @nrwl/angular:setup-ssr ${ssrApp} --no-interactive`);
|
||||
|
||||
updateProjectConfig(ssrApp, (project) => {
|
||||
project.targets.server.executor = '@nrwl/angular:webpack-server';
|
||||
return project;
|
||||
});
|
||||
|
||||
const port = 4501;
|
||||
|
||||
// ACT
|
||||
let process = await runCommandUntil(
|
||||
`serve-ssr ${ssrApp} --port=${port}`,
|
||||
(output) => {
|
||||
return output.includes(
|
||||
`Angular Universal Live Development Server is listening on http://localhost:${port}`
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
// port and process cleanup
|
||||
try {
|
||||
if (process && process.pid) {
|
||||
await promisifiedTreeKill(process.pid, 'SIGKILL');
|
||||
}
|
||||
await killPort(port);
|
||||
} catch (err) {
|
||||
expect(err).toBeFalsy();
|
||||
}
|
||||
}, 300000);
|
||||
});
|
||||
|
||||
@ -64,11 +64,10 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
project = uniq('proj');
|
||||
packageManager = getSelectedPackageManager();
|
||||
// TODO: solve issues with pnpm and remove this fallback
|
||||
packageManager = packageManager === 'pnpm' ? 'yarn' : packageManager;
|
||||
runNgNew(project, packageManager);
|
||||
project = runNgNew(packageManager);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@ -436,55 +435,12 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should support a workspace with multiple libraries', () => {
|
||||
// add some libraries
|
||||
const lib1 = uniq('lib1');
|
||||
const lib2 = uniq('lib2');
|
||||
runCommand(`ng g @schematics/angular:library ${lib1}`);
|
||||
runCommand(`ng g @schematics/angular:library ${lib2}`);
|
||||
|
||||
runNgAdd('@nrwl/angular', '--npm-scope projscope');
|
||||
|
||||
// check angular.json does not exist
|
||||
checkFilesDoNotExist('angular.json');
|
||||
|
||||
// check building lib1
|
||||
let output = runCLI(`build ${lib1}`);
|
||||
expect(output).toContain(`> nx run ${lib1}:build:production`);
|
||||
expect(output).toContain(
|
||||
`Successfully ran target build for project ${lib1}`
|
||||
);
|
||||
checkFilesExist(`dist/${lib1}/package.json`);
|
||||
|
||||
output = runCLI(`build ${lib1}`);
|
||||
expect(output).toContain(
|
||||
`> nx run ${lib1}:build:production [local cache]`
|
||||
);
|
||||
expect(output).toContain(
|
||||
`Successfully ran target build for project ${lib1}`
|
||||
);
|
||||
|
||||
// check building lib2
|
||||
output = runCLI(`build ${lib2}`);
|
||||
expect(output).toContain(`> nx run ${lib2}:build:production`);
|
||||
expect(output).toContain(
|
||||
`Successfully ran target build for project ${lib2}`
|
||||
);
|
||||
checkFilesExist(`dist/${lib2}/package.json`);
|
||||
|
||||
output = runCLI(`build ${lib2}`);
|
||||
expect(output).toContain(
|
||||
`> nx run ${lib2}:build:production [local cache]`
|
||||
);
|
||||
expect(output).toContain(
|
||||
`Successfully ran target build for project ${lib2}`
|
||||
);
|
||||
});
|
||||
|
||||
it('should support a workspace with multiple applications', () => {
|
||||
// add another app
|
||||
it('should support a workspace with multiple projects', () => {
|
||||
// add other projects
|
||||
const app1 = uniq('app1');
|
||||
const lib1 = uniq('lib1');
|
||||
runCommand(`ng g @schematics/angular:application ${app1}`);
|
||||
runCommand(`ng g @schematics/angular:library ${lib1}`);
|
||||
|
||||
runNgAdd('@nrwl/angular', '--npm-scope projscope');
|
||||
|
||||
@ -526,5 +482,21 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
||||
expect(output).toContain(
|
||||
`Successfully ran target build for project ${app1}`
|
||||
);
|
||||
|
||||
// check building lib1
|
||||
output = runCLI(`build ${lib1}`);
|
||||
expect(output).toContain(`> nx run ${lib1}:build:production`);
|
||||
expect(output).toContain(
|
||||
`Successfully ran target build for project ${lib1}`
|
||||
);
|
||||
checkFilesExist(`dist/${lib1}/package.json`);
|
||||
|
||||
output = runCLI(`build ${lib1}`);
|
||||
expect(output).toContain(
|
||||
`> nx run ${lib1}:build:production [local cache]`
|
||||
);
|
||||
expect(output).toContain(
|
||||
`Successfully ran target build for project ${lib1}`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,45 +0,0 @@
|
||||
import * as isCI from 'is-ci';
|
||||
import {
|
||||
checkFilesExist,
|
||||
getSelectedPackageManager,
|
||||
packageInstall,
|
||||
readJson,
|
||||
runCommand,
|
||||
runNgNew,
|
||||
tmpProjPath,
|
||||
uniq,
|
||||
updateFile,
|
||||
} from '@nrwl/e2e/utils';
|
||||
import { PackageManager } from 'nx/src/utils/package-manager';
|
||||
import { removeSync } from 'fs-extra';
|
||||
|
||||
describe('using Nx executors and generators with Angular CLI', () => {
|
||||
let project: string;
|
||||
let packageManager: PackageManager;
|
||||
|
||||
beforeEach(() => {
|
||||
project = uniq('proj');
|
||||
packageManager = getSelectedPackageManager();
|
||||
runNgNew(project, packageManager);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (isCI) {
|
||||
try {
|
||||
removeSync(tmpProjPath());
|
||||
} catch (e) {}
|
||||
}
|
||||
});
|
||||
|
||||
it('should convert Nx executors into Angular CLI compatible builders', () => {
|
||||
packageInstall('@nrwl/angular');
|
||||
const angularJson = readJson('angular.json');
|
||||
angularJson.projects[project].architect.build.builder =
|
||||
'@nrwl/angular:webpack-browser';
|
||||
updateFile('angular.json', JSON.stringify(angularJson, null, 2));
|
||||
|
||||
runCommand(`npx ng build ${project} --configuration=development`);
|
||||
|
||||
checkFilesExist(`dist/${project}/main.js`);
|
||||
});
|
||||
});
|
||||
@ -1,11 +1,13 @@
|
||||
import { names } from '@nrwl/devkit';
|
||||
import {
|
||||
checkFilesExist,
|
||||
cleanupProject,
|
||||
getSize,
|
||||
killPorts,
|
||||
killProcessAndPorts,
|
||||
newProject,
|
||||
promisifiedTreeKill,
|
||||
readFile,
|
||||
removeFile,
|
||||
runCLI,
|
||||
runCommandUntil,
|
||||
runCypressTests,
|
||||
@ -14,95 +16,151 @@ import {
|
||||
updateFile,
|
||||
updateProjectConfig,
|
||||
} from '@nrwl/e2e/utils';
|
||||
|
||||
import { names } from '@nrwl/devkit';
|
||||
import { normalize } from 'path';
|
||||
|
||||
describe('Angular Projects', () => {
|
||||
let proj: string;
|
||||
const app1 = uniq('app1');
|
||||
const lib1 = uniq('lib1');
|
||||
let app1DefaultModule: string;
|
||||
let app1DefaultComponentTemplate: string;
|
||||
|
||||
beforeAll(() => {
|
||||
proj = newProject();
|
||||
runCLI(`generate @nrwl/angular:app ${app1} --no-interactive`);
|
||||
runCLI(
|
||||
`generate @nrwl/angular:lib ${lib1} --add-module-spec --no-interactive`
|
||||
);
|
||||
app1DefaultModule = readFile(`apps/${app1}/src/app/app.module.ts`);
|
||||
app1DefaultComponentTemplate = readFile(
|
||||
`apps/${app1}/src/app/app.component.html`
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
updateFile(`apps/${app1}/src/app/app.module.ts`, app1DefaultModule);
|
||||
updateFile(
|
||||
`apps/${app1}/src/app/app.component.html`,
|
||||
app1DefaultComponentTemplate
|
||||
);
|
||||
});
|
||||
|
||||
beforeAll(() => (proj = newProject()));
|
||||
afterAll(() => cleanupProject());
|
||||
|
||||
it('should generate an app, a lib, link them, build, serve and test both correctly', async () => {
|
||||
const myapp = uniq('myapp');
|
||||
const myapp2 = uniq('myapp2');
|
||||
const mylib = uniq('mylib');
|
||||
it('should successfully generate apps and libs and work correctly', async () => {
|
||||
const standaloneApp = uniq('standalone-app');
|
||||
runCLI(
|
||||
`generate @nrwl/angular:app ${myapp} --directory=myDir --no-interactive`
|
||||
);
|
||||
runCLI(
|
||||
`generate @nrwl/angular:app ${myapp2} --standalone=true --directory=myDir --no-interactive`
|
||||
);
|
||||
runCLI(
|
||||
`generate @nrwl/angular:lib ${mylib} --directory=myDir --add-module-spec --no-interactive`
|
||||
`generate @nrwl/angular:app ${standaloneApp} --directory=myDir --standalone=true --no-interactive`
|
||||
);
|
||||
|
||||
updateFile(
|
||||
`apps/my-dir/${myapp}/src/app/app.module.ts`,
|
||||
`apps/${app1}/src/app/app.module.ts`,
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { ${names(lib1).className}Module } from '@${proj}/${lib1}';
|
||||
import { AppComponent } from './app.component';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [BrowserModule, ${names(lib1).className}Module],
|
||||
declarations: [AppComponent, NxWelcomeComponent],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule {}
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { MyDir${
|
||||
names(mylib).className
|
||||
}Module } from '@${proj}/my-dir/${mylib}';
|
||||
import { AppComponent } from './app.component';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [BrowserModule, MyDir${names(mylib).className}Module],
|
||||
declarations: [AppComponent, NxWelcomeComponent],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule {}
|
||||
`
|
||||
);
|
||||
|
||||
// check build
|
||||
runCLI(
|
||||
`run-many --target build --projects=my-dir-${myapp},my-dir-${myapp2} --parallel --prod --output-hashing none`
|
||||
`run-many --target build --projects=${app1},my-dir-${standaloneApp} --parallel --prod --output-hashing none`
|
||||
);
|
||||
|
||||
checkFilesExist(`dist/apps/my-dir/${myapp}/main.js`);
|
||||
|
||||
checkFilesExist(`dist/apps/${app1}/main.js`);
|
||||
checkFilesExist(`dist/apps/my-dir/${standaloneApp}/main.js`);
|
||||
// This is a loose requirement because there are a lot of
|
||||
// influences external from this project that affect this.
|
||||
const es2015BundleSize = getSize(
|
||||
tmpProjPath(`dist/apps/my-dir/${myapp}/main.js`)
|
||||
);
|
||||
const es2015BundleSize = getSize(tmpProjPath(`dist/apps/${app1}/main.js`));
|
||||
console.log(
|
||||
`The current es2015 bundle size is ${es2015BundleSize / 1000} KB`
|
||||
);
|
||||
expect(es2015BundleSize).toBeLessThanOrEqual(160000);
|
||||
|
||||
// check unit tests
|
||||
runCLI(
|
||||
`run-many --target test --projects=my-dir-${myapp},my-dir-${mylib} --parallel`
|
||||
`run-many --target test --projects=${app1},my-dir-${standaloneApp},${lib1} --parallel`
|
||||
);
|
||||
|
||||
// check e2e tests
|
||||
if (runCypressTests()) {
|
||||
const e2eResults = runCLI(`e2e my-dir-${myapp}-e2e --no-watch`);
|
||||
const e2eResults = runCLI(`e2e ${app1}-e2e --no-watch`);
|
||||
expect(e2eResults).toContain('All specs passed!');
|
||||
expect(await killPorts()).toBeTruthy();
|
||||
}
|
||||
|
||||
const appPort = 4207;
|
||||
const process = await runCommandUntil(
|
||||
`serve my-dir-${myapp} -- --port=4207`,
|
||||
`serve ${app1} -- --port=${appPort}`,
|
||||
(output) => output.includes(`listening on localhost:4207`)
|
||||
);
|
||||
|
||||
// port and process cleanup
|
||||
try {
|
||||
await promisifiedTreeKill(process.pid, 'SIGKILL');
|
||||
await killPorts(4207);
|
||||
} catch (err) {
|
||||
expect(err).toBeFalsy();
|
||||
}
|
||||
await killProcessAndPorts(process.pid, appPort);
|
||||
}, 1000000);
|
||||
|
||||
it('should lint correctly with eslint and handle external HTML files and inline templates', async () => {
|
||||
// check apps and lib pass linting for initial generated code
|
||||
runCLI(`run-many --target lint --projects=${app1},${lib1} --parallel`);
|
||||
|
||||
// External HTML template file
|
||||
const templateWhichFailsBananaInBoxLintCheck = `<div ([foo])="bar"></div>`;
|
||||
updateFile(
|
||||
`apps/${app1}/src/app/app.component.html`,
|
||||
templateWhichFailsBananaInBoxLintCheck
|
||||
);
|
||||
// Inline template within component.ts file
|
||||
const wrappedAsInlineTemplate = `
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'inline-template-component',
|
||||
template: \`
|
||||
${templateWhichFailsBananaInBoxLintCheck}
|
||||
\`,
|
||||
})
|
||||
export class InlineTemplateComponent {}
|
||||
`;
|
||||
updateFile(
|
||||
`apps/${app1}/src/app/inline-template.component.ts`,
|
||||
wrappedAsInlineTemplate
|
||||
);
|
||||
|
||||
const appLintStdOut = runCLI(`lint ${app1}`, {
|
||||
silenceError: true,
|
||||
});
|
||||
expect(appLintStdOut).toContain(
|
||||
normalize(`apps/${app1}/src/app/app.component.html`)
|
||||
);
|
||||
expect(appLintStdOut).toContain(`1:6`);
|
||||
expect(appLintStdOut).toContain(`Invalid binding syntax`);
|
||||
expect(appLintStdOut).toContain(
|
||||
normalize(`apps/${app1}/src/app/inline-template.component.ts`)
|
||||
);
|
||||
expect(appLintStdOut).toContain(`5:19`);
|
||||
expect(appLintStdOut).toContain(
|
||||
`The selector should start with one of these prefixes`
|
||||
);
|
||||
expect(appLintStdOut).toContain(`7:16`);
|
||||
expect(appLintStdOut).toContain(`Invalid binding syntax`);
|
||||
|
||||
// cleanup added component
|
||||
removeFile(`apps/${app1}/src/app/inline-template.component.ts`);
|
||||
}, 1000000);
|
||||
|
||||
it('should build the dependent buildable lib and its child lib, as well as the app', async () => {
|
||||
// ARRANGE
|
||||
const app = uniq('app');
|
||||
const buildableLib = uniq('buildlib1');
|
||||
const buildableChildLib = uniq('buildlib2');
|
||||
|
||||
runCLI(`generate @nrwl/angular:app ${app} --style=css --no-interactive`);
|
||||
runCLI(
|
||||
`generate @nrwl/angular:library ${buildableLib} --buildable=true --no-interactive`
|
||||
);
|
||||
@ -112,7 +170,7 @@ describe('Angular Projects', () => {
|
||||
|
||||
// update the app module to include a ref to the buildable lib
|
||||
updateFile(
|
||||
`apps/${app}/src/app/app.module.ts`,
|
||||
`apps/${app1}/src/app/app.module.ts`,
|
||||
`
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
@ -152,7 +210,7 @@ describe('Angular Projects', () => {
|
||||
);
|
||||
|
||||
// update the angular.json
|
||||
updateProjectConfig(app, (config) => {
|
||||
updateProjectConfig(app1, (config) => {
|
||||
config.targets.build.executor = '@nrwl/angular:webpack-browser';
|
||||
config.targets.build.options = {
|
||||
...config.targets.build.options,
|
||||
@ -162,17 +220,17 @@ describe('Angular Projects', () => {
|
||||
});
|
||||
|
||||
// ACT
|
||||
const libOutput = runCLI(`build ${app} --configuration=development`);
|
||||
const libOutput = runCLI(`build ${app1} --configuration=development`);
|
||||
|
||||
// ASSERT
|
||||
expect(libOutput).toContain(
|
||||
`Building entry point '@${proj}/${buildableLib}'`
|
||||
);
|
||||
expect(libOutput).toContain(`nx run ${app}:build:development`);
|
||||
expect(libOutput).toContain(`nx run ${app1}:build:development`);
|
||||
|
||||
// to proof it has been built from source the "main.js" should actually contain
|
||||
// the path to dist
|
||||
const mainBundle = readFile(`dist/apps/${app}/main.js`);
|
||||
const mainBundle = readFile(`dist/apps/${app1}/main.js`);
|
||||
expect(mainBundle).toContain(`dist/libs/${buildableLib}`);
|
||||
});
|
||||
|
||||
|
||||
@ -3,7 +3,6 @@ import {
|
||||
getSelectedPackageManager,
|
||||
runNgNew,
|
||||
tmpProjPath,
|
||||
uniq,
|
||||
} from '../../utils';
|
||||
import { PackageManager } from 'nx/src/utils/package-manager';
|
||||
import { execSync } from 'child_process';
|
||||
@ -13,10 +12,10 @@ describe('make-angular-cli-faster', () => {
|
||||
let packageManager: PackageManager;
|
||||
|
||||
beforeEach(() => {
|
||||
project = uniq('proj');
|
||||
packageManager = getSelectedPackageManager();
|
||||
// TODO: solve issues with pnpm and remove this fallback
|
||||
packageManager = packageManager === 'pnpm' ? 'yarn' : packageManager;
|
||||
project = runNgNew(packageManager);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@ -25,9 +24,6 @@ describe('make-angular-cli-faster', () => {
|
||||
|
||||
// TODO(colum): skip until we can investigate why it is installing incorrect version
|
||||
xit('should successfully install make-angular-cli-faster with nx cloud', () => {
|
||||
// ARRANGE
|
||||
runNgNew(project, packageManager);
|
||||
|
||||
expect(() =>
|
||||
execSync(
|
||||
`NPM_CONFIG_REGISTRY=https://registry.npmjs.org npx --yes make-angular-cli-faster@latest --useNxCloud=true`,
|
||||
|
||||
@ -9,7 +9,6 @@ import {
|
||||
runCLI,
|
||||
runCommand,
|
||||
runNgNew,
|
||||
uniq,
|
||||
} from '../../utils';
|
||||
|
||||
describe('nx init (Angular CLI)', () => {
|
||||
@ -18,11 +17,11 @@ describe('nx init (Angular CLI)', () => {
|
||||
let pmc: ReturnType<typeof getPackageManagerCommand>;
|
||||
|
||||
beforeEach(() => {
|
||||
project = uniq('proj');
|
||||
packageManager = getSelectedPackageManager();
|
||||
// TODO: solve issues with pnpm and remove this fallback
|
||||
packageManager = packageManager === 'pnpm' ? 'yarn' : packageManager;
|
||||
pmc = getPackageManagerCommand({ packageManager });
|
||||
project = runNgNew(packageManager);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@ -30,8 +29,6 @@ describe('nx init (Angular CLI)', () => {
|
||||
});
|
||||
|
||||
it('should successfully convert an Angular CLI workspace to an Nx workspace', () => {
|
||||
runNgNew(project, packageManager);
|
||||
|
||||
const output = runCommand(
|
||||
`${pmc.runUninstalledPackage} nx@${getPublishedVersion()} init -y`
|
||||
);
|
||||
|
||||
@ -2,6 +2,7 @@ import { copySync, ensureDirSync, moveSync, removeSync } from 'fs-extra';
|
||||
import {
|
||||
createFile,
|
||||
directoryExists,
|
||||
tmpBackupNgCliProjPath,
|
||||
tmpBackupProjPath,
|
||||
updateFile,
|
||||
updateJson,
|
||||
@ -9,10 +10,10 @@ import {
|
||||
import {
|
||||
e2eCwd,
|
||||
getLatestLernaVersion,
|
||||
getNpmMajorVersion,
|
||||
getPublishedVersion,
|
||||
getSelectedPackageManager,
|
||||
isVerbose,
|
||||
isVerboseE2ERun,
|
||||
} from './get-env-info';
|
||||
import * as isCI from 'is-ci';
|
||||
|
||||
@ -28,6 +29,8 @@ import {
|
||||
runCommand,
|
||||
} from './command-utils';
|
||||
import { output } from '@nrwl/devkit';
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
let projName: string;
|
||||
|
||||
@ -311,24 +314,51 @@ export function packageInstall(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Angular CLI workspace or restores a cached one if exists.
|
||||
* @returns the workspace name
|
||||
*/
|
||||
export function runNgNew(
|
||||
projectName: string,
|
||||
packageManager = getSelectedPackageManager(),
|
||||
angularCliVersion = defaultAngularCliVersion
|
||||
): string {
|
||||
projName = projectName;
|
||||
const pmc = getPackageManagerCommand({ packageManager });
|
||||
|
||||
const npmMajorVersion = getNpmMajorVersion();
|
||||
const command = `npx ${
|
||||
+npmMajorVersion >= 7 ? '--yes' : ''
|
||||
} @angular/cli@${angularCliVersion} new ${projectName} --package-manager=${packageManager}`;
|
||||
if (directoryExists(tmpBackupNgCliProjPath())) {
|
||||
const angularJson = JSON.parse(
|
||||
readFileSync(join(tmpBackupNgCliProjPath(), 'angular.json'), 'utf-8')
|
||||
);
|
||||
// the name of the workspace matches the name of the generated default app,
|
||||
// we need to reuse the same name that's cached in order to avoid issues
|
||||
// with tests relying on a different name
|
||||
projName = Object.keys(angularJson.projects)[0];
|
||||
copySync(tmpBackupNgCliProjPath(), tmpProjPath());
|
||||
|
||||
return execSync(command, {
|
||||
if (isVerboseE2ERun()) {
|
||||
logInfo(
|
||||
`NX`,
|
||||
`E2E restored an Angular CLI project from cache: ${tmpProjPath()}`
|
||||
);
|
||||
}
|
||||
|
||||
return projName;
|
||||
}
|
||||
|
||||
projName = uniq('ng-proj');
|
||||
const command = `${pmc.runUninstalledPackage} @angular/cli@${angularCliVersion} new ${projName} --package-manager=${packageManager}`;
|
||||
execSync(command, {
|
||||
cwd: e2eCwd,
|
||||
stdio: isVerbose() ? 'inherit' : 'pipe',
|
||||
env: process.env,
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
copySync(tmpProjPath(), tmpBackupNgCliProjPath());
|
||||
|
||||
if (isVerboseE2ERun()) {
|
||||
logInfo(`NX`, `E2E created an Angular CLI project: ${tmpProjPath()}`);
|
||||
}
|
||||
|
||||
return projName;
|
||||
}
|
||||
|
||||
export function newLernaWorkspace({
|
||||
|
||||
@ -119,3 +119,9 @@ export function getSize(filePath: string): number {
|
||||
export function tmpBackupProjPath(path?: string) {
|
||||
return path ? `${e2eCwd}/proj-backup/${path}` : `${e2eCwd}/proj-backup`;
|
||||
}
|
||||
|
||||
export function tmpBackupNgCliProjPath(path?: string) {
|
||||
return path
|
||||
? `${e2eCwd}/ng-cli-proj-backup/${path}`
|
||||
: `${e2eCwd}/ng-cli-proj-backup`;
|
||||
}
|
||||
|
||||
@ -39,3 +39,19 @@ export async function killPorts(port?: number): Promise<boolean> {
|
||||
? await killPort(port)
|
||||
: (await killPort(3333)) && (await killPort(4200));
|
||||
}
|
||||
|
||||
export async function killProcessAndPorts(
|
||||
pid: number | undefined,
|
||||
...ports: number[]
|
||||
): Promise<void> {
|
||||
try {
|
||||
if (pid) {
|
||||
await promisifiedTreeKill(pid, 'SIGKILL');
|
||||
}
|
||||
for (const port of ports) {
|
||||
await killPort(port);
|
||||
}
|
||||
} catch (err) {
|
||||
expect(err).toBeFalsy();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user