feat(angular): prompt users for standalone components in application (#14987)
This commit is contained in:
parent
2899b3abfb
commit
1e6a4f8e65
@ -148,7 +148,7 @@
|
|||||||
"standalone": {
|
"standalone": {
|
||||||
"description": "Generate an application that is setup to use standalone components. _Note: This is only supported in Angular versions >= 14.1.0_",
|
"description": "Generate an application that is setup to use standalone components. _Note: This is only supported in Angular versions >= 14.1.0_",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"rootProject": {
|
"rootProject": {
|
||||||
"description": "Create an application at the root of the workspace.",
|
"description": "Create an application at the root of the workspace.",
|
||||||
|
|||||||
@ -14,18 +14,24 @@ describe('Angular Package', () => {
|
|||||||
|
|
||||||
it('should support eslint and pass linting on the standard generated code', async () => {
|
it('should support eslint and pass linting on the standard generated code', async () => {
|
||||||
const myapp = uniq('myapp');
|
const myapp = uniq('myapp');
|
||||||
runCLI(`generate @nrwl/angular:app ${myapp} --linter=eslint`);
|
runCLI(
|
||||||
|
`generate @nrwl/angular:app ${myapp} --linter=eslint --no-interactive`
|
||||||
|
);
|
||||||
expect(runCLI(`lint ${myapp}`)).toContain('All files pass linting.');
|
expect(runCLI(`lint ${myapp}`)).toContain('All files pass linting.');
|
||||||
|
|
||||||
const mylib = uniq('mylib');
|
const mylib = uniq('mylib');
|
||||||
runCLI(`generate @nrwl/angular:lib ${mylib} --linter=eslint`);
|
runCLI(
|
||||||
|
`generate @nrwl/angular:lib ${mylib} --linter=eslint --no-interactive`
|
||||||
|
);
|
||||||
expect(runCLI(`lint ${mylib}`)).toContain('All files pass linting.');
|
expect(runCLI(`lint ${mylib}`)).toContain('All files pass linting.');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support eslint and successfully lint external HTML files and inline templates', async () => {
|
it('should support eslint and successfully lint external HTML files and inline templates', async () => {
|
||||||
const myapp = uniq('myapp');
|
const myapp = uniq('myapp');
|
||||||
|
|
||||||
runCLI(`generate @nrwl/angular:app ${myapp} --linter=eslint`);
|
runCLI(
|
||||||
|
`generate @nrwl/angular:app ${myapp} --linter=eslint --no-interactive`
|
||||||
|
);
|
||||||
|
|
||||||
const templateWhichFailsBananaInBoxLintCheck = `<div ([foo])="bar"></div>`;
|
const templateWhichFailsBananaInBoxLintCheck = `<div ([foo])="bar"></div>`;
|
||||||
const wrappedAsInlineTemplate = `
|
const wrappedAsInlineTemplate = `
|
||||||
|
|||||||
@ -20,7 +20,7 @@ describe('Move Angular Project', () => {
|
|||||||
app1 = uniq('app1');
|
app1 = uniq('app1');
|
||||||
app2 = uniq('app2');
|
app2 = uniq('app2');
|
||||||
newPath = `subfolder/${app2}`;
|
newPath = `subfolder/${app2}`;
|
||||||
runCLI(`generate @nrwl/angular:app ${app1}`);
|
runCLI(`generate @nrwl/angular:app ${app1} --no-interactive`);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(() => cleanupProject());
|
afterAll(() => cleanupProject());
|
||||||
@ -99,13 +99,13 @@ describe('Move Angular Project', () => {
|
|||||||
it('should work for libraries', () => {
|
it('should work for libraries', () => {
|
||||||
const lib1 = uniq('mylib');
|
const lib1 = uniq('mylib');
|
||||||
const lib2 = uniq('mylib');
|
const lib2 = uniq('mylib');
|
||||||
runCLI(`generate @nrwl/angular:lib ${lib1}`);
|
runCLI(`generate @nrwl/angular:lib ${lib1} --no-interactive`);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a library which imports the module from the other lib
|
* Create a library which imports the module from the other lib
|
||||||
*/
|
*/
|
||||||
|
|
||||||
runCLI(`generate @nrwl/angular:lib ${lib2}`);
|
runCLI(`generate @nrwl/angular:lib ${lib2} --no-interactive`);
|
||||||
|
|
||||||
updateFile(
|
updateFile(
|
||||||
`libs/${lib2}/src/lib/${lib2}.module.ts`,
|
`libs/${lib2}/src/lib/${lib2}.module.ts`,
|
||||||
|
|||||||
@ -22,7 +22,8 @@
|
|||||||
"semver",
|
"semver",
|
||||||
"webpack",
|
"webpack",
|
||||||
"http-server",
|
"http-server",
|
||||||
"magic-string"
|
"magic-string",
|
||||||
|
"enquirer"
|
||||||
],
|
],
|
||||||
"keepLifecycleScripts": true
|
"keepLifecycleScripts": true
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,7 +54,8 @@
|
|||||||
"ts-node": "10.9.1",
|
"ts-node": "10.9.1",
|
||||||
"tsconfig-paths": "^4.1.2",
|
"tsconfig-paths": "^4.1.2",
|
||||||
"webpack": "^5.75.0",
|
"webpack": "^5.75.0",
|
||||||
"webpack-merge": "5.7.3"
|
"webpack-merge": "5.7.3",
|
||||||
|
"enquirer": "^2.3.6"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@angular-devkit/build-angular": ">= 14.0.0 < 16.0.0",
|
"@angular-devkit/build-angular": ">= 14.0.0 < 16.0.0",
|
||||||
|
|||||||
@ -20,17 +20,23 @@ import {
|
|||||||
} from '../../utils/versions';
|
} from '../../utils/versions';
|
||||||
import { applicationGenerator } from './application';
|
import { applicationGenerator } from './application';
|
||||||
import type { Schema } from './schema';
|
import type { Schema } from './schema';
|
||||||
|
import * as enquirer from 'enquirer';
|
||||||
// need to mock cypress otherwise it'll use the nx installed version from package.json
|
// need to mock cypress otherwise it'll use the nx installed version from package.json
|
||||||
// which is v9 while we are testing for the new v10 version
|
// which is v9 while we are testing for the new v10 version
|
||||||
jest.mock('@nrwl/cypress/src/utils/cypress-version');
|
jest.mock('@nrwl/cypress/src/utils/cypress-version');
|
||||||
|
jest.mock('enquirer');
|
||||||
describe('app', () => {
|
describe('app', () => {
|
||||||
let appTree: Tree;
|
let appTree: Tree;
|
||||||
let mockedInstalledCypressVersion: jest.Mock<
|
let mockedInstalledCypressVersion: jest.Mock<
|
||||||
ReturnType<typeof installedCypressVersion>
|
ReturnType<typeof installedCypressVersion>
|
||||||
> = installedCypressVersion as never;
|
> = installedCypressVersion as never;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockedInstalledCypressVersion.mockReturnValue(10);
|
mockedInstalledCypressVersion.mockReturnValue(10);
|
||||||
|
// @ts-ignore
|
||||||
|
enquirer.prompt = jest
|
||||||
|
.fn()
|
||||||
|
.mockReturnValue(Promise.resolve({ 'standalone-components': true }));
|
||||||
appTree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
appTree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -819,6 +825,48 @@ describe('app', () => {
|
|||||||
appTree.read('apps/standalone/src/app/nx-welcome.component.ts', 'utf-8')
|
appTree.read('apps/standalone/src/app/nx-welcome.component.ts', 'utf-8')
|
||||||
).toContain('standalone: true');
|
).toContain('standalone: true');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should prompt for standalone components and not use them when the user selects false', async () => {
|
||||||
|
// ARRANGE
|
||||||
|
process.env.NX_INTERACTIVE = 'true';
|
||||||
|
// @ts-ignore
|
||||||
|
enquirer.prompt = jest
|
||||||
|
.fn()
|
||||||
|
.mockReturnValue(Promise.resolve({ 'standalone-components': false }));
|
||||||
|
|
||||||
|
// ACT
|
||||||
|
await generateApp(appTree, 'nostandalone');
|
||||||
|
|
||||||
|
// ASSERT
|
||||||
|
expect(
|
||||||
|
appTree.exists('apps/nostandalone/src/app/app.module.ts')
|
||||||
|
).toBeTruthy();
|
||||||
|
expect(enquirer.prompt).toHaveBeenCalled();
|
||||||
|
|
||||||
|
// CLEANUP
|
||||||
|
process.env.NX_INTERACTIVE = undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should prompt for standalone components and use them when the user selects true', async () => {
|
||||||
|
// ARRANGE
|
||||||
|
process.env.NX_INTERACTIVE = 'true';
|
||||||
|
// @ts-ignore
|
||||||
|
enquirer.prompt = jest
|
||||||
|
.fn()
|
||||||
|
.mockReturnValue(Promise.resolve({ 'standalone-components': true }));
|
||||||
|
|
||||||
|
// ACT
|
||||||
|
await generateApp(appTree, 'nostandalone');
|
||||||
|
|
||||||
|
// ASSERT
|
||||||
|
expect(
|
||||||
|
appTree.exists('apps/nostandalone/src/app/app.module.ts')
|
||||||
|
).not.toBeTruthy();
|
||||||
|
expect(enquirer.prompt).toHaveBeenCalled();
|
||||||
|
|
||||||
|
// CLEANUP
|
||||||
|
process.env.NX_INTERACTIVE = undefined;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should generate correct main.ts', async () => {
|
it('should generate correct main.ts', async () => {
|
||||||
|
|||||||
@ -34,7 +34,8 @@ import {
|
|||||||
updateNxComponentTemplate,
|
updateNxComponentTemplate,
|
||||||
} from './lib';
|
} from './lib';
|
||||||
import type { Schema } from './schema';
|
import type { Schema } from './schema';
|
||||||
import { lt } from 'semver';
|
import { gte, lt } from 'semver';
|
||||||
|
import { prompt } from 'enquirer';
|
||||||
|
|
||||||
export async function applicationGenerator(
|
export async function applicationGenerator(
|
||||||
tree: Tree,
|
tree: Tree,
|
||||||
@ -47,6 +48,18 @@ export async function applicationGenerator(
|
|||||||
You can resolve this error by removing the "standalone" option or by migrating to Angular 14.1.0.`);
|
You can resolve this error by removing the "standalone" option or by migrating to Angular 14.1.0.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
gte(installedAngularVersionInfo.version, '14.1.0') &&
|
||||||
|
schema.standalone === undefined &&
|
||||||
|
process.env.NX_INTERACTIVE === 'true'
|
||||||
|
) {
|
||||||
|
schema.standalone = await prompt({
|
||||||
|
name: 'standalone-components',
|
||||||
|
message: 'Would you like to use Standalone Components?',
|
||||||
|
type: 'confirm',
|
||||||
|
}).then((a) => a['standalone-components']);
|
||||||
|
}
|
||||||
|
|
||||||
const generatorDirectory =
|
const generatorDirectory =
|
||||||
getGeneratorDirectoryForInstalledAngularVersion(tree);
|
getGeneratorDirectoryForInstalledAngularVersion(tree);
|
||||||
if (generatorDirectory) {
|
if (generatorDirectory) {
|
||||||
|
|||||||
@ -151,7 +151,7 @@
|
|||||||
"standalone": {
|
"standalone": {
|
||||||
"description": "Generate an application that is setup to use standalone components. _Note: This is only supported in Angular versions >= 14.1.0_",
|
"description": "Generate an application that is setup to use standalone components. _Note: This is only supported in Angular versions >= 14.1.0_",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"rootProject": {
|
"rootProject": {
|
||||||
"description": "Create an application at the root of the workspace.",
|
"description": "Create an application at the root of the workspace.",
|
||||||
|
|||||||
@ -37,6 +37,7 @@ export async function host(tree: Tree, options: Schema) {
|
|||||||
|
|
||||||
const appInstallTask = await applicationGenerator(tree, {
|
const appInstallTask = await applicationGenerator(tree, {
|
||||||
...options,
|
...options,
|
||||||
|
standalone: options.standalone ?? false,
|
||||||
routing: true,
|
routing: true,
|
||||||
port: 4200,
|
port: 4200,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
|
|||||||
@ -29,6 +29,7 @@ export async function remote(tree: Tree, options: Schema) {
|
|||||||
|
|
||||||
const appInstallTask = await applicationGenerator(tree, {
|
const appInstallTask = await applicationGenerator(tree, {
|
||||||
...options,
|
...options,
|
||||||
|
standalone: options.standalone ?? false,
|
||||||
routing: true,
|
routing: true,
|
||||||
port,
|
port,
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user