chore(angular): skip formatting generated code when not needed in unit tests (#20819)

This commit is contained in:
Leosvel Pérez Espinosa 2023-12-18 17:05:44 +01:00 committed by GitHub
parent de0d238e13
commit 626605ef97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
161 changed files with 2168 additions and 1406 deletions

View File

@ -22,6 +22,12 @@
"$default": { "$source": "argv", "index": 0 }, "$default": { "$source": "argv", "index": 0 },
"x-prompt": "What micro frontend project would you like to migrate?", "x-prompt": "What micro frontend project would you like to migrate?",
"x-priority": "important" "x-priority": "important"
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
"default": false,
"x-priority": "internal"
} }
}, },
"presets": [] "presets": []

View File

@ -29,6 +29,12 @@
"type": "boolean", "type": "boolean",
"description": "Skip generating a module for the secondary entry point.", "description": "Skip generating a module for the secondary entry point.",
"default": false "default": false
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
"default": false,
"x-priority": "internal"
} }
}, },
"additionalProperties": false, "additionalProperties": false,

View File

@ -77,6 +77,12 @@
"description": "Specifies if the SCAM should be exported from the project's entry point (normally `index.ts`). It only applies to libraries.", "description": "Specifies if the SCAM should be exported from the project's entry point (normally `index.ts`). It only applies to libraries.",
"default": true, "default": true,
"x-priority": "important" "x-priority": "important"
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
"default": false,
"x-priority": "internal"
} }
}, },
"required": ["name"], "required": ["name"],

View File

@ -63,6 +63,12 @@
"description": "Specifies if the SCAM should be exported from the project's entry point (normally `index.ts`). It only applies to libraries.", "description": "Specifies if the SCAM should be exported from the project's entry point (normally `index.ts`). It only applies to libraries.",
"default": true, "default": true,
"x-priority": "important" "x-priority": "important"
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
"default": false,
"x-priority": "internal"
} }
}, },
"required": ["name"], "required": ["name"],

View File

@ -31,6 +31,7 @@ describe('addLinting generator', () => {
prefix: 'myOrg', prefix: 'myOrg',
projectName: appProjectName, projectName: appProjectName,
projectRoot: appProjectRoot, projectRoot: appProjectRoot,
skipFormat: true,
}); });
expect(linter.lintProjectGenerator).toHaveBeenCalled(); expect(linter.lintProjectGenerator).toHaveBeenCalled();
@ -41,6 +42,7 @@ describe('addLinting generator', () => {
prefix: 'myOrg', prefix: 'myOrg',
projectName: appProjectName, projectName: appProjectName,
projectRoot: appProjectRoot, projectRoot: appProjectRoot,
skipFormat: true,
}); });
const { devDependencies } = readJson(tree, 'package.json'); const { devDependencies } = readJson(tree, 'package.json');
@ -56,6 +58,7 @@ describe('addLinting generator', () => {
prefix: 'myOrg', prefix: 'myOrg',
projectName: appProjectName, projectName: appProjectName,
projectRoot: appProjectRoot, projectRoot: appProjectRoot,
skipFormat: true,
}); });
const eslintConfig = readJson(tree, `${appProjectRoot}/.eslintrc.json`); const eslintConfig = readJson(tree, `${appProjectRoot}/.eslintrc.json`);
@ -67,6 +70,7 @@ describe('addLinting generator', () => {
prefix: 'myOrg', prefix: 'myOrg',
projectName: appProjectName, projectName: appProjectName,
projectRoot: appProjectRoot, projectRoot: appProjectRoot,
skipFormat: true,
}); });
const project = readProjectConfiguration(tree, appProjectName); const project = readProjectConfiguration(tree, appProjectName);

View File

@ -9,7 +9,10 @@ import { appRoutes } from './app.routes';
@NgModule({ @NgModule({
declarations: [AppComponent], declarations: [AppComponent],
imports: [BrowserModule, RouterModule.forRoot(appRoutes)], imports: [
BrowserModule,
RouterModule.forRoot(appRoutes),
],
providers: [], providers: [],
bootstrap: [AppComponent], bootstrap: [AppComponent],
}) })
@ -38,7 +41,7 @@ describe('AppComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [RouterTestingModule], imports: [RouterTestingModule],
declarations: [AppComponent], declarations: [AppComponent]
}).compileComponents(); }).compileComponents();
}); });
@ -55,8 +58,7 @@ describe('AppComponent', () => {
`; `;
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for non-standalone apps with routing 4`] = ` exports[`app --minimal should skip "nx-welcome.component.ts" file and references for non-standalone apps with routing 4`] = `
"<h1>Welcome plain</h1> "<h1>Welcome plain</h1> <router-outlet></router-outlet>
<router-outlet></router-outlet>
" "
`; `;
@ -67,7 +69,9 @@ import { AppComponent } from './app.component';
@NgModule({ @NgModule({
declarations: [AppComponent], declarations: [AppComponent],
imports: [BrowserModule], imports: [
BrowserModule,
],
providers: [], providers: [],
bootstrap: [AppComponent], bootstrap: [AppComponent],
}) })
@ -95,7 +99,7 @@ describe('AppComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [], imports: [],
declarations: [AppComponent], declarations: [AppComponent]
}).compileComponents(); }).compileComponents();
}); });
@ -112,7 +116,7 @@ describe('AppComponent', () => {
`; `;
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for non-standalone apps without routing 4`] = ` exports[`app --minimal should skip "nx-welcome.component.ts" file and references for non-standalone apps without routing 4`] = `
"<h1>Welcome plain</h1> "<h1>Welcome plain</h1>
" "
`; `;
@ -156,8 +160,7 @@ describe('AppComponent', () => {
`; `;
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for standalone apps with routing 3`] = ` exports[`app --minimal should skip "nx-welcome.component.ts" file and references for standalone apps with routing 3`] = `
"<h1>Welcome plain</h1> "<h1>Welcome plain</h1> <router-outlet></router-outlet>
<router-outlet></router-outlet>
" "
`; `;
@ -199,7 +202,7 @@ describe('AppComponent', () => {
`; `;
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for standalone apps without routing 3`] = ` exports[`app --minimal should skip "nx-welcome.component.ts" file and references for standalone apps without routing 3`] = `
"<h1>Welcome plain</h1> "<h1>Welcome plain</h1>
" "
`; `;
@ -670,7 +673,7 @@ import { provideRouter } from '@angular/router';
import { appRoutes } from './app.routes'; import { appRoutes } from './app.routes';
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {
providers: [provideRouter(appRoutes)], providers: [provideRouter(appRoutes) ]
}; };
" "
`; `;
@ -746,7 +749,7 @@ exports[`app --standalone should generate a standalone app correctly without rou
"import { ApplicationConfig } from '@angular/core'; "import { ApplicationConfig } from '@angular/core';
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {
providers: [], providers: []
}; };
" "
`; `;
@ -757,7 +760,7 @@ import { NxWelcomeComponent } from './nx-welcome.component';
@Component({ @Component({
standalone: true, standalone: true,
imports: [NxWelcomeComponent], imports: [NxWelcomeComponent, ],
selector: 'proj-root', selector: 'proj-root',
templateUrl: './app.component.html', templateUrl: './app.component.html',
styleUrl: './app.component.css', styleUrl: './app.component.css',
@ -870,13 +873,84 @@ import { provideRouter } from '@angular/router';
import { appRoutes } from './app.routes'; import { appRoutes } from './app.routes';
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {
providers: [provideRouter(appRoutes)], providers: [provideRouter(appRoutes) ]
}; };
" "
`; `;
exports[`app at the root should accept numbers in the path 1`] = `"src/9-websites/my-app"`; exports[`app at the root should accept numbers in the path 1`] = `"src/9-websites/my-app"`;
exports[`app format files should format files 1`] = `
"import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { appRoutes } from './app.routes';
import { NxWelcomeComponent } from './nx-welcome.component';
@NgModule({
declarations: [AppComponent, NxWelcomeComponent],
imports: [BrowserModule, RouterModule.forRoot(appRoutes)],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
"
`;
exports[`app format files should format files 2`] = `
"import { Component } from '@angular/core';
@Component({
selector: 'proj-root',
templateUrl: './app.component.html',
styleUrl: './app.component.css',
})
export class AppComponent {
title = 'my-app';
}
"
`;
exports[`app format files should format files 3`] = `
"import { TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { NxWelcomeComponent } from './nx-welcome.component';
import { RouterTestingModule } from '@angular/router/testing';
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [RouterTestingModule],
declarations: [AppComponent, NxWelcomeComponent],
}).compileComponents();
});
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain(
'Welcome my-app'
);
});
it(\`should have as title 'my-app'\`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual('my-app');
});
});
"
`;
exports[`app format files should format files 4`] = `
"import { Route } from '@angular/router';
export const appRoutes: Route[] = [];
"
`;
exports[`app nested should create project configs 1`] = ` exports[`app nested should create project configs 1`] = `
{ {
"$schema": "../../node_modules/nx/schemas/project-schema.json", "$schema": "../../node_modules/nx/schemas/project-schema.json",

View File

@ -477,24 +477,25 @@ describe('app', () => {
}); });
}); });
describe('--skipFormat', () => { describe('format files', () => {
it('should format files by default', async () => { it('should format files', async () => {
const spy = jest.spyOn(devkit, 'formatFiles'); const formatFilesSpy = jest.spyOn(devkit, 'formatFiles');
await generateApp(appTree); await generateApp(appTree, 'my-app', { skipFormat: false });
expect(spy).toHaveBeenCalled(); expect(formatFilesSpy).toHaveBeenCalled();
}); expect(
appTree.read('my-app/src/app/app.module.ts', 'utf-8')
// Need a better way of determing if the formatFiles function ).toMatchSnapshot();
// was called directly from the application generator expect(
// and not by a different generator that's used withing this appTree.read('my-app/src/app/app.component.ts', 'utf-8')
xit('should skip format when set to true', async () => { ).toMatchSnapshot();
const spy = jest.spyOn(devkit, 'formatFiles'); expect(
appTree.read('my-app/src/app/app.component.spec.ts', 'utf-8')
await generateApp(appTree, 'my-app', { skipFormat: true }); ).toMatchSnapshot();
expect(
expect(spy).not.toHaveBeenCalled(); appTree.read('my-app/src/app/app.routes.ts', 'utf-8')
).toMatchSnapshot();
}); });
}); });
@ -1182,7 +1183,7 @@ async function generateApp(
) { ) {
await generateTestApplication(appTree, { await generateTestApplication(appTree, {
name, name,
skipFormat: false, skipFormat: true,
e2eTestRunner: E2eTestRunner.Cypress, e2eTestRunner: E2eTestRunner.Cypress,
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
linter: Linter.EsLint, linter: Linter.EsLint,

View File

@ -15,7 +15,9 @@ describe('AppComponent', () => {
const fixture = TestBed.createComponent(AppComponent); const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges(); fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement; const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Welcome <%= appName %>'); expect(compiled.querySelector('h1')?.textContent).toContain(
'Welcome <%= appName %>'
);
});<% if(!minimal) { %> });<% if(!minimal) { %>
it(`should have as title '<%= appName %>'`, () => { it(`should have as title '<%= appName %>'`, () => {

View File

@ -11,10 +11,12 @@ describe('AppComponent', () => {
}); });
it('should render title', () => { it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent); const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges(); fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement; const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Welcome <%= appName %>'); expect(compiled.querySelector('h1')?.textContent).toContain(
'Welcome <%= appName %>'
);
});<% if(!minimal) { %> });<% if(!minimal) { %>
it(`should have as title '<%= appName %>'`, () => { it(`should have as title '<%= appName %>'`, () => {

View File

@ -2,4 +2,6 @@ import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config'; import { appConfig } from './app/app.config';
import { AppComponent } from './app/app.component'; import { AppComponent } from './app/app.component';
bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err)); bootstrapApplication(AppComponent, appConfig).catch((err) =>
console.error(err)
);

View File

@ -7,6 +7,7 @@ exports[`componentCypressSpec generator should generate .spec.ts when using cypr
'/iframe.html?id=testbuttoncomponent--primary&args=buttonType:button;style:default;age;isOn:false;' '/iframe.html?id=testbuttoncomponent--primary&args=buttonType:button;style:default;age;isOn:false;'
) )
); );
it('should render the component', () => { it('should render the component', () => {
cy.get('proj-test-button').should('exist'); cy.get('proj-test-button').should('exist');
}); });
@ -21,6 +22,7 @@ exports[`componentCypressSpec generator should generate the component spec file
'/iframe.html?id=testbuttoncomponent--primary&args=buttonType:button;style:default;age;isOn:false;' '/iframe.html?id=testbuttoncomponent--primary&args=buttonType:button;style:default;age;isOn:false;'
) )
); );
it('should render the component', () => { it('should render the component', () => {
cy.get('proj-test-button').should('exist'); cy.get('proj-test-button').should('exist');
}); });

View File

@ -21,10 +21,11 @@ describe('componentCypressSpec generator', () => {
beforeEach(async () => { beforeEach(async () => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
await generateTestApplication(tree, { name: appName }); await generateTestApplication(tree, { name: appName, skipFormat: true });
await componentGenerator(tree, { await componentGenerator(tree, {
name: 'test-button', name: 'test-button',
project: appName, project: appName,
skipFormat: true,
}); });
tree.write( tree.write(
@ -59,6 +60,7 @@ export class TestButtonComponent {
componentPath: `test-button`, componentPath: `test-button`,
projectPath: `${appName}/src/app`, projectPath: `${appName}/src/app`,
projectName: appName, projectName: appName,
skipFormat: true,
}); });
expect(storybookUtils.getComponentProps).not.toHaveBeenCalled(); expect(storybookUtils.getComponentProps).not.toHaveBeenCalled();
@ -93,6 +95,7 @@ export class TestButtonComponent {
componentPath: `test-button`, componentPath: `test-button`,
projectPath: `${appName}/src/app`, projectPath: `${appName}/src/app`,
projectName: appName, projectName: appName,
skipFormat: true,
}); });
expect(tree.exists(v9SpecFile)).toBe(true); expect(tree.exists(v9SpecFile)).toBe(true);

View File

@ -1,12 +1,17 @@
describe('<%=projectName%>', () => { describe('<%=projectName%>', () => {
beforeEach(() => cy.visit('/iframe.html?id=<%= componentName.toLowerCase() %>--primary<% if ( props && props.length > 0 ) { %>&args=<% } %><% beforeEach(() =>
for(let prop of props) { cy.visit(
%><%=prop.name%><% '/iframe.html?id=<%= componentName.toLowerCase() %>--primary<% if ( props && props.length > 0 ) { %>&args=<% } %><%
if(prop.defaultValue !== undefined && (prop.defaultValue || prop.defaultValue === false)) { for(let prop of props) {
%>:<%=prop.defaultValue%><% %><%=prop.name%><%
} %>;<% if(prop.defaultValue !== undefined && (prop.defaultValue || prop.defaultValue === false)) {
}%>')); %>:<%=prop.defaultValue%><%
} %>;<%
}%>'
)
);
it('should render the component', () => { it('should render the component', () => {
cy.get('<%=componentSelector%>').should('exist'); cy.get('<%=componentSelector%>').should('exist');
}); });
}); });

View File

@ -14,10 +14,11 @@ describe('componentStory generator', () => {
beforeEach(async () => { beforeEach(async () => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
await generateTestLibrary(tree, { name: libName }); await generateTestLibrary(tree, { name: libName, skipFormat: true });
await componentGenerator(tree, { await componentGenerator(tree, {
name: 'test-button', name: 'test-button',
project: libName, project: libName,
skipFormat: true,
}); });
tree.write( tree.write(
@ -53,6 +54,7 @@ describe('componentStory generator', () => {
componentName: 'TestButtonComponent', componentName: 'TestButtonComponent',
componentPath: `src/lib/test-button`, componentPath: `src/lib/test-button`,
projectPath: `${libName}`, projectPath: `${libName}`,
skipFormat: true,
}); });
expect(storybookUtils.getComponentProps).not.toHaveBeenCalled(); expect(storybookUtils.getComponentProps).not.toHaveBeenCalled();
@ -66,6 +68,7 @@ describe('componentStory generator', () => {
componentName: 'TestButtonComponent', componentName: 'TestButtonComponent',
componentPath: `src/lib/test-button`, componentPath: `src/lib/test-button`,
projectPath: `${libName}`, projectPath: `${libName}`,
skipFormat: true,
}); });
expect(tree.exists(storyFile)).toBe(true); expect(tree.exists(storyFile)).toBe(true);

View File

@ -14,14 +14,14 @@ type Story = StoryObj<<%=componentName%>>;
export const Primary: Story = { export const Primary: Story = {
args: {<% for (let prop of props) { %> args: {<% for (let prop of props) { %>
<%= prop.name %>: <%- prop.defaultValue %>,<% } %> <%= prop.name %>: <%- prop.defaultValue %>,<% } %>
}, },
}; };
<% if ( interactionTests ) { %> <% if ( interactionTests ) { %>
export const Heading: Story = { export const Heading: Story = {
args: {<% for (let prop of props) { %> args: {<% for (let prop of props) { %>
<%= prop.name %>: <%- prop.defaultValue %>,<% } %> <%= prop.name %>: <%- prop.defaultValue %>,<% } %>
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const canvas = within(canvasElement); const canvas = within(canvasElement);

View File

@ -5,28 +5,26 @@ exports[`Angular Cypress Component Test Generator should generate a component te
import { MyLibComponent } from './my-lib.component'; import { MyLibComponent } from './my-lib.component';
describe(MyLibComponent.name, () => { describe(MyLibComponent.name, () => {
beforeEach(() => { beforeEach(() => {
TestBed.overrideComponent(MyLibComponent, { TestBed.overrideComponent(MyLibComponent, {
add: { add: {
imports: [], imports: [],
providers: [] providers: [],
} },
}) });
}) });
it('renders', () => { it('renders', () => {
cy.mount(MyLibComponent, { cy.mount(MyLibComponent, {
componentProperties: { componentProperties: {
type: 'button', type: 'button',
style: 'default', style: 'default',
age: 0, age: 0,
isOn: false, isOn: false,
} },
}); });
}) });
});
})
" "
`; `;
@ -35,21 +33,19 @@ exports[`Angular Cypress Component Test Generator should handle component w/o in
import { MyLibComponent } from './my-lib.component'; import { MyLibComponent } from './my-lib.component';
describe(MyLibComponent.name, () => { describe(MyLibComponent.name, () => {
beforeEach(() => { beforeEach(() => {
TestBed.overrideComponent(MyLibComponent, { TestBed.overrideComponent(MyLibComponent, {
add: { add: {
imports: [], imports: [],
providers: [] providers: []
} }
}) });
}) });
it('renders', () => { it('renders', () => {
cy.mount(MyLibComponent,); cy.mount(MyLibComponent);
}) });
});
})
" "
`; `;
@ -58,27 +54,25 @@ exports[`Angular Cypress Component Test Generator should work with standalone co
import { MyLibComponent } from './my-lib.component'; import { MyLibComponent } from './my-lib.component';
describe(MyLibComponent.name, () => { describe(MyLibComponent.name, () => {
beforeEach(() => { beforeEach(() => {
TestBed.overrideComponent(MyLibComponent, { TestBed.overrideComponent(MyLibComponent, {
add: { add: {
imports: [], imports: [],
providers: [] providers: [],
} },
}) });
}) });
it('renders', () => { it('renders', () => {
cy.mount(MyLibComponent, { cy.mount(MyLibComponent, {
componentProperties: { componentProperties: {
type: 'button', type: 'button',
style: 'default', style: 'default',
age: 0, age: 0,
isOn: false, isOn: false,
} },
}); });
}) });
});
})
" "
`; `;

View File

@ -26,16 +26,19 @@ describe('Angular Cypress Component Test Generator', () => {
name: 'my-lib', name: 'my-lib',
unitTestRunner: UnitTestRunner.None, unitTestRunner: UnitTestRunner.None,
linter: Linter.None, linter: Linter.None,
skipFormat: true,
}); });
await componentGenerator(tree, { await componentGenerator(tree, {
project: 'my-lib', project: 'my-lib',
name: 'my-lib', name: 'my-lib',
skipFormat: true,
}); });
componentTestGenerator(tree, { await componentTestGenerator(tree, {
componentName: 'MyLibComponent', componentName: 'MyLibComponent',
componentFileName: './my-lib.component', componentFileName: './my-lib.component',
project: 'my-lib', project: 'my-lib',
componentDir: 'src/lib/my-lib', componentDir: 'src/lib/my-lib',
skipFormat: true,
}); });
expect( expect(
tree.read('my-lib/src/lib/my-lib/my-lib.component.cy.ts', 'utf-8') tree.read('my-lib/src/lib/my-lib/my-lib.component.cy.ts', 'utf-8')
@ -47,10 +50,12 @@ describe('Angular Cypress Component Test Generator', () => {
name: 'my-lib', name: 'my-lib',
unitTestRunner: UnitTestRunner.None, unitTestRunner: UnitTestRunner.None,
linter: Linter.None, linter: Linter.None,
skipFormat: true,
}); });
await componentGenerator(tree, { await componentGenerator(tree, {
project: 'my-lib', project: 'my-lib',
name: 'my-lib', name: 'my-lib',
skipFormat: true,
}); });
tree.write( tree.write(
@ -82,7 +87,7 @@ export class MyLibComponent implements OnInit {
}` }`
); );
componentTestGenerator(tree, { await componentTestGenerator(tree, {
componentName: 'MyLibComponent', componentName: 'MyLibComponent',
componentFileName: './my-lib.component', componentFileName: './my-lib.component',
project: 'my-lib', project: 'my-lib',
@ -99,11 +104,13 @@ export class MyLibComponent implements OnInit {
name: 'my-lib', name: 'my-lib',
unitTestRunner: UnitTestRunner.None, unitTestRunner: UnitTestRunner.None,
linter: Linter.None, linter: Linter.None,
skipFormat: true,
}); });
await componentGenerator(tree, { await componentGenerator(tree, {
project: 'my-lib', project: 'my-lib',
name: 'my-lib', name: 'my-lib',
standalone: true, standalone: true,
skipFormat: true,
}); });
tree.write( tree.write(
'my-lib/src/lib/my-lib/my-lib.component.ts', 'my-lib/src/lib/my-lib/my-lib.component.ts',
@ -134,7 +141,7 @@ export class MyLibComponent implements OnInit {
} }
` `
); );
componentTestGenerator(tree, { await componentTestGenerator(tree, {
componentName: 'MyLibComponent', componentName: 'MyLibComponent',
componentFileName: './my-lib.component', componentFileName: './my-lib.component',
project: 'my-lib', project: 'my-lib',
@ -150,19 +157,25 @@ export class MyLibComponent implements OnInit {
name: 'my-lib', name: 'my-lib',
unitTestRunner: UnitTestRunner.None, unitTestRunner: UnitTestRunner.None,
linter: Linter.None, linter: Linter.None,
skipFormat: true,
}); });
await componentGenerator(tree, { name: 'my-lib', project: 'my-lib' }); await componentGenerator(tree, {
name: 'my-lib',
project: 'my-lib',
skipFormat: true,
});
tree.write( tree.write(
'my-lib/src/lib/my-lib/my-lib.component.cy.ts', 'my-lib/src/lib/my-lib/my-lib.component.cy.ts',
`should not overwrite` `should not overwrite`
); );
componentTestGenerator(tree, { await componentTestGenerator(tree, {
componentName: 'MyLibComponent', componentName: 'MyLibComponent',
componentFileName: './my-lib.component', componentFileName: './my-lib.component',
project: 'my-lib', project: 'my-lib',
componentDir: 'src/lib/my-lib', componentDir: 'src/lib/my-lib',
skipFormat: true,
}); });
expect( expect(
@ -175,46 +188,51 @@ export class MyLibComponent implements OnInit {
name: 'my-lib', name: 'my-lib',
unitTestRunner: UnitTestRunner.None, unitTestRunner: UnitTestRunner.None,
linter: Linter.None, linter: Linter.None,
skipFormat: true,
}); });
await componentGenerator(tree, { name: 'my-lib', project: 'my-lib' }); await componentGenerator(tree, {
name: 'my-lib',
project: 'my-lib',
skipFormat: true,
});
const expected = `import { TestBed } from '@angular/core/testing'; const expected = `import { TestBed } from '@angular/core/testing';
import { MyLibComponent } from './my-lib.component'; import { MyLibComponent } from './my-lib.component';
describe(MyLibComponent.name, () => { describe(MyLibComponent.name, () => {
beforeEach(() => { beforeEach(() => {
TestBed.overrideComponent(MyLibComponent, { TestBed.overrideComponent(MyLibComponent, {
add: { add: {
imports: [], imports: [],
providers: [] providers: []
} }
}) });
}) });
it('renders', () => { it('renders', () => {
cy.mount(MyLibComponent,); cy.mount(MyLibComponent);
}) });
});
})
`; `;
componentTestGenerator(tree, { await componentTestGenerator(tree, {
componentName: 'MyLibComponent', componentName: 'MyLibComponent',
componentFileName: './my-lib.component', componentFileName: './my-lib.component',
project: 'my-lib', project: 'my-lib',
componentDir: 'src/lib/my-lib', componentDir: 'src/lib/my-lib',
skipFormat: true,
}); });
expect( expect(
tree.read('my-lib/src/lib/my-lib/my-lib.component.cy.ts', 'utf-8') tree.read('my-lib/src/lib/my-lib/my-lib.component.cy.ts', 'utf-8')
).toEqual(expected); ).toEqual(expected);
componentTestGenerator(tree, { await componentTestGenerator(tree, {
componentName: 'MyLibComponent', componentName: 'MyLibComponent',
componentFileName: './my-lib.component', componentFileName: './my-lib.component',
project: 'my-lib', project: 'my-lib',
componentDir: 'src/lib/my-lib', componentDir: 'src/lib/my-lib',
skipFormat: true,
}); });
expect( expect(
tree.read('my-lib/src/lib/my-lib/my-lib.component.cy.ts', 'utf-8') tree.read('my-lib/src/lib/my-lib/my-lib.component.cy.ts', 'utf-8')

View File

@ -1,5 +1,6 @@
import { assertMinimumCypressVersion } from '@nx/cypress/src/utils/cypress-version'; import { assertMinimumCypressVersion } from '@nx/cypress/src/utils/cypress-version';
import { import {
formatFiles,
generateFiles, generateFiles,
joinPathFragments, joinPathFragments,
readProjectConfiguration, readProjectConfiguration,
@ -11,7 +12,7 @@ import {
} from '../utils/storybook-ast/storybook-inputs'; } from '../utils/storybook-ast/storybook-inputs';
import { ComponentTestSchema } from './schema'; import { ComponentTestSchema } from './schema';
export function componentTestGenerator( export async function componentTestGenerator(
tree: Tree, tree: Tree,
options: ComponentTestSchema options: ComponentTestSchema
) { ) {
@ -48,6 +49,10 @@ export function componentTestGenerator(
} }
); );
} }
if (!options.skipFormat) {
await formatFiles(tree);
}
} }
export default componentTestGenerator; export default componentTestGenerator;

View File

@ -2,22 +2,20 @@ import { TestBed } from '@angular/core/testing';
import { <%= componentName %> } from './<%= componentFileName %>'; import { <%= componentName %> } from './<%= componentFileName %>';
describe(<%= componentName %>.name, () => { describe(<%= componentName %>.name, () => {
beforeEach(() => { beforeEach(() => {
TestBed.overrideComponent(<%= componentName %>, { TestBed.overrideComponent(<%= componentName %>, {
add: { add: {
imports: [], imports: [],
providers: [] providers: []
} }
}) });
}) });
it('renders', () => { it('renders', () => {
cy.mount(<%= componentName %>,<% if(props.length > 0) { %> { cy.mount(<%= componentName %><% if(props.length > 0) { %>, {
componentProperties: {<% for (let prop of props) { %> componentProperties: {<% for (let prop of props) { %>
<%= prop.name %>: <%- prop.defaultValue %>,<% } %> <%= prop.name %>: <%- prop.defaultValue %>,<% } %>
} }
}<% } %>); }<% } %>);
}) });
});
})

View File

@ -6,7 +6,7 @@ exports[`component Generator --flat should create the component correctly and ex
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.component.html', templateUrl: './example.component.html',
styleUrl: './example.component.css', styleUrl: './example.component.css'
}) })
export class ExampleComponent {} export class ExampleComponent {}
" "
@ -18,19 +18,20 @@ exports[`component Generator --flat should create the component correctly and no
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.component.html', templateUrl: './example.component.html',
styleUrl: './example.component.css', styleUrl: './example.component.css'
}) })
export class ExampleComponent {} export class ExampleComponent {}
" "
`; `;
exports[`component Generator --module should import the component correctly to the module file when flat is false 1`] = ` exports[`component Generator --module should import the component correctly to the module file when flat is false 1`] = `
"import { NgModule } from '@angular/core'; "
import { NgModule } from '@angular/core';
import { ExampleComponent } from './example/example.component'; import { ExampleComponent } from './example/example.component';
@NgModule({ @NgModule({
declarations: [ExampleComponent], declarations: [ExampleComponent],
exports: [ExampleComponent], exports: [ExampleComponent]
}) })
export class LibModule {} export class LibModule {}
" "
@ -42,7 +43,7 @@ exports[`component Generator --path should create the component correctly and ex
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.component.html', templateUrl: './example.component.html',
styleUrl: './example.component.css', styleUrl: './example.component.css'
}) })
export class ExampleComponent {} export class ExampleComponent {}
" "
@ -54,7 +55,7 @@ exports[`component Generator compat should inline styles when --inline-style=tru
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.component.html', templateUrl: './example.component.html',
styles: \`\`, styles: \`\`
}) })
export class ExampleComponent {} export class ExampleComponent {}
" "
@ -66,7 +67,7 @@ exports[`component Generator secondary entry points should create the component
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.component.html', templateUrl: './example.component.html',
styleUrl: './example.component.css', styleUrl: './example.component.css'
}) })
export class ExampleComponent {} export class ExampleComponent {}
" "
@ -74,8 +75,7 @@ export class ExampleComponent {}
exports[`component Generator secondary entry points should create the component correctly and export it in the entry point 2`] = ` exports[`component Generator secondary entry points should create the component correctly and export it in the entry point 2`] = `
"export * from './lib/secondary.module'; "export * from './lib/secondary.module';
export * from './lib/example/example.component'; export * from './lib/example/example.component';"
"
`; `;
exports[`component Generator should create component files correctly: component 1`] = ` exports[`component Generator should create component files correctly: component 1`] = `
@ -133,7 +133,7 @@ exports[`component Generator should create the component correctly and export it
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.component.html', templateUrl: './example.component.html',
styleUrl: './example.component.css', styleUrl: './example.component.css'
}) })
export class ExampleComponent {} export class ExampleComponent {}
" "
@ -141,8 +141,7 @@ export class ExampleComponent {}
exports[`component Generator should create the component correctly and export it in the entry point when "export=true" 2`] = ` exports[`component Generator should create the component correctly and export it in the entry point when "export=true" 2`] = `
"export * from './lib/lib.module'; "export * from './lib/lib.module';
export * from './lib/example/example.component'; export * from './lib/example/example.component';"
"
`; `;
exports[`component Generator should create the component correctly and export it in the entry point when is standalone and "export=true" 1`] = ` exports[`component Generator should create the component correctly and export it in the entry point when is standalone and "export=true" 1`] = `
@ -154,7 +153,7 @@ import { CommonModule } from '@angular/common';
standalone: true, standalone: true,
imports: [CommonModule], imports: [CommonModule],
templateUrl: './example.component.html', templateUrl: './example.component.html',
styleUrl: './example.component.css', styleUrl: './example.component.css'
}) })
export class ExampleComponent {} export class ExampleComponent {}
" "
@ -166,7 +165,7 @@ exports[`component Generator should create the component correctly and not expor
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.component.html', templateUrl: './example.component.html',
styleUrl: './example.component.css', styleUrl: './example.component.css'
}) })
export class ExampleComponent {} export class ExampleComponent {}
" "
@ -181,7 +180,7 @@ import { CommonModule } from '@angular/common';
standalone: true, standalone: true,
imports: [CommonModule], imports: [CommonModule],
templateUrl: './example.component.html', templateUrl: './example.component.html',
styleUrl: './example.component.css', styleUrl: './example.component.css'
}) })
export class ExampleComponent {} export class ExampleComponent {}
" "
@ -193,7 +192,7 @@ exports[`component Generator should create the component correctly and not expor
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.component.html', templateUrl: './example.component.html',
styleUrl: './example.component.css', styleUrl: './example.component.css'
}) })
export class ExampleComponent {} export class ExampleComponent {}
" "
@ -205,7 +204,7 @@ exports[`component Generator should create the component correctly but not expor
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.component.html', templateUrl: './example.component.html',
styleUrl: './example.component.css', styleUrl: './example.component.css'
}) })
export class ExampleComponent {} export class ExampleComponent {}
" "
@ -217,7 +216,7 @@ exports[`component Generator should inline styles when --inline-style=true 1`] =
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.component.html', templateUrl: './example.component.html',
styles: \`\`, styles: \`\`
}) })
export class ExampleComponent {} export class ExampleComponent {}
" "
@ -229,7 +228,7 @@ exports[`component Generator should inline template when --inline-template=true
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
template: \`<p>example works!</p>\`, template: \`<p>example works!</p>\`,
styleUrl: './example.component.css', styleUrl: './example.component.css'
}) })
export class ExampleComponent {} export class ExampleComponent {}
" "

View File

@ -22,7 +22,7 @@ describe('component Generator', () => {
}) })
export class LibModule {}` export class LibModule {}`
); );
tree.write('libs/lib1/src/index.ts', 'export * from "./lib/lib.module";'); tree.write('libs/lib1/src/index.ts', `export * from './lib/lib.module';`);
// ACT // ACT
await componentGenerator(tree, { await componentGenerator(tree, {
@ -76,6 +76,7 @@ describe('component Generator', () => {
project: 'lib1', project: 'lib1',
skipTests: true, skipTests: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -111,6 +112,7 @@ describe('component Generator', () => {
project: 'lib1', project: 'lib1',
inlineTemplate: true, inlineTemplate: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -149,6 +151,7 @@ describe('component Generator', () => {
project: 'lib1', project: 'lib1',
inlineStyle: true, inlineStyle: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -187,6 +190,7 @@ describe('component Generator', () => {
project: 'lib1', project: 'lib1',
style: 'none', style: 'none',
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -199,7 +203,7 @@ describe('component Generator', () => {
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.component.html', templateUrl: './example.component.html'
}) })
export class ExampleComponent {} export class ExampleComponent {}
" "
@ -225,7 +229,7 @@ describe('component Generator', () => {
}) })
export class LibModule {}` export class LibModule {}`
); );
tree.write('libs/lib1/src/index.ts', 'export * from "./lib/lib.module";'); tree.write('libs/lib1/src/index.ts', `export * from './lib/lib.module';`);
// ACT // ACT
await componentGenerator(tree, { await componentGenerator(tree, {
@ -233,6 +237,7 @@ describe('component Generator', () => {
project: 'lib1', project: 'lib1',
export: true, export: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -272,6 +277,7 @@ describe('component Generator', () => {
name: 'example', name: 'example',
project: 'lib1', project: 'lib1',
export: true, export: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -282,10 +288,9 @@ describe('component Generator', () => {
expect(componentSource).toMatchSnapshot(); expect(componentSource).toMatchSnapshot();
const indexSource = tree.read('libs/lib1/src/index.ts', 'utf-8'); const indexSource = tree.read('libs/lib1/src/index.ts', 'utf-8');
expect(indexSource).toMatchInlineSnapshot(` expect(indexSource).toMatchInlineSnapshot(
"export * from './lib/example/example.component'; `"export * from './lib/example/example.component';"`
" );
`);
}); });
it('should create the component correctly and not export it in the entry point when "export=false"', async () => { it('should create the component correctly and not export it in the entry point when "export=false"', async () => {
@ -307,7 +312,7 @@ describe('component Generator', () => {
}) })
export class LibModule {}` export class LibModule {}`
); );
tree.write('libs/lib1/src/index.ts', 'export * from "./lib/lib.module";'); tree.write('libs/lib1/src/index.ts', `export * from './lib/lib.module';`);
// ACT // ACT
await componentGenerator(tree, { await componentGenerator(tree, {
@ -315,6 +320,7 @@ describe('component Generator', () => {
project: 'lib1', project: 'lib1',
export: false, export: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -349,13 +355,14 @@ describe('component Generator', () => {
}) })
export class LibModule {}` export class LibModule {}`
); );
tree.write('libs/lib1/src/index.ts', 'export * from "./lib/lib.module";'); tree.write('libs/lib1/src/index.ts', `export * from './lib/lib.module';`);
// ACT // ACT
await componentGenerator(tree, { await componentGenerator(tree, {
name: 'example', name: 'example',
project: 'lib1', project: 'lib1',
export: false, export: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -390,7 +397,7 @@ describe('component Generator', () => {
}) })
export class LibModule {}` export class LibModule {}`
); );
tree.write('libs/lib1/src/index.ts', 'export * from "./lib/lib.module";'); tree.write('libs/lib1/src/index.ts', `export * from './lib/lib.module';`);
// ACT // ACT
await componentGenerator(tree, { await componentGenerator(tree, {
@ -398,6 +405,7 @@ describe('component Generator', () => {
project: 'lib1', project: 'lib1',
skipImport: true, skipImport: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -439,6 +447,7 @@ describe('component Generator', () => {
project: 'lib1', project: 'lib1',
export: true, export: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -479,6 +488,7 @@ describe('component Generator', () => {
project: 'lib1', project: 'lib1',
export: true, export: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -506,7 +516,7 @@ describe('component Generator', () => {
}) })
export class LibModule {}` export class LibModule {}`
); );
tree.write('libs/lib1/src/index.ts', 'export * from "./lib/lib.module";'); tree.write('libs/lib1/src/index.ts', `export * from './lib/lib.module';`);
// ACT // ACT
await componentGenerator(tree, { await componentGenerator(tree, {
@ -515,6 +525,7 @@ describe('component Generator', () => {
flat: true, flat: true,
export: true, export: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -547,7 +558,7 @@ describe('component Generator', () => {
}) })
export class LibModule {}` export class LibModule {}`
); );
tree.write('libs/lib1/src/index.ts', 'export * from "./lib/lib.module";'); tree.write('libs/lib1/src/index.ts', `export * from './lib/lib.module';`);
// ACT // ACT
await componentGenerator(tree, { await componentGenerator(tree, {
@ -556,6 +567,7 @@ describe('component Generator', () => {
flat: true, flat: true,
export: false, export: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -592,7 +604,7 @@ describe('component Generator', () => {
}) })
export class LibModule {}` export class LibModule {}`
); );
tree.write('libs/lib1/src/index.ts', 'export * from "./lib/lib.module";'); tree.write('libs/lib1/src/index.ts', `export * from './lib/lib.module';`);
// ACT // ACT
await componentGenerator(tree, { await componentGenerator(tree, {
@ -601,6 +613,7 @@ describe('component Generator', () => {
path: 'libs/lib1/src/lib/mycomp', path: 'libs/lib1/src/lib/mycomp',
export: true, export: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -635,7 +648,7 @@ describe('component Generator', () => {
}) })
export class LibModule {}` export class LibModule {}`
); );
tree.write('libs/lib1/src/index.ts', 'export * from "./lib/lib.module";'); tree.write('libs/lib1/src/index.ts', `export * from './lib/lib.module';`);
// ACT & ASSERT // ACT & ASSERT
await expect( await expect(
@ -645,6 +658,7 @@ describe('component Generator', () => {
path: 'apps/app1/src/mycomp', path: 'apps/app1/src/mycomp',
export: false, export: false,
standalone: false, standalone: false,
skipFormat: true,
}) })
).rejects.toThrow(); ).rejects.toThrow();
}); });
@ -681,7 +695,7 @@ describe('component Generator', () => {
); );
tree.write( tree.write(
'libs/lib1/src/index.ts', 'libs/lib1/src/index.ts',
'export * from "./lib/lib.module";' `export * from './lib/lib.module';`
); );
// ACT // ACT
@ -691,6 +705,7 @@ describe('component Generator', () => {
module, module,
export: true, export: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -712,17 +727,18 @@ describe('component Generator', () => {
tree.write( tree.write(
'libs/shared/ui/src/lib/lib.module.ts', 'libs/shared/ui/src/lib/lib.module.ts',
` `
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
@NgModule({ @NgModule({
declarations: [], declarations: [],
exports: [] exports: []
}) })
export class LibModule {}` export class LibModule {}
`
); );
tree.write( tree.write(
'libs/shared/ui/src/index.ts', 'libs/shared/ui/src/index.ts',
'export * from "./lib/lib.module";' `export * from './lib/lib.module';`
); );
// ACT // ACT
@ -732,6 +748,7 @@ describe('component Generator', () => {
export: true, export: true,
flat: false, flat: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -772,7 +789,7 @@ describe('component Generator', () => {
}) })
export class NotExportedModule {}` export class NotExportedModule {}`
); );
tree.write('libs/lib1/src/index.ts', 'export * from "./lib/lib.module";'); tree.write('libs/lib1/src/index.ts', `export * from './lib/lib.module';`);
// ACT // ACT
await componentGenerator(tree, { await componentGenerator(tree, {
@ -781,14 +798,14 @@ describe('component Generator', () => {
module: 'not-exported', module: 'not-exported',
export: true, export: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
const indexSource = tree.read('libs/lib1/src/index.ts', 'utf-8'); const indexSource = tree.read('libs/lib1/src/index.ts', 'utf-8');
expect(indexSource).toMatchInlineSnapshot(` expect(indexSource).toMatchInlineSnapshot(
"export * from './lib/lib.module'; `"export * from './lib/lib.module';"`
" );
`);
}); });
it('should throw an error when the module is not found', async () => { it('should throw an error when the module is not found', async () => {
@ -819,6 +836,7 @@ describe('component Generator', () => {
path: 'libs/lib1/src/lib', path: 'libs/lib1/src/lib',
module: 'not-found', module: 'not-found',
standalone: false, standalone: false,
skipFormat: true,
}) })
).rejects.toThrow(); ).rejects.toThrow();
}); });
@ -861,6 +879,7 @@ describe('component Generator', () => {
project: 'lib1', project: 'lib1',
path: 'libs/lib1/src/lib', path: 'libs/lib1/src/lib',
standalone: false, standalone: false,
skipFormat: true,
}) })
).rejects.toThrow(); ).rejects.toThrow();
}); });
@ -886,7 +905,7 @@ describe('component Generator', () => {
}) })
export class LibModule {}` export class LibModule {}`
); );
tree.write('libs/lib1/src/index.ts', 'export * from "./lib/lib.module";'); tree.write('libs/lib1/src/index.ts', `export * from './lib/lib.module';`);
// secondary entry point // secondary entry point
writeJson(tree, 'libs/lib1/secondary/ng-package.json', { writeJson(tree, 'libs/lib1/secondary/ng-package.json', {
@ -894,7 +913,7 @@ describe('component Generator', () => {
}); });
tree.write( tree.write(
'libs/lib1/secondary/src/index.ts', 'libs/lib1/secondary/src/index.ts',
'export * from "./lib/secondary.module";' `export * from './lib/secondary.module';`
); );
tree.write( tree.write(
'libs/lib1/secondary/src/lib/secondary.module.ts', 'libs/lib1/secondary/src/lib/secondary.module.ts',
@ -915,6 +934,7 @@ describe('component Generator', () => {
path: 'libs/lib1/secondary/src/lib', path: 'libs/lib1/secondary/src/lib',
export: true, export: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -950,7 +970,7 @@ describe('component Generator', () => {
}) })
export class LibModule {}` export class LibModule {}`
); );
tree.write('libs/lib1/src/index.ts', 'export * from "./lib/lib.module";'); tree.write('libs/lib1/src/index.ts', `export * from './lib/lib.module';`);
// secondary entry point // secondary entry point
writeJson(tree, 'libs/lib1/secondary/ng-package.json', { writeJson(tree, 'libs/lib1/secondary/ng-package.json', {
@ -975,6 +995,7 @@ describe('component Generator', () => {
project: 'lib1', project: 'lib1',
export: true, export: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -1012,6 +1033,7 @@ describe('component Generator', () => {
project: 'lib1', project: 'lib1',
inlineStyle: true, inlineStyle: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
expect( expect(

View File

@ -7,9 +7,8 @@ describe('<%= symbolName %>', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
<%= standalone ? 'imports' : 'declarations' %>: [ <%= symbolName %> ] <%= standalone ? 'imports' : 'declarations' %>: [<%= symbolName %>]
}) }).compileComponents();
.compileComponents();
fixture = TestBed.createComponent(<%= symbolName %>); fixture = TestBed.createComponent(<%= symbolName %>);
component = fixture.componentInstance; component = fixture.componentInstance;

View File

@ -54,7 +54,7 @@ export function exportComponentInEntryPoint(
entryPointPath, entryPointPath,
'utf-8' 'utf-8'
)} )}
export * from "${relativePathFromEntryPoint}";`; export * from '${relativePathFromEntryPoint}';`;
tree.write(entryPointPath, updateEntryPointContent); tree.write(entryPointPath, updateEntryPointContent);
} }

View File

@ -65,6 +65,7 @@ describe('convertToWithMF', () => {
// ACT // ACT
await convertToWithMF(tree, { await convertToWithMF(tree, {
project: 'remote1', project: 'remote1',
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -96,6 +97,7 @@ describe('convertToWithMF', () => {
// ACT // ACT
await convertToWithMF(tree, { await convertToWithMF(tree, {
project: 'remote1', project: 'remote1',
skipFormat: true,
}); });
// ASSERT // ASSERT

View File

@ -58,7 +58,9 @@ export async function convertToWithMF(tree: Tree, schema: Schema) {
mfConfig mfConfig
); );
await formatFiles(tree); if (!schema.skipFormat) {
await formatFiles(tree);
}
} }
export default convertToWithMF; export default convertToWithMF;

View File

@ -3,8 +3,9 @@
exports[`writeNewWebpackConfig should convert config that is both remote and host correctly 1`] = ` exports[`writeNewWebpackConfig should convert config that is both remote and host correctly 1`] = `
[ [
"const { withModuleFederation } = require('@nx/angular/module-federation'); "const { withModuleFederation } = require('@nx/angular/module-federation');
const config = require('./module-federation.config'); const config = require('./module-federation.config');
module.exports = withModuleFederation(config);", module.exports = withModuleFederation(config);
",
" "
module.exports = { module.exports = {
name: 'both1', name: 'both1',
@ -19,8 +20,9 @@ exports[`writeNewWebpackConfig should convert config that is both remote and hos
exports[`writeNewWebpackConfig should convert config that is neither remote and host correctly 1`] = ` exports[`writeNewWebpackConfig should convert config that is neither remote and host correctly 1`] = `
[ [
"const { withModuleFederation } = require('@nx/angular/module-federation'); "const { withModuleFederation } = require('@nx/angular/module-federation');
const config = require('./module-federation.config'); const config = require('./module-federation.config');
module.exports = withModuleFederation(config);", module.exports = withModuleFederation(config);
",
" "
module.exports = { module.exports = {
name: 'neither', name: 'neither',
@ -31,8 +33,9 @@ exports[`writeNewWebpackConfig should convert config that is neither remote and
exports[`writeNewWebpackConfig should convert host config correctly 1`] = ` exports[`writeNewWebpackConfig should convert host config correctly 1`] = `
[ [
"const { withModuleFederation } = require('@nx/angular/module-federation'); "const { withModuleFederation } = require('@nx/angular/module-federation');
const config = require('./module-federation.config'); const config = require('./module-federation.config');
module.exports = withModuleFederation(config);", module.exports = withModuleFederation(config);
",
" "
module.exports = { module.exports = {
name: 'host1', name: 'host1',
@ -44,8 +47,9 @@ exports[`writeNewWebpackConfig should convert host config correctly 1`] = `
exports[`writeNewWebpackConfig should convert remote config correctly 1`] = ` exports[`writeNewWebpackConfig should convert remote config correctly 1`] = `
[ [
"const { withModuleFederation } = require('@nx/angular/module-federation'); "const { withModuleFederation } = require('@nx/angular/module-federation');
const config = require('./module-federation.config'); const config = require('./module-federation.config');
module.exports = withModuleFederation(config);", module.exports = withModuleFederation(config);
",
" "
module.exports = { module.exports = {
name: 'remote1', name: 'remote1',

View File

@ -11,8 +11,9 @@ export function writeNewWebpackConfig(
projectName: string projectName: string
) { ) {
const webpackConfig = `const { withModuleFederation } = require('@nx/angular/module-federation'); const webpackConfig = `const { withModuleFederation } = require('@nx/angular/module-federation');
const config = require('./module-federation.config'); const config = require('./module-federation.config');
module.exports = withModuleFederation(config);`; module.exports = withModuleFederation(config);
`;
let mfeConfig = ''; let mfeConfig = '';
if (!mfType) { if (!mfType) {

View File

@ -1,3 +1,4 @@
export interface Schema { export interface Schema {
project: string; project: string;
skipFormat?: boolean;
} }

View File

@ -22,6 +22,12 @@
}, },
"x-prompt": "What micro frontend project would you like to migrate?", "x-prompt": "What micro frontend project would you like to migrate?",
"x-priority": "important" "x-priority": "important"
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
"default": false,
"x-priority": "internal"
} }
} }
} }

View File

@ -22,17 +22,17 @@ import './commands';
// add component testing only related command here, such as mount // add component testing only related command here, such as mount
declare global { declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace // eslint-disable-next-line @typescript-eslint/no-namespace
namespace Cypress { namespace Cypress {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Chainable<Subject> { interface Chainable<Subject> {
mount: typeof mount; mount: typeof mount;
} }
} }
} }
Cypress.Commands.add('mount', mount); Cypress.Commands.add('mount', mount);"
"
`; `;
exports[`Cypress Component Testing Configuration should work with complex component 1`] = ` exports[`Cypress Component Testing Configuration should work with complex component 1`] = `
@ -44,8 +44,8 @@ describe(SomethingOneComponent.name, () => {
TestBed.overrideComponent(SomethingOneComponent, { TestBed.overrideComponent(SomethingOneComponent, {
add: { add: {
imports: [], imports: [],
providers: [], providers: []
}, }
}); });
}); });
@ -65,8 +65,8 @@ describe(SomethingTwoComponent.name, () => {
TestBed.overrideComponent(SomethingTwoComponent, { TestBed.overrideComponent(SomethingTwoComponent, {
add: { add: {
imports: [], imports: [],
providers: [], providers: []
}, }
}); });
}); });
@ -86,8 +86,8 @@ describe(SomethingThreeComponent.name, () => {
TestBed.overrideComponent(SomethingThreeComponent, { TestBed.overrideComponent(SomethingThreeComponent, {
add: { add: {
imports: [], imports: [],
providers: [], providers: []
}, }
}); });
}); });
@ -170,8 +170,8 @@ describe(FancyButtonComponent.name, () => {
TestBed.overrideComponent(FancyButtonComponent, { TestBed.overrideComponent(FancyButtonComponent, {
add: { add: {
imports: [], imports: [],
providers: [], providers: []
}, }
}); });
}); });
@ -191,8 +191,8 @@ describe(StandaloneFancyButtonComponent.name, () => {
TestBed.overrideComponent(StandaloneFancyButtonComponent, { TestBed.overrideComponent(StandaloneFancyButtonComponent, {
add: { add: {
imports: [], imports: [],
providers: [], providers: []
}, }
}); });
}); });
@ -212,8 +212,8 @@ describe(SomethingOneComponent.name, () => {
TestBed.overrideComponent(SomethingOneComponent, { TestBed.overrideComponent(SomethingOneComponent, {
add: { add: {
imports: [], imports: [],
providers: [], providers: []
}, }
}); });
}); });
@ -233,8 +233,8 @@ describe(SomethingTwoComponent.name, () => {
TestBed.overrideComponent(SomethingTwoComponent, { TestBed.overrideComponent(SomethingTwoComponent, {
add: { add: {
imports: [], imports: [],
providers: [], providers: []
}, }
}); });
}); });
@ -254,8 +254,8 @@ describe(SomethingThreeComponent.name, () => {
TestBed.overrideComponent(SomethingThreeComponent, { TestBed.overrideComponent(SomethingThreeComponent, {
add: { add: {
imports: [], imports: [],
providers: [], providers: []
}, }
}); });
}); });

View File

@ -47,14 +47,17 @@ describe('Cypress Component Testing Configuration', () => {
it('should add project config with --target=<project>:<target>', async () => { it('should add project config with --target=<project>:<target>', async () => {
await generateTestApplication(tree, { await generateTestApplication(tree, {
name: 'fancy-app', name: 'fancy-app',
skipFormat: true,
}); });
await generateTestLibrary(tree, { await generateTestLibrary(tree, {
name: 'fancy-lib', name: 'fancy-lib',
skipFormat: true,
}); });
await componentGenerator(tree, { await componentGenerator(tree, {
name: 'fancy-cmp', name: 'fancy-cmp',
project: 'fancy-lib', project: 'fancy-lib',
export: true, export: true,
skipFormat: true,
}); });
projectGraph = { projectGraph = {
nodes: { nodes: {
@ -83,11 +86,14 @@ describe('Cypress Component Testing Configuration', () => {
], ],
}, },
}; };
await cypressComponentConfiguration(tree, { await cypressComponentConfiguration(tree, {
project: 'fancy-lib', project: 'fancy-lib',
buildTarget: 'fancy-app:build', buildTarget: 'fancy-app:build',
generateTests: false, generateTests: false,
skipFormat: true,
}); });
expect( expect(
tree.exists('fancy-lib/src/lib/fancy-cmp/fancy-cmp.component.cy.ts') tree.exists('fancy-lib/src/lib/fancy-cmp/fancy-cmp.component.cy.ts')
).toBeFalsy(); ).toBeFalsy();
@ -107,14 +113,17 @@ describe('Cypress Component Testing Configuration', () => {
it('should add project config with --target=<project>:<target>:<config>', async () => { it('should add project config with --target=<project>:<target>:<config>', async () => {
await generateTestApplication(tree, { await generateTestApplication(tree, {
name: 'fancy-app', name: 'fancy-app',
skipFormat: true,
}); });
await generateTestLibrary(tree, { await generateTestLibrary(tree, {
name: 'fancy-lib', name: 'fancy-lib',
skipFormat: true,
}); });
await componentGenerator(tree, { await componentGenerator(tree, {
name: 'fancy-cmp', name: 'fancy-cmp',
project: 'fancy-lib', project: 'fancy-lib',
export: true, export: true,
skipFormat: true,
}); });
projectGraph = { projectGraph = {
nodes: { nodes: {
@ -143,11 +152,14 @@ describe('Cypress Component Testing Configuration', () => {
], ],
}, },
}; };
await cypressComponentConfiguration(tree, { await cypressComponentConfiguration(tree, {
project: 'fancy-lib', project: 'fancy-lib',
buildTarget: 'fancy-app:build:development', buildTarget: 'fancy-app:build:development',
generateTests: false, generateTests: false,
skipFormat: true,
}); });
expect( expect(
tree.exists('fancy-lib/src/lib/fancy-cmp/fancy-cmp.component.cy.ts') tree.exists('fancy-lib/src/lib/fancy-cmp/fancy-cmp.component.cy.ts')
).toBeFalsy(); ).toBeFalsy();
@ -167,14 +179,17 @@ describe('Cypress Component Testing Configuration', () => {
it('should not throw with invalid --build-target', async () => { it('should not throw with invalid --build-target', async () => {
await generateTestApplication(tree, { await generateTestApplication(tree, {
name: 'fancy-app', name: 'fancy-app',
skipFormat: true,
}); });
await generateTestLibrary(tree, { await generateTestLibrary(tree, {
name: 'fancy-lib', name: 'fancy-lib',
skipFormat: true,
}); });
await componentGenerator(tree, { await componentGenerator(tree, {
name: 'fancy-cmp', name: 'fancy-cmp',
project: 'fancy-lib', project: 'fancy-lib',
export: true, export: true,
skipFormat: true,
}); });
const appConfig = readProjectConfiguration(tree, 'fancy-app'); const appConfig = readProjectConfiguration(tree, 'fancy-app');
appConfig.targets['build'].executor = 'something/else'; appConfig.targets['build'].executor = 'something/else';
@ -206,23 +221,28 @@ describe('Cypress Component Testing Configuration', () => {
], ],
}, },
}; };
await expect(async () => { await expect(async () => {
await cypressComponentConfiguration(tree, { await cypressComponentConfiguration(tree, {
project: 'fancy-lib', project: 'fancy-lib',
buildTarget: 'fancy-app:build', buildTarget: 'fancy-app:build',
generateTests: false, generateTests: false,
skipFormat: true,
}); });
}).resolves; }).resolves;
}); });
it('should use own project config', async () => { it('should use own project config', async () => {
await generateTestApplication(tree, { await generateTestApplication(tree, {
name: 'fancy-app', name: 'fancy-app',
bundler: 'webpack', bundler: 'webpack',
skipFormat: true,
}); });
await componentGenerator(tree, { await componentGenerator(tree, {
name: 'fancy-cmp', name: 'fancy-cmp',
project: 'fancy-app', project: 'fancy-app',
export: true, export: true,
skipFormat: true,
}); });
projectGraph = { projectGraph = {
nodes: { nodes: {
@ -236,10 +256,13 @@ describe('Cypress Component Testing Configuration', () => {
}, },
dependencies: {}, dependencies: {},
}; };
await cypressComponentConfiguration(tree, { await cypressComponentConfiguration(tree, {
project: 'fancy-app', project: 'fancy-app',
generateTests: false, generateTests: false,
skipFormat: true,
}); });
expect( expect(
readProjectConfiguration(tree, 'fancy-app').targets['component-test'] readProjectConfiguration(tree, 'fancy-app').targets['component-test']
).toEqual({ ).toEqual({
@ -257,14 +280,17 @@ describe('Cypress Component Testing Configuration', () => {
await generateTestApplication(tree, { await generateTestApplication(tree, {
name: 'fancy-app', name: 'fancy-app',
bundler: 'webpack', bundler: 'webpack',
skipFormat: true,
}); });
await generateTestLibrary(tree, { await generateTestLibrary(tree, {
name: 'fancy-lib', name: 'fancy-lib',
skipFormat: true,
}); });
await componentGenerator(tree, { await componentGenerator(tree, {
name: 'fancy-cmp', name: 'fancy-cmp',
project: 'fancy-lib', project: 'fancy-lib',
export: true, export: true,
skipFormat: true,
}); });
tree.write( tree.write(
'fancy-app/src/app/blah.component.ts', 'fancy-app/src/app/blah.component.ts',
@ -297,10 +323,13 @@ describe('Cypress Component Testing Configuration', () => {
], ],
}, },
}; };
await cypressComponentConfiguration(tree, { await cypressComponentConfiguration(tree, {
project: 'fancy-lib', project: 'fancy-lib',
generateTests: false, generateTests: false,
skipFormat: true,
}); });
expect( expect(
readProjectConfiguration(tree, 'fancy-lib').targets['component-test'] readProjectConfiguration(tree, 'fancy-lib').targets['component-test']
).toEqual({ ).toEqual({
@ -314,11 +343,12 @@ describe('Cypress Component Testing Configuration', () => {
}); });
}); });
}); });
it('should setup angular specific configs', async () => { it('should setup angular specific configs', async () => {
await generateTestLibrary(tree, { await generateTestLibrary(tree, {
name: 'my-lib', name: 'my-lib',
skipFormat: true,
}); });
await setup(tree, { await setup(tree, {
project: 'my-lib', project: 'my-lib',
name: 'something', name: 'something',
@ -351,10 +381,12 @@ describe('Cypress Component Testing Configuration', () => {
], ],
}, },
}; };
await cypressComponentConfiguration(tree, { await cypressComponentConfiguration(tree, {
project: 'my-lib', project: 'my-lib',
buildTarget: 'something:build', buildTarget: 'something:build',
generateTests: true, generateTests: true,
skipFormat: true,
}); });
expect(tree.read('my-lib/cypress.config.ts', 'utf-8')) expect(tree.read('my-lib/cypress.config.ts', 'utf-8'))
@ -363,7 +395,7 @@ describe('Cypress Component Testing Configuration', () => {
import { defineConfig } from 'cypress'; import { defineConfig } from 'cypress';
export default defineConfig({ export default defineConfig({
component: nxComponentTestingPreset(__filename), component: nxComponentTestingPreset(__filename)
}); });
" "
`); `);
@ -371,11 +403,12 @@ describe('Cypress Component Testing Configuration', () => {
tree.read('my-lib/cypress/support/component.ts', 'utf-8') tree.read('my-lib/cypress/support/component.ts', 'utf-8')
).toMatchSnapshot('component.ts'); ).toMatchSnapshot('component.ts');
}); });
it('should work with simple components', async () => { it('should work with simple components', async () => {
await generateTestLibrary(tree, { await generateTestLibrary(tree, {
name: 'my-lib', name: 'my-lib',
skipFormat: true,
}); });
await setup(tree, { await setup(tree, {
project: 'my-lib', project: 'my-lib',
name: 'something', name: 'something',
@ -408,10 +441,12 @@ describe('Cypress Component Testing Configuration', () => {
], ],
}, },
}; };
await cypressComponentConfiguration(tree, { await cypressComponentConfiguration(tree, {
project: 'my-lib', project: 'my-lib',
buildTarget: 'something:build', buildTarget: 'something:build',
generateTests: true, generateTests: true,
skipFormat: true,
}); });
const [one, two, three] = getCmpsFromTree(tree, { const [one, two, three] = getCmpsFromTree(tree, {
@ -426,8 +461,8 @@ describe('Cypress Component Testing Configuration', () => {
it('should work with standalone component', async () => { it('should work with standalone component', async () => {
await generateTestLibrary(tree, { await generateTestLibrary(tree, {
name: 'my-lib-standalone', name: 'my-lib-standalone',
skipFormat: true,
}); });
await setup(tree, { await setup(tree, {
project: 'my-lib-standalone', project: 'my-lib-standalone',
name: 'something', name: 'something',
@ -460,6 +495,7 @@ describe('Cypress Component Testing Configuration', () => {
], ],
}, },
}; };
await cypressComponentConfiguration(tree, { await cypressComponentConfiguration(tree, {
project: 'my-lib-standalone', project: 'my-lib-standalone',
buildTarget: 'something:build', buildTarget: 'something:build',
@ -478,8 +514,8 @@ describe('Cypress Component Testing Configuration', () => {
it('should work with complex component', async () => { it('should work with complex component', async () => {
await generateTestLibrary(tree, { await generateTestLibrary(tree, {
name: 'with-inputs-cmp', name: 'with-inputs-cmp',
skipFormat: true,
}); });
await setup(tree, { await setup(tree, {
project: 'with-inputs-cmp', project: 'with-inputs-cmp',
name: 'something', name: 'something',
@ -514,10 +550,12 @@ describe('Cypress Component Testing Configuration', () => {
], ],
}, },
}; };
await cypressComponentConfiguration(tree, { await cypressComponentConfiguration(tree, {
project: 'with-inputs-cmp', project: 'with-inputs-cmp',
buildTarget: 'something:build', buildTarget: 'something:build',
generateTests: true, generateTests: true,
skipFormat: true,
}); });
const [one, two, three] = getCmpsFromTree(tree, { const [one, two, three] = getCmpsFromTree(tree, {
@ -532,8 +570,8 @@ describe('Cypress Component Testing Configuration', () => {
it('should work with complex standalone component', async () => { it('should work with complex standalone component', async () => {
await generateTestLibrary(tree, { await generateTestLibrary(tree, {
name: 'with-inputs-standalone-cmp', name: 'with-inputs-standalone-cmp',
skipFormat: true,
}); });
await setup(tree, { await setup(tree, {
project: 'with-inputs-standalone-cmp', project: 'with-inputs-standalone-cmp',
name: 'something', name: 'something',
@ -568,6 +606,7 @@ describe('Cypress Component Testing Configuration', () => {
], ],
}, },
}; };
await cypressComponentConfiguration(tree, { await cypressComponentConfiguration(tree, {
project: 'with-inputs-standalone-cmp', project: 'with-inputs-standalone-cmp',
buildTarget: 'something:build', buildTarget: 'something:build',
@ -586,20 +625,24 @@ describe('Cypress Component Testing Configuration', () => {
it('should work with secondary entry point libs', async () => { it('should work with secondary entry point libs', async () => {
await generateTestApplication(tree, { await generateTestApplication(tree, {
name: 'my-cool-app', name: 'my-cool-app',
skipFormat: true,
}); });
await generateTestLibrary(tree, { await generateTestLibrary(tree, {
name: 'secondary', name: 'secondary',
buildable: true, buildable: true,
skipFormat: true,
}); });
await librarySecondaryEntryPointGenerator(tree, { await librarySecondaryEntryPointGenerator(tree, {
name: 'button', name: 'button',
library: 'secondary', library: 'secondary',
skipFormat: true,
}); });
await componentGenerator(tree, { await componentGenerator(tree, {
name: 'fancy-button', name: 'fancy-button',
path: 'secondary/src/lib/button', path: 'secondary/src/lib/button',
project: 'secondary', project: 'secondary',
flat: true, flat: true,
skipFormat: true,
}); });
await componentGenerator(tree, { await componentGenerator(tree, {
name: 'standalone-fancy-button', name: 'standalone-fancy-button',
@ -607,6 +650,7 @@ describe('Cypress Component Testing Configuration', () => {
project: 'secondary', project: 'secondary',
standalone: true, standalone: true,
flat: true, flat: true,
skipFormat: true,
}); });
projectGraph = { projectGraph = {
nodes: { nodes: {
@ -632,7 +676,9 @@ describe('Cypress Component Testing Configuration', () => {
generateTests: true, generateTests: true,
project: 'secondary', project: 'secondary',
buildTarget: 'my-cool-app:build', buildTarget: 'my-cool-app:build',
skipFormat: true,
}); });
expect( expect(
tree.read( tree.read(
'secondary/src/lib/button/fancy-button.component.cy.ts', 'secondary/src/lib/button/fancy-button.component.cy.ts',
@ -651,6 +697,7 @@ describe('Cypress Component Testing Configuration', () => {
await generateTestLibrary(tree, { await generateTestLibrary(tree, {
name: 'cool-lib', name: 'cool-lib',
flat: true, flat: true,
skipFormat: true,
}); });
await setup(tree, { project: 'cool-lib', name: 'abc', standalone: false }); await setup(tree, { project: 'cool-lib', name: 'abc', standalone: false });
tree.write( tree.write(
@ -684,29 +731,27 @@ describe('Cypress Component Testing Configuration', () => {
}, },
dependencies: {}, dependencies: {},
}; };
await cypressComponentConfiguration(tree, { await cypressComponentConfiguration(tree, {
project: 'cool-lib', project: 'cool-lib',
buildTarget: 'abc:build', buildTarget: 'abc:build',
generateTests: true, generateTests: true,
skipFormat: true,
}); });
const [one, two, three] = getCmpsFromTree(tree, { const [one, two, three] = getCmpsFromTree(tree, {
name: 'abc', name: 'abc',
basePath: 'cool-lib/src/lib', basePath: 'cool-lib/src/lib',
}); });
expect(one.cy).toMatchInlineSnapshot(
expect(one.cy).toMatchInlineSnapshot(` `"const msg = 'should not overwrite abc-one';"`
"const msg = 'should not overwrite abc-one'; );
" expect(two.cy).toMatchInlineSnapshot(
`); `"const msg = 'should not overwrite abc-two';"`
expect(two.cy).toMatchInlineSnapshot(` );
"const msg = 'should not overwrite abc-two'; expect(three.cy).toMatchInlineSnapshot(
" `"const msg = 'should not overwrite abc-three';"`
`); );
expect(three.cy).toMatchInlineSnapshot(`
"const msg = 'should not overwrite abc-three';
"
`);
}); });
// TODO: should we support this? // TODO: should we support this?
@ -714,17 +759,19 @@ describe('Cypress Component Testing Configuration', () => {
await generateTestLibrary(tree, { await generateTestLibrary(tree, {
name: 'multiple-components', name: 'multiple-components',
flat: true, flat: true,
skipFormat: true,
}); });
await componentGenerator(tree, { await componentGenerator(tree, {
name: 'cmp-one', name: 'cmp-one',
project: 'multiple-components', project: 'multiple-components',
flat: true, flat: true,
skipFormat: true,
}); });
await componentGenerator(tree, { await componentGenerator(tree, {
name: 'cmp-two', name: 'cmp-two',
project: 'multiple-components', project: 'multiple-components',
flat: true, flat: true,
skipFormat: true,
}); });
tree.write( tree.write(
`multiple-components/src/lib/cmp-one.component.ts`, `multiple-components/src/lib/cmp-one.component.ts`,
@ -757,7 +804,6 @@ export class CmpMultiComponent implements OnInit {
} }
` `
); );
tree.write( tree.write(
'', '',
` `
@ -782,7 +828,9 @@ export class MultipleComponentsModule { }
await cypressComponentConfiguration(tree, { await cypressComponentConfiguration(tree, {
project: 'multiple-components', project: 'multiple-components',
generateTests: true, generateTests: true,
skipFormat: true,
}); });
expect( expect(
tree.read('multiple-components/src/lib/cmp-one.component.cy.ts', 'utf-8') tree.read('multiple-components/src/lib/cmp-one.component.cy.ts', 'utf-8')
).toEqual(''); ).toEqual('');
@ -802,13 +850,18 @@ async function setup(
await generateTestApplication(tree, { await generateTestApplication(tree, {
name: options.name, name: options.name,
standalone: options.standalone, standalone: options.standalone,
skipFormat: true,
}); });
for (const name of [ for (const name of [
`${options.name}-one`, `${options.name}-one`,
`${options.name}-two`, `${options.name}-two`,
`${options.name}-three`, `${options.name}-three`,
]) { ]) {
await componentGenerator(tree, { project: options.project, name }); await componentGenerator(tree, {
project: options.project,
name,
skipFormat: true,
});
if (options.withInputs) { if (options.withInputs) {
const cmpPath = joinPathFragments( const cmpPath = joinPathFragments(
@ -816,11 +869,7 @@ async function setup(
name, name,
`${name}.component.ts` `${name}.component.ts`
); );
const oldContent = tree.read( const oldContent = tree.read(cmpPath, 'utf-8');
cmpPath,
'utf-8'
);
const newContent = oldContent.replace( const newContent = oldContent.replace(
'constructor()', 'constructor()',

View File

@ -44,9 +44,8 @@ export async function cypressComponentConfiguration(
if (!options.skipFormat) { if (!options.skipFormat) {
await formatFiles(tree); await formatFiles(tree);
} }
return () => {
installTask(); return installTask;
};
} }
async function addFiles( async function addFiles(
@ -105,7 +104,7 @@ async function addFiles(
projectConfig.root, projectConfig.root,
joinPathFragments(info.moduleFolderPath, info.path) joinPathFragments(info.moduleFolderPath, info.path)
); );
componentTestGenerator(tree, { await componentTestGenerator(tree, {
project: options.project, project: options.project,
componentName: info.name, componentName: info.name,
componentDir: componentDirFromProjectRoot, componentDir: componentDirFromProjectRoot,

View File

@ -52,7 +52,7 @@ exports[`directive generator --no-standalone should import the directive correct
"import { Directive } from '@angular/core'; "import { Directive } from '@angular/core';
@Directive({ @Directive({
selector: '[projTest]', selector: '[projTest]'
}) })
export class TestDirective { export class TestDirective {
constructor() {} constructor() {}
@ -88,7 +88,7 @@ exports[`directive generator --no-standalone should import the directive correct
"import { Directive } from '@angular/core'; "import { Directive } from '@angular/core';
@Directive({ @Directive({
selector: '[projTest]', selector: '[projTest]'
}) })
export class TestDirective { export class TestDirective {
constructor() {} constructor() {}

View File

@ -18,7 +18,7 @@ describe('directive generator', () => {
it('should generate correctly', async () => { it('should generate correctly', async () => {
// ACT // ACT
await generateDirectiveWithDefaultOptions(tree); await generateDirectiveWithDefaultOptions(tree, { skipFormat: false });
// ASSERT // ASSERT
expect( expect(
@ -67,7 +67,10 @@ describe('directive generator', () => {
// ARRANGE // ARRANGE
// ACT // ACT
await generateDirectiveWithDefaultOptions(tree, { standalone: false }); await generateDirectiveWithDefaultOptions(tree, {
standalone: false,
skipFormat: false,
});
// ASSERT // ASSERT
expect( expect(
@ -166,13 +169,14 @@ describe('directive generator', () => {
function addModule(tree: Tree) { function addModule(tree: Tree) {
tree.write( tree.write(
'test/src/app/test.module.ts', 'test/src/app/test.module.ts',
`import {NgModule} from "@angular/core"; `import { NgModule } from '@angular/core';
@NgModule({ @NgModule({
imports: [], imports: [],
declarations: [], declarations: [],
exports: [] exports: [],
}) })
export class TestModule {}` export class TestModule {}
`
); );
} }
@ -184,6 +188,7 @@ async function generateDirectiveWithDefaultOptions(
name: 'test', name: 'test',
project: 'test', project: 'test',
flat: true, flat: true,
skipFormat: true,
...overrides, ...overrides,
}); });
} }

View File

@ -5,7 +5,5 @@ import { Directive } from '@angular/core';
standalone: true<%}%> standalone: true<%}%>
}) })
export class <%= symbolName %> { export class <%= symbolName %> {
constructor() {}
constructor() { }
} }

View File

@ -77,6 +77,7 @@ describe('federate-module', () => {
await federateModuleGenerator(tree, { await federateModuleGenerator(tree, {
...schema, ...schema,
remote: remoteSchema.name, remote: remoteSchema.name,
skipFormat: true,
}); });
content = tree.read( content = tree.read(

View File

@ -26,7 +26,7 @@ export function app(): express.Express {
server.engine( server.engine(
'html', 'html',
ngExpressEngine({ ngExpressEngine({
bootstrap, bootstrap
}) })
); );
@ -572,10 +572,7 @@ export default bootstrap;
" "
`; `;
exports[`Host App Generator --ssr should generate the correct files for standalone when --typescript=true 4`] = ` exports[`Host App Generator --ssr should generate the correct files for standalone when --typescript=true 4`] = `"import('./src/main.server');"`;
"import('./src/main.server');
"
`;
exports[`Host App Generator --ssr should generate the correct files for standalone when --typescript=true 5`] = ` exports[`Host App Generator --ssr should generate the correct files for standalone when --typescript=true 5`] = `
"import { ModuleFederationConfig } from '@nx/webpack'; "import { ModuleFederationConfig } from '@nx/webpack';
@ -594,7 +591,7 @@ const config: ModuleFederationConfig = {
* declare module 'my-external-remote'; * declare module 'my-external-remote';
* *
*/ */
remotes: [], remotes: []
}; };
export default config; export default config;
@ -614,11 +611,10 @@ exports[`Host App Generator --ssr should generate the correct files for standalo
import { Route } from '@angular/router'; import { Route } from '@angular/router';
export const appRoutes: Route[] = [ export const appRoutes: Route[] = [
{ {
path: '', path: '',
component: NxWelcomeComponent, component: NxWelcomeComponent
}, },];
];
" "
`; `;
@ -801,10 +797,7 @@ export default AppServerModule;
" "
`; `;
exports[`Host App Generator --ssr should generate the correct files when --typescript=true 5`] = ` exports[`Host App Generator --ssr should generate the correct files when --typescript=true 5`] = `"import('./src/main.server');"`;
"import('./src/main.server');
"
`;
exports[`Host App Generator --ssr should generate the correct files when --typescript=true 6`] = ` exports[`Host App Generator --ssr should generate the correct files when --typescript=true 6`] = `
"import { ModuleFederationConfig } from '@nx/webpack'; "import { ModuleFederationConfig } from '@nx/webpack';
@ -823,7 +816,7 @@ const config: ModuleFederationConfig = {
* declare module 'my-external-remote'; * declare module 'my-external-remote';
* *
*/ */
remotes: [], remotes: []
}; };
export default config; export default config;
@ -843,11 +836,10 @@ exports[`Host App Generator --ssr should generate the correct files when --types
import { Route } from '@angular/router'; import { Route } from '@angular/router';
export const appRoutes: Route[] = [ export const appRoutes: Route[] = [
{ {
path: '', path: '',
component: NxWelcomeComponent, component: NxWelcomeComponent
}, },];
];
" "
`; `;
@ -1011,7 +1003,9 @@ describe('AppComponent', () => {
tick(); tick();
fixture.detectChanges(); fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement; const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Welcome host'); expect(compiled.querySelector('h1')?.textContent).toContain(
'Welcome host'
);
})); }));
}); });
" "

View File

@ -1,4 +1,4 @@
import {withModuleFederationForSSR} from '@nx/angular/module-federation'; import { withModuleFederationForSSR } from '@nx/angular/module-federation';
import config from './module-federation.config'; import config from './module-federation.config';
export default withModuleFederationForSSR(config) export default withModuleFederationForSSR(config);

View File

@ -20,6 +20,7 @@ describe('Host App Generator', () => {
name: 'test', name: 'test',
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -34,6 +35,7 @@ describe('Host App Generator', () => {
name: 'test', name: 'test',
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -48,6 +50,7 @@ describe('Host App Generator', () => {
name: 'remote', name: 'remote',
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -56,6 +59,7 @@ describe('Host App Generator', () => {
remotes: ['remote'], remotes: ['remote'],
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -70,6 +74,7 @@ describe('Host App Generator', () => {
name: 'remote', name: 'remote',
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -78,6 +83,7 @@ describe('Host App Generator', () => {
remotes: ['remote'], remotes: ['remote'],
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -96,6 +102,7 @@ describe('Host App Generator', () => {
remotes: ['remote1', 'remote2'], remotes: ['remote1', 'remote2'],
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -103,13 +110,13 @@ describe('Host App Generator', () => {
expect(tree.exists('remote2/project.json')).toBeTruthy(); expect(tree.exists('remote2/project.json')).toBeTruthy();
expect( expect(
tree.read('host-app/module-federation.config.js', 'utf-8') tree.read('host-app/module-federation.config.js', 'utf-8')
).toContain(`'remote1', 'remote2'`); ).toContain(`'remote1','remote2'`);
expect(tree.read('host-app/src/app/app.component.html', 'utf-8')) expect(tree.read('host-app/src/app/app.component.html', 'utf-8'))
.toMatchInlineSnapshot(` .toMatchInlineSnapshot(`
"<ul class="remote-menu"> "<ul class="remote-menu">
<li><a routerLink="/">Home</a></li> <li><a routerLink="/">Home</a></li>
<li><a routerLink="remote1">Remote1</a></li> <li><a routerLink="remote1">Remote1</a></li>
<li><a routerLink="remote2">Remote2</a></li> <li><a routerLink="remote2">Remote2</a></li>
</ul> </ul>
<router-outlet></router-outlet> <router-outlet></router-outlet>
" "
@ -127,6 +134,7 @@ describe('Host App Generator', () => {
remotes: ['remote1', 'remote2'], remotes: ['remote1', 'remote2'],
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -134,13 +142,13 @@ describe('Host App Generator', () => {
expect(tree.exists('remote2/project.json')).toBeTruthy(); expect(tree.exists('remote2/project.json')).toBeTruthy();
expect( expect(
tree.read('host-app/module-federation.config.ts', 'utf-8') tree.read('host-app/module-federation.config.ts', 'utf-8')
).toContain(`'remote1', 'remote2'`); ).toContain(`'remote1','remote2'`);
expect(tree.read('host-app/src/app/app.component.html', 'utf-8')) expect(tree.read('host-app/src/app/app.component.html', 'utf-8'))
.toMatchInlineSnapshot(` .toMatchInlineSnapshot(`
"<ul class="remote-menu"> "<ul class="remote-menu">
<li><a routerLink="/">Home</a></li> <li><a routerLink="/">Home</a></li>
<li><a routerLink="remote1">Remote1</a></li> <li><a routerLink="remote1">Remote1</a></li>
<li><a routerLink="remote2">Remote2</a></li> <li><a routerLink="remote2">Remote2</a></li>
</ul> </ul>
<router-outlet></router-outlet> <router-outlet></router-outlet>
" "
@ -154,6 +162,7 @@ describe('Host App Generator', () => {
name: 'remote1', name: 'remote1',
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -162,6 +171,7 @@ describe('Host App Generator', () => {
remotes: ['remote1', 'remote2', 'remote3'], remotes: ['remote1', 'remote2', 'remote3'],
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -170,7 +180,7 @@ describe('Host App Generator', () => {
expect(tree.exists('remote3/project.json')).toBeTruthy(); expect(tree.exists('remote3/project.json')).toBeTruthy();
expect( expect(
tree.read('host-app/module-federation.config.js', 'utf-8') tree.read('host-app/module-federation.config.js', 'utf-8')
).toContain(`'remote1', 'remote2', 'remote3'`); ).toContain(`'remote1','remote2','remote3'`);
}); });
it('should generate a host, integrate existing remotes and generate any remotes that dont exist when --typescript=true', async () => { it('should generate a host, integrate existing remotes and generate any remotes that dont exist when --typescript=true', async () => {
@ -180,6 +190,7 @@ describe('Host App Generator', () => {
name: 'remote1', name: 'remote1',
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -188,6 +199,7 @@ describe('Host App Generator', () => {
remotes: ['remote1', 'remote2', 'remote3'], remotes: ['remote1', 'remote2', 'remote3'],
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -196,7 +208,7 @@ describe('Host App Generator', () => {
expect(tree.exists('remote3/project.json')).toBeTruthy(); expect(tree.exists('remote3/project.json')).toBeTruthy();
expect( expect(
tree.read('host-app/module-federation.config.ts', 'utf-8') tree.read('host-app/module-federation.config.ts', 'utf-8')
).toContain(`'remote1', 'remote2', 'remote3'`); ).toContain(`'remote1','remote2','remote3'`);
}); });
it('should generate a host, integrate existing remotes and generate any remotes that dont exist, in a directory', async () => { it('should generate a host, integrate existing remotes and generate any remotes that dont exist, in a directory', async () => {
@ -206,6 +218,7 @@ describe('Host App Generator', () => {
name: 'remote1', name: 'remote1',
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -215,6 +228,7 @@ describe('Host App Generator', () => {
remotes: ['remote1', 'remote2', 'remote3'], remotes: ['remote1', 'remote2', 'remote3'],
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -223,7 +237,7 @@ describe('Host App Generator', () => {
expect(tree.exists('foo/remote3/project.json')).toBeTruthy(); expect(tree.exists('foo/remote3/project.json')).toBeTruthy();
expect( expect(
tree.read('foo/host-app/module-federation.config.js', 'utf-8') tree.read('foo/host-app/module-federation.config.js', 'utf-8')
).toContain(`'remote1', 'remote2', 'remote3'`); ).toContain(`'remote1','remote2','remote3'`);
}); });
it('should generate a host, integrate existing remotes and generate any remotes that dont exist, in a directory when --typescript=true', async () => { it('should generate a host, integrate existing remotes and generate any remotes that dont exist, in a directory when --typescript=true', async () => {
@ -233,6 +247,7 @@ describe('Host App Generator', () => {
name: 'remote1', name: 'remote1',
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -242,6 +257,7 @@ describe('Host App Generator', () => {
remotes: ['remote1', 'remote2', 'remote3'], remotes: ['remote1', 'remote2', 'remote3'],
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -250,7 +266,7 @@ describe('Host App Generator', () => {
expect(tree.exists('foo/remote3/project.json')).toBeTruthy(); expect(tree.exists('foo/remote3/project.json')).toBeTruthy();
expect( expect(
tree.read('foo/host-app/module-federation.config.ts', 'utf-8') tree.read('foo/host-app/module-federation.config.ts', 'utf-8')
).toContain(`'remote1', 'remote2', 'remote3'`); ).toContain(`'remote1','remote2','remote3'`);
}); });
it('should generate a host with remotes using standalone components', async () => { it('should generate a host with remotes using standalone components', async () => {
@ -261,6 +277,7 @@ describe('Host App Generator', () => {
await generateTestHostApplication(tree, { await generateTestHostApplication(tree, {
name: 'host', name: 'host',
remotes: ['remote1'], remotes: ['remote1'],
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -279,6 +296,7 @@ describe('Host App Generator', () => {
await generateTestHostApplication(tree, { await generateTestHostApplication(tree, {
name: 'host', name: 'host',
remotes: ['remote1'], remotes: ['remote1'],
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -296,6 +314,7 @@ describe('Host App Generator', () => {
name: 'dashboard', name: 'dashboard',
remotes: ['remote1'], remotes: ['remote1'],
directory: 'test/dashboard', directory: 'test/dashboard',
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -314,6 +333,7 @@ describe('Host App Generator', () => {
remotes: ['remote1'], remotes: ['remote1'],
e2eTestRunner: E2eTestRunner.None, e2eTestRunner: E2eTestRunner.None,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -369,6 +389,7 @@ describe('Host App Generator', () => {
ssr: true, ssr: true,
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -443,6 +464,7 @@ describe('Host App Generator', () => {
name: 'test', name: 'test',
ssr: true, ssr: true,
typescriptConfiguration: true, typescriptConfiguration: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -483,7 +505,11 @@ describe('Host App Generator', () => {
}, },
})); }));
await generateTestHostApplication(tree, { name: 'test', ssr: true }); await generateTestHostApplication(tree, {
name: 'test',
ssr: true,
skipFormat: true,
});
expect(tree.read(`test/src/main.server.ts`, 'utf-8')).toMatchSnapshot(); expect(tree.read(`test/src/main.server.ts`, 'utf-8')).toMatchSnapshot();
}); });
@ -499,6 +525,7 @@ describe('Host App Generator', () => {
projectNameAndRootFormat: 'derived', projectNameAndRootFormat: 'derived',
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -508,6 +535,7 @@ describe('Host App Generator', () => {
projectNameAndRootFormat: 'derived', projectNameAndRootFormat: 'derived',
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -516,7 +544,7 @@ describe('Host App Generator', () => {
expect(tree.exists('apps/remote3/project.json')).toBeTruthy(); expect(tree.exists('apps/remote3/project.json')).toBeTruthy();
expect( expect(
tree.read('apps/host-app/module-federation.config.js', 'utf-8') tree.read('apps/host-app/module-federation.config.js', 'utf-8')
).toContain(`'remote1', 'remote2', 'remote3'`); ).toContain(`'remote1','remote2','remote3'`);
}); });
it('should generate a host, integrate existing remotes and generate any remotes that dont exist, in a directory', async () => { it('should generate a host, integrate existing remotes and generate any remotes that dont exist, in a directory', async () => {
@ -527,6 +555,7 @@ describe('Host App Generator', () => {
projectNameAndRootFormat: 'derived', projectNameAndRootFormat: 'derived',
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -537,6 +566,7 @@ describe('Host App Generator', () => {
projectNameAndRootFormat: 'derived', projectNameAndRootFormat: 'derived',
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -545,7 +575,7 @@ describe('Host App Generator', () => {
expect(tree.exists('apps/foo/remote3/project.json')).toBeTruthy(); expect(tree.exists('apps/foo/remote3/project.json')).toBeTruthy();
expect( expect(
tree.read('apps/foo/host-app/module-federation.config.js', 'utf-8') tree.read('apps/foo/host-app/module-federation.config.js', 'utf-8')
).toContain(`'remote1', 'foo-remote2', 'foo-remote3'`); ).toContain(`'remote1','foo-remote2','foo-remote3'`);
}); });
it('should generate a host, integrate existing remotes and generate any remotes that dont exist, in a directory when --typescript=true', async () => { it('should generate a host, integrate existing remotes and generate any remotes that dont exist, in a directory when --typescript=true', async () => {
// ARRANGE // ARRANGE
@ -555,6 +585,7 @@ describe('Host App Generator', () => {
projectNameAndRootFormat: 'derived', projectNameAndRootFormat: 'derived',
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -565,6 +596,7 @@ describe('Host App Generator', () => {
projectNameAndRootFormat: 'derived', projectNameAndRootFormat: 'derived',
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -573,7 +605,7 @@ describe('Host App Generator', () => {
expect(tree.exists('apps/foo/remote3/project.json')).toBeTruthy(); expect(tree.exists('apps/foo/remote3/project.json')).toBeTruthy();
expect( expect(
tree.read('apps/foo/host-app/module-federation.config.ts', 'utf-8') tree.read('apps/foo/host-app/module-federation.config.ts', 'utf-8')
).toContain(`'remote1', 'foo-remote2', 'foo-remote3'`); ).toContain(`'remote1','foo-remote2','foo-remote3'`);
}); });
}); });
}); });

View File

@ -35,7 +35,7 @@ describe('init', () => {
await init(tree, { await init(tree, {
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
// ASSERT // ASSERT
@ -79,7 +79,7 @@ describe('init', () => {
})); }));
// ACT // ACT
await init(tree, {}); await init(tree, { skipFormat: true });
// ASSERT // ASSERT
const { dependencies, devDependencies } = readJson(tree, 'package.json'); const { dependencies, devDependencies } = readJson(tree, 'package.json');
@ -112,7 +112,7 @@ describe('init', () => {
})); }));
// ACT // ACT
await init(tree, {}); await init(tree, { skipFormat: true });
// ASSERT // ASSERT
const { dependencies } = readJson(tree, 'package.json'); const { dependencies } = readJson(tree, 'package.json');
@ -128,7 +128,7 @@ describe('init', () => {
await init(tree, { await init(tree, {
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
const { devDependencies } = readJson(tree, 'package.json'); const { devDependencies } = readJson(tree, 'package.json');
@ -144,7 +144,7 @@ describe('init', () => {
await init(tree, { await init(tree, {
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
const hasJestConfigFile = tree.exists('jest.config.ts'); const hasJestConfigFile = tree.exists('jest.config.ts');
@ -158,7 +158,7 @@ describe('init', () => {
await init(tree, { await init(tree, {
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json'); const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -182,7 +182,7 @@ describe('init', () => {
unitTestRunner: UnitTestRunner.None, unitTestRunner: UnitTestRunner.None,
e2eTestRunner: E2eTestRunner.Playwright, e2eTestRunner: E2eTestRunner.Playwright,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
expect(ensurePackage).toHaveBeenLastCalledWith( expect(ensurePackage).toHaveBeenLastCalledWith(
@ -197,7 +197,7 @@ describe('init', () => {
unitTestRunner: UnitTestRunner.None, unitTestRunner: UnitTestRunner.None,
e2eTestRunner: E2eTestRunner.Playwright, e2eTestRunner: E2eTestRunner.Playwright,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json'); const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -215,7 +215,7 @@ describe('init', () => {
unitTestRunner: UnitTestRunner.None, unitTestRunner: UnitTestRunner.None,
e2eTestRunner: E2eTestRunner.Cypress, e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
expect(ensurePackage).toHaveBeenLastCalledWith('@nx/cypress', '0.0.1'); expect(ensurePackage).toHaveBeenLastCalledWith('@nx/cypress', '0.0.1');
@ -227,7 +227,7 @@ describe('init', () => {
unitTestRunner: UnitTestRunner.None, unitTestRunner: UnitTestRunner.None,
e2eTestRunner: E2eTestRunner.Cypress, e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json'); const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -247,7 +247,7 @@ describe('init', () => {
await init(tree, { await init(tree, {
unitTestRunner: UnitTestRunner.None, unitTestRunner: UnitTestRunner.None,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json'); const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -264,7 +264,7 @@ describe('init', () => {
await init(tree, { await init(tree, {
unitTestRunner: UnitTestRunner.None, unitTestRunner: UnitTestRunner.None,
linter: Linter.None, linter: Linter.None,
skipFormat: false, skipFormat: true,
}); });
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json'); const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -284,7 +284,7 @@ describe('init', () => {
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress, e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
expect(tree.read('.gitignore', 'utf-8')).toContain('.angular'); expect(tree.read('.gitignore', 'utf-8')).toContain('.angular');
@ -305,7 +305,7 @@ bar
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress, e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
const angularEntries = tree const angularEntries = tree
@ -321,7 +321,7 @@ bar
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress, e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
expect(tree.read('.prettierignore', 'utf-8')).toContain('.angular'); expect(tree.read('.prettierignore', 'utf-8')).toContain('.angular');
@ -342,7 +342,7 @@ bar
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress, e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
const angularEntries = tree const angularEntries = tree
@ -363,7 +363,7 @@ bar
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress, e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
expect(tree.read('.gitignore', 'utf-8')).toContain( expect(tree.read('.gitignore', 'utf-8')).toContain(
@ -393,7 +393,7 @@ bar
await init(tree, { await init(tree, {
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
// ASSERT // ASSERT
@ -458,7 +458,7 @@ bar
})); }));
// ACT // ACT
await init(tree, {}); await init(tree, { skipFormat: true });
// ASSERT // ASSERT
const { dependencies, devDependencies } = readJson(tree, 'package.json'); const { dependencies, devDependencies } = readJson(tree, 'package.json');
@ -491,7 +491,7 @@ bar
})); }));
// ACT // ACT
await init(tree, {}); await init(tree, { skipFormat: true });
// ASSERT // ASSERT
const { dependencies } = readJson(tree, 'package.json'); const { dependencies } = readJson(tree, 'package.json');
@ -507,7 +507,7 @@ bar
await init(tree, { await init(tree, {
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
const { devDependencies } = readJson(tree, 'package.json'); const { devDependencies } = readJson(tree, 'package.json');
@ -525,7 +525,7 @@ bar
await init(tree, { await init(tree, {
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
const hasJestConfigFile = tree.exists('jest.config.ts'); const hasJestConfigFile = tree.exists('jest.config.ts');
@ -539,7 +539,7 @@ bar
await init(tree, { await init(tree, {
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json'); const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -562,7 +562,7 @@ bar
unitTestRunner: UnitTestRunner.None, unitTestRunner: UnitTestRunner.None,
e2eTestRunner: E2eTestRunner.Playwright, e2eTestRunner: E2eTestRunner.Playwright,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
expect(ensurePackage).toHaveBeenLastCalledWith( expect(ensurePackage).toHaveBeenLastCalledWith(
@ -577,7 +577,7 @@ bar
unitTestRunner: UnitTestRunner.None, unitTestRunner: UnitTestRunner.None,
e2eTestRunner: E2eTestRunner.Playwright, e2eTestRunner: E2eTestRunner.Playwright,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json'); const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -595,7 +595,7 @@ bar
unitTestRunner: UnitTestRunner.None, unitTestRunner: UnitTestRunner.None,
e2eTestRunner: E2eTestRunner.Cypress, e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
// ASSERT // ASSERT
expect(ensurePackage).toHaveBeenLastCalledWith( expect(ensurePackage).toHaveBeenLastCalledWith(
@ -610,7 +610,7 @@ bar
unitTestRunner: UnitTestRunner.None, unitTestRunner: UnitTestRunner.None,
e2eTestRunner: E2eTestRunner.Cypress, e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json'); const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -630,7 +630,7 @@ bar
await init(tree, { await init(tree, {
unitTestRunner: UnitTestRunner.None, unitTestRunner: UnitTestRunner.None,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json'); const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -649,7 +649,7 @@ bar
await init(tree, { await init(tree, {
unitTestRunner: UnitTestRunner.None, unitTestRunner: UnitTestRunner.None,
linter: Linter.None, linter: Linter.None,
skipFormat: false, skipFormat: true,
}); });
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json'); const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -669,7 +669,7 @@ bar
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress, e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
expect(tree.read('.gitignore', 'utf-8')).toContain('.angular'); expect(tree.read('.gitignore', 'utf-8')).toContain('.angular');
@ -690,7 +690,7 @@ bar
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress, e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
const angularEntries = tree const angularEntries = tree
@ -706,7 +706,7 @@ bar
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress, e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
expect(tree.read('.prettierignore', 'utf-8')).toContain('.angular'); expect(tree.read('.prettierignore', 'utf-8')).toContain('.angular');
@ -727,7 +727,7 @@ bar
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress, e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
const angularEntries = tree const angularEntries = tree
@ -748,7 +748,7 @@ bar
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress, e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
}); });
expect(tree.read('.gitignore', 'utf-8')).toContain( expect(tree.read('.gitignore', 'utf-8')).toContain(

View File

@ -5,6 +5,22 @@ exports[`librarySecondaryEntryPoint generator --skipModule should not generate a
" "
`; `;
exports[`librarySecondaryEntryPoint generator should format files 1`] = `
"export * from './lib/testing.module';
"
`;
exports[`librarySecondaryEntryPoint generator should format files 2`] = `
"import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
@NgModule({
imports: [CommonModule],
})
export class TestingModule {}
"
`;
exports[`librarySecondaryEntryPoint generator should generate files for the secondary entry point 1`] = ` exports[`librarySecondaryEntryPoint generator should generate files for the secondary entry point 1`] = `
"export * from './lib/testing.module'; "export * from './lib/testing.module';
" "

View File

@ -1,5 +1 @@
<% if (!skipModule) { %> <% if (!skipModule) { %>export * from './lib/<%= fileName %>.module';<% } else { %>export const greeting = 'Hello World!';<% } %>
export * from './lib/<%= fileName %>.module';
<% } else { %>
export const greeting = 'Hello World!';
<% } %>

View File

@ -1,10 +1,5 @@
import * as devkit from '@nx/devkit'; import * as devkit from '@nx/devkit';
import { import { addProjectConfiguration, readJson, Tree } from '@nx/devkit';
addProjectConfiguration,
readJson,
readProjectConfiguration,
Tree,
} from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { generateTestLibrary } from '../utils/testing'; import { generateTestLibrary } from '../utils/testing';
import { librarySecondaryEntryPointGenerator } from './library-secondary-entry-point'; import { librarySecondaryEntryPointGenerator } from './library-secondary-entry-point';
@ -21,6 +16,7 @@ describe('librarySecondaryEntryPoint generator', () => {
librarySecondaryEntryPointGenerator(tree, { librarySecondaryEntryPointGenerator(tree, {
name: 'testing', name: 'testing',
library: 'lib1', library: 'lib1',
skipFormat: true,
}) })
).rejects.toThrow(); ).rejects.toThrow();
}); });
@ -35,6 +31,7 @@ describe('librarySecondaryEntryPoint generator', () => {
librarySecondaryEntryPointGenerator(tree, { librarySecondaryEntryPointGenerator(tree, {
name: 'testing', name: 'testing',
library: 'app1', library: 'app1',
skipFormat: true,
}) })
).rejects.toThrow(); ).rejects.toThrow();
}); });
@ -54,6 +51,7 @@ describe('librarySecondaryEntryPoint generator', () => {
librarySecondaryEntryPointGenerator(tree, { librarySecondaryEntryPointGenerator(tree, {
name: 'testing', name: 'testing',
library: 'lib1', library: 'lib1',
skipFormat: true,
}) })
).rejects.toThrow(); ).rejects.toThrow();
}); });
@ -71,6 +69,7 @@ describe('librarySecondaryEntryPoint generator', () => {
await librarySecondaryEntryPointGenerator(tree, { await librarySecondaryEntryPointGenerator(tree, {
name: 'testing', name: 'testing',
library: 'lib1', library: 'lib1',
skipFormat: true,
}); });
expect(tree.exists('libs/lib1/testing/ng-package.json')).toBeTruthy(); expect(tree.exists('libs/lib1/testing/ng-package.json')).toBeTruthy();
@ -97,6 +96,7 @@ describe('librarySecondaryEntryPoint generator', () => {
await librarySecondaryEntryPointGenerator(tree, { await librarySecondaryEntryPointGenerator(tree, {
name: 'testing', name: 'testing',
library: 'lib1', library: 'lib1',
skipFormat: true,
}); });
const ngPackageJson = readJson(tree, 'libs/lib1/testing/ng-package.json'); const ngPackageJson = readJson(tree, 'libs/lib1/testing/ng-package.json');
@ -116,6 +116,7 @@ describe('librarySecondaryEntryPoint generator', () => {
await librarySecondaryEntryPointGenerator(tree, { await librarySecondaryEntryPointGenerator(tree, {
name: 'testing', name: 'testing',
library: 'lib1', library: 'lib1',
skipFormat: true,
}); });
const tsConfig = readJson(tree, 'tsconfig.base.json'); const tsConfig = readJson(tree, 'tsconfig.base.json');
@ -138,6 +139,7 @@ describe('librarySecondaryEntryPoint generator', () => {
await librarySecondaryEntryPointGenerator(tree, { await librarySecondaryEntryPointGenerator(tree, {
name: 'testing', name: 'testing',
library: 'lib1', library: 'lib1',
skipFormat: true,
}); });
const tsConfig = readJson(tree, 'tsconfig.json'); const tsConfig = readJson(tree, 'tsconfig.json');
@ -152,6 +154,7 @@ describe('librarySecondaryEntryPoint generator', () => {
directory: 'libs/lib1', directory: 'libs/lib1',
importPath: '@my-org/lib1', importPath: '@my-org/lib1',
publishable: true, publishable: true,
skipFormat: true,
}); });
// verify initial state // verify initial state
let tsConfig = readJson(tree, 'libs/lib1/tsconfig.lib.json'); let tsConfig = readJson(tree, 'libs/lib1/tsconfig.lib.json');
@ -166,6 +169,7 @@ describe('librarySecondaryEntryPoint generator', () => {
await librarySecondaryEntryPointGenerator(tree, { await librarySecondaryEntryPointGenerator(tree, {
name: 'testing', name: 'testing',
library: 'lib1', library: 'lib1',
skipFormat: true,
}); });
tsConfig = readJson(tree, 'libs/lib1/tsconfig.lib.json'); tsConfig = readJson(tree, 'libs/lib1/tsconfig.lib.json');
@ -195,6 +199,12 @@ describe('librarySecondaryEntryPoint generator', () => {
}); });
expect(devkit.formatFiles).toHaveBeenCalled(); expect(devkit.formatFiles).toHaveBeenCalled();
expect(
tree.read('libs/lib1/testing/src/index.ts', 'utf-8')
).toMatchSnapshot();
expect(
tree.read('libs/lib1/testing/src/lib/testing.module.ts', 'utf-8')
).toMatchSnapshot();
}); });
describe('--skipModule', () => { describe('--skipModule', () => {
@ -212,6 +222,7 @@ describe('librarySecondaryEntryPoint generator', () => {
name: 'testing', name: 'testing',
library: 'lib1', library: 'lib1',
skipModule: true, skipModule: true,
skipFormat: true,
}); });
expect( expect(

View File

@ -17,7 +17,9 @@ export async function librarySecondaryEntryPointGenerator(
addPathMapping(tree, options); addPathMapping(tree, options);
updateTsConfigIncludedFiles(tree, options); updateTsConfigIncludedFiles(tree, options);
await formatFiles(tree); if (!options.skipFormat) {
await formatFiles(tree);
}
} }
export default librarySecondaryEntryPointGenerator; export default librarySecondaryEntryPointGenerator;

View File

@ -4,6 +4,7 @@ export interface GeneratorOptions {
library: string; library: string;
name: string; name: string;
skipModule?: boolean; skipModule?: boolean;
skipFormat?: boolean;
} }
export interface NormalizedGeneratorOptions extends GeneratorOptions { export interface NormalizedGeneratorOptions extends GeneratorOptions {

View File

@ -29,6 +29,12 @@
"type": "boolean", "type": "boolean",
"description": "Skip generating a module for the secondary entry point.", "description": "Skip generating a module for the secondary entry point.",
"default": false "default": false
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
"default": false,
"x-priority": "internal"
} }
}, },
"additionalProperties": false, "additionalProperties": false,

View File

@ -1,9 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`lib --standalone should generate a library with a standalone component and have it flat 1`] = ` exports[`lib --standalone should generate a library with a standalone component and have it flat 1`] = `"export * from './lib/my-lib.component';"`;
"export * from './lib/my-lib.component';
"
`;
exports[`lib --standalone should generate a library with a standalone component and have it flat 2`] = ` exports[`lib --standalone should generate a library with a standalone component and have it flat 2`] = `
"import { Component } from '@angular/core'; "import { Component } from '@angular/core';
@ -14,7 +11,7 @@ import { CommonModule } from '@angular/common';
standalone: true, standalone: true,
imports: [CommonModule], imports: [CommonModule],
templateUrl: './my-lib.component.html', templateUrl: './my-lib.component.html',
styleUrl: './my-lib.component.css', styleUrl: './my-lib.component.css'
}) })
export class MyLibComponent {} export class MyLibComponent {}
" "
@ -30,7 +27,7 @@ describe('MyLibComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [MyLibComponent], imports: [MyLibComponent]
}).compileComponents(); }).compileComponents();
fixture = TestBed.createComponent(MyLibComponent); fixture = TestBed.createComponent(MyLibComponent);
@ -48,8 +45,7 @@ describe('MyLibComponent', () => {
exports[`lib --standalone should generate a library with a standalone component and have it flat with routing setup 1`] = ` exports[`lib --standalone should generate a library with a standalone component and have it flat with routing setup 1`] = `
"export * from './lib/lib.routes'; "export * from './lib/lib.routes';
export * from './lib/my-lib.component'; export * from './lib/my-lib.component';"
"
`; `;
exports[`lib --standalone should generate a library with a standalone component and have it flat with routing setup 2`] = ` exports[`lib --standalone should generate a library with a standalone component and have it flat with routing setup 2`] = `
@ -61,7 +57,7 @@ import { CommonModule } from '@angular/common';
standalone: true, standalone: true,
imports: [CommonModule], imports: [CommonModule],
templateUrl: './my-lib.component.html', templateUrl: './my-lib.component.html',
styleUrl: './my-lib.component.css', styleUrl: './my-lib.component.css'
}) })
export class MyLibComponent {} export class MyLibComponent {}
" "
@ -77,7 +73,7 @@ describe('MyLibComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [MyLibComponent], imports: [MyLibComponent]
}).compileComponents(); }).compileComponents();
fixture = TestBed.createComponent(MyLibComponent); fixture = TestBed.createComponent(MyLibComponent);
@ -96,14 +92,13 @@ exports[`lib --standalone should generate a library with a standalone component
"import { Route } from '@angular/router'; "import { Route } from '@angular/router';
import { MyLibComponent } from './my-lib.component'; import { MyLibComponent } from './my-lib.component';
export const myLibRoutes: Route[] = [{ path: '', component: MyLibComponent }]; export const myLibRoutes: Route[] = [
{ path: '', component: MyLibComponent }
];
" "
`; `;
exports[`lib --standalone should generate a library with a standalone component as entry point 1`] = ` exports[`lib --standalone should generate a library with a standalone component as entry point 1`] = `"export * from './lib/my-lib/my-lib.component';"`;
"export * from './lib/my-lib/my-lib.component';
"
`;
exports[`lib --standalone should generate a library with a standalone component as entry point 2`] = ` exports[`lib --standalone should generate a library with a standalone component as entry point 2`] = `
"import { Component } from '@angular/core'; "import { Component } from '@angular/core';
@ -114,7 +109,7 @@ import { CommonModule } from '@angular/common';
standalone: true, standalone: true,
imports: [CommonModule], imports: [CommonModule],
templateUrl: './my-lib.component.html', templateUrl: './my-lib.component.html',
styleUrl: './my-lib.component.css', styleUrl: './my-lib.component.css'
}) })
export class MyLibComponent {} export class MyLibComponent {}
" "
@ -130,7 +125,7 @@ describe('MyLibComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [MyLibComponent], imports: [MyLibComponent]
}).compileComponents(); }).compileComponents();
fixture = TestBed.createComponent(MyLibComponent); fixture = TestBed.createComponent(MyLibComponent);
@ -145,17 +140,10 @@ describe('MyLibComponent', () => {
" "
`; `;
exports[`lib --standalone should generate a library with a standalone component as entry point and set up view encapsulation and change detection 1`] = ` exports[`lib --standalone should generate a library with a standalone component as entry point and set up view encapsulation and change detection 1`] = `"export * from './lib/my-lib/my-lib.component';"`;
"export * from './lib/my-lib/my-lib.component';
"
`;
exports[`lib --standalone should generate a library with a standalone component as entry point and set up view encapsulation and change detection 2`] = ` exports[`lib --standalone should generate a library with a standalone component as entry point and set up view encapsulation and change detection 2`] = `
"import { "import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
ChangeDetectionStrategy,
Component,
ViewEncapsulation,
} from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@Component({ @Component({
@ -165,16 +153,13 @@ import { CommonModule } from '@angular/common';
template: \`<p>my-lib works!</p>\`, template: \`<p>my-lib works!</p>\`,
styles: \`\`, styles: \`\`,
encapsulation: ViewEncapsulation.ShadowDom, encapsulation: ViewEncapsulation.ShadowDom,
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class MyLibComponent {} export class MyLibComponent {}
" "
`; `;
exports[`lib --standalone should generate a library with a standalone component as entry point and skip tests 1`] = ` exports[`lib --standalone should generate a library with a standalone component as entry point and skip tests 1`] = `"export * from './lib/my-lib/my-lib.component';"`;
"export * from './lib/my-lib/my-lib.component';
"
`;
exports[`lib --standalone should generate a library with a standalone component as entry point and skip tests 2`] = ` exports[`lib --standalone should generate a library with a standalone component as entry point and skip tests 2`] = `
"import { Component } from '@angular/core'; "import { Component } from '@angular/core';
@ -185,16 +170,13 @@ import { CommonModule } from '@angular/common';
standalone: true, standalone: true,
imports: [CommonModule], imports: [CommonModule],
template: \`<p>my-lib works!</p>\`, template: \`<p>my-lib works!</p>\`,
styles: \`\`, styles: \`\`
}) })
export class MyLibComponent {} export class MyLibComponent {}
" "
`; `;
exports[`lib --standalone should generate a library with a standalone component as entry point following SFC pattern 1`] = ` exports[`lib --standalone should generate a library with a standalone component as entry point following SFC pattern 1`] = `"export * from './lib/my-lib/my-lib.component';"`;
"export * from './lib/my-lib/my-lib.component';
"
`;
exports[`lib --standalone should generate a library with a standalone component as entry point following SFC pattern 2`] = ` exports[`lib --standalone should generate a library with a standalone component as entry point following SFC pattern 2`] = `
"import { Component } from '@angular/core'; "import { Component } from '@angular/core';
@ -205,7 +187,7 @@ import { CommonModule } from '@angular/common';
standalone: true, standalone: true,
imports: [CommonModule], imports: [CommonModule],
template: \`<p>my-lib works!</p>\`, template: \`<p>my-lib works!</p>\`,
styles: \`\`, styles: \`\`
}) })
export class MyLibComponent {} export class MyLibComponent {}
" "
@ -221,7 +203,7 @@ describe('MyLibComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [MyLibComponent], imports: [MyLibComponent]
}).compileComponents(); }).compileComponents();
fixture = TestBed.createComponent(MyLibComponent); fixture = TestBed.createComponent(MyLibComponent);
@ -239,15 +221,16 @@ describe('MyLibComponent', () => {
exports[`lib --standalone should generate a library with a standalone component as entry point with routing setup 1`] = ` exports[`lib --standalone should generate a library with a standalone component as entry point with routing setup 1`] = `
"export * from './lib/lib.routes'; "export * from './lib/lib.routes';
export * from './lib/my-lib/my-lib.component'; export * from './lib/my-lib/my-lib.component';"
"
`; `;
exports[`lib --standalone should generate a library with a standalone component as entry point with routing setup 2`] = ` exports[`lib --standalone should generate a library with a standalone component as entry point with routing setup 2`] = `
"import { Route } from '@angular/router'; "import { Route } from '@angular/router';
import { MyLibComponent } from './my-lib/my-lib.component'; import { MyLibComponent } from './my-lib/my-lib.component';
export const myLibRoutes: Route[] = [{ path: '', component: MyLibComponent }]; export const myLibRoutes: Route[] = [
{ path: '', component: MyLibComponent }
];
" "
`; `;
@ -260,7 +243,7 @@ import { CommonModule } from '@angular/common';
standalone: true, standalone: true,
imports: [CommonModule], imports: [CommonModule],
templateUrl: './my-lib.component.html', templateUrl: './my-lib.component.html',
styleUrl: './my-lib.component.css', styleUrl: './my-lib.component.css'
}) })
export class MyLibComponent {} export class MyLibComponent {}
" "
@ -276,7 +259,7 @@ describe('MyLibComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [MyLibComponent], imports: [MyLibComponent]
}).compileComponents(); }).compileComponents();
fixture = TestBed.createComponent(MyLibComponent); fixture = TestBed.createComponent(MyLibComponent);
@ -294,15 +277,16 @@ describe('MyLibComponent', () => {
exports[`lib --standalone should generate a library with a standalone component as entry point with routing setup and attach it to parent module as a lazy child 1`] = ` exports[`lib --standalone should generate a library with a standalone component as entry point with routing setup and attach it to parent module as a lazy child 1`] = `
"export * from './lib/lib.routes'; "export * from './lib/lib.routes';
export * from './lib/my-lib/my-lib.component'; export * from './lib/my-lib/my-lib.component';"
"
`; `;
exports[`lib --standalone should generate a library with a standalone component as entry point with routing setup and attach it to parent module as a lazy child 2`] = ` exports[`lib --standalone should generate a library with a standalone component as entry point with routing setup and attach it to parent module as a lazy child 2`] = `
"import { Route } from '@angular/router'; "import { Route } from '@angular/router';
import { MyLibComponent } from './my-lib/my-lib.component'; import { MyLibComponent } from './my-lib/my-lib.component';
export const myLibRoutes: Route[] = [{ path: '', component: MyLibComponent }]; export const myLibRoutes: Route[] = [
{ path: '', component: MyLibComponent }
];
" "
`; `;
@ -310,26 +294,23 @@ exports[`lib --standalone should generate a library with a standalone component
"import { Route } from '@angular/router'; "import { Route } from '@angular/router';
export const appRoutes: Route[] = [ export const appRoutes: Route[] = [
{ { path: 'my-lib', loadChildren: () => import('@proj/my-lib').then(m => m.myLibRoutes) },];
path: 'my-lib',
loadChildren: () => import('@proj/my-lib').then((m) => m.myLibRoutes),
},
];
" "
`; `;
exports[`lib --standalone should generate a library with a standalone component as entry point with routing setup and attach it to parent module as direct child 1`] = ` exports[`lib --standalone should generate a library with a standalone component as entry point with routing setup and attach it to parent module as direct child 1`] = `
"export * from './lib/lib.routes'; "export * from './lib/lib.routes';
export * from './lib/my-lib/my-lib.component'; export * from './lib/my-lib/my-lib.component';"
"
`; `;
exports[`lib --standalone should generate a library with a standalone component as entry point with routing setup and attach it to parent module as direct child 2`] = ` exports[`lib --standalone should generate a library with a standalone component as entry point with routing setup and attach it to parent module as direct child 2`] = `
"import { Route } from '@angular/router'; "import { Route } from '@angular/router';
import { MyLibComponent } from './my-lib/my-lib.component'; import { MyLibComponent } from './my-lib/my-lib.component';
export const myLibRoutes: Route[] = [{ path: '', component: MyLibComponent }]; export const myLibRoutes: Route[] = [
{ path: '', component: MyLibComponent }
];
" "
`; `;
@ -337,7 +318,8 @@ exports[`lib --standalone should generate a library with a standalone component
"import { Route } from '@angular/router'; "import { Route } from '@angular/router';
import { myLibRoutes } from '@proj/my-lib'; import { myLibRoutes } from '@proj/my-lib';
export const appRoutes: Route[] = [{ path: 'my-lib', children: myLibRoutes }]; export const appRoutes: Route[] = [
{ path: 'my-lib', children: myLibRoutes },];
" "
`; `;
@ -346,11 +328,8 @@ exports[`lib --standalone should generate a library with a standalone component
import { MyLibComponent } from './my-lib/my-lib.component'; import { MyLibComponent } from './my-lib/my-lib.component';
export const myLibRoutes: Route[] = [ export const myLibRoutes: Route[] = [
{ { path: 'second', loadChildren: () => import('@proj/second').then(m => m.secondRoutes) },
path: 'second', { path: '', component: MyLibComponent }
loadChildren: () => import('@proj/second').then((m) => m.secondRoutes),
},
{ path: '', component: MyLibComponent },
]; ];
" "
`; `;
@ -361,16 +340,13 @@ import { MyLibComponent } from './my-lib/my-lib.component';
import { secondRoutes } from '@proj/second'; import { secondRoutes } from '@proj/second';
export const myLibRoutes: Route[] = [ export const myLibRoutes: Route[] = [
{ path: 'second', children: secondRoutes }, { path: 'second', children: secondRoutes },
{ path: '', component: MyLibComponent }, { path: '', component: MyLibComponent }
]; ];
" "
`; `;
exports[`lib --standalone should generate a library with a standalone component in a directory 1`] = ` exports[`lib --standalone should generate a library with a standalone component in a directory 1`] = `"export * from './lib/my-lib/my-lib.component';"`;
"export * from './lib/my-lib/my-lib.component';
"
`;
exports[`lib --standalone should generate a library with a standalone component in a directory 2`] = ` exports[`lib --standalone should generate a library with a standalone component in a directory 2`] = `
"import { Component } from '@angular/core'; "import { Component } from '@angular/core';
@ -381,7 +357,7 @@ import { CommonModule } from '@angular/common';
standalone: true, standalone: true,
imports: [CommonModule], imports: [CommonModule],
templateUrl: './my-lib.component.html', templateUrl: './my-lib.component.html',
styleUrl: './my-lib.component.css', styleUrl: './my-lib.component.css'
}) })
export class MyLibComponent {} export class MyLibComponent {}
" "
@ -397,7 +373,7 @@ describe('MyLibComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [MyLibComponent], imports: [MyLibComponent]
}).compileComponents(); }).compileComponents();
fixture = TestBed.createComponent(MyLibComponent); fixture = TestBed.createComponent(MyLibComponent);
@ -412,10 +388,7 @@ describe('MyLibComponent', () => {
" "
`; `;
exports[`lib --standalone should generate a library with a standalone component in a directory with a simple name 1`] = ` exports[`lib --standalone should generate a library with a standalone component in a directory with a simple name 1`] = `"export * from './lib/my-lib/my-lib.component';"`;
"export * from './lib/my-lib/my-lib.component';
"
`;
exports[`lib --standalone should generate a library with a standalone component in a directory with a simple name 2`] = ` exports[`lib --standalone should generate a library with a standalone component in a directory with a simple name 2`] = `
"import { Component } from '@angular/core'; "import { Component } from '@angular/core';
@ -426,7 +399,7 @@ import { CommonModule } from '@angular/common';
standalone: true, standalone: true,
imports: [CommonModule], imports: [CommonModule],
templateUrl: './my-lib.component.html', templateUrl: './my-lib.component.html',
styleUrl: './my-lib.component.css', styleUrl: './my-lib.component.css'
}) })
export class MyLibComponent {} export class MyLibComponent {}
" "
@ -442,7 +415,7 @@ describe('MyLibComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [MyLibComponent], imports: [MyLibComponent]
}).compileComponents(); }).compileComponents();
fixture = TestBed.createComponent(MyLibComponent); fixture = TestBed.createComponent(MyLibComponent);
@ -536,23 +509,19 @@ export class AppModule {}
`; `;
exports[`lib router lazy should update the parent module even if the route is declared outside the .forRoot(...) 1`] = ` exports[`lib router lazy should update the parent module even if the route is declared outside the .forRoot(...) 1`] = `
"import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
const routes = [
{
path: 'my-lib',
loadChildren: () => import('@proj/my-lib').then((m) => m.MyLibModule),
},
];
@NgModule({
imports: [BrowserModule, RouterModule.forRoot(routes)],
declarations: [AppComponent],
bootstrap: [AppComponent],
})
export class AppModule {}
" "
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
const routes = [{ path: 'my-lib', loadChildren: () => import('@proj/my-lib').then(m => m.MyLibModule) }];
@NgModule({
imports: [BrowserModule, RouterModule.forRoot(routes)],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
"
`; `;

View File

@ -1,5 +1,5 @@
import { Route } from '@angular/router'; import { Route } from '@angular/router';
export const <%= libPropertyName %>Routes: Route[] = [ export const <%= libPropertyName %>Routes: Route[] = [
/* {path: '', pathMatch: 'full', component: InsertYourComponentHere} */ /* { path: '', pathMatch: 'full', component: InsertYourComponentHere } */
]; ];

View File

@ -2,5 +2,5 @@ import { Route } from '@angular/router';
import { <%= libClassName %>Component } from './<%= pathToComponent %>.component'; import { <%= libClassName %>Component } from './<%= pathToComponent %>.component';
export const <%= libPropertyName %>Routes: Route[] = [ export const <%= libPropertyName %>Routes: Route[] = [
{path: '', component: <%= libClassName %>Component} { path: '', component: <%= libClassName %>Component }
]; ];

View File

@ -24,13 +24,13 @@ export function addLoadChildren(
true true
); );
const route = `{path: '${ const route = `{ path: '${
names(options.fileName).fileName names(options.fileName).fileName
}', loadChildren: () => import('${options.importPath}').then(m => m.${ }', loadChildren: () => import('${options.importPath}').then(m => m.${
options.standalone options.standalone
? `${names(options.name).propertyName}Routes` ? `${names(options.name).propertyName}Routes`
: options.moduleName : options.moduleName
})}`; }) }`;
addRoute(tree, options.parent, route); addRoute(tree, options.parent, route);
} }

View File

@ -37,7 +37,7 @@ describe('lib', () => {
publishable: false, publishable: false,
buildable: false, buildable: false,
linter: Linter.EsLint, linter: Linter.EsLint,
skipFormat: false, skipFormat: true,
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
simpleName: false, simpleName: false,
strict: true, strict: true,
@ -151,7 +151,10 @@ describe('lib', () => {
const moduleFileExists = tree.exists('my-lib/src/lib/my-lib.module.ts'); const moduleFileExists = tree.exists('my-lib/src/lib/my-lib.module.ts');
expect(moduleFileExists).toBeFalsy(); expect(moduleFileExists).toBeFalsy();
const indexApi = tree.read('my-lib/src/index.ts', 'utf-8'); const indexApi = tree.read('my-lib/src/index.ts', 'utf-8');
expect(indexApi).toMatchInlineSnapshot(`""`); expect(indexApi).toMatchInlineSnapshot(`
"
"
`);
}); });
it('should remove "build" target from project.json when a library is not publishable', async () => { it('should remove "build" target from project.json when a library is not publishable', async () => {
@ -594,11 +597,17 @@ describe('lib', () => {
expect(tree.read('my-dir/my-lib/.eslintrc.json', 'utf-8')) expect(tree.read('my-dir/my-lib/.eslintrc.json', 'utf-8'))
.toMatchInlineSnapshot(` .toMatchInlineSnapshot(`
"{ "{
"extends": ["../../.eslintrc.json"], "extends": [
"ignorePatterns": ["!**/*"], "../../.eslintrc.json"
],
"ignorePatterns": [
"!**/*"
],
"overrides": [ "overrides": [
{ {
"files": ["*.ts"], "files": [
"*.ts"
],
"extends": [ "extends": [
"plugin:@nx/angular", "plugin:@nx/angular",
"plugin:@angular-eslint/template/process-inline-templates" "plugin:@angular-eslint/template/process-inline-templates"
@ -623,12 +632,18 @@ describe('lib', () => {
} }
}, },
{ {
"files": ["*.html"], "files": [
"extends": ["plugin:@nx/angular-template"], "*.html"
],
"extends": [
"plugin:@nx/angular-template"
],
"rules": {} "rules": {}
}, },
{ {
"files": ["*.json"], "files": [
"*.json"
],
"parser": "jsonc-eslint-parser", "parser": "jsonc-eslint-parser",
"rules": { "rules": {
"@nx/dependency-checks": "error" "@nx/dependency-checks": "error"
@ -721,6 +736,7 @@ describe('lib', () => {
routing: true, routing: true,
lazy: true, lazy: true,
parent: 'myapp/src/app/app.module.ts', parent: 'myapp/src/app/app.module.ts',
skipFormat: false,
}); });
const moduleContents = tree const moduleContents = tree
@ -737,6 +753,7 @@ describe('lib', () => {
lazy: true, lazy: true,
simpleName: true, simpleName: true,
parent: 'myapp/src/app/app.module.ts', parent: 'myapp/src/app/app.module.ts',
skipFormat: false,
}); });
const moduleContents2 = tree const moduleContents2 = tree
@ -753,6 +770,7 @@ describe('lib', () => {
lazy: true, lazy: true,
simpleName: true, simpleName: true,
parent: 'myapp/src/app/app.module.ts', parent: 'myapp/src/app/app.module.ts',
skipFormat: false,
}); });
const moduleContents3 = tree const moduleContents3 = tree
@ -1480,6 +1498,7 @@ describe('lib', () => {
await generateTestApplication(tree, { await generateTestApplication(tree, {
name: 'app1', name: 'app1',
routing: true, routing: true,
skipFormat: true,
}); });
// ACT // ACT
@ -1504,6 +1523,7 @@ describe('lib', () => {
await generateTestApplication(tree, { await generateTestApplication(tree, {
name: 'app1', name: 'app1',
routing: true, routing: true,
skipFormat: true,
}); });
// ACT // ACT
@ -1530,6 +1550,7 @@ describe('lib', () => {
name: 'app1', name: 'app1',
routing: true, routing: true,
standalone: true, standalone: true,
skipFormat: true,
}); });
// ACT // ACT
@ -1545,7 +1566,8 @@ describe('lib', () => {
"import { Route } from '@angular/router'; "import { Route } from '@angular/router';
import { myLibRoutes } from '@proj/my-lib'; import { myLibRoutes } from '@proj/my-lib';
export const appRoutes: Route[] = [{ path: 'my-lib', children: myLibRoutes }]; export const appRoutes: Route[] = [
{ path: 'my-lib', children: myLibRoutes },];
" "
`); `);
}); });
@ -1556,6 +1578,7 @@ describe('lib', () => {
name: 'app1', name: 'app1',
routing: true, routing: true,
standalone: true, standalone: true,
skipFormat: true,
}); });
// ACT // ACT
@ -1572,11 +1595,7 @@ describe('lib', () => {
"import { Route } from '@angular/router'; "import { Route } from '@angular/router';
export const appRoutes: Route[] = [ export const appRoutes: Route[] = [
{ { path: 'my-lib', loadChildren: () => import('@proj/my-lib').then(m => m.myLibRoutes) },];
path: 'my-lib',
loadChildren: () => import('@proj/my-lib').then((m) => m.myLibRoutes),
},
];
" "
`); `);
}); });

View File

@ -37,7 +37,7 @@ describe('@nx/angular:move', () => {
linter: Linter.EsLint, linter: Linter.EsLint,
publishable: false, publishable: false,
simpleName: true, simpleName: true,
skipFormat: false, skipFormat: true,
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
standalone: false, standalone: false,
}); });
@ -56,13 +56,18 @@ describe('@nx/angular:move', () => {
destination: 'mynewlib', destination: 'mynewlib',
updateImportPath: true, updateImportPath: true,
projectNameAndRootFormat: 'as-provided', projectNameAndRootFormat: 'as-provided',
skipFormat: true,
}); });
expect(tree.exists('mynewlib/src/lib/mynewlib.module.ts')).toEqual(true); expect(tree.exists('mynewlib/src/lib/mynewlib.module.ts')).toEqual(true);
}); });
it('should update ng-package.json dest property', async () => { it('should update ng-package.json dest property', async () => {
await generateTestLibrary(tree, { name: 'mylib2', buildable: true }); await generateTestLibrary(tree, {
name: 'mylib2',
buildable: true,
skipFormat: true,
});
addProjectToGraph('mylib2'); addProjectToGraph('mylib2');
await angularMoveGenerator(tree, { await angularMoveGenerator(tree, {
@ -70,6 +75,7 @@ describe('@nx/angular:move', () => {
destination: 'mynewlib2', destination: 'mynewlib2',
updateImportPath: true, updateImportPath: true,
projectNameAndRootFormat: 'as-provided', projectNameAndRootFormat: 'as-provided',
skipFormat: true,
}); });
const ngPackageJson = readJson(tree, 'mynewlib2/ng-package.json'); const ngPackageJson = readJson(tree, 'mynewlib2/ng-package.json');
@ -77,10 +83,15 @@ describe('@nx/angular:move', () => {
}); });
it('should update secondary entry points readme file', async () => { it('should update secondary entry points readme file', async () => {
await generateTestLibrary(tree, { name: 'mylib2', buildable: true }); await generateTestLibrary(tree, {
name: 'mylib2',
buildable: true,
skipFormat: true,
});
await librarySecondaryEntryPointGenerator(tree, { await librarySecondaryEntryPointGenerator(tree, {
library: 'mylib2', library: 'mylib2',
name: 'testing', name: 'testing',
skipFormat: true,
}); });
addProjectToGraph('mylib2'); addProjectToGraph('mylib2');
@ -90,6 +101,7 @@ describe('@nx/angular:move', () => {
destination: 'mynewlib2', destination: 'mynewlib2',
updateImportPath: true, updateImportPath: true,
projectNameAndRootFormat: 'as-provided', projectNameAndRootFormat: 'as-provided',
skipFormat: true,
}); });
const readme = tree.read('mynewlib2/testing/README.md', 'utf-8'); const readme = tree.read('mynewlib2/testing/README.md', 'utf-8');
@ -109,6 +121,7 @@ describe('@nx/angular:move', () => {
destination: 'my/lib', destination: 'my/lib',
updateImportPath: true, updateImportPath: true,
projectNameAndRootFormat: 'as-provided', projectNameAndRootFormat: 'as-provided',
skipFormat: true,
}); });
expect(tree.exists('my/lib/src/lib/my-lib.module.ts')).toBe(true); expect(tree.exists('my/lib/src/lib/my-lib.module.ts')).toBe(true);
@ -124,7 +137,7 @@ describe('@nx/angular:move', () => {
linter: Linter.EsLint, linter: Linter.EsLint,
publishable: false, publishable: false,
simpleName: true, simpleName: true,
skipFormat: false, skipFormat: true,
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
}); });
tree.write( tree.write(
@ -173,6 +186,7 @@ describe('@nx/angular:move', () => {
destination: 'shared/my-lib', destination: 'shared/my-lib',
updateImportPath: true, updateImportPath: true,
projectNameAndRootFormat: 'as-provided', projectNameAndRootFormat: 'as-provided',
skipFormat: true,
}); });
expect(tree.exists('shared/my-lib/src/lib/shared-my-lib.module.ts')).toBe( expect(tree.exists('shared/my-lib/src/lib/shared-my-lib.module.ts')).toBe(
@ -211,6 +225,7 @@ describe('@nx/angular:move', () => {
destination: 'shared/my-lib', destination: 'shared/my-lib',
updateImportPath: true, updateImportPath: true,
projectNameAndRootFormat: 'as-provided', projectNameAndRootFormat: 'as-provided',
skipFormat: true,
}); });
const importerFile = tree.read( const importerFile = tree.read(
@ -234,6 +249,7 @@ describe('@nx/angular:move', () => {
destination: 'shared/my-lib', destination: 'shared/my-lib',
updateImportPath: true, updateImportPath: true,
projectNameAndRootFormat: 'as-provided', projectNameAndRootFormat: 'as-provided',
skipFormat: true,
}); });
const indexFile = tree.read('shared/my-lib/src/index.ts', 'utf-8'); const indexFile = tree.read('shared/my-lib/src/index.ts', 'utf-8');
@ -251,7 +267,7 @@ describe('@nx/angular:move', () => {
linter: Linter.EsLint, linter: Linter.EsLint,
publishable: false, publishable: false,
simpleName: true, simpleName: true,
skipFormat: false, skipFormat: true,
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
}); });
@ -272,6 +288,7 @@ describe('@nx/angular:move', () => {
destination: 'my-destination', destination: 'my-destination',
updateImportPath: true, updateImportPath: true,
projectNameAndRootFormat: 'as-provided', projectNameAndRootFormat: 'as-provided',
skipFormat: true,
}); });
expect( expect(
@ -294,6 +311,7 @@ describe('@nx/angular:move', () => {
destination: 'my-destination', destination: 'my-destination',
updateImportPath: true, updateImportPath: true,
projectNameAndRootFormat: 'as-provided', projectNameAndRootFormat: 'as-provided',
skipFormat: true,
}); });
const importerFile = tree.read( const importerFile = tree.read(
@ -317,6 +335,7 @@ describe('@nx/angular:move', () => {
destination: 'my-destination', destination: 'my-destination',
updateImportPath: true, updateImportPath: true,
projectNameAndRootFormat: 'as-provided', projectNameAndRootFormat: 'as-provided',
skipFormat: true,
}); });
const indexFile = tree.read('my-destination/src/index.ts', 'utf-8'); const indexFile = tree.read('my-destination/src/index.ts', 'utf-8');
@ -334,7 +353,7 @@ describe('@nx/angular:move', () => {
linter: Linter.EsLint, linter: Linter.EsLint,
publishable: false, publishable: false,
simpleName: true, simpleName: true,
skipFormat: false, skipFormat: true,
unitTestRunner: UnitTestRunner.Jest, unitTestRunner: UnitTestRunner.Jest,
standalone: false, standalone: false,
}); });
@ -346,6 +365,7 @@ describe('@nx/angular:move', () => {
destination: 'my-destination', destination: 'my-destination',
updateImportPath: true, updateImportPath: true,
projectNameAndRootFormat: 'as-provided', projectNameAndRootFormat: 'as-provided',
skipFormat: true,
}); });
const moduleFile = tree.read( const moduleFile = tree.read(
@ -361,6 +381,7 @@ describe('@nx/angular:move', () => {
name: 'mylib2', name: 'mylib2',
buildable: true, buildable: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
addProjectToGraph('mylib2'); addProjectToGraph('mylib2');
@ -369,6 +390,7 @@ describe('@nx/angular:move', () => {
destination: 'mynewlib', destination: 'mynewlib',
updateImportPath: true, updateImportPath: true,
projectNameAndRootFormat: 'derived', projectNameAndRootFormat: 'derived',
skipFormat: true,
}); });
expect(tree.exists('libs/mynewlib/src/lib/mynewlib.module.ts')).toEqual( expect(tree.exists('libs/mynewlib/src/lib/mynewlib.module.ts')).toEqual(

View File

@ -144,7 +144,7 @@ describe('workspace', () => {
}) })
); );
await migrateFromAngularCli(tree, {}); await migrateFromAngularCli(tree, { skipFormat: true });
expect(readJson(tree, 'package.json').scripts).toStrictEqual({ expect(readJson(tree, 'package.json').scripts).toStrictEqual({
ng: 'ng', ng: 'ng',
@ -208,35 +208,38 @@ describe('workspace', () => {
tree.write('/projects/myApp/e2e/protractor.conf.js', '// content'); tree.write('/projects/myApp/e2e/protractor.conf.js', '// content');
tree.write('/projects/myApp/src/app/app.module.ts', '// content'); tree.write('/projects/myApp/src/app/app.module.ts', '// content');
await migrateFromAngularCli(tree, {}); await migrateFromAngularCli(tree, { skipFormat: true });
expect(tree.exists('angular.json')).toBe(false); expect(tree.exists('angular.json')).toBe(false);
}); });
it('should set the default project correctly', async () => { it('should set the default project correctly', async () => {
await migrateFromAngularCli(tree, {}); await migrateFromAngularCli(tree, { skipFormat: true });
expect(readJson(tree, 'nx.json').defaultProject).toBe('myApp'); expect(readJson(tree, 'nx.json').defaultProject).toBe('myApp');
}); });
it('should create nx.json', async () => { it('should create nx.json', async () => {
await migrateFromAngularCli(tree, { defaultBase: 'main' }); await migrateFromAngularCli(tree, {
defaultBase: 'main',
skipFormat: true,
});
expect(readJson(tree, 'nx.json')).toMatchSnapshot(); expect(readJson(tree, 'nx.json')).toMatchSnapshot();
}); });
it('should work if angular-cli workspace had tsconfig.base.json', async () => { it('should work if angular-cli workspace had tsconfig.base.json', async () => {
tree.rename('tsconfig.json', 'tsconfig.base.json'); tree.rename('tsconfig.json', 'tsconfig.base.json');
await migrateFromAngularCli(tree, {}); await migrateFromAngularCli(tree, { skipFormat: true });
expect(readJson(tree, 'tsconfig.base.json')).toMatchSnapshot(); expect(readJson(tree, 'tsconfig.base.json')).toMatchSnapshot();
}); });
it('should update tsconfig.base.json if present', async () => { it('should update tsconfig.base.json if present', async () => {
await migrateFromAngularCli(tree, {}); await migrateFromAngularCli(tree, { skipFormat: true });
expect(readJson(tree, 'tsconfig.base.json')).toMatchSnapshot(); expect(readJson(tree, 'tsconfig.base.json')).toMatchSnapshot();
}); });
it('should work with existing .prettierignore file', async () => { it('should work with existing .prettierignore file', async () => {
tree.write('/.prettierignore', '# existing ignore rules'); tree.write('/.prettierignore', '# existing ignore rules');
await migrateFromAngularCli(tree, {}); await migrateFromAngularCli(tree, { skipFormat: true });
const prettierIgnore = tree.read('/.prettierignore').toString(); const prettierIgnore = tree.read('/.prettierignore').toString();
expect(prettierIgnore).toBe('# existing ignore rules'); expect(prettierIgnore).toBe('# existing ignore rules');
@ -269,19 +272,19 @@ describe('workspace', () => {
}, },
}); });
await migrateFromAngularCli(tree, {}); await migrateFromAngularCli(tree, { skipFormat: true });
expect(tree.exists('apps/.gitkeep')).toBe(true); expect(tree.exists('apps/.gitkeep')).toBe(true);
}); });
it('should not generate .gitkeep file in apps directory when there is at least one application', async () => { it('should not generate .gitkeep file in apps directory when there is at least one application', async () => {
await migrateFromAngularCli(tree, {}); await migrateFromAngularCli(tree, { skipFormat: true });
expect(tree.exists('apps/.gitkeep')).toBe(false); expect(tree.exists('apps/.gitkeep')).toBe(false);
}); });
it('should generate .gitkeep file in libs directory when there are no libraries', async () => { it('should generate .gitkeep file in libs directory when there are no libraries', async () => {
await migrateFromAngularCli(tree, {}); await migrateFromAngularCli(tree, { skipFormat: true });
expect(tree.exists('libs/.gitkeep')).toBe(true); expect(tree.exists('libs/.gitkeep')).toBe(true);
}); });
@ -332,13 +335,13 @@ describe('workspace', () => {
}, },
}); });
await migrateFromAngularCli(tree, {}); await migrateFromAngularCli(tree, { skipFormat: true });
expect(tree.exists('libs/.gitkeep')).toBe(false); expect(tree.exists('libs/.gitkeep')).toBe(false);
}); });
it('should create a root eslint config', async () => { it('should create a root eslint config', async () => {
await migrateFromAngularCli(tree, {}); await migrateFromAngularCli(tree, { skipFormat: true });
expect(readJson(tree, '.eslintrc.json')).toMatchSnapshot(); expect(readJson(tree, '.eslintrc.json')).toMatchSnapshot();
}); });
@ -350,7 +353,7 @@ describe('workspace', () => {
return json; return json;
}); });
await migrateFromAngularCli(tree, {}); await migrateFromAngularCli(tree, { skipFormat: true });
expect(tree.exists('.eslintrc.json')).toBe(false); expect(tree.exists('.eslintrc.json')).toBe(false);
}); });
@ -415,7 +418,7 @@ describe('workspace', () => {
}, },
}); });
await migrateFromAngularCli(tree, {}); await migrateFromAngularCli(tree, { skipFormat: true });
expect(tree.exists('angular.json')).toBe(false); expect(tree.exists('angular.json')).toBe(false);
expect(tree.exists('apps/app1/project.json')).toBe(true); expect(tree.exists('apps/app1/project.json')).toBe(true);
@ -511,7 +514,7 @@ describe('workspace', () => {
}, },
}); });
await migrateFromAngularCli(tree, {}); await migrateFromAngularCli(tree, { skipFormat: true });
expect(tree.exists('angular.json')).toBe(false); expect(tree.exists('angular.json')).toBe(false);
expect(tree.exists('apps/app1/project.json')).toBe(true); expect(tree.exists('apps/app1/project.json')).toBe(true);

View File

@ -19,7 +19,7 @@ describe('ngAdd generator', () => {
}); });
it('should initialize the Angular plugin when in an Nx workspace', async () => { it('should initialize the Angular plugin when in an Nx workspace', async () => {
await ngAddGenerator(tree, {}); await ngAddGenerator(tree, { skipFormat: true });
expect(initGenerator.angularInitGenerator).toHaveBeenCalled(); expect(initGenerator.angularInitGenerator).toHaveBeenCalled();
expect(angularCliMigrator.migrateFromAngularCli).not.toHaveBeenCalled(); expect(angularCliMigrator.migrateFromAngularCli).not.toHaveBeenCalled();
@ -28,7 +28,7 @@ describe('ngAdd generator', () => {
it('should perform a migration when in an Angular CLI workspace', async () => { it('should perform a migration when in an Angular CLI workspace', async () => {
tree.delete('nx.json'); tree.delete('nx.json');
await ngAddGenerator(tree, {}); await ngAddGenerator(tree, { skipFormat: true });
expect(angularCliMigrator.migrateFromAngularCli).toHaveBeenCalled(); expect(angularCliMigrator.migrateFromAngularCli).toHaveBeenCalled();
expect(initGenerator.angularInitGenerator).not.toHaveBeenCalled(); expect(initGenerator.angularInitGenerator).not.toHaveBeenCalled();

View File

@ -14,7 +14,9 @@ exports[`ngrx-feature-store NgModule should generate into a subdirectory correct
"import { createAction, props } from '@ngrx/store'; "import { createAction, props } from '@ngrx/store';
import { UsersEntity } from './users.models'; import { UsersEntity } from './users.models';
export const initUsers = createAction('[Users Page] Init'); export const initUsers = createAction(
'[Users Page] Init'
);
export const loadUsersSuccess = createAction( export const loadUsersSuccess = createAction(
'[Users/API] Load Users Success', '[Users/API] Load Users Success',
@ -39,16 +41,15 @@ import * as UsersFeature from './users.reducer';
export class UsersEffects { export class UsersEffects {
private actions$ = inject(Actions); private actions$ = inject(Actions);
init$ = createEffect(() => init$ = createEffect(() => this.actions$.pipe(
this.actions$.pipe( ofType(UsersActions.initUsers),
ofType(UsersActions.initUsers), switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))),
switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))), catchError((error) => {
catchError((error) => {
console.error('Error', error); console.error('Error', error);
return of(UsersActions.loadUsersFailure({ error })); return of(UsersActions.loadUsersFailure({ error }));
}) }
) )
); ));
} }
" "
`; `;
@ -103,25 +104,24 @@ export interface UsersPartialState {
readonly [USERS_FEATURE_KEY]: UsersState; readonly [USERS_FEATURE_KEY]: UsersState;
} }
export const usersAdapter: EntityAdapter<UsersEntity> = export const usersAdapter: EntityAdapter<UsersEntity> = createEntityAdapter<UsersEntity>();
createEntityAdapter<UsersEntity>();
export const initialUsersState: UsersState = usersAdapter.getInitialState({ export const initialUsersState: UsersState = usersAdapter.getInitialState({
// set initial required properties // set initial required properties
loaded: false, loaded: false
}); });
const reducer = createReducer( const reducer = createReducer(
initialUsersState, initialUsersState,
on(UsersActions.initUsers, (state) => ({ on(UsersActions.initUsers,
...state, state => ({ ...state, loaded: false, error: null })
loaded: false, ),
error: null, on(UsersActions.loadUsersSuccess,
})), (state, { users }) => usersAdapter.setAll(users, { ...state, loaded: true })
on(UsersActions.loadUsersSuccess, (state, { users }) => ),
usersAdapter.setAll(users, { ...state, loaded: true }) on(UsersActions.loadUsersFailure,
(state, { error }) => ({ ...state, error })
), ),
on(UsersActions.loadUsersFailure, (state, { error }) => ({ ...state, error }))
); );
export function usersReducer(state: UsersState | undefined, action: Action) { export function usersReducer(state: UsersState | undefined, action: Action) {
@ -135,8 +135,7 @@ exports[`ngrx-feature-store NgModule should generate into a subdirectory correct
import { USERS_FEATURE_KEY, UsersState, usersAdapter } from './users.reducer'; import { USERS_FEATURE_KEY, UsersState, usersAdapter } from './users.reducer';
// Lookup the 'Users' feature state managed by NgRx // Lookup the 'Users' feature state managed by NgRx
export const selectUsersState = export const selectUsersState = createFeatureSelector<UsersState>(USERS_FEATURE_KEY);
createFeatureSelector<UsersState>(USERS_FEATURE_KEY);
const { selectAll, selectEntities } = usersAdapter.getSelectors(); const { selectAll, selectEntities } = usersAdapter.getSelectors();
@ -183,11 +182,7 @@ import { UsersEffects } from './+state/users/users.effects';
import { UsersFacade } from './+state/users/users.facade'; import { UsersFacade } from './+state/users/users.facade';
@NgModule({ @NgModule({
imports: [ imports: [CommonModule, StoreModule.forFeature(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer), EffectsModule.forFeature([UsersEffects])],
CommonModule,
StoreModule.forFeature(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
EffectsModule.forFeature([UsersEffects]),
],
providers: [UsersFacade], providers: [UsersFacade],
}) })
export class FeatureModuleModule {} export class FeatureModuleModule {}
@ -717,7 +712,7 @@ import {
USERS_FEATURE_KEY, USERS_FEATURE_KEY,
UsersState, UsersState,
initialUsersState, initialUsersState,
usersReducer, usersReducer
} from './users.reducer'; } from './users.reducer';
import * as UsersSelectors from './users.selectors'; import * as UsersSelectors from './users.selectors';
@ -730,7 +725,7 @@ describe('UsersFacade', () => {
let store: Store<TestSchema>; let store: Store<TestSchema>;
const createUsersEntity = (id: string, name = ''): UsersEntity => ({ const createUsersEntity = (id: string, name = ''): UsersEntity => ({
id, id,
name: name || \`name-\${id}\`, name: name || \`name-\${id}\`
}); });
describe('used in NgModule', () => { describe('used in NgModule', () => {
@ -738,9 +733,9 @@ describe('UsersFacade', () => {
@NgModule({ @NgModule({
imports: [ imports: [
StoreModule.forFeature(USERS_FEATURE_KEY, usersReducer), StoreModule.forFeature(USERS_FEATURE_KEY, usersReducer),
EffectsModule.forFeature([UsersEffects]), EffectsModule.forFeature([UsersEffects])
], ],
providers: [UsersFacade], providers: [UsersFacade]
}) })
class CustomFeatureModule {} class CustomFeatureModule {}
@ -749,7 +744,7 @@ describe('UsersFacade', () => {
StoreModule.forRoot({}), StoreModule.forRoot({}),
EffectsModule.forRoot([]), EffectsModule.forRoot([]),
CustomFeatureModule, CustomFeatureModule,
], ]
}) })
class RootModule {} class RootModule {}
TestBed.configureTestingModule({ imports: [RootModule] }); TestBed.configureTestingModule({ imports: [RootModule] });
@ -787,10 +782,11 @@ describe('UsersFacade', () => {
expect(list.length).toBe(0); expect(list.length).toBe(0);
expect(isLoaded).toBe(false); expect(isLoaded).toBe(false);
store.dispatch( store.dispatch(UsersActions.loadUsersSuccess({
UsersActions.loadUsersSuccess({ users: [
users: [createUsersEntity('AAA'), createUsersEntity('BBB')], createUsersEntity('AAA'),
}) createUsersEntity('BBB')
]})
); );
list = await readFirst(facade.allUsers$); list = await readFirst(facade.allUsers$);
@ -808,7 +804,9 @@ exports[`ngrx-feature-store Standalone APIs should generate the files with the c
"import { createAction, props } from '@ngrx/store'; "import { createAction, props } from '@ngrx/store';
import { UsersEntity } from './users.models'; import { UsersEntity } from './users.models';
export const initUsers = createAction('[Users Page] Init'); export const initUsers = createAction(
'[Users Page] Init'
);
export const loadUsersSuccess = createAction( export const loadUsersSuccess = createAction(
'[Users/API] Load Users Success', '[Users/API] Load Users Success',
@ -833,16 +831,15 @@ import * as UsersFeature from './users.reducer';
export class UsersEffects { export class UsersEffects {
private actions$ = inject(Actions); private actions$ = inject(Actions);
init$ = createEffect(() => init$ = createEffect(() => this.actions$.pipe(
this.actions$.pipe( ofType(UsersActions.initUsers),
ofType(UsersActions.initUsers), switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))),
switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))), catchError((error) => {
catchError((error) => {
console.error('Error', error); console.error('Error', error);
return of(UsersActions.loadUsersFailure({ error })); return of(UsersActions.loadUsersFailure({ error }));
}) }
) )
); ));
} }
" "
`; `;
@ -868,7 +865,7 @@ describe('UsersEffects', () => {
providers: [ providers: [
UsersEffects, UsersEffects,
provideMockActions(() => actions), provideMockActions(() => actions),
provideMockStore(), provideMockStore()
], ],
}); });
@ -879,9 +876,7 @@ describe('UsersEffects', () => {
it('should work', () => { it('should work', () => {
actions = hot('-a-|', { a: UsersActions.initUsers() }); actions = hot('-a-|', { a: UsersActions.initUsers() });
const expected = hot('-a-|', { const expected = hot('-a-|', { a: UsersActions.loadUsersSuccess({ users: [] }) });
a: UsersActions.loadUsersSuccess({ users: [] }),
});
expect(effects.init$).toBeObservable(expected); expect(effects.init$).toBeObservable(expected);
}); });
@ -920,25 +915,24 @@ export interface UsersPartialState {
readonly [USERS_FEATURE_KEY]: UsersState; readonly [USERS_FEATURE_KEY]: UsersState;
} }
export const usersAdapter: EntityAdapter<UsersEntity> = export const usersAdapter: EntityAdapter<UsersEntity> = createEntityAdapter<UsersEntity>();
createEntityAdapter<UsersEntity>();
export const initialUsersState: UsersState = usersAdapter.getInitialState({ export const initialUsersState: UsersState = usersAdapter.getInitialState({
// set initial required properties // set initial required properties
loaded: false, loaded: false
}); });
const reducer = createReducer( const reducer = createReducer(
initialUsersState, initialUsersState,
on(UsersActions.initUsers, (state) => ({ on(UsersActions.initUsers,
...state, state => ({ ...state, loaded: false, error: null })
loaded: false, ),
error: null, on(UsersActions.loadUsersSuccess,
})), (state, { users }) => usersAdapter.setAll(users, { ...state, loaded: true })
on(UsersActions.loadUsersSuccess, (state, { users }) => ),
usersAdapter.setAll(users, { ...state, loaded: true }) on(UsersActions.loadUsersFailure,
(state, { error }) => ({ ...state, error })
), ),
on(UsersActions.loadUsersFailure, (state, { error }) => ({ ...state, error }))
); );
export function usersReducer(state: UsersState | undefined, action: Action) { export function usersReducer(state: UsersState | undefined, action: Action) {
@ -957,14 +951,14 @@ import { UsersState, initialUsersState, usersReducer } from './users.reducer';
describe('Users Reducer', () => { describe('Users Reducer', () => {
const createUsersEntity = (id: string, name = ''): UsersEntity => ({ const createUsersEntity = (id: string, name = ''): UsersEntity => ({
id, id,
name: name || \`name-\${id}\`, name: name || \`name-\${id}\`
}); });
describe('valid Users actions', () => { describe('valid Users actions', () => {
it('loadUsersSuccess should return the list of known Users', () => { it('loadUsersSuccess should return the list of known Users', () => {
const users = [ const users = [
createUsersEntity('PRODUCT-AAA'), createUsersEntity('PRODUCT-AAA'),
createUsersEntity('PRODUCT-zzz'), createUsersEntity('PRODUCT-zzz')
]; ];
const action = UsersActions.loadUsersSuccess({ users }); const action = UsersActions.loadUsersSuccess({ users });
@ -993,8 +987,7 @@ exports[`ngrx-feature-store Standalone APIs should generate the files with the c
import { USERS_FEATURE_KEY, UsersState, usersAdapter } from './users.reducer'; import { USERS_FEATURE_KEY, UsersState, usersAdapter } from './users.reducer';
// Lookup the 'Users' feature state managed by NgRx // Lookup the 'Users' feature state managed by NgRx
export const selectUsersState = export const selectUsersState = createFeatureSelector<UsersState>(USERS_FEATURE_KEY);
createFeatureSelector<UsersState>(USERS_FEATURE_KEY);
const { selectAll, selectEntities } = usersAdapter.getSelectors(); const { selectAll, selectEntities } = usersAdapter.getSelectors();
@ -1033,39 +1026,31 @@ export const selectEntity = createSelector(
exports[`ngrx-feature-store Standalone APIs should generate the files with the correct content 10`] = ` exports[`ngrx-feature-store Standalone APIs should generate the files with the correct content 10`] = `
"import { UsersEntity } from './users.models'; "import { UsersEntity } from './users.models';
import { import { usersAdapter, UsersPartialState, initialUsersState } from './users.reducer';
usersAdapter,
UsersPartialState,
initialUsersState,
} from './users.reducer';
import * as UsersSelectors from './users.selectors'; import * as UsersSelectors from './users.selectors';
describe('Users Selectors', () => { describe('Users Selectors', () => {
const ERROR_MSG = 'No Error Available'; const ERROR_MSG = 'No Error Available';
const getUsersId = (it: UsersEntity) => it.id; const getUsersId = (it: UsersEntity) => it.id;
const createUsersEntity = (id: string, name = '') => const createUsersEntity = (id: string, name = '') => ({
({ id,
id, name: name || \`name-\${id}\`
name: name || \`name-\${id}\`, }) as UsersEntity;
} as UsersEntity);
let state: UsersPartialState; let state: UsersPartialState;
beforeEach(() => { beforeEach(() => {
state = { state = {
users: usersAdapter.setAll( users: usersAdapter.setAll([
[ createUsersEntity('PRODUCT-AAA'),
createUsersEntity('PRODUCT-AAA'), createUsersEntity('PRODUCT-BBB'),
createUsersEntity('PRODUCT-BBB'), createUsersEntity('PRODUCT-CCC')
createUsersEntity('PRODUCT-CCC'), ], {
], ...initialUsersState,
{ selectedId: 'PRODUCT-BBB',
...initialUsersState, error: ERROR_MSG,
selectedId: 'PRODUCT-BBB', loaded: true
error: ERROR_MSG, })
loaded: true,
}
),
}; };
}); });
@ -1111,15 +1096,7 @@ import { UsersEffects } from './+state/users.effects';
import { UsersFacade } from './+state/users.facade'; import { UsersFacade } from './+state/users.facade';
export const featureRoutes: Route[] = [ export const featureRoutes: Route[] = [
{ { path: '', component: FeatureComponent , providers: [UsersFacade, provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer), provideEffects(UsersEffects)]}
path: '',
component: FeatureComponent,
providers: [
UsersFacade,
provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
provideEffects(UsersEffects),
],
},
]; ];
" "
`; `;
@ -1132,8 +1109,7 @@ export * from './lib/+state/users.reducer';
export * from './lib/+state/users.actions'; export * from './lib/+state/users.actions';
export * from './lib/lib.routes'; export * from './lib/lib.routes';
export * from './lib/feature/feature.component'; export * from './lib/feature/feature.component';"
"
`; `;
exports[`ngrx-feature-store Standalone APIs should have the correct entry point when --barrels=true 1`] = ` exports[`ngrx-feature-store Standalone APIs should have the correct entry point when --barrels=true 1`] = `
@ -1150,6 +1126,5 @@ export * from './lib/+state/users.models';
export { UsersActions, UsersFeature, UsersSelectors }; export { UsersActions, UsersFeature, UsersSelectors };
export * from './lib/lib.routes'; export * from './lib/lib.routes';
export * from './lib/feature/feature.component'; export * from './lib/feature/feature.component';"
"
`; `;

View File

@ -4,4 +4,4 @@
export interface <%= className %>Entity { export interface <%= className %>Entity {
id: string | number; // Primary ID id: string | number; // Primary ID
name: string; name: string;
}; }

View File

@ -20,7 +20,7 @@ describe('<%= className %> Selectors', () => {
create<%= className %>Entity('PRODUCT-CCC') create<%= className %>Entity('PRODUCT-CCC')
], { ], {
...initial<%= className %>State, ...initial<%= className %>State,
selectedId : 'PRODUCT-BBB', selectedId: 'PRODUCT-BBB',
error: ERROR_MSG, error: ERROR_MSG,
loaded: true loaded: true
}) })

View File

@ -19,6 +19,7 @@ describe('ngrx-feature-store', () => {
minimal: true, minimal: true,
directory: '+state', directory: '+state',
parent, parent,
skipFormat: true,
}) })
).rejects.toThrowError( ).rejects.toThrowError(
`Parent does not exist: feature-module/src/lib/feature-module.module.ts.` `Parent does not exist: feature-module/src/lib/feature-module.module.ts.`
@ -36,6 +37,7 @@ describe('ngrx-feature-store', () => {
minimal: true, minimal: true,
directory: '+state', directory: '+state',
parent, parent,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -70,6 +72,7 @@ describe('ngrx-feature-store', () => {
directory: '+state', directory: '+state',
skipPackageJson: true, skipPackageJson: true,
parent, parent,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -97,6 +100,7 @@ describe('ngrx-feature-store', () => {
minimal: false, minimal: false,
directory: '+state', directory: '+state',
parent, parent,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -124,6 +128,7 @@ describe('ngrx-feature-store', () => {
directory: '+state', directory: '+state',
facade: true, facade: true,
parent, parent,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -151,6 +156,7 @@ describe('ngrx-feature-store', () => {
directory: 'custom', directory: 'custom',
facade: true, facade: true,
parent, parent,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -226,6 +232,7 @@ describe('ngrx-feature-store', () => {
directory: '+state', directory: '+state',
facade: true, facade: true,
parent, parent,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -247,6 +254,7 @@ describe('ngrx-feature-store', () => {
facade: true, facade: true,
parent, parent,
barrels: true, barrels: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -267,6 +275,7 @@ describe('ngrx-feature-store', () => {
directory: '+state', directory: '+state',
facade: true, facade: true,
parent, parent,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -320,6 +329,7 @@ describe('ngrx-feature-store', () => {
minimal: true, minimal: true,
directory: '+state', directory: '+state',
parent, parent,
skipFormat: true,
}) })
).rejects.toThrowError( ).rejects.toThrowError(
`Parent does not exist: feature/src/lib/lib.routes.ts` `Parent does not exist: feature/src/lib/lib.routes.ts`
@ -337,6 +347,7 @@ describe('ngrx-feature-store', () => {
minimal: true, minimal: true,
parent, parent,
directory: '+state', directory: '+state',
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -371,6 +382,7 @@ describe('ngrx-feature-store', () => {
parent, parent,
directory: '+state', directory: '+state',
skipPackageJson: true, skipPackageJson: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -398,6 +410,7 @@ describe('ngrx-feature-store', () => {
minimal: false, minimal: false,
parent, parent,
directory: '+state', directory: '+state',
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -425,6 +438,7 @@ describe('ngrx-feature-store', () => {
parent, parent,
directory: '+state', directory: '+state',
facade: true, facade: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -452,6 +466,7 @@ describe('ngrx-feature-store', () => {
parent, parent,
directory: 'custom', directory: 'custom',
facade: true, facade: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -479,6 +494,7 @@ describe('ngrx-feature-store', () => {
parent, parent,
directory: '+state', directory: '+state',
facade: true, facade: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -529,6 +545,7 @@ describe('ngrx-feature-store', () => {
parent, parent,
directory: '+state', directory: '+state',
facade: true, facade: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -548,6 +565,7 @@ describe('ngrx-feature-store', () => {
directory: '+state', directory: '+state',
facade: true, facade: true,
barrels: true, barrels: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -560,6 +578,7 @@ async function addNgModuleLib(tree: Tree, name = 'feature-module') {
await libraryGenerator(tree, { await libraryGenerator(tree, {
name, name,
standalone: false, standalone: false,
skipFormat: true,
}); });
} }
@ -568,5 +587,6 @@ async function addStandaloneLib(tree: Tree, name = 'feature') {
name, name,
standalone: true, standalone: true,
routing: true, routing: true,
skipFormat: true,
}); });
} }

View File

@ -373,16 +373,13 @@ import { StoreRouterConnectingModule } from '@ngrx/router-store';
imports: [ imports: [
BrowserModule, BrowserModule,
RouterModule.forRoot(appRoutes), RouterModule.forRoot(appRoutes),
StoreModule.forRoot( StoreModule.forRoot({}, {
{}, metaReducers: [],
{ runtimeChecks: {
metaReducers: [], strictActionImmutability: true,
runtimeChecks: { strictStateImmutability: true
strictActionImmutability: true,
strictStateImmutability: true,
},
} }
), }),
EffectsModule.forRoot([]), EffectsModule.forRoot([]),
StoreRouterConnectingModule.forRoot(), StoreRouterConnectingModule.forRoot(),
], ],
@ -410,16 +407,13 @@ import { StoreDevtoolsModule } from '@ngrx/store-devtools';
imports: [ imports: [
BrowserModule, BrowserModule,
RouterModule.forRoot(appRoutes), RouterModule.forRoot(appRoutes),
StoreModule.forRoot( StoreModule.forRoot({}, {
{}, metaReducers: [],
{ runtimeChecks: {
metaReducers: [], strictActionImmutability: true,
runtimeChecks: { strictStateImmutability: true
strictActionImmutability: true,
strictStateImmutability: true,
},
} }
), }),
EffectsModule.forRoot([]), EffectsModule.forRoot([]),
StoreRouterConnectingModule.forRoot(), StoreRouterConnectingModule.forRoot(),
StoreDevtoolsModule.instrument({ logOnly: !isDevMode() }), StoreDevtoolsModule.instrument({ logOnly: !isDevMode() }),
@ -442,14 +436,7 @@ import { UsersEffects } from './+state/users.effects';
import { UsersFacade } from './+state/users.facade'; import { UsersFacade } from './+state/users.facade';
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {
providers: [ providers: [provideEffects(UsersEffects),provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),UsersFacade,provideEffects(),provideStore(),provideRouter(appRoutes) ]
provideEffects(UsersEffects),
provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
UsersFacade,
provideEffects(),
provideStore(),
provideRouter(appRoutes),
],
}; };
" "
`; `;
@ -495,13 +482,7 @@ import * as fromUsers from './+state/users.reducer';
import { UsersEffects } from './+state/users.effects'; import { UsersEffects } from './+state/users.effects';
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {
providers: [ providers: [provideEffects(UsersEffects),provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),provideEffects(),provideStore(),provideRouter(appRoutes) ]
provideEffects(UsersEffects),
provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
provideEffects(),
provideStore(),
provideRouter(appRoutes),
],
}; };
" "
`; `;
@ -510,7 +491,9 @@ exports[`NgRxRootStoreGenerator Standalone APIs should add a root module and roo
"import { createAction, props } from '@ngrx/store'; "import { createAction, props } from '@ngrx/store';
import { UsersEntity } from './users.models'; import { UsersEntity } from './users.models';
export const initUsers = createAction('[Users Page] Init'); export const initUsers = createAction(
'[Users Page] Init'
);
export const loadUsersSuccess = createAction( export const loadUsersSuccess = createAction(
'[Users/API] Load Users Success', '[Users/API] Load Users Success',
@ -535,16 +518,15 @@ import * as UsersFeature from './users.reducer';
export class UsersEffects { export class UsersEffects {
private actions$ = inject(Actions); private actions$ = inject(Actions);
init$ = createEffect(() => init$ = createEffect(() => this.actions$.pipe(
this.actions$.pipe( ofType(UsersActions.initUsers),
ofType(UsersActions.initUsers), switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))),
switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))), catchError((error) => {
catchError((error) => {
console.error('Error', error); console.error('Error', error);
return of(UsersActions.loadUsersFailure({ error })); return of(UsersActions.loadUsersFailure({ error }));
}) }
) )
); ));
} }
" "
`; `;
@ -570,7 +552,7 @@ describe('UsersEffects', () => {
providers: [ providers: [
UsersEffects, UsersEffects,
provideMockActions(() => actions), provideMockActions(() => actions),
provideMockStore(), provideMockStore()
], ],
}); });
@ -581,9 +563,7 @@ describe('UsersEffects', () => {
it('should work', () => { it('should work', () => {
actions = hot('-a-|', { a: UsersActions.initUsers() }); actions = hot('-a-|', { a: UsersActions.initUsers() });
const expected = hot('-a-|', { const expected = hot('-a-|', { a: UsersActions.loadUsersSuccess({ users: [] }) });
a: UsersActions.loadUsersSuccess({ users: [] }),
});
expect(effects.init$).toBeObservable(expected); expect(effects.init$).toBeObservable(expected);
}); });
@ -611,25 +591,24 @@ export interface UsersPartialState {
readonly [USERS_FEATURE_KEY]: UsersState; readonly [USERS_FEATURE_KEY]: UsersState;
} }
export const usersAdapter: EntityAdapter<UsersEntity> = export const usersAdapter: EntityAdapter<UsersEntity> = createEntityAdapter<UsersEntity>();
createEntityAdapter<UsersEntity>();
export const initialUsersState: UsersState = usersAdapter.getInitialState({ export const initialUsersState: UsersState = usersAdapter.getInitialState({
// set initial required properties // set initial required properties
loaded: false, loaded: false
}); });
const reducer = createReducer( const reducer = createReducer(
initialUsersState, initialUsersState,
on(UsersActions.initUsers, (state) => ({ on(UsersActions.initUsers,
...state, state => ({ ...state, loaded: false, error: null })
loaded: false, ),
error: null, on(UsersActions.loadUsersSuccess,
})), (state, { users }) => usersAdapter.setAll(users, { ...state, loaded: true })
on(UsersActions.loadUsersSuccess, (state, { users }) => ),
usersAdapter.setAll(users, { ...state, loaded: true }) on(UsersActions.loadUsersFailure,
(state, { error }) => ({ ...state, error })
), ),
on(UsersActions.loadUsersFailure, (state, { error }) => ({ ...state, error }))
); );
export function usersReducer(state: UsersState | undefined, action: Action) { export function usersReducer(state: UsersState | undefined, action: Action) {
@ -643,8 +622,7 @@ exports[`NgRxRootStoreGenerator Standalone APIs should add a root module and roo
import { USERS_FEATURE_KEY, UsersState, usersAdapter } from './users.reducer'; import { USERS_FEATURE_KEY, UsersState, usersAdapter } from './users.reducer';
// Lookup the 'Users' feature state managed by NgRx // Lookup the 'Users' feature state managed by NgRx
export const selectUsersState = export const selectUsersState = createFeatureSelector<UsersState>(USERS_FEATURE_KEY);
createFeatureSelector<UsersState>(USERS_FEATURE_KEY);
const { selectAll, selectEntities } = usersAdapter.getSelectors(); const { selectAll, selectEntities } = usersAdapter.getSelectors();
@ -683,39 +661,31 @@ export const selectEntity = createSelector(
exports[`NgRxRootStoreGenerator Standalone APIs should add a root module and root state when --minimal=false 7`] = ` exports[`NgRxRootStoreGenerator Standalone APIs should add a root module and root state when --minimal=false 7`] = `
"import { UsersEntity } from './users.models'; "import { UsersEntity } from './users.models';
import { import { usersAdapter, UsersPartialState, initialUsersState } from './users.reducer';
usersAdapter,
UsersPartialState,
initialUsersState,
} from './users.reducer';
import * as UsersSelectors from './users.selectors'; import * as UsersSelectors from './users.selectors';
describe('Users Selectors', () => { describe('Users Selectors', () => {
const ERROR_MSG = 'No Error Available'; const ERROR_MSG = 'No Error Available';
const getUsersId = (it: UsersEntity) => it.id; const getUsersId = (it: UsersEntity) => it.id;
const createUsersEntity = (id: string, name = '') => const createUsersEntity = (id: string, name = '') => ({
({ id,
id, name: name || \`name-\${id}\`
name: name || \`name-\${id}\`, }) as UsersEntity;
} as UsersEntity);
let state: UsersPartialState; let state: UsersPartialState;
beforeEach(() => { beforeEach(() => {
state = { state = {
users: usersAdapter.setAll( users: usersAdapter.setAll([
[ createUsersEntity('PRODUCT-AAA'),
createUsersEntity('PRODUCT-AAA'), createUsersEntity('PRODUCT-BBB'),
createUsersEntity('PRODUCT-BBB'), createUsersEntity('PRODUCT-CCC')
createUsersEntity('PRODUCT-CCC'), ], {
], ...initialUsersState,
{ selectedId: 'PRODUCT-BBB',
...initialUsersState, error: ERROR_MSG,
selectedId: 'PRODUCT-BBB', loaded: true
error: ERROR_MSG, })
loaded: true,
}
),
}; };
}); });
@ -759,7 +729,7 @@ import { provideStore } from '@ngrx/store';
import { provideEffects } from '@ngrx/effects'; import { provideEffects } from '@ngrx/effects';
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {
providers: [provideEffects(), provideStore(), provideRouter(appRoutes)], providers: [provideEffects(),provideStore(),provideRouter(appRoutes) ]
}; };
" "
`; `;
@ -773,12 +743,7 @@ import { provideEffects } from '@ngrx/effects';
import { provideStoreDevtools } from '@ngrx/store-devtools'; import { provideStoreDevtools } from '@ngrx/store-devtools';
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {
providers: [ providers: [provideStoreDevtools({ logOnly: !isDevMode() }),provideEffects(),provideStore(),provideRouter(appRoutes) ]
provideStoreDevtools({ logOnly: !isDevMode() }),
provideEffects(),
provideStore(),
provideRouter(appRoutes),
],
}; };
" "
`; `;

View File

@ -15,6 +15,7 @@ describe('NgRxRootStoreGenerator', () => {
project: 'non-exist', project: 'non-exist',
minimal: true, minimal: true,
name: '', name: '',
skipFormat: true,
}) })
).rejects.toThrowError(); ).rejects.toThrowError();
}); });
@ -30,6 +31,7 @@ describe('NgRxRootStoreGenerator', () => {
project: 'my-app', project: 'my-app',
minimal: false, minimal: false,
name: undefined, name: undefined,
skipFormat: true,
}) })
).rejects.toThrowError(); ).rejects.toThrowError();
}); });
@ -43,6 +45,7 @@ describe('NgRxRootStoreGenerator', () => {
await ngrxRootStoreGenerator(tree, { await ngrxRootStoreGenerator(tree, {
project: 'my-app', project: 'my-app',
minimal: true, minimal: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -137,6 +140,7 @@ describe('NgRxRootStoreGenerator', () => {
project: 'my-app', project: 'my-app',
minimal: true, minimal: true,
addDevTools: true, addDevTools: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -154,6 +158,7 @@ describe('NgRxRootStoreGenerator', () => {
await ngrxRootStoreGenerator(tree, { await ngrxRootStoreGenerator(tree, {
project: 'my-app', project: 'my-app',
minimal: true, minimal: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -186,6 +191,7 @@ describe('NgRxRootStoreGenerator', () => {
project: 'my-app', project: 'my-app',
minimal: true, minimal: true,
addDevTools: true, addDevTools: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -205,6 +211,7 @@ describe('NgRxRootStoreGenerator', () => {
project: 'my-app', project: 'my-app',
minimal: true, minimal: true,
skipPackageJson: true, skipPackageJson: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -231,6 +238,7 @@ describe('NgRxRootStoreGenerator', () => {
project: 'non-exist', project: 'non-exist',
minimal: true, minimal: true,
name: '', name: '',
skipFormat: true,
}) })
).rejects.toThrowError(); ).rejects.toThrowError();
}); });
@ -246,6 +254,7 @@ describe('NgRxRootStoreGenerator', () => {
project: 'my-app', project: 'my-app',
minimal: false, minimal: false,
name: undefined, name: undefined,
skipFormat: true,
}) })
).rejects.toThrowError(); ).rejects.toThrowError();
}); });
@ -259,6 +268,7 @@ describe('NgRxRootStoreGenerator', () => {
await ngrxRootStoreGenerator(tree, { await ngrxRootStoreGenerator(tree, {
project: 'my-app', project: 'my-app',
minimal: true, minimal: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -295,6 +305,7 @@ describe('NgRxRootStoreGenerator', () => {
project: 'my-app', project: 'my-app',
minimal: false, minimal: false,
name: 'users', name: 'users',
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -332,6 +343,7 @@ describe('NgRxRootStoreGenerator', () => {
minimal: false, minimal: false,
name: 'users', name: 'users',
facade: true, facade: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -353,6 +365,7 @@ describe('NgRxRootStoreGenerator', () => {
project: 'my-app', project: 'my-app',
minimal: true, minimal: true,
addDevTools: true, addDevTools: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -370,6 +383,7 @@ describe('NgRxRootStoreGenerator', () => {
await ngrxRootStoreGenerator(tree, { await ngrxRootStoreGenerator(tree, {
project: 'my-app', project: 'my-app',
minimal: true, minimal: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -402,6 +416,7 @@ describe('NgRxRootStoreGenerator', () => {
project: 'my-app', project: 'my-app',
minimal: true, minimal: true,
addDevTools: true, addDevTools: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -421,6 +436,7 @@ describe('NgRxRootStoreGenerator', () => {
project: 'my-app', project: 'my-app',
minimal: true, minimal: true,
skipPackageJson: true, skipPackageJson: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -444,6 +460,7 @@ async function createNgModuleApp(tree: Tree, name = 'my-app') {
name, name,
standalone: false, standalone: false,
routing: true, routing: true,
skipFormat: true,
}); });
} }
@ -452,5 +469,6 @@ async function createStandaloneApp(tree: Tree, name = 'my-app') {
name, name,
standalone: true, standalone: true,
routing: true, routing: true,
skipFormat: true,
}); });
} }

View File

@ -21,7 +21,7 @@ describe('SuperUsersEffects', () => {
providers: [ providers: [
SuperUsersEffects, SuperUsersEffects,
provideMockActions(() => actions), provideMockActions(() => actions),
provideMockStore(), provideMockStore()
], ],
}); });
@ -32,9 +32,7 @@ describe('SuperUsersEffects', () => {
it('should work', () => { it('should work', () => {
actions = hot('-a-|', { a: SuperUsersActions.initSuperUsers() }); actions = hot('-a-|', { a: SuperUsersActions.initSuperUsers() });
const expected = hot('-a-|', { const expected = hot('-a-|', { a: SuperUsersActions.loadSuperUsersSuccess({ superUsers: [] }) });
a: SuperUsersActions.loadSuperUsersSuccess({ superUsers: [] }),
});
expect(effects.init$).toBeObservable(expected); expect(effects.init$).toBeObservable(expected);
}); });
@ -58,7 +56,7 @@ import {
SUPER_USERS_FEATURE_KEY, SUPER_USERS_FEATURE_KEY,
SuperUsersState, SuperUsersState,
initialSuperUsersState, initialSuperUsersState,
superUsersReducer, superUsersReducer
} from './super-users.reducer'; } from './super-users.reducer';
import * as SuperUsersSelectors from './super-users.selectors'; import * as SuperUsersSelectors from './super-users.selectors';
@ -71,7 +69,7 @@ describe('SuperUsersFacade', () => {
let store: Store<TestSchema>; let store: Store<TestSchema>;
const createSuperUsersEntity = (id: string, name = ''): SuperUsersEntity => ({ const createSuperUsersEntity = (id: string, name = ''): SuperUsersEntity => ({
id, id,
name: name || \`name-\${id}\`, name: name || \`name-\${id}\`
}); });
describe('used in NgModule', () => { describe('used in NgModule', () => {
@ -79,9 +77,9 @@ describe('SuperUsersFacade', () => {
@NgModule({ @NgModule({
imports: [ imports: [
StoreModule.forFeature(SUPER_USERS_FEATURE_KEY, superUsersReducer), StoreModule.forFeature(SUPER_USERS_FEATURE_KEY, superUsersReducer),
EffectsModule.forFeature([SuperUsersEffects]), EffectsModule.forFeature([SuperUsersEffects])
], ],
providers: [SuperUsersFacade], providers: [SuperUsersFacade]
}) })
class CustomFeatureModule {} class CustomFeatureModule {}
@ -90,7 +88,7 @@ describe('SuperUsersFacade', () => {
StoreModule.forRoot({}), StoreModule.forRoot({}),
EffectsModule.forRoot([]), EffectsModule.forRoot([]),
CustomFeatureModule, CustomFeatureModule,
], ]
}) })
class RootModule {} class RootModule {}
TestBed.configureTestingModule({ imports: [RootModule] }); TestBed.configureTestingModule({ imports: [RootModule] });
@ -128,13 +126,11 @@ describe('SuperUsersFacade', () => {
expect(list.length).toBe(0); expect(list.length).toBe(0);
expect(isLoaded).toBe(false); expect(isLoaded).toBe(false);
store.dispatch( store.dispatch(SuperUsersActions.loadSuperUsersSuccess({
SuperUsersActions.loadSuperUsersSuccess({ superUsers: [
superUsers: [ createSuperUsersEntity('AAA'),
createSuperUsersEntity('AAA'), createSuperUsersEntity('BBB')
createSuperUsersEntity('BBB'), ]})
],
})
); );
list = await readFirst(facade.allSuperUsers$); list = await readFirst(facade.allSuperUsers$);
@ -153,30 +149,23 @@ exports[`ngrx NgModule Syntax generated unit tests should generate specs for the
import * as SuperUsersActions from './super-users.actions'; import * as SuperUsersActions from './super-users.actions';
import { SuperUsersEntity } from './super-users.models'; import { SuperUsersEntity } from './super-users.models';
import { import { SuperUsersState, initialSuperUsersState, superUsersReducer } from './super-users.reducer';
SuperUsersState,
initialSuperUsersState,
superUsersReducer,
} from './super-users.reducer';
describe('SuperUsers Reducer', () => { describe('SuperUsers Reducer', () => {
const createSuperUsersEntity = (id: string, name = ''): SuperUsersEntity => ({ const createSuperUsersEntity = (id: string, name = ''): SuperUsersEntity => ({
id, id,
name: name || \`name-\${id}\`, name: name || \`name-\${id}\`
}); });
describe('valid SuperUsers actions', () => { describe('valid SuperUsers actions', () => {
it('loadSuperUsersSuccess should return the list of known SuperUsers', () => { it('loadSuperUsersSuccess should return the list of known SuperUsers', () => {
const superUsers = [ const superUsers = [
createSuperUsersEntity('PRODUCT-AAA'), createSuperUsersEntity('PRODUCT-AAA'),
createSuperUsersEntity('PRODUCT-zzz'), createSuperUsersEntity('PRODUCT-zzz')
]; ];
const action = SuperUsersActions.loadSuperUsersSuccess({ superUsers }); const action = SuperUsersActions.loadSuperUsersSuccess({ superUsers });
const result: SuperUsersState = superUsersReducer( const result: SuperUsersState = superUsersReducer(initialSuperUsersState, action);
initialSuperUsersState,
action
);
expect(result.loaded).toBe(true); expect(result.loaded).toBe(true);
expect(result.ids.length).toBe(2); expect(result.ids.length).toBe(2);
@ -198,39 +187,31 @@ describe('SuperUsers Reducer', () => {
exports[`ngrx NgModule Syntax generated unit tests should generate specs for the ngrx selectors 1`] = ` exports[`ngrx NgModule Syntax generated unit tests should generate specs for the ngrx selectors 1`] = `
"import { SuperUsersEntity } from './super-users.models'; "import { SuperUsersEntity } from './super-users.models';
import { import { superUsersAdapter, SuperUsersPartialState, initialSuperUsersState } from './super-users.reducer';
superUsersAdapter,
SuperUsersPartialState,
initialSuperUsersState,
} from './super-users.reducer';
import * as SuperUsersSelectors from './super-users.selectors'; import * as SuperUsersSelectors from './super-users.selectors';
describe('SuperUsers Selectors', () => { describe('SuperUsers Selectors', () => {
const ERROR_MSG = 'No Error Available'; const ERROR_MSG = 'No Error Available';
const getSuperUsersId = (it: SuperUsersEntity) => it.id; const getSuperUsersId = (it: SuperUsersEntity) => it.id;
const createSuperUsersEntity = (id: string, name = '') => const createSuperUsersEntity = (id: string, name = '') => ({
({ id,
id, name: name || \`name-\${id}\`
name: name || \`name-\${id}\`, }) as SuperUsersEntity;
} as SuperUsersEntity);
let state: SuperUsersPartialState; let state: SuperUsersPartialState;
beforeEach(() => { beforeEach(() => {
state = { state = {
superUsers: superUsersAdapter.setAll( superUsers: superUsersAdapter.setAll([
[ createSuperUsersEntity('PRODUCT-AAA'),
createSuperUsersEntity('PRODUCT-AAA'), createSuperUsersEntity('PRODUCT-BBB'),
createSuperUsersEntity('PRODUCT-BBB'), createSuperUsersEntity('PRODUCT-CCC')
createSuperUsersEntity('PRODUCT-CCC'), ], {
], ...initialSuperUsersState,
{ selectedId: 'PRODUCT-BBB',
...initialSuperUsersState, error: ERROR_MSG,
selectedId: 'PRODUCT-BBB', loaded: true
error: ERROR_MSG, })
loaded: true,
}
),
}; };
}); });
@ -244,9 +225,7 @@ describe('SuperUsers Selectors', () => {
}); });
it('selectEntity() should return the selected Entity', () => { it('selectEntity() should return the selected Entity', () => {
const result = SuperUsersSelectors.selectEntity( const result = SuperUsersSelectors.selectEntity(state) as SuperUsersEntity;
state
) as SuperUsersEntity;
const selId = getSuperUsersId(result); const selId = getSuperUsersId(result);
expect(selId).toBe('PRODUCT-BBB'); expect(selId).toBe('PRODUCT-BBB');
@ -279,25 +258,15 @@ import * as fromUsers from './+state/users.reducer';
import { UsersEffects } from './+state/users.effects'; import { UsersEffects } from './+state/users.effects';
import { StoreRouterConnectingModule } from '@ngrx/router-store'; import { StoreRouterConnectingModule } from '@ngrx/router-store';
@NgModule({ @NgModule({
imports: [ imports: [BrowserModule, RouterModule.forRoot([]), StoreModule.forRoot({}, {
BrowserModule, metaReducers: [],
RouterModule.forRoot([]), runtimeChecks: {
StoreModule.forRoot( strictActionImmutability: true,
{}, strictStateImmutability: true
{
metaReducers: [],
runtimeChecks: {
strictActionImmutability: true,
strictStateImmutability: true,
},
} }
), }), EffectsModule.forRoot([UsersEffects]), StoreRouterConnectingModule.forRoot(), StoreModule.forFeature(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer)],
EffectsModule.forRoot([UsersEffects]),
StoreRouterConnectingModule.forRoot(),
StoreModule.forFeature(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
],
declarations: [AppComponent], declarations: [AppComponent],
bootstrap: [AppComponent], bootstrap: [AppComponent]
}) })
export class AppModule {} export class AppModule {}
" "
@ -314,25 +283,15 @@ import * as fromUsers from './+state/users.reducer';
import { UsersEffects } from './+state/users.effects'; import { UsersEffects } from './+state/users.effects';
import { StoreRouterConnectingModule } from '@ngrx/router-store'; import { StoreRouterConnectingModule } from '@ngrx/router-store';
@NgModule({ @NgModule({
imports: [ imports: [BrowserModule, RouterModule.forRoot([]), StoreModule.forRoot({}, {
BrowserModule, metaReducers: [],
RouterModule.forRoot([]), runtimeChecks: {
StoreModule.forRoot( strictActionImmutability: true,
{}, strictStateImmutability: true
{
metaReducers: [],
runtimeChecks: {
strictActionImmutability: true,
strictStateImmutability: true,
},
} }
), }), EffectsModule.forRoot([UsersEffects]), StoreRouterConnectingModule.forRoot(), StoreModule.forFeature(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer)],
EffectsModule.forRoot([UsersEffects]),
StoreRouterConnectingModule.forRoot(),
StoreModule.forFeature(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
],
declarations: [AppComponent], declarations: [AppComponent],
bootstrap: [AppComponent], bootstrap: [AppComponent]
}) })
export class AppModule {} export class AppModule {}
" "
@ -346,22 +305,36 @@ import { AppComponent } from './app.component';
import { StoreModule } from '@ngrx/store'; import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects'; import { EffectsModule } from '@ngrx/effects';
import { StoreRouterConnectingModule } from '@ngrx/router-store'; import { StoreRouterConnectingModule } from '@ngrx/router-store';
@NgModule({
imports: [BrowserModule, RouterModule.forRoot([]), StoreModule.forRoot({}, {
metaReducers: [],
runtimeChecks: {
strictActionImmutability: true,
strictStateImmutability: true
}
}), EffectsModule.forRoot([]), StoreRouterConnectingModule.forRoot()],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
"
`;
exports[`ngrx NgModule Syntax should format files 1`] = `
"import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import * as fromUsers from './+state/users.reducer';
import { UsersEffects } from './+state/users.effects';
@NgModule({ @NgModule({
imports: [ imports: [
BrowserModule, BrowserModule,
RouterModule.forRoot([]), RouterModule.forRoot([]),
StoreModule.forRoot( StoreModule.forFeature(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
{}, EffectsModule.forFeature([UsersEffects]),
{
metaReducers: [],
runtimeChecks: {
strictActionImmutability: true,
strictStateImmutability: true,
},
}
),
EffectsModule.forRoot([]),
StoreRouterConnectingModule.forRoot(),
], ],
declarations: [AppComponent], declarations: [AppComponent],
bootstrap: [AppComponent], bootstrap: [AppComponent],
@ -370,6 +343,149 @@ export class AppModule {}
" "
`; `;
exports[`ngrx NgModule Syntax should format files 2`] = `
"import { createAction, props } from '@ngrx/store';
import { UsersEntity } from './users.models';
export const initUsers = createAction('[Users Page] Init');
export const loadUsersSuccess = createAction(
'[Users/API] Load Users Success',
props<{ users: UsersEntity[] }>()
);
export const loadUsersFailure = createAction(
'[Users/API] Load Users Failure',
props<{ error: any }>()
);
"
`;
exports[`ngrx NgModule Syntax should format files 3`] = `
"import { Injectable, inject } from '@angular/core';
import { createEffect, Actions, ofType } from '@ngrx/effects';
import { switchMap, catchError, of } from 'rxjs';
import * as UsersActions from './users.actions';
import * as UsersFeature from './users.reducer';
@Injectable()
export class UsersEffects {
private actions$ = inject(Actions);
init$ = createEffect(() =>
this.actions$.pipe(
ofType(UsersActions.initUsers),
switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))),
catchError((error) => {
console.error('Error', error);
return of(UsersActions.loadUsersFailure({ error }));
})
)
);
}
"
`;
exports[`ngrx NgModule Syntax should format files 4`] = `
"/**
* Interface for the 'Users' data
*/
export interface UsersEntity {
id: string | number; // Primary ID
name: string;
}
"
`;
exports[`ngrx NgModule Syntax should format files 5`] = `
"import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { createReducer, on, Action } from '@ngrx/store';
import * as UsersActions from './users.actions';
import { UsersEntity } from './users.models';
export const USERS_FEATURE_KEY = 'users';
export interface UsersState extends EntityState<UsersEntity> {
selectedId?: string | number; // which Users record has been selected
loaded: boolean; // has the Users list been loaded
error?: string | null; // last known error (if any)
}
export interface UsersPartialState {
readonly [USERS_FEATURE_KEY]: UsersState;
}
export const usersAdapter: EntityAdapter<UsersEntity> =
createEntityAdapter<UsersEntity>();
export const initialUsersState: UsersState = usersAdapter.getInitialState({
// set initial required properties
loaded: false,
});
const reducer = createReducer(
initialUsersState,
on(UsersActions.initUsers, (state) => ({
...state,
loaded: false,
error: null,
})),
on(UsersActions.loadUsersSuccess, (state, { users }) =>
usersAdapter.setAll(users, { ...state, loaded: true })
),
on(UsersActions.loadUsersFailure, (state, { error }) => ({ ...state, error }))
);
export function usersReducer(state: UsersState | undefined, action: Action) {
return reducer(state, action);
}
"
`;
exports[`ngrx NgModule Syntax should format files 6`] = `
"import { createFeatureSelector, createSelector } from '@ngrx/store';
import { USERS_FEATURE_KEY, UsersState, usersAdapter } from './users.reducer';
// Lookup the 'Users' feature state managed by NgRx
export const selectUsersState =
createFeatureSelector<UsersState>(USERS_FEATURE_KEY);
const { selectAll, selectEntities } = usersAdapter.getSelectors();
export const selectUsersLoaded = createSelector(
selectUsersState,
(state: UsersState) => state.loaded
);
export const selectUsersError = createSelector(
selectUsersState,
(state: UsersState) => state.error
);
export const selectAllUsers = createSelector(
selectUsersState,
(state: UsersState) => selectAll(state)
);
export const selectUsersEntities = createSelector(
selectUsersState,
(state: UsersState) => selectEntities(state)
);
export const selectSelectedId = createSelector(
selectUsersState,
(state: UsersState) => state.selectedId
);
export const selectEntity = createSelector(
selectUsersEntities,
selectSelectedId,
(entities, selectedId) => (selectedId ? entities[selectedId] : undefined)
);
"
`;
exports[`ngrx NgModule Syntax should generate a models file for the feature 1`] = ` exports[`ngrx NgModule Syntax should generate a models file for the feature 1`] = `
"/** "/**
* Interface for the 'Users' data * Interface for the 'Users' data
@ -385,7 +501,9 @@ exports[`ngrx NgModule Syntax should generate the ngrx actions 1`] = `
"import { createAction, props } from '@ngrx/store'; "import { createAction, props } from '@ngrx/store';
import { UsersEntity } from './users.models'; import { UsersEntity } from './users.models';
export const initUsers = createAction('[Users Page] Init'); export const initUsers = createAction(
'[Users Page] Init'
);
export const loadUsersSuccess = createAction( export const loadUsersSuccess = createAction(
'[Users/API] Load Users Success', '[Users/API] Load Users Success',
@ -410,16 +528,15 @@ import * as UsersFeature from './users.reducer';
export class UsersEffects { export class UsersEffects {
private actions$ = inject(Actions); private actions$ = inject(Actions);
init$ = createEffect(() => init$ = createEffect(() => this.actions$.pipe(
this.actions$.pipe( ofType(UsersActions.initUsers),
ofType(UsersActions.initUsers), switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))),
switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))), catchError((error) => {
catchError((error) => {
console.error('Error', error); console.error('Error', error);
return of(UsersActions.loadUsersFailure({ error })); return of(UsersActions.loadUsersFailure({ error }));
}) }
) )
); ));
} }
" "
`; `;
@ -474,25 +591,24 @@ export interface UsersPartialState {
readonly [USERS_FEATURE_KEY]: UsersState; readonly [USERS_FEATURE_KEY]: UsersState;
} }
export const usersAdapter: EntityAdapter<UsersEntity> = export const usersAdapter: EntityAdapter<UsersEntity> = createEntityAdapter<UsersEntity>();
createEntityAdapter<UsersEntity>();
export const initialUsersState: UsersState = usersAdapter.getInitialState({ export const initialUsersState: UsersState = usersAdapter.getInitialState({
// set initial required properties // set initial required properties
loaded: false, loaded: false
}); });
const reducer = createReducer( const reducer = createReducer(
initialUsersState, initialUsersState,
on(UsersActions.initUsers, (state) => ({ on(UsersActions.initUsers,
...state, state => ({ ...state, loaded: false, error: null })
loaded: false, ),
error: null, on(UsersActions.loadUsersSuccess,
})), (state, { users }) => usersAdapter.setAll(users, { ...state, loaded: true })
on(UsersActions.loadUsersSuccess, (state, { users }) => ),
usersAdapter.setAll(users, { ...state, loaded: true }) on(UsersActions.loadUsersFailure,
(state, { error }) => ({ ...state, error })
), ),
on(UsersActions.loadUsersFailure, (state, { error }) => ({ ...state, error }))
); );
export function usersReducer(state: UsersState | undefined, action: Action) { export function usersReducer(state: UsersState | undefined, action: Action) {
@ -506,8 +622,7 @@ exports[`ngrx NgModule Syntax should generate the ngrx selectors 1`] = `
import { USERS_FEATURE_KEY, UsersState, usersAdapter } from './users.reducer'; import { USERS_FEATURE_KEY, UsersState, usersAdapter } from './users.reducer';
// Lookup the 'Users' feature state managed by NgRx // Lookup the 'Users' feature state managed by NgRx
export const selectUsersState = export const selectUsersState = createFeatureSelector<UsersState>(USERS_FEATURE_KEY);
createFeatureSelector<UsersState>(USERS_FEATURE_KEY);
const { selectAll, selectEntities } = usersAdapter.getSelectors(); const { selectAll, selectEntities } = usersAdapter.getSelectors();
@ -552,7 +667,7 @@ import { AppComponent } from './app.component';
@NgModule({ @NgModule({
imports: [BrowserModule, RouterModule.forRoot([])], imports: [BrowserModule, RouterModule.forRoot([])],
declarations: [AppComponent], declarations: [AppComponent],
bootstrap: [AppComponent], bootstrap: [AppComponent]
}) })
export class AppModule {} export class AppModule {}
" "
@ -570,7 +685,6 @@ export * from './lib/+state/super-users.facade';
export * from './lib/+state/super-users.models'; export * from './lib/+state/super-users.models';
export { SuperUsersActions, SuperUsersFeature, SuperUsersSelectors }; export { SuperUsersActions, SuperUsersFeature, SuperUsersSelectors };
export * from './lib/flights.module'; export * from './lib/flights.module';
" "
`; `;
@ -580,7 +694,6 @@ exports[`ngrx NgModule Syntax should update the entry point file with no facade
export * from './lib/+state/super-users.selectors'; export * from './lib/+state/super-users.selectors';
export * from './lib/+state/super-users.reducer'; export * from './lib/+state/super-users.reducer';
export * from './lib/+state/super-users.actions'; export * from './lib/+state/super-users.actions';
export * from './lib/flights.module'; export * from './lib/flights.module';
" "
`; `;
@ -591,7 +704,6 @@ export * from './lib/+state/super-users.models';
export * from './lib/+state/super-users.selectors'; export * from './lib/+state/super-users.selectors';
export * from './lib/+state/super-users.reducer'; export * from './lib/+state/super-users.reducer';
export * from './lib/+state/super-users.actions'; export * from './lib/+state/super-users.actions';
export * from './lib/flights.module'; export * from './lib/flights.module';
" "
`; `;
@ -603,16 +715,8 @@ import { provideStore, provideState } from '@ngrx/store';
import { provideEffects } from '@ngrx/effects'; import { provideEffects } from '@ngrx/effects';
import * as fromUsers from './+state/users.reducer'; import * as fromUsers from './+state/users.reducer';
import { UsersEffects } from './+state/users.effects'; import { UsersEffects } from './+state/users.effects';
export const appRoutes: Routes = [
{ export const appRoutes: Routes = [{ path: 'home', component: NxWelcomeComponent , providers: [provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer), provideEffects(UsersEffects)]}];
path: 'home',
component: NxWelcomeComponent,
providers: [
provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
provideEffects(UsersEffects),
],
},
];
" "
`; `;
@ -623,16 +727,8 @@ import { provideStore, provideState } from '@ngrx/store';
import { provideEffects } from '@ngrx/effects'; import { provideEffects } from '@ngrx/effects';
import * as fromUsers from './+state/users.reducer'; import * as fromUsers from './+state/users.reducer';
import { UsersEffects } from './+state/users.effects'; import { UsersEffects } from './+state/users.effects';
export const appRoutes: Routes = [
{ export const appRoutes: Routes = [{ path: '', component: NxWelcomeComponent , providers: [provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer), provideEffects(UsersEffects)]}];
path: '',
component: NxWelcomeComponent,
providers: [
provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
provideEffects(UsersEffects),
],
},
];
" "
`; `;
@ -643,16 +739,8 @@ import { provideStore, provideState } from '@ngrx/store';
import { provideEffects } from '@ngrx/effects'; import { provideEffects } from '@ngrx/effects';
import * as fromUsers from './+state/users.reducer'; import * as fromUsers from './+state/users.reducer';
import { UsersEffects } from './+state/users.effects'; import { UsersEffects } from './+state/users.effects';
export const appRoutes: Routes = [
{ export const appRoutes: Routes = [{ path: '', component: NxWelcomeComponent , providers: [provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer), provideEffects(UsersEffects)]}];
path: '',
component: NxWelcomeComponent,
providers: [
provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
provideEffects(UsersEffects),
],
},
];
" "
`; `;
@ -677,13 +765,7 @@ import * as fromUsers from './+state/users.reducer';
import { UsersEffects } from './+state/users.effects'; import { UsersEffects } from './+state/users.effects';
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {
providers: [ providers: [provideEffects(UsersEffects),provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),provideEffects(),provideStore(),provideRouter(appRoutes) ]
provideEffects(UsersEffects),
provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
provideEffects(),
provideStore(),
provideRouter(appRoutes),
],
}; };
" "
`; `;
@ -707,7 +789,7 @@ import { provideStore, provideState } from '@ngrx/store';
import { provideEffects } from '@ngrx/effects'; import { provideEffects } from '@ngrx/effects';
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {
providers: [provideEffects(), provideStore(), provideRouter(appRoutes)], providers: [provideEffects(),provideStore(),provideRouter(appRoutes) ]
}; };
" "
`; `;
@ -734,14 +816,7 @@ import { UsersEffects } from './+state/users.effects';
import { UsersFacade } from './+state/users.facade'; import { UsersFacade } from './+state/users.facade';
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {
providers: [ providers: [provideEffects(UsersEffects),provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),provideEffects(),provideStore(),UsersFacade,provideRouter(appRoutes) ]
provideEffects(UsersEffects),
provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
provideEffects(),
provideStore(),
UsersFacade,
provideRouter(appRoutes),
],
}; };
" "
`; `;
@ -754,17 +829,8 @@ import { provideEffects } from '@ngrx/effects';
import * as fromUsers from './+state/users.reducer'; import * as fromUsers from './+state/users.reducer';
import { UsersEffects } from './+state/users.effects'; import { UsersEffects } from './+state/users.effects';
import { UsersFacade } from './+state/users.facade'; import { UsersFacade } from './+state/users.facade';
export const appRoutes: Routes = [
{ export const appRoutes: Routes = [{ path: '', component: NxWelcomeComponent , providers: [UsersFacade, provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer), provideEffects(UsersEffects)]}];
path: '',
component: NxWelcomeComponent,
providers: [
UsersFacade,
provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
provideEffects(UsersEffects),
],
},
];
" "
`; `;
@ -780,16 +846,15 @@ import * as UsersFeature from './users.reducer';
export class UsersEffects { export class UsersEffects {
private actions$ = inject(Actions); private actions$ = inject(Actions);
init$ = createEffect(() => init$ = createEffect(() => this.actions$.pipe(
this.actions$.pipe( ofType(UsersActions.initUsers),
ofType(UsersActions.initUsers), switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))),
switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))), catchError((error) => {
catchError((error) => {
console.error('Error', error); console.error('Error', error);
return of(UsersActions.loadUsersFailure({ error })); return of(UsersActions.loadUsersFailure({ error }));
}) }
) )
); ));
} }
" "
`; `;

View File

@ -4,4 +4,4 @@
export interface <%= className %>Entity { export interface <%= className %>Entity {
id: string | number; // Primary ID id: string | number; // Primary ID
name: string; name: string;
}; }

View File

@ -20,7 +20,7 @@ describe('<%= className %> Selectors', () => {
create<%= className %>Entity('PRODUCT-CCC') create<%= className %>Entity('PRODUCT-CCC')
], { ], {
...initial<%= className %>State, ...initial<%= className %>State,
selectedId : 'PRODUCT-BBB', selectedId: 'PRODUCT-BBB',
error: ERROR_MSG, error: ERROR_MSG,
loaded: true loaded: true
}) })

View File

@ -25,6 +25,7 @@ describe('ngrx', () => {
minimal: true, minimal: true,
parent: 'myapp/src/app/app.module.ts', parent: 'myapp/src/app/app.module.ts',
name: 'users', name: 'users',
skipFormat: true,
}; };
const defaultStandaloneOptions: NgRxGeneratorOptions = { const defaultStandaloneOptions: NgRxGeneratorOptions = {
@ -32,6 +33,7 @@ describe('ngrx', () => {
minimal: true, minimal: true,
parent: 'my-app/src/app/app.config.ts', parent: 'my-app/src/app/app.config.ts',
name: 'users', name: 'users',
skipFormat: true,
}; };
const defaultModuleOptions: NgRxGeneratorOptions = { const defaultModuleOptions: NgRxGeneratorOptions = {
@ -39,6 +41,7 @@ describe('ngrx', () => {
minimal: true, minimal: true,
module: 'myapp/src/app/app.module.ts', module: 'myapp/src/app/app.module.ts',
name: 'users', name: 'users',
skipFormat: true,
}; };
const expectFileToExist = (file: string) => const expectFileToExist = (file: string) =>
@ -417,9 +420,27 @@ describe('ngrx', () => {
it('should format files', async () => { it('should format files', async () => {
jest.spyOn(devkit, 'formatFiles'); jest.spyOn(devkit, 'formatFiles');
await ngrxGenerator(tree, defaultOptions); await ngrxGenerator(tree, { ...defaultOptions, skipFormat: false });
expect(devkit.formatFiles).toHaveBeenCalled(); expect(devkit.formatFiles).toHaveBeenCalled();
expect(
tree.read('myapp/src/app/app.module.ts', 'utf-8')
).toMatchSnapshot();
expect(
tree.read('myapp/src/app/+state/users.actions.ts', 'utf-8')
).toMatchSnapshot();
expect(
tree.read('myapp/src/app/+state/users.effects.ts', 'utf-8')
).toMatchSnapshot();
expect(
tree.read('myapp/src/app/+state/users.models.ts', 'utf-8')
).toMatchSnapshot();
expect(
tree.read('myapp/src/app/+state/users.reducer.ts', 'utf-8')
).toMatchSnapshot();
expect(
tree.read('myapp/src/app/+state/users.selectors.ts', 'utf-8')
).toMatchSnapshot();
}); });
it('should not format files when skipFormat is true', async () => { it('should not format files when skipFormat is true', async () => {
@ -494,6 +515,7 @@ describe('ngrx', () => {
name: 'my-app', name: 'my-app',
standalone: true, standalone: true,
routing: true, routing: true,
skipFormat: true,
}); });
tree.write( tree.write(
'my-app/src/app/app.component.html', 'my-app/src/app/app.component.html',
@ -502,8 +524,10 @@ describe('ngrx', () => {
tree.write( tree.write(
'my-app/src/app/app.routes.ts', 'my-app/src/app/app.routes.ts',
`import { Routes } from '@angular/router'; `import { Routes } from '@angular/router';
import { NxWelcomeComponent } from './nx-welcome.component'; import { NxWelcomeComponent } from './nx-welcome.component';
export const appRoutes: Routes = [{ path: '', component: NxWelcomeComponent }];`
export const appRoutes: Routes = [{ path: '', component: NxWelcomeComponent }];
`
); );
}); });
@ -575,8 +599,10 @@ describe('ngrx', () => {
tree.write( tree.write(
'my-app/src/app/app.routes.ts', 'my-app/src/app/app.routes.ts',
`import { Routes } from '@angular/router'; `import { Routes } from '@angular/router';
import { NxWelcomeComponent } from './nx-welcome.component'; import { NxWelcomeComponent } from './nx-welcome.component';
export const appRoutes: Routes = [{ path: 'home', component: NxWelcomeComponent }];`
export const appRoutes: Routes = [{ path: 'home', component: NxWelcomeComponent }];
`
); );
await ngrxGenerator(tree, { await ngrxGenerator(tree, {
@ -637,7 +663,11 @@ describe('ngrx', () => {
beforeEach(async () => { beforeEach(async () => {
jest.clearAllMocks(); jest.clearAllMocks();
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
await generateTestApplication(tree, { name: 'myapp', standalone: false }); await generateTestApplication(tree, {
name: 'myapp',
standalone: false,
skipFormat: true,
});
devkit.updateJson(tree, 'package.json', (json) => ({ devkit.updateJson(tree, 'package.json', (json) => ({
...json, ...json,
dependencies: { dependencies: {
@ -679,7 +709,11 @@ describe('ngrx', () => {
describe('rxjs v6 support', () => { describe('rxjs v6 support', () => {
beforeEach(async () => { beforeEach(async () => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
await generateTestApplication(tree, { name: 'myapp', standalone: false }); await generateTestApplication(tree, {
name: 'myapp',
standalone: false,
skipFormat: true,
});
devkit.updateJson(tree, 'package.json', (json) => ({ devkit.updateJson(tree, 'package.json', (json) => ({
...json, ...json,
dependencies: { dependencies: {

View File

@ -54,7 +54,7 @@ exports[`pipe generator --no-standalone should import the pipe correctly when fl
"import { Pipe, PipeTransform } from '@angular/core'; "import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ @Pipe({
name: 'test', name: 'test'
}) })
export class TestPipe implements PipeTransform { export class TestPipe implements PipeTransform {
transform(value: unknown, ...args: unknown[]): unknown { transform(value: unknown, ...args: unknown[]): unknown {
@ -92,7 +92,7 @@ exports[`pipe generator --no-standalone should import the pipe correctly when fl
"import { Pipe, PipeTransform } from '@angular/core'; "import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ @Pipe({
name: 'test', name: 'test'
}) })
export class TestPipe implements PipeTransform { export class TestPipe implements PipeTransform {
transform(value: unknown, ...args: unknown[]): unknown { transform(value: unknown, ...args: unknown[]): unknown {

View File

@ -5,9 +5,7 @@ import { Pipe, PipeTransform } from '@angular/core';
standalone: true<%}%> standalone: true<%}%>
}) })
export class <%= symbolName %> implements PipeTransform { export class <%= symbolName %> implements PipeTransform {
transform(value: unknown, ...args: unknown[]): unknown { transform(value: unknown, ...args: unknown[]): unknown {
return null; return null;
} }
} }

View File

@ -18,7 +18,7 @@ describe('pipe generator', () => {
it('should generate correctly', async () => { it('should generate correctly', async () => {
// ACT // ACT
await generatePipeWithDefaultOptions(tree); await generatePipeWithDefaultOptions(tree, { skipFormat: false });
// ASSERT // ASSERT
expect(tree.read('test/src/app/test.pipe.ts', 'utf-8')).toMatchSnapshot(); expect(tree.read('test/src/app/test.pipe.ts', 'utf-8')).toMatchSnapshot();
@ -63,7 +63,10 @@ describe('pipe generator', () => {
// ARRANGE // ARRANGE
// ACT // ACT
await generatePipeWithDefaultOptions(tree, { standalone: false }); await generatePipeWithDefaultOptions(tree, {
standalone: false,
skipFormat: false,
});
// ASSERT // ASSERT
expect(tree.read('test/src/app/test.pipe.ts', 'utf-8')).toMatchSnapshot(); expect(tree.read('test/src/app/test.pipe.ts', 'utf-8')).toMatchSnapshot();
@ -157,13 +160,14 @@ describe('pipe generator', () => {
function addModule(tree: Tree) { function addModule(tree: Tree) {
tree.write( tree.write(
'test/src/app/test.module.ts', 'test/src/app/test.module.ts',
`import {NgModule} from "@angular/core"; `import { NgModule } from '@angular/core';
@NgModule({ @NgModule({
imports: [], imports: [],
declarations: [], declarations: [],
exports: [] exports: [],
}) })
export class TestModule {}` export class TestModule {}
`
); );
} }
@ -175,6 +179,7 @@ async function generatePipeWithDefaultOptions(
name: 'test', name: 'test',
project: 'test', project: 'test',
flat: true, flat: true,
skipFormat: true,
...overrides, ...overrides,
}); });
} }

View File

@ -27,7 +27,7 @@ export function app(): express.Express {
server.engine( server.engine(
'html', 'html',
ngExpressEngine({ ngExpressEngine({
bootstrap, bootstrap
}) })
); );
@ -317,24 +317,15 @@ import { AppComponent } from './app.component';
declarations: [AppComponent], declarations: [AppComponent],
imports: [ imports: [
BrowserModule, BrowserModule,
RouterModule.forRoot( RouterModule.forRoot([{
[ path: '',
{ loadChildren: () => import('./remote-entry/entry.module').then(m => m.RemoteEntryModule)
path: '', }], { initialNavigation: 'enabledBlocking' }),
loadChildren: () =>
import('./remote-entry/entry.module').then(
(m) => m.RemoteEntryModule
),
},
],
{ initialNavigation: 'enabledBlocking' }
),
], ],
providers: [], providers: [],
bootstrap: [AppComponent], bootstrap: [AppComponent],
}) })
export class AppModule {} export class AppModule {}"
"
`; `;
exports[`MF Remote App Generator --ssr should generate the correct files when --typescriptConfiguration=true 2`] = ` exports[`MF Remote App Generator --ssr should generate the correct files when --typescriptConfiguration=true 2`] = `
@ -429,10 +420,7 @@ export default AppServerModule;
" "
`; `;
exports[`MF Remote App Generator --ssr should generate the correct files when --typescriptConfiguration=true 5`] = ` exports[`MF Remote App Generator --ssr should generate the correct files when --typescriptConfiguration=true 5`] = `"import('./src/main.server');"`;
"import('./src/main.server');
"
`;
exports[`MF Remote App Generator --ssr should generate the correct files when --typescriptConfiguration=true 6`] = ` exports[`MF Remote App Generator --ssr should generate the correct files when --typescriptConfiguration=true 6`] = `
"import { ModuleFederationConfig } from '@nx/webpack'; "import { ModuleFederationConfig } from '@nx/webpack';
@ -461,7 +449,7 @@ exports[`MF Remote App Generator --ssr should generate the correct files when --
@Component({ @Component({
selector: 'proj-test-entry', selector: 'proj-test-entry',
template: \`<proj-nx-welcome></proj-nx-welcome>\`, template: \`<proj-nx-welcome></proj-nx-welcome>\`
}) })
export class RemoteEntryComponent {} export class RemoteEntryComponent {}
" "
@ -471,12 +459,7 @@ exports[`MF Remote App Generator --ssr should generate the correct files when --
"import { Route } from '@angular/router'; "import { Route } from '@angular/router';
export const appRoutes: Route[] = [ export const appRoutes: Route[] = [
{ { path: '', loadChildren: () => import('./remote-entry/entry.module').then(m => m.RemoteEntryModule) },];
path: '',
loadChildren: () =>
import('./remote-entry/entry.module').then((m) => m.RemoteEntryModule),
},
];
" "
`; `;
@ -484,10 +467,7 @@ exports[`MF Remote App Generator --ssr should generate the correct files when --
"import { Route } from '@angular/router'; "import { Route } from '@angular/router';
import { RemoteEntryComponent } from './entry.component'; import { RemoteEntryComponent } from './entry.component';
export const remoteRoutes: Route[] = [ export const remoteRoutes: Route[] = [{ path: '', component: RemoteEntryComponent }];"
{ path: '', component: RemoteEntryComponent },
];
"
`; `;
exports[`MF Remote App Generator --ssr should generate the correct files when --typescriptConfiguration=true 11`] = ` exports[`MF Remote App Generator --ssr should generate the correct files when --typescriptConfiguration=true 11`] = `
@ -524,10 +504,7 @@ exports[`MF Remote App Generator --ssr should generate the correct files when --
"import { Route } from '@angular/router'; "import { Route } from '@angular/router';
import { RemoteEntryComponent } from './entry.component'; import { RemoteEntryComponent } from './entry.component';
export const remoteRoutes: Route[] = [ export const remoteRoutes: Route[] = [{ path: '', component: RemoteEntryComponent }];"
{ path: '', component: RemoteEntryComponent },
];
"
`; `;
exports[`MF Remote App Generator --ssr should generate the correct files when --typescriptConfiguration=true 13`] = ` exports[`MF Remote App Generator --ssr should generate the correct files when --typescriptConfiguration=true 13`] = `
@ -681,7 +658,7 @@ import { NxWelcomeComponent } from './nx-welcome.component';
standalone: true, standalone: true,
imports: [CommonModule, NxWelcomeComponent], imports: [CommonModule, NxWelcomeComponent],
selector: 'proj-test-entry', selector: 'proj-test-entry',
template: \`<proj-nx-welcome></proj-nx-welcome>\`, template: \`<proj-nx-welcome></proj-nx-welcome>\`
}) })
export class RemoteEntryComponent {} export class RemoteEntryComponent {}
" "
@ -691,12 +668,7 @@ exports[`MF Remote App Generator should generate the a remote setup for standalo
"import { Route } from '@angular/router'; "import { Route } from '@angular/router';
export const appRoutes: Route[] = [ export const appRoutes: Route[] = [
{ {path: '', loadChildren: () => import('./remote-entry/entry.routes').then(m => m.remoteRoutes)},];
path: '',
loadChildren: () =>
import('./remote-entry/entry.routes').then((m) => m.remoteRoutes),
},
];
" "
`; `;
@ -704,8 +676,5 @@ exports[`MF Remote App Generator should generate the a remote setup for standalo
"import { Route } from '@angular/router'; "import { Route } from '@angular/router';
import { RemoteEntryComponent } from './entry.component'; import { RemoteEntryComponent } from './entry.component';
export const remoteRoutes: Route[] = [ export const remoteRoutes: Route[] = [{ path: '', component: RemoteEntryComponent }];"
{ path: '', component: RemoteEntryComponent },
];
"
`; `;

View File

@ -1,4 +1,4 @@
import {withModuleFederationForSSR} from '@nx/angular/module-federation'; import { withModuleFederationForSSR } from '@nx/angular/module-federation';
import config from './module-federation.config'; import config from './module-federation.config';
export default withModuleFederationForSSR(config) export default withModuleFederationForSSR(config);

View File

@ -31,7 +31,6 @@ export function app(): express.Express {
server.set('view engine', 'html'); server.set('view engine', 'html');
server.set('views', browserBundles); server.set('views', browserBundles);
// Example Express Rest API endpoints // Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { }); // server.get('/api/**', (req, res) => { });
// Serve static files from /browser // Serve static files from /browser
@ -41,7 +40,6 @@ export function app(): express.Express {
// All regular routes use the Universal engine // All regular routes use the Universal engine
server.get('*', (req, res) => { server.get('*', (req, res) => {
res.render(indexHtml, { res.render(indexHtml, {
req, req,
providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }], providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }],

View File

@ -24,7 +24,6 @@ export function app(): express.Express {
server.set('view engine', 'html'); server.set('view engine', 'html');
server.set('views', browserBundles); server.set('views', browserBundles);
// Example Express Rest API endpoints // Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { }); // server.get('/api/**', (req, res) => { });
// Serve static files from /browser // Serve static files from /browser

View File

@ -24,6 +24,7 @@ describe('MF Remote App Generator', () => {
port: 4201, port: 4201,
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -44,6 +45,7 @@ describe('MF Remote App Generator', () => {
port: 4201, port: 4201,
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -58,6 +60,7 @@ describe('MF Remote App Generator', () => {
name: 'host', name: 'host',
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -66,6 +69,7 @@ describe('MF Remote App Generator', () => {
host: 'host', host: 'host',
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -81,6 +85,7 @@ describe('MF Remote App Generator', () => {
name: 'host', name: 'host',
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -89,6 +94,7 @@ describe('MF Remote App Generator', () => {
host: 'host', host: 'host',
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -106,6 +112,7 @@ describe('MF Remote App Generator', () => {
name: 'test', name: 'test',
host: 'host', host: 'host',
standalone: false, standalone: false,
skipFormat: true,
}); });
} catch (error) { } catch (error) {
// ASSERT // ASSERT
@ -122,12 +129,14 @@ describe('MF Remote App Generator', () => {
name: 'existing', name: 'existing',
port: 4201, port: 4201,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
await generateTestRemoteApplication(tree, { await generateTestRemoteApplication(tree, {
name: 'test', name: 'test',
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -143,6 +152,7 @@ describe('MF Remote App Generator', () => {
await generateTestRemoteApplication(tree, { await generateTestRemoteApplication(tree, {
name: 'test', name: 'test',
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -159,6 +169,7 @@ describe('MF Remote App Generator', () => {
name: 'test', name: 'test',
port: 4201, port: 4201,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -207,6 +218,7 @@ describe('MF Remote App Generator', () => {
await generateTestRemoteApplication(tree, { await generateTestRemoteApplication(tree, {
name: 'test', name: 'test',
typescriptConfiguration: true, typescriptConfiguration: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -237,6 +249,7 @@ describe('MF Remote App Generator', () => {
name: 'remote1', name: 'remote1',
e2eTestRunner: E2eTestRunner.None, e2eTestRunner: E2eTestRunner.None,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -253,6 +266,7 @@ describe('MF Remote App Generator', () => {
name: 'test', name: 'test',
inlineTemplate: true, inlineTemplate: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -262,10 +276,10 @@ describe('MF Remote App Generator', () => {
@Component({ @Component({
selector: 'proj-root', selector: 'proj-root',
template: '<router-outlet></router-outlet>', template: '<router-outlet></router-outlet>'
}) })
export class AppComponent {} export class AppComponent {}"
"
`); `);
}); });
@ -276,6 +290,7 @@ describe('MF Remote App Generator', () => {
// ACT // ACT
await generateTestRemoteApplication(tree, { await generateTestRemoteApplication(tree, {
name: 'test', name: 'test',
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -346,6 +361,7 @@ describe('MF Remote App Generator', () => {
ssr: true, ssr: true,
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -394,7 +410,11 @@ describe('MF Remote App Generator', () => {
}, },
})); }));
await generateTestRemoteApplication(tree, { name: 'test', ssr: true }); await generateTestRemoteApplication(tree, {
name: 'test',
ssr: true,
skipFormat: true,
});
expect(tree.read(`test/src/main.server.ts`, 'utf-8')).toMatchSnapshot(); expect(tree.read(`test/src/main.server.ts`, 'utf-8')).toMatchSnapshot();
}); });
@ -411,6 +431,7 @@ describe('MF Remote App Generator', () => {
projectNameAndRootFormat: 'derived', projectNameAndRootFormat: 'derived',
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
expect(tree.exists('apps/test/webpack.config.js')).toBe(true); expect(tree.exists('apps/test/webpack.config.js')).toBe(true);
@ -427,6 +448,7 @@ describe('MF Remote App Generator', () => {
projectNameAndRootFormat: 'derived', projectNameAndRootFormat: 'derived',
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
expect(tree.exists('apps/shared/test/webpack.config.js')).toBe(true); expect(tree.exists('apps/shared/test/webpack.config.js')).toBe(true);

View File

@ -20,6 +20,7 @@ describe('convertDirectiveToScam', () => {
export: false, export: false,
flat: false, flat: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -46,7 +47,7 @@ describe('convertDirectiveToScam', () => {
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@Directive({ @Directive({
selector: '[projExample]', selector: '[projExample]'
}) })
export class ExampleDirective { export class ExampleDirective {
constructor() {} constructor() {}
@ -57,7 +58,8 @@ describe('convertDirectiveToScam', () => {
declarations: [ExampleDirective], declarations: [ExampleDirective],
exports: [ExampleDirective], exports: [ExampleDirective],
}) })
export class ExampleDirectiveModule {}" export class ExampleDirectiveModule {}
"
`); `);
}); });
@ -77,6 +79,7 @@ describe('convertDirectiveToScam', () => {
export: false, export: false,
flat: false, flat: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -108,7 +111,8 @@ describe('convertDirectiveToScam', () => {
declarations: [ExampleDirective], declarations: [ExampleDirective],
exports: [ExampleDirective], exports: [ExampleDirective],
}) })
export class ExampleDirectiveModule {}" export class ExampleDirectiveModule {}
"
`); `);
}); });
@ -128,6 +132,7 @@ describe('convertDirectiveToScam', () => {
export: false, export: false,
flat: true, flat: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -154,7 +159,7 @@ describe('convertDirectiveToScam', () => {
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@Directive({ @Directive({
selector: '[projExample]', selector: '[projExample]'
}) })
export class ExampleDirective { export class ExampleDirective {
constructor() {} constructor() {}
@ -165,7 +170,8 @@ describe('convertDirectiveToScam', () => {
declarations: [ExampleDirective], declarations: [ExampleDirective],
exports: [ExampleDirective], exports: [ExampleDirective],
}) })
export class ExampleDirectiveModule {}" export class ExampleDirectiveModule {}
"
`); `);
}); });
@ -185,6 +191,7 @@ describe('convertDirectiveToScam', () => {
export: false, export: false,
flat: true, flat: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -216,7 +223,8 @@ describe('convertDirectiveToScam', () => {
declarations: [ExampleDirective], declarations: [ExampleDirective],
exports: [ExampleDirective], exports: [ExampleDirective],
}) })
export class ExampleDirectiveModule {}" export class ExampleDirectiveModule {}
"
`); `);
}); });
@ -237,6 +245,7 @@ describe('convertDirectiveToScam', () => {
flat: false, flat: false,
path: 'apps/app1/src/app/random', path: 'apps/app1/src/app/random',
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -263,7 +272,7 @@ describe('convertDirectiveToScam', () => {
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@Directive({ @Directive({
selector: '[projExample]', selector: '[projExample]'
}) })
export class ExampleDirective { export class ExampleDirective {
constructor() {} constructor() {}
@ -274,7 +283,8 @@ describe('convertDirectiveToScam', () => {
declarations: [ExampleDirective], declarations: [ExampleDirective],
exports: [ExampleDirective], exports: [ExampleDirective],
}) })
export class ExampleDirectiveModule {}" export class ExampleDirectiveModule {}
"
`); `);
}); });
@ -295,6 +305,7 @@ describe('convertDirectiveToScam', () => {
flat: true, flat: true,
path: 'apps/app1/src/app/random', path: 'apps/app1/src/app/random',
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -321,7 +332,7 @@ describe('convertDirectiveToScam', () => {
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@Directive({ @Directive({
selector: '[projExample]', selector: '[projExample]'
}) })
export class ExampleDirective { export class ExampleDirective {
constructor() {} constructor() {}
@ -332,7 +343,8 @@ describe('convertDirectiveToScam', () => {
declarations: [ExampleDirective], declarations: [ExampleDirective],
exports: [ExampleDirective], exports: [ExampleDirective],
}) })
export class ExampleDirectiveModule {}" export class ExampleDirectiveModule {}
"
`); `);
}); });
}); });

View File

@ -80,5 +80,6 @@ function getNgModuleDeclaration(directiveClassName: string): string {
declarations: [${directiveClassName}], declarations: [${directiveClassName}],
exports: [${directiveClassName}], exports: [${directiveClassName}],
}) })
export class ${directiveClassName}Module {}`; export class ${directiveClassName}Module {}
`;
} }

View File

@ -18,6 +18,7 @@ describe('SCAM Directive Generator', () => {
project: 'app1', project: 'app1',
inlineScam: true, inlineScam: true,
flat: true, flat: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -30,7 +31,7 @@ describe('SCAM Directive Generator', () => {
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@Directive({ @Directive({
selector: '[projExample]', selector: '[projExample]'
}) })
export class ExampleDirective { export class ExampleDirective {
constructor() {} constructor() {}
@ -61,6 +62,7 @@ describe('SCAM Directive Generator', () => {
project: 'app1', project: 'app1',
inlineScam: false, inlineScam: false,
flat: true, flat: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -103,6 +105,7 @@ describe('SCAM Directive Generator', () => {
path: 'libs/lib1/feature/src/lib', path: 'libs/lib1/feature/src/lib',
inlineScam: false, inlineScam: false,
export: true, export: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -129,8 +132,7 @@ describe('SCAM Directive Generator', () => {
); );
expect(secondaryEntryPointSource).toMatchInlineSnapshot(` expect(secondaryEntryPointSource).toMatchInlineSnapshot(`
"export * from './lib/example/example.directive'; "export * from './lib/example/example.directive';
export * from './lib/example/example.module'; export * from './lib/example/example.module';"
"
`); `);
}); });
@ -151,6 +153,7 @@ describe('SCAM Directive Generator', () => {
path: 'apps/app1/src/app/random', path: 'apps/app1/src/app/random',
inlineScam: true, inlineScam: true,
flat: false, flat: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -163,7 +166,7 @@ describe('SCAM Directive Generator', () => {
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@Directive({ @Directive({
selector: '[projExample]', selector: '[projExample]'
}) })
export class ExampleDirective { export class ExampleDirective {
constructor() {} constructor() {}
@ -195,6 +198,7 @@ describe('SCAM Directive Generator', () => {
path: '/apps/app1/src/app/random', path: '/apps/app1/src/app/random',
inlineScam: true, inlineScam: true,
flat: false, flat: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -207,7 +211,7 @@ describe('SCAM Directive Generator', () => {
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@Directive({ @Directive({
selector: '[projExample]', selector: '[projExample]'
}) })
export class ExampleDirective { export class ExampleDirective {
constructor() {} constructor() {}
@ -240,6 +244,7 @@ describe('SCAM Directive Generator', () => {
path: 'libs/proj/src/lib/random', path: 'libs/proj/src/lib/random',
inlineScam: true, inlineScam: true,
flat: false, flat: false,
skipFormat: true,
}) })
).rejects.toThrowErrorMatchingInlineSnapshot( ).rejects.toThrowErrorMatchingInlineSnapshot(
`"The provided directory "libs/proj/src/lib/random" is not under the provided project root "apps/app1". Please provide a directory that is under the provided project root or use the "as-provided" format and only provide the directory."` `"The provided directory "libs/proj/src/lib/random" is not under the provided project root "apps/app1". Please provide a directory that is under the provided project root or use the "as-provided" format and only provide the directory."`

View File

@ -20,7 +20,9 @@ export async function scamDirectiveGenerator(tree: Tree, rawOptions: Schema) {
convertDirectiveToScam(tree, options); convertDirectiveToScam(tree, options);
exportScam(tree, options); exportScam(tree, options);
await formatFiles(tree); if (!options.skipFormat) {
await formatFiles(tree);
}
} }
export default scamDirectiveGenerator; export default scamDirectiveGenerator;

View File

@ -9,6 +9,7 @@ export interface Schema {
prefix?: string; prefix?: string;
selector?: string; selector?: string;
export?: boolean; export?: boolean;
skipFormat?: boolean;
/** /**
* @deprecated Provide the `directory` option instead and use the `as-provided` format. It will be removed in Nx v18. * @deprecated Provide the `directory` option instead and use the `as-provided` format. It will be removed in Nx v18.
*/ */

View File

@ -84,6 +84,12 @@
"description": "Specifies if the SCAM should be exported from the project's entry point (normally `index.ts`). It only applies to libraries.", "description": "Specifies if the SCAM should be exported from the project's entry point (normally `index.ts`). It only applies to libraries.",
"default": true, "default": true,
"x-priority": "important" "x-priority": "important"
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
"default": false,
"x-priority": "internal"
} }
}, },
"required": ["name"] "required": ["name"]

View File

@ -20,6 +20,7 @@ describe('convertPipeToScam', () => {
export: false, export: false,
flat: false, flat: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -46,7 +47,7 @@ describe('convertPipeToScam', () => {
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@Pipe({ @Pipe({
name: 'example', name: 'example'
}) })
export class ExamplePipe implements PipeTransform { export class ExamplePipe implements PipeTransform {
transform(value: unknown, ...args: unknown[]): unknown { transform(value: unknown, ...args: unknown[]): unknown {
@ -59,7 +60,8 @@ describe('convertPipeToScam', () => {
declarations: [ExamplePipe], declarations: [ExamplePipe],
exports: [ExamplePipe], exports: [ExamplePipe],
}) })
export class ExamplePipeModule {}" export class ExamplePipeModule {}
"
`); `);
}); });
@ -78,6 +80,7 @@ describe('convertPipeToScam', () => {
skipImport: true, skipImport: true,
export: false, export: false,
flat: false, flat: false,
skipFormat: true,
}); });
// ACT // ACT
@ -109,7 +112,8 @@ describe('convertPipeToScam', () => {
declarations: [ExamplePipe], declarations: [ExamplePipe],
exports: [ExamplePipe], exports: [ExamplePipe],
}) })
export class ExamplePipeModule {}" export class ExamplePipeModule {}
"
`); `);
}); });
@ -129,6 +133,7 @@ describe('convertPipeToScam', () => {
export: false, export: false,
flat: true, flat: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -152,7 +157,7 @@ describe('convertPipeToScam', () => {
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@Pipe({ @Pipe({
name: 'example', name: 'example'
}) })
export class ExamplePipe implements PipeTransform { export class ExamplePipe implements PipeTransform {
transform(value: unknown, ...args: unknown[]): unknown { transform(value: unknown, ...args: unknown[]): unknown {
@ -165,7 +170,8 @@ describe('convertPipeToScam', () => {
declarations: [ExamplePipe], declarations: [ExamplePipe],
exports: [ExamplePipe], exports: [ExamplePipe],
}) })
export class ExamplePipeModule {}" export class ExamplePipeModule {}
"
`); `);
}); });
@ -185,6 +191,7 @@ describe('convertPipeToScam', () => {
export: false, export: false,
flat: true, flat: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -216,7 +223,8 @@ describe('convertPipeToScam', () => {
declarations: [ExamplePipe], declarations: [ExamplePipe],
exports: [ExamplePipe], exports: [ExamplePipe],
}) })
export class ExamplePipeModule {}" export class ExamplePipeModule {}
"
`); `);
}); });
@ -237,6 +245,7 @@ describe('convertPipeToScam', () => {
flat: false, flat: false,
path: 'apps/app1/src/app/random', path: 'apps/app1/src/app/random',
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -263,7 +272,7 @@ describe('convertPipeToScam', () => {
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@Pipe({ @Pipe({
name: 'example', name: 'example'
}) })
export class ExamplePipe implements PipeTransform { export class ExamplePipe implements PipeTransform {
transform(value: unknown, ...args: unknown[]): unknown { transform(value: unknown, ...args: unknown[]): unknown {
@ -276,7 +285,8 @@ describe('convertPipeToScam', () => {
declarations: [ExamplePipe], declarations: [ExamplePipe],
exports: [ExamplePipe], exports: [ExamplePipe],
}) })
export class ExamplePipeModule {}" export class ExamplePipeModule {}
"
`); `);
}); });
@ -297,6 +307,7 @@ describe('convertPipeToScam', () => {
flat: true, flat: true,
path: 'apps/app1/src/app/random', path: 'apps/app1/src/app/random',
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -323,7 +334,7 @@ describe('convertPipeToScam', () => {
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@Pipe({ @Pipe({
name: 'example', name: 'example'
}) })
export class ExamplePipe implements PipeTransform { export class ExamplePipe implements PipeTransform {
transform(value: unknown, ...args: unknown[]): unknown { transform(value: unknown, ...args: unknown[]): unknown {
@ -336,7 +347,8 @@ describe('convertPipeToScam', () => {
declarations: [ExamplePipe], declarations: [ExamplePipe],
exports: [ExamplePipe], exports: [ExamplePipe],
}) })
export class ExamplePipeModule {}" export class ExamplePipeModule {}
"
`); `);
}); });
}); });

View File

@ -77,5 +77,6 @@ function getNgModuleDeclaration(pipeClassName: string): string {
declarations: [${pipeClassName}], declarations: [${pipeClassName}],
exports: [${pipeClassName}], exports: [${pipeClassName}],
}) })
export class ${pipeClassName}Module {}`; export class ${pipeClassName}Module {}
`;
} }

View File

@ -18,6 +18,7 @@ describe('SCAM Pipe Generator', () => {
project: 'app1', project: 'app1',
inlineScam: true, inlineScam: true,
flat: false, flat: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -30,7 +31,7 @@ describe('SCAM Pipe Generator', () => {
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@Pipe({ @Pipe({
name: 'example', name: 'example'
}) })
export class ExamplePipe implements PipeTransform { export class ExamplePipe implements PipeTransform {
transform(value: unknown, ...args: unknown[]): unknown { transform(value: unknown, ...args: unknown[]): unknown {
@ -63,6 +64,7 @@ describe('SCAM Pipe Generator', () => {
project: 'app1', project: 'app1',
inlineScam: false, inlineScam: false,
flat: false, flat: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -105,6 +107,7 @@ describe('SCAM Pipe Generator', () => {
path: 'libs/lib1/feature/src/lib', path: 'libs/lib1/feature/src/lib',
inlineScam: false, inlineScam: false,
export: true, export: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -131,8 +134,7 @@ describe('SCAM Pipe Generator', () => {
); );
expect(secondaryEntryPointSource).toMatchInlineSnapshot(` expect(secondaryEntryPointSource).toMatchInlineSnapshot(`
"export * from './lib/example/example.pipe'; "export * from './lib/example/example.pipe';
export * from './lib/example/example.module'; export * from './lib/example/example.module';"
"
`); `);
}); });
@ -153,6 +155,7 @@ describe('SCAM Pipe Generator', () => {
path: 'apps/app1/src/app/random', path: 'apps/app1/src/app/random',
inlineScam: true, inlineScam: true,
flat: false, flat: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -165,7 +168,7 @@ describe('SCAM Pipe Generator', () => {
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@Pipe({ @Pipe({
name: 'example', name: 'example'
}) })
export class ExamplePipe implements PipeTransform { export class ExamplePipe implements PipeTransform {
transform(value: unknown, ...args: unknown[]): unknown { transform(value: unknown, ...args: unknown[]): unknown {
@ -199,6 +202,7 @@ describe('SCAM Pipe Generator', () => {
path: '/apps/app1/src/app/random', path: '/apps/app1/src/app/random',
inlineScam: true, inlineScam: true,
flat: false, flat: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -211,7 +215,7 @@ describe('SCAM Pipe Generator', () => {
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@Pipe({ @Pipe({
name: 'example', name: 'example'
}) })
export class ExamplePipe implements PipeTransform { export class ExamplePipe implements PipeTransform {
transform(value: unknown, ...args: unknown[]): unknown { transform(value: unknown, ...args: unknown[]): unknown {
@ -245,6 +249,7 @@ describe('SCAM Pipe Generator', () => {
project: 'app1', project: 'app1',
path: 'libs/proj/src/lib/random', path: 'libs/proj/src/lib/random',
inlineScam: true, inlineScam: true,
skipFormat: true,
}) })
).rejects.toThrowErrorMatchingInlineSnapshot( ).rejects.toThrowErrorMatchingInlineSnapshot(
`"The provided directory "libs/proj/src/lib/random" is not under the provided project root "apps/app1". Please provide a directory that is under the provided project root or use the "as-provided" format and only provide the directory."` `"The provided directory "libs/proj/src/lib/random" is not under the provided project root "apps/app1". Please provide a directory that is under the provided project root or use the "as-provided" format and only provide the directory."`

View File

@ -20,7 +20,9 @@ export async function scamPipeGenerator(tree: Tree, rawOptions: Schema) {
convertPipeToScam(tree, options); convertPipeToScam(tree, options);
exportScam(tree, options); exportScam(tree, options);
await formatFiles(tree); if (!options.skipFormat) {
await formatFiles(tree);
}
} }
export default scamPipeGenerator; export default scamPipeGenerator;

View File

@ -7,6 +7,7 @@ export interface Schema {
skipTests?: boolean; skipTests?: boolean;
inlineScam?: boolean; inlineScam?: boolean;
export?: boolean; export?: boolean;
skipFormat?: boolean;
/** /**
* @deprecated Provide the `directory` option instead and use the `as-provided` format. It will be removed in Nx v18. * @deprecated Provide the `directory` option instead and use the `as-provided` format. It will be removed in Nx v18.
*/ */

View File

@ -65,6 +65,12 @@
"description": "Specifies if the SCAM should be exported from the project's entry point (normally `index.ts`). It only applies to libraries.", "description": "Specifies if the SCAM should be exported from the project's entry point (normally `index.ts`). It only applies to libraries.",
"default": true, "default": true,
"x-priority": "important" "x-priority": "important"
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
"default": false,
"x-priority": "internal"
} }
}, },
"required": ["name"] "required": ["name"]

View File

@ -6,8 +6,12 @@ import { scamToStandalone } from './scam-to-standalone';
describe('scam-to-standalone', () => { describe('scam-to-standalone', () => {
it('should convert an inline scam to standalone', async () => { it('should convert an inline scam to standalone', async () => {
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
await generateTestApplication(tree, { name: 'foo' }); await generateTestApplication(tree, { name: 'foo', skipFormat: true });
await scamGenerator(tree, { name: 'bar', project: 'foo' }); await scamGenerator(tree, {
name: 'bar',
project: 'foo',
skipFormat: true,
});
tree.write( tree.write(
'foo/src/app/mymodule.module.ts', 'foo/src/app/mymodule.module.ts',

View File

@ -19,6 +19,7 @@ describe('convertComponentToScam', () => {
skipImport: true, skipImport: true,
export: false, export: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -46,7 +47,7 @@ describe('convertComponentToScam', () => {
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.component.html', templateUrl: './example.component.html',
styleUrl: './example.component.css', styleUrl: './example.component.css'
}) })
export class ExampleComponent {} export class ExampleComponent {}
@ -55,7 +56,8 @@ describe('convertComponentToScam', () => {
declarations: [ExampleComponent], declarations: [ExampleComponent],
exports: [ExampleComponent], exports: [ExampleComponent],
}) })
export class ExampleComponentModule {}" export class ExampleComponentModule {}
"
`); `);
}); });
@ -74,6 +76,7 @@ describe('convertComponentToScam', () => {
skipImport: true, skipImport: true,
export: false, export: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -104,7 +107,8 @@ describe('convertComponentToScam', () => {
declarations: [ExampleComponent], declarations: [ExampleComponent],
exports: [ExampleComponent], exports: [ExampleComponent],
}) })
export class ExampleComponentModule {}" export class ExampleComponentModule {}
"
`); `);
}); });
@ -124,6 +128,7 @@ describe('convertComponentToScam', () => {
export: false, export: false,
flat: true, flat: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -152,7 +157,7 @@ describe('convertComponentToScam', () => {
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.component.html', templateUrl: './example.component.html',
styleUrl: './example.component.css', styleUrl: './example.component.css'
}) })
export class ExampleComponent {} export class ExampleComponent {}
@ -161,7 +166,8 @@ describe('convertComponentToScam', () => {
declarations: [ExampleComponent], declarations: [ExampleComponent],
exports: [ExampleComponent], exports: [ExampleComponent],
}) })
export class ExampleComponentModule {}" export class ExampleComponentModule {}
"
`); `);
}); });
@ -181,6 +187,7 @@ describe('convertComponentToScam', () => {
export: false, export: false,
flat: true, flat: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -212,7 +219,8 @@ describe('convertComponentToScam', () => {
declarations: [ExampleComponent], declarations: [ExampleComponent],
exports: [ExampleComponent], exports: [ExampleComponent],
}) })
export class ExampleComponentModule {}" export class ExampleComponentModule {}
"
`); `);
}); });
@ -233,6 +241,7 @@ describe('convertComponentToScam', () => {
flat: true, flat: true,
type: 'random', type: 'random',
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -262,7 +271,7 @@ describe('convertComponentToScam', () => {
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.random.html', templateUrl: './example.random.html',
styleUrl: './example.random.css', styleUrl: './example.random.css'
}) })
export class ExampleRandom {} export class ExampleRandom {}
@ -271,7 +280,8 @@ describe('convertComponentToScam', () => {
declarations: [ExampleRandom], declarations: [ExampleRandom],
exports: [ExampleRandom], exports: [ExampleRandom],
}) })
export class ExampleRandomModule {}" export class ExampleRandomModule {}
"
`); `);
}); });
@ -292,6 +302,7 @@ describe('convertComponentToScam', () => {
flat: true, flat: true,
type: 'random', type: 'random',
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -324,7 +335,8 @@ describe('convertComponentToScam', () => {
declarations: [ExampleRandom], declarations: [ExampleRandom],
exports: [ExampleRandom], exports: [ExampleRandom],
}) })
export class ExampleRandomModule {}" export class ExampleRandomModule {}
"
`); `);
}); });
@ -345,6 +357,7 @@ describe('convertComponentToScam', () => {
flat: false, flat: false,
path: 'apps/app1/src/app/random', path: 'apps/app1/src/app/random',
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -373,7 +386,7 @@ describe('convertComponentToScam', () => {
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.component.html', templateUrl: './example.component.html',
styleUrl: './example.component.css', styleUrl: './example.component.css'
}) })
export class ExampleComponent {} export class ExampleComponent {}
@ -382,7 +395,8 @@ describe('convertComponentToScam', () => {
declarations: [ExampleComponent], declarations: [ExampleComponent],
exports: [ExampleComponent], exports: [ExampleComponent],
}) })
export class ExampleComponentModule {}" export class ExampleComponentModule {}
"
`); `);
}); });
@ -403,6 +417,7 @@ describe('convertComponentToScam', () => {
flat: true, flat: true,
path: 'apps/app1/src/app/random', path: 'apps/app1/src/app/random',
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -431,7 +446,7 @@ describe('convertComponentToScam', () => {
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.component.html', templateUrl: './example.component.html',
styleUrl: './example.component.css', styleUrl: './example.component.css'
}) })
export class ExampleComponent {} export class ExampleComponent {}
@ -440,7 +455,8 @@ describe('convertComponentToScam', () => {
declarations: [ExampleComponent], declarations: [ExampleComponent],
exports: [ExampleComponent], exports: [ExampleComponent],
}) })
export class ExampleComponentModule {}" export class ExampleComponentModule {}
"
`); `);
}); });
}); });

View File

@ -78,5 +78,6 @@ function getNgModuleDeclaration(componentClassName: string): string {
declarations: [${componentClassName}], declarations: [${componentClassName}],
exports: [${componentClassName}], exports: [${componentClassName}],
}) })
export class ${componentClassName}Module {}`; export class ${componentClassName}Module {}
`;
} }

View File

@ -17,6 +17,7 @@ describe('SCAM Generator', () => {
name: 'example', name: 'example',
project: 'app1', project: 'app1',
inlineScam: true, inlineScam: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -31,7 +32,7 @@ describe('SCAM Generator', () => {
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.component.html', templateUrl: './example.component.html',
styleUrl: './example.component.css', styleUrl: './example.component.css'
}) })
export class ExampleComponent {} export class ExampleComponent {}
@ -59,6 +60,7 @@ describe('SCAM Generator', () => {
name: 'example', name: 'example',
project: 'app1', project: 'app1',
inlineScam: false, inlineScam: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -101,6 +103,7 @@ describe('SCAM Generator', () => {
path: 'libs/lib1/feature/src/lib', path: 'libs/lib1/feature/src/lib',
inlineScam: false, inlineScam: false,
export: true, export: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -127,8 +130,7 @@ describe('SCAM Generator', () => {
); );
expect(secondaryEntryPointSource).toMatchInlineSnapshot(` expect(secondaryEntryPointSource).toMatchInlineSnapshot(`
"export * from './lib/example/example.component'; "export * from './lib/example/example.component';
export * from './lib/example/example.module'; export * from './lib/example/example.module';"
"
`); `);
}); });
@ -148,6 +150,7 @@ describe('SCAM Generator', () => {
project: 'app1', project: 'app1',
path: 'apps/app1/src/app/random', path: 'apps/app1/src/app/random',
inlineScam: true, inlineScam: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -162,7 +165,7 @@ describe('SCAM Generator', () => {
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.component.html', templateUrl: './example.component.html',
styleUrl: './example.component.css', styleUrl: './example.component.css'
}) })
export class ExampleComponent {} export class ExampleComponent {}
@ -191,6 +194,7 @@ describe('SCAM Generator', () => {
project: 'app1', project: 'app1',
path: '/apps/app1/src/app/random', path: '/apps/app1/src/app/random',
inlineScam: true, inlineScam: true,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -205,7 +209,7 @@ describe('SCAM Generator', () => {
@Component({ @Component({
selector: 'proj-example', selector: 'proj-example',
templateUrl: './example.component.html', templateUrl: './example.component.html',
styleUrl: './example.component.css', styleUrl: './example.component.css'
}) })
export class ExampleComponent {} export class ExampleComponent {}
@ -235,6 +239,7 @@ describe('SCAM Generator', () => {
project: 'app1', project: 'app1',
path: 'libs/proj/src/lib/random', path: 'libs/proj/src/lib/random',
inlineScam: true, inlineScam: true,
skipFormat: true,
}) })
).rejects.toThrowErrorMatchingInlineSnapshot( ).rejects.toThrowErrorMatchingInlineSnapshot(
`"The provided directory "libs/proj/src/lib/random" is not under the provided project root "apps/app1". Please provide a directory that is under the provided project root or use the "as-provided" format and only provide the directory."` `"The provided directory "libs/proj/src/lib/random" is not under the provided project root "apps/app1". Please provide a directory that is under the provided project root or use the "as-provided" format and only provide the directory."`

View File

@ -5,9 +5,8 @@ exports[`Init MF --federationType=dynamic should create a host with the correct
fetch('/assets/module-federation.manifest.json') fetch('/assets/module-federation.manifest.json')
.then((res) => res.json()) .then((res) => res.json())
.then((definitions) => setRemoteDefinitions(definitions)) .then(definitions => setRemoteDefinitions(definitions))
.then(() => import('./bootstrap').catch((err) => console.error(err))); .then(() => import('./bootstrap').catch(err => console.error(err));)"
"
`; `;
exports[`Init MF --federationType=dynamic should create a host with the correct configurations when --typescriptConfiguration=true 1`] = ` exports[`Init MF --federationType=dynamic should create a host with the correct configurations when --typescriptConfiguration=true 1`] = `
@ -15,9 +14,8 @@ exports[`Init MF --federationType=dynamic should create a host with the correct
fetch('/assets/module-federation.manifest.json') fetch('/assets/module-federation.manifest.json')
.then((res) => res.json()) .then((res) => res.json())
.then((definitions) => setRemoteDefinitions(definitions)) .then(definitions => setRemoteDefinitions(definitions))
.then(() => import('./bootstrap').catch((err) => console.error(err))); .then(() => import('./bootstrap').catch(err => console.error(err));)"
"
`; `;
exports[`Init MF should add a remote application and add it to a specified host applications router config 1`] = ` exports[`Init MF should add a remote application and add it to a specified host applications router config 1`] = `
@ -25,21 +23,18 @@ exports[`Init MF should add a remote application and add it to a specified host
import { Route } from '@angular/router'; import { Route } from '@angular/router';
export const appRoutes: Route[] = [ export const appRoutes: Route[] = [
{ {
path: 'remote2', path: 'remote2',
loadChildren: () => loadChildren: () => import('remote2/Module').then(m => m.RemoteEntryModule)
import('remote2/Module').then((m) => m.RemoteEntryModule), },
}, {
{
path: 'remote1', path: 'remote1',
loadChildren: () => loadChildren: () => import('remote1/Module').then(m => m.RemoteEntryModule)
import('remote1/Module').then((m) => m.RemoteEntryModule), },
}, {
{ path: '',
path: '', component: NxWelcomeComponent
component: NxWelcomeComponent, },];
},
];
" "
`; `;
@ -58,7 +53,7 @@ exports[`Init MF should add a remote application and add it to a specified host
* declare module 'my-external-remote'; * declare module 'my-external-remote';
* *
*/ */
remotes: ['remote1', 'remote2'], remotes: ['remote1','remote2',]
}; };
" "
`; `;
@ -80,7 +75,7 @@ const config: ModuleFederationConfig = {
* declare module 'my-external-remote'; * declare module 'my-external-remote';
* *
*/ */
remotes: ['remote1', 'remote2'], remotes: ['remote1','remote2',]
}; };
export default config; export default config;
@ -124,7 +119,7 @@ const config: ModuleFederationConfig = {
* declare module 'my-external-remote'; * declare module 'my-external-remote';
* *
*/ */
remotes: ['remote1'], remotes: ['remote1',]
}; };
export default config; export default config;
@ -137,16 +132,14 @@ import { Route } from '@angular/router';
import { loadRemoteModule } from '@nx/angular/mf'; import { loadRemoteModule } from '@nx/angular/mf';
export const appRoutes: Route[] = [ export const appRoutes: Route[] = [
{ {
path: 'remote1', path: 'remote1',
loadChildren: () => loadChildren: () => loadRemoteModule('remote1', './Module').then(m => m.RemoteEntryModule)
loadRemoteModule('remote1', './Module').then((m) => m.RemoteEntryModule), },
}, {
{ path: '',
path: '', component: NxWelcomeComponent
component: NxWelcomeComponent, },];
},
];
" "
`; `;
@ -156,16 +149,14 @@ import { Route } from '@angular/router';
import { loadRemoteModule } from '@nx/angular/mf'; import { loadRemoteModule } from '@nx/angular/mf';
export const appRoutes: Route[] = [ export const appRoutes: Route[] = [
{ {
path: 'remote1', path: 'remote1',
loadChildren: () => loadChildren: () => loadRemoteModule('remote1', './Module').then(m => m.RemoteEntryModule)
loadRemoteModule('remote1', './Module').then((m) => m.RemoteEntryModule), },
}, {
{ path: '',
path: '', component: NxWelcomeComponent
component: NxWelcomeComponent, },];
},
];
" "
`; `;
@ -191,7 +182,7 @@ exports[`Init MF should create webpack and mf configs correctly 2`] = `
* declare module 'my-external-remote'; * declare module 'my-external-remote';
* *
*/ */
remotes: [], remotes: []
}; };
" "
`; `;
@ -238,7 +229,7 @@ const config: ModuleFederationConfig = {
* declare module 'my-external-remote'; * declare module 'my-external-remote';
* *
*/ */
remotes: [], remotes: []
}; };
export default config; export default config;
@ -272,7 +263,7 @@ exports[`Init MF should generate the remote entry component correctly when prefi
@Component({ @Component({
selector: 'proj-remote1-entry', selector: 'proj-remote1-entry',
template: \`<proj-nx-welcome></proj-nx-welcome>\`, template: \`<proj-nx-welcome></proj-nx-welcome>\`
}) })
export class RemoteEntryComponent {} export class RemoteEntryComponent {}
" "

View File

@ -37,6 +37,8 @@ describe('AppComponent', () => {
tick(); tick();
fixture.detectChanges(); fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement; const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Welcome <%= appName %>'); expect(compiled.querySelector('h1')?.textContent).toContain(
'Welcome <%= appName %>'
);
})); }));
}); });

View File

@ -1,4 +1,4 @@
import {withModuleFederation} from '@nx/angular/module-federation'; import { withModuleFederation } from '@nx/angular/module-federation';
import config from './module-federation.config'; import config from './module-federation.config';
export default withModuleFederation(config); export default withModuleFederation(config);

View File

@ -1,16 +1,16 @@
import {withModuleFederation} from '@nx/angular/module-federation'; import { withModuleFederation } from '@nx/angular/module-federation';
import config from './module-federation.config'; import config from './module-federation.config';
export default withModuleFederation({ export default withModuleFederation({
...config, ...config,
/* /*
* Remote overrides for production. * Remote overrides for production.
* Each entry is a pair of a unique name and the URL where it is deployed. * Each entry is a pair of a unique name and the URL where it is deployed.
* *
* e.g. * e.g.
* remotes: [ * remotes: [
* ['app1', 'https://app1.example.com'], * ['app1', 'https://app1.example.com'],
* ['app2', 'https://app2.example.com'], * ['app2', 'https://app2.example.com'],
* ] * ]
*/ */
}); });

View File

@ -17,4 +17,4 @@ module.exports = {
'./Routes': '<%= projectRoot %>/src/app/remote-entry/entry.routes.ts',<% } else { %> './Routes': '<%= projectRoot %>/src/app/remote-entry/entry.routes.ts',<% } else { %>
'./Module': '<%= projectRoot %>/src/app/remote-entry/entry.module.ts',<% } %> './Module': '<%= projectRoot %>/src/app/remote-entry/entry.module.ts',<% } %>
},<% } %> },<% } %>
} };

View File

@ -35,7 +35,7 @@ export function addRemoteEntry(
addRoute( addRoute(
tree, tree,
joinPathFragments(appRoot, 'src/app/app.routes.ts'), joinPathFragments(appRoot, 'src/app/app.routes.ts'),
`{path: '', loadChildren: () => import('./remote-entry/entry.module').then(m => m.RemoteEntryModule)}` `{ path: '', loadChildren: () => import('./remote-entry/entry.module').then(m => m.RemoteEntryModule) }`
); );
} }
} }

View File

@ -193,7 +193,7 @@ function addLazyLoadedRouteToHostAppModule(
const newAppComponent = `${appComponent.slice( const newAppComponent = `${appComponent.slice(
0, 0,
indexOfClosingMenuTag indexOfClosingMenuTag
)}<li><a routerLink='${options.appName}'>${ )}<li><a routerLink="${options.appName}">${
names(options.appName).className names(options.appName).className
}</a></li>\n${appComponent.slice(indexOfClosingMenuTag)}`; }</a></li>\n${appComponent.slice(indexOfClosingMenuTag)}`;
tree.write(pathToAppComponentTemplate, newAppComponent); tree.write(pathToAppComponentTemplate, newAppComponent);

View File

@ -11,11 +11,11 @@ export function fixBootstrap(tree: Tree, appRoot: string, options: Schema) {
tree.write(joinPathFragments(appRoot, 'src/bootstrap.ts'), bootstrapCode); tree.write(joinPathFragments(appRoot, 'src/bootstrap.ts'), bootstrapCode);
} }
const bootstrapImportCode = `import('./bootstrap').catch(err => console.error(err))`; const bootstrapImportCode = `import('./bootstrap').catch(err => console.error(err));`;
const fetchMFManifestCode = `import { setRemoteDefinitions } from '@nx/angular/mf'; const fetchMFManifestCode = `import { setRemoteDefinitions } from '@nx/angular/mf';
fetch('/assets/module-federation.manifest.json') fetch('/assets/module-federation.manifest.json')
.then((res) => res.json()) .then((res) => res.json())
.then(definitions => setRemoteDefinitions(definitions)) .then(definitions => setRemoteDefinitions(definitions))
.then(() => ${bootstrapImportCode})`; .then(() => ${bootstrapImportCode})`;
@ -29,10 +29,11 @@ export function fixBootstrap(tree: Tree, appRoot: string, options: Schema) {
} }
const standaloneBootstrapCode = const standaloneBootstrapCode =
() => `import {bootstrapApplication} from "@angular/platform-browser"; () => `import { bootstrapApplication } from '@angular/platform-browser';
import {appConfig} from './app/app.config'; import { appConfig } from './app/app.config';
import {RemoteEntryComponent} from './app/remote-entry/entry.component'; import { RemoteEntryComponent } from './app/remote-entry/entry.component';
bootstrapApplication(RemoteEntryComponent, appConfig).catch((err) => bootstrapApplication(RemoteEntryComponent, appConfig).catch((err) =>
console.error(err) console.error(err)
);`; );
`;

View File

@ -55,16 +55,16 @@ import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
@NgModule({ @NgModule({
declarations: [AppComponent], declarations: [AppComponent],
imports: [ imports: [
BrowserModule, BrowserModule,
RouterModule.forRoot([{ RouterModule.forRoot([{
path: '', path: '',
loadChildren: () => import('./remote-entry/entry.module').then(m => m.RemoteEntryModule) loadChildren: () => import('./remote-entry/entry.module').then(m => m.RemoteEntryModule)
}], { initialNavigation: 'enabledBlocking' }), }], { initialNavigation: 'enabledBlocking' }),
], ],
providers: [], providers: [],
bootstrap: [AppComponent], bootstrap: [AppComponent],
}) })
export class AppModule {}` export class AppModule {}`
); );

View File

@ -28,7 +28,7 @@ export function updateHostAppRoutes(tree: Tree, options: Schema) {
tree.write( tree.write(
joinPathFragments(sourceRoot, 'app/app.component.html'), joinPathFragments(sourceRoot, 'app/app.component.html'),
`<ul class="remote-menu"> `<ul class="remote-menu">
<li><a routerLink='/'>Home</a></li>${remoteRoutes} <li><a routerLink="/">Home</a></li>${remoteRoutes}
</ul> </ul>
<router-outlet></router-outlet> <router-outlet></router-outlet>
` `
@ -68,7 +68,7 @@ export function updateHostAppRoutes(tree: Tree, options: Schema) {
tree.write( tree.write(
pathToHostRootRoutingFile, pathToHostRootRoutingFile,
`import { NxWelcomeComponent } from './nx-welcome.component'; `import { NxWelcomeComponent } from './nx-welcome.component';
${tree.read(pathToHostRootRoutingFile, 'utf-8')}` ${tree.read(pathToHostRootRoutingFile, 'utf-8')}`
); );
generateFiles( generateFiles(

View File

@ -12,11 +12,13 @@ describe('Init MF', () => {
name: 'app1', name: 'app1',
routing: true, routing: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
await generateTestApplication(tree, { await generateTestApplication(tree, {
name: 'remote1', name: 'remote1',
routing: true, routing: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
}); });
@ -32,6 +34,7 @@ describe('Init MF', () => {
mfType: type, mfType: type,
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -62,6 +65,7 @@ describe('Init MF', () => {
mfType: type, mfType: type,
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -94,6 +98,7 @@ describe('Init MF', () => {
appName: app, appName: app,
mfType: type, mfType: type,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -119,13 +124,14 @@ describe('Init MF', () => {
appName: app, appName: app,
mfType: type, mfType: type,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
const updatedMainContents = tree.read(`${app}/src/main.ts`, 'utf-8'); const updatedMainContents = tree.read(`${app}/src/main.ts`, 'utf-8');
expect(updatedMainContents).toEqual( expect(updatedMainContents).toEqual(
`import('./bootstrap').catch((err) => console.error(err));\n` `import('./bootstrap').catch(err => console.error(err));`
); );
expect(updatedMainContents).not.toEqual(mainContents); expect(updatedMainContents).not.toEqual(mainContents);
} }
@ -143,6 +149,7 @@ describe('Init MF', () => {
mfType: type, mfType: type,
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -172,6 +179,7 @@ describe('Init MF', () => {
mfType: type, mfType: type,
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -196,6 +204,7 @@ describe('Init MF', () => {
mfType: 'host', mfType: 'host',
federationType: 'dynamic', federationType: 'dynamic',
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -228,6 +237,7 @@ describe('Init MF', () => {
appName: 'remote1', appName: 'remote1',
mfType: 'remote', mfType: 'remote',
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -244,6 +254,7 @@ describe('Init MF', () => {
remotes: ['remote1'], remotes: ['remote1'],
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -263,6 +274,7 @@ describe('Init MF', () => {
remotes: ['remote1'], remotes: ['remote1'],
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -281,6 +293,7 @@ describe('Init MF', () => {
mfType: 'host', mfType: 'host',
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -304,6 +317,7 @@ describe('Init MF', () => {
mfType: 'host', mfType: 'host',
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -313,6 +327,7 @@ describe('Init MF', () => {
host: 'app1', host: 'app1',
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -325,6 +340,7 @@ describe('Init MF', () => {
await generateTestApplication(tree, { await generateTestApplication(tree, {
name: 'remote2', name: 'remote2',
standalone: false, standalone: false,
skipFormat: true,
}); });
await setupMf(tree, { await setupMf(tree, {
@ -332,6 +348,7 @@ describe('Init MF', () => {
mfType: 'host', mfType: 'host',
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
await setupMf(tree, { await setupMf(tree, {
@ -341,6 +358,7 @@ describe('Init MF', () => {
port: 4201, port: 4201,
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -351,6 +369,7 @@ describe('Init MF', () => {
port: 4202, port: 4202,
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -363,6 +382,7 @@ describe('Init MF', () => {
await generateTestApplication(tree, { await generateTestApplication(tree, {
name: 'remote2', name: 'remote2',
standalone: false, standalone: false,
skipFormat: true,
}); });
await setupMf(tree, { await setupMf(tree, {
@ -370,6 +390,7 @@ describe('Init MF', () => {
mfType: 'host', mfType: 'host',
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
await setupMf(tree, { await setupMf(tree, {
@ -379,6 +400,7 @@ describe('Init MF', () => {
port: 4201, port: 4201,
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -389,6 +411,7 @@ describe('Init MF', () => {
port: 4202, port: 4202,
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -402,6 +425,7 @@ describe('Init MF', () => {
name: 'remote2', name: 'remote2',
routing: true, routing: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
await setupMf(tree, { await setupMf(tree, {
@ -409,6 +433,7 @@ describe('Init MF', () => {
mfType: 'host', mfType: 'host',
routing: true, routing: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
await setupMf(tree, { await setupMf(tree, {
@ -418,6 +443,7 @@ describe('Init MF', () => {
port: 4201, port: 4201,
routing: true, routing: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -428,6 +454,7 @@ describe('Init MF', () => {
port: 4202, port: 4202,
routing: true, routing: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -441,6 +468,7 @@ describe('Init MF', () => {
name: 'test-app', name: 'test-app',
routing: true, routing: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -450,6 +478,7 @@ describe('Init MF', () => {
routing: true, routing: true,
e2eProjectName: 'test-app-e2e', e2eProjectName: 'test-app-e2e',
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -472,6 +501,7 @@ describe('Init MF', () => {
federationType: 'dynamic', federationType: 'dynamic',
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -493,6 +523,7 @@ describe('Init MF', () => {
federationType: 'dynamic', federationType: 'dynamic',
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -515,6 +546,7 @@ describe('Init MF', () => {
federationType: 'dynamic', federationType: 'dynamic',
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -526,6 +558,7 @@ describe('Init MF', () => {
routing: true, routing: true,
typescriptConfiguration: false, typescriptConfiguration: false,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT
@ -549,6 +582,7 @@ describe('Init MF', () => {
federationType: 'dynamic', federationType: 'dynamic',
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ACT // ACT
@ -560,6 +594,7 @@ describe('Init MF', () => {
routing: true, routing: true,
typescriptConfiguration: true, typescriptConfiguration: true,
standalone: false, standalone: false,
skipFormat: true,
}); });
// ASSERT // ASSERT

View File

@ -14,17 +14,12 @@ import { AppServerModule } from './src/main.server';
export function app(): express.Express { export function app(): express.Express {
const server = express(); const server = express();
const distFolder = join(process.cwd(), 'dist/app1/browser'); const distFolder = join(process.cwd(), 'dist/app1/browser');
const indexHtml = existsSync(join(distFolder, 'index.original.html')) const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';
? 'index.original.html'
: 'index';
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/main/modules/express-engine) // Our Universal express-engine (found @ https://github.com/angular/universal/tree/main/modules/express-engine)
server.engine( server.engine('html', ngExpressEngine({
'html', bootstrap: AppServerModule,
ngExpressEngine({ }));
bootstrap: AppServerModule,
})
);
server.set('view engine', 'html'); server.set('view engine', 'html');
server.set('views', distFolder); server.set('views', distFolder);
@ -32,19 +27,13 @@ export function app(): express.Express {
// Example Express Rest API endpoints // Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { }); // server.get('/api/**', (req, res) => { });
// Serve static files from /browser // Serve static files from /browser
server.get( server.get('*.*', express.static(distFolder, {
'*.*', maxAge: '1y'
express.static(distFolder, { }));
maxAge: '1y',
})
);
// All regular routes use the Universal engine // All regular routes use the Universal engine
server.get('*', (req, res) => { server.get('*', (req, res) => {
res.render(indexHtml, { res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
req,
providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }],
});
}); });
return server; return server;
@ -65,7 +54,7 @@ function run(): void {
// The below code is to ensure that the server is run only when not requiring the bundle. // The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire; declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main; const mainModule = __non_webpack_require__.main;
const moduleFilename = (mainModule && mainModule.filename) || ''; const moduleFilename = mainModule && mainModule.filename || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) { if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
run(); run();
} }
@ -357,12 +346,9 @@ export function app(): express.Express {
// Example Express Rest API endpoints // Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { }); // server.get('/api/**', (req, res) => { });
// Serve static files from /browser // Serve static files from /browser
server.get( server.get('*.*', express.static(distFolder, {
'*.*', maxAge: '1y'
express.static(distFolder, { }));
maxAge: '1y',
})
);
// All regular routes use the Angular engine // All regular routes use the Angular engine
server.get('*', (req, res, next) => { server.get('*', (req, res, next) => {
@ -398,7 +384,7 @@ function run(): void {
// The below code is to ensure that the server is run only when not requiring the bundle. // The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire; declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main; const mainModule = __non_webpack_require__.main;
const moduleFilename = (mainModule && mainModule.filename) || ''; const moduleFilename = mainModule && mainModule.filename || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) { if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
run(); run();
} }
@ -460,12 +446,9 @@ export function app(): express.Express {
// Example Express Rest API endpoints // Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { }); // server.get('/api/**', (req, res) => { });
// Serve static files from /browser // Serve static files from /browser
server.get( server.get('*.*', express.static(distFolder, {
'*.*', maxAge: '1y'
express.static(distFolder, { }));
maxAge: '1y',
})
);
// All regular routes use the Angular engine // All regular routes use the Angular engine
server.get('*', (req, res, next) => { server.get('*', (req, res, next) => {
@ -501,7 +484,7 @@ function run(): void {
// The below code is to ensure that the server is run only when not requiring the bundle. // The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire; declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main; const mainModule = __non_webpack_require__.main;
const moduleFilename = (mainModule && mainModule.filename) || ''; const moduleFilename = mainModule && mainModule.filename || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) { if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
run(); run();
} }

Some files were not shown because too many files have changed in this diff Show More