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 },
"x-prompt": "What micro frontend project would you like to migrate?",
"x-priority": "important"
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
"default": false,
"x-priority": "internal"
}
},
"presets": []

View File

@ -29,6 +29,12 @@
"type": "boolean",
"description": "Skip generating a module for the secondary entry point.",
"default": false
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
"default": false,
"x-priority": "internal"
}
},
"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.",
"default": true,
"x-priority": "important"
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
"default": false,
"x-priority": "internal"
}
},
"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.",
"default": true,
"x-priority": "important"
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
"default": false,
"x-priority": "internal"
}
},
"required": ["name"],

View File

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

View File

@ -9,7 +9,10 @@ import { appRoutes } from './app.routes';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, RouterModule.forRoot(appRoutes)],
imports: [
BrowserModule,
RouterModule.forRoot(appRoutes),
],
providers: [],
bootstrap: [AppComponent],
})
@ -38,7 +41,7 @@ describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [RouterTestingModule],
declarations: [AppComponent],
declarations: [AppComponent]
}).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`] = `
"<h1>Welcome plain</h1>
<router-outlet></router-outlet>
"<h1>Welcome plain</h1> <router-outlet></router-outlet>
"
`;
@ -67,7 +69,9 @@ import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
imports: [
BrowserModule,
],
providers: [],
bootstrap: [AppComponent],
})
@ -95,7 +99,7 @@ describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [],
declarations: [AppComponent],
declarations: [AppComponent]
}).compileComponents();
});
@ -156,8 +160,7 @@ describe('AppComponent', () => {
`;
exports[`app --minimal should skip "nx-welcome.component.ts" file and references for standalone apps with routing 3`] = `
"<h1>Welcome plain</h1>
<router-outlet></router-outlet>
"<h1>Welcome plain</h1> <router-outlet></router-outlet>
"
`;
@ -670,7 +673,7 @@ import { provideRouter } from '@angular/router';
import { appRoutes } from './app.routes';
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';
export const appConfig: ApplicationConfig = {
providers: [],
providers: []
};
"
`;
@ -757,7 +760,7 @@ import { NxWelcomeComponent } from './nx-welcome.component';
@Component({
standalone: true,
imports: [NxWelcomeComponent],
imports: [NxWelcomeComponent, ],
selector: 'proj-root',
templateUrl: './app.component.html',
styleUrl: './app.component.css',
@ -870,13 +873,84 @@ import { provideRouter } from '@angular/router';
import { appRoutes } from './app.routes';
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 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`] = `
{
"$schema": "../../node_modules/nx/schemas/project-schema.json",

View File

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

View File

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

View File

@ -11,10 +11,12 @@ describe('AppComponent', () => {
});
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Welcome <%= appName %>');
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain(
'Welcome <%= appName %>'
);
});<% if(!minimal) { %>
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 { 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;'
)
);
it('should render the component', () => {
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;'
)
);
it('should render the component', () => {
cy.get('proj-test-button').should('exist');
});

View File

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

View File

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

View File

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

View File

@ -14,14 +14,14 @@ type Story = StoryObj<<%=componentName%>>;
export const Primary: Story = {
args: {<% for (let prop of props) { %>
<%= prop.name %>: <%- prop.defaultValue %>,<% } %>
<%= prop.name %>: <%- prop.defaultValue %>,<% } %>
},
};
<% if ( interactionTests ) { %>
export const Heading: Story = {
args: {<% for (let prop of props) { %>
<%= prop.name %>: <%- prop.defaultValue %>,<% } %>
<%= prop.name %>: <%- prop.defaultValue %>,<% } %>
},
play: async ({ 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';
describe(MyLibComponent.name, () => {
beforeEach(() => {
TestBed.overrideComponent(MyLibComponent, {
add: {
imports: [],
providers: []
}
})
})
providers: [],
},
});
});
it('renders', () => {
cy.mount(MyLibComponent, {
componentProperties: {
type: 'button',
style: 'default',
age: 0,
isOn: false,
}
});
})
})
cy.mount(MyLibComponent, {
componentProperties: {
type: 'button',
style: 'default',
age: 0,
isOn: false,
},
});
});
});
"
`;
@ -35,21 +33,19 @@ exports[`Angular Cypress Component Test Generator should handle component w/o in
import { MyLibComponent } from './my-lib.component';
describe(MyLibComponent.name, () => {
beforeEach(() => {
TestBed.overrideComponent(MyLibComponent, {
add: {
imports: [],
providers: []
}
})
})
});
});
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';
describe(MyLibComponent.name, () => {
beforeEach(() => {
TestBed.overrideComponent(MyLibComponent, {
add: {
imports: [],
providers: []
}
})
})
providers: [],
},
});
});
it('renders', () => {
cy.mount(MyLibComponent, {
componentProperties: {
type: 'button',
style: 'default',
age: 0,
isOn: false,
}
});
})
})
cy.mount(MyLibComponent, {
componentProperties: {
type: 'button',
style: 'default',
age: 0,
isOn: false,
},
});
});
});
"
`;

View File

@ -26,16 +26,19 @@ describe('Angular Cypress Component Test Generator', () => {
name: 'my-lib',
unitTestRunner: UnitTestRunner.None,
linter: Linter.None,
skipFormat: true,
});
await componentGenerator(tree, {
project: 'my-lib',
name: 'my-lib',
skipFormat: true,
});
componentTestGenerator(tree, {
await componentTestGenerator(tree, {
componentName: 'MyLibComponent',
componentFileName: './my-lib.component',
project: 'my-lib',
componentDir: 'src/lib/my-lib',
skipFormat: true,
});
expect(
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',
unitTestRunner: UnitTestRunner.None,
linter: Linter.None,
skipFormat: true,
});
await componentGenerator(tree, {
project: 'my-lib',
name: 'my-lib',
skipFormat: true,
});
tree.write(
@ -82,7 +87,7 @@ export class MyLibComponent implements OnInit {
}`
);
componentTestGenerator(tree, {
await componentTestGenerator(tree, {
componentName: 'MyLibComponent',
componentFileName: './my-lib.component',
project: 'my-lib',
@ -99,11 +104,13 @@ export class MyLibComponent implements OnInit {
name: 'my-lib',
unitTestRunner: UnitTestRunner.None,
linter: Linter.None,
skipFormat: true,
});
await componentGenerator(tree, {
project: 'my-lib',
name: 'my-lib',
standalone: true,
skipFormat: true,
});
tree.write(
'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',
componentFileName: './my-lib.component',
project: 'my-lib',
@ -150,19 +157,25 @@ export class MyLibComponent implements OnInit {
name: 'my-lib',
unitTestRunner: UnitTestRunner.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(
'my-lib/src/lib/my-lib/my-lib.component.cy.ts',
`should not overwrite`
);
componentTestGenerator(tree, {
await componentTestGenerator(tree, {
componentName: 'MyLibComponent',
componentFileName: './my-lib.component',
project: 'my-lib',
componentDir: 'src/lib/my-lib',
skipFormat: true,
});
expect(
@ -175,46 +188,51 @@ export class MyLibComponent implements OnInit {
name: 'my-lib',
unitTestRunner: UnitTestRunner.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';
import { MyLibComponent } from './my-lib.component';
describe(MyLibComponent.name, () => {
beforeEach(() => {
TestBed.overrideComponent(MyLibComponent, {
add: {
imports: [],
providers: []
}
})
})
});
});
it('renders', () => {
cy.mount(MyLibComponent,);
})
})
cy.mount(MyLibComponent);
});
});
`;
componentTestGenerator(tree, {
await componentTestGenerator(tree, {
componentName: 'MyLibComponent',
componentFileName: './my-lib.component',
project: 'my-lib',
componentDir: 'src/lib/my-lib',
skipFormat: true,
});
expect(
tree.read('my-lib/src/lib/my-lib/my-lib.component.cy.ts', 'utf-8')
).toEqual(expected);
componentTestGenerator(tree, {
await componentTestGenerator(tree, {
componentName: 'MyLibComponent',
componentFileName: './my-lib.component',
project: 'my-lib',
componentDir: 'src/lib/my-lib',
skipFormat: true,
});
expect(
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 {
formatFiles,
generateFiles,
joinPathFragments,
readProjectConfiguration,
@ -11,7 +12,7 @@ import {
} from '../utils/storybook-ast/storybook-inputs';
import { ComponentTestSchema } from './schema';
export function componentTestGenerator(
export async function componentTestGenerator(
tree: Tree,
options: ComponentTestSchema
) {
@ -48,6 +49,10 @@ export function componentTestGenerator(
}
);
}
if (!options.skipFormat) {
await formatFiles(tree);
}
}
export default componentTestGenerator;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -22,6 +22,12 @@
},
"x-prompt": "What micro frontend project would you like to migrate?",
"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
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Cypress {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Chainable<Subject> {
mount: typeof mount;
}
}
}
Cypress.Commands.add('mount', mount);
"
Cypress.Commands.add('mount', mount);"
`;
exports[`Cypress Component Testing Configuration should work with complex component 1`] = `
@ -44,8 +44,8 @@ describe(SomethingOneComponent.name, () => {
TestBed.overrideComponent(SomethingOneComponent, {
add: {
imports: [],
providers: [],
},
providers: []
}
});
});
@ -65,8 +65,8 @@ describe(SomethingTwoComponent.name, () => {
TestBed.overrideComponent(SomethingTwoComponent, {
add: {
imports: [],
providers: [],
},
providers: []
}
});
});
@ -86,8 +86,8 @@ describe(SomethingThreeComponent.name, () => {
TestBed.overrideComponent(SomethingThreeComponent, {
add: {
imports: [],
providers: [],
},
providers: []
}
});
});
@ -170,8 +170,8 @@ describe(FancyButtonComponent.name, () => {
TestBed.overrideComponent(FancyButtonComponent, {
add: {
imports: [],
providers: [],
},
providers: []
}
});
});
@ -191,8 +191,8 @@ describe(StandaloneFancyButtonComponent.name, () => {
TestBed.overrideComponent(StandaloneFancyButtonComponent, {
add: {
imports: [],
providers: [],
},
providers: []
}
});
});
@ -212,8 +212,8 @@ describe(SomethingOneComponent.name, () => {
TestBed.overrideComponent(SomethingOneComponent, {
add: {
imports: [],
providers: [],
},
providers: []
}
});
});
@ -233,8 +233,8 @@ describe(SomethingTwoComponent.name, () => {
TestBed.overrideComponent(SomethingTwoComponent, {
add: {
imports: [],
providers: [],
},
providers: []
}
});
});
@ -254,8 +254,8 @@ describe(SomethingThreeComponent.name, () => {
TestBed.overrideComponent(SomethingThreeComponent, {
add: {
imports: [],
providers: [],
},
providers: []
}
});
});

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -20,6 +20,7 @@ describe('Host App Generator', () => {
name: 'test',
typescriptConfiguration: false,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -34,6 +35,7 @@ describe('Host App Generator', () => {
name: 'test',
typescriptConfiguration: true,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -48,6 +50,7 @@ describe('Host App Generator', () => {
name: 'remote',
typescriptConfiguration: false,
standalone: false,
skipFormat: true,
});
// ACT
@ -56,6 +59,7 @@ describe('Host App Generator', () => {
remotes: ['remote'],
typescriptConfiguration: false,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -70,6 +74,7 @@ describe('Host App Generator', () => {
name: 'remote',
typescriptConfiguration: true,
standalone: false,
skipFormat: true,
});
// ACT
@ -78,6 +83,7 @@ describe('Host App Generator', () => {
remotes: ['remote'],
typescriptConfiguration: true,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -96,6 +102,7 @@ describe('Host App Generator', () => {
remotes: ['remote1', 'remote2'],
typescriptConfiguration: false,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -103,13 +110,13 @@ describe('Host App Generator', () => {
expect(tree.exists('remote2/project.json')).toBeTruthy();
expect(
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'))
.toMatchInlineSnapshot(`
"<ul class="remote-menu">
<li><a routerLink="/">Home</a></li>
<li><a routerLink="remote1">Remote1</a></li>
<li><a routerLink="remote2">Remote2</a></li>
<li><a routerLink="/">Home</a></li>
<li><a routerLink="remote1">Remote1</a></li>
<li><a routerLink="remote2">Remote2</a></li>
</ul>
<router-outlet></router-outlet>
"
@ -127,6 +134,7 @@ describe('Host App Generator', () => {
remotes: ['remote1', 'remote2'],
typescriptConfiguration: true,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -134,13 +142,13 @@ describe('Host App Generator', () => {
expect(tree.exists('remote2/project.json')).toBeTruthy();
expect(
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'))
.toMatchInlineSnapshot(`
"<ul class="remote-menu">
<li><a routerLink="/">Home</a></li>
<li><a routerLink="remote1">Remote1</a></li>
<li><a routerLink="remote2">Remote2</a></li>
<li><a routerLink="/">Home</a></li>
<li><a routerLink="remote1">Remote1</a></li>
<li><a routerLink="remote2">Remote2</a></li>
</ul>
<router-outlet></router-outlet>
"
@ -154,6 +162,7 @@ describe('Host App Generator', () => {
name: 'remote1',
typescriptConfiguration: false,
standalone: false,
skipFormat: true,
});
// ACT
@ -162,6 +171,7 @@ describe('Host App Generator', () => {
remotes: ['remote1', 'remote2', 'remote3'],
typescriptConfiguration: false,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -170,7 +180,7 @@ describe('Host App Generator', () => {
expect(tree.exists('remote3/project.json')).toBeTruthy();
expect(
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 () => {
@ -180,6 +190,7 @@ describe('Host App Generator', () => {
name: 'remote1',
typescriptConfiguration: true,
standalone: false,
skipFormat: true,
});
// ACT
@ -188,6 +199,7 @@ describe('Host App Generator', () => {
remotes: ['remote1', 'remote2', 'remote3'],
typescriptConfiguration: true,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -196,7 +208,7 @@ describe('Host App Generator', () => {
expect(tree.exists('remote3/project.json')).toBeTruthy();
expect(
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 () => {
@ -206,6 +218,7 @@ describe('Host App Generator', () => {
name: 'remote1',
typescriptConfiguration: false,
standalone: false,
skipFormat: true,
});
// ACT
@ -215,6 +228,7 @@ describe('Host App Generator', () => {
remotes: ['remote1', 'remote2', 'remote3'],
typescriptConfiguration: false,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -223,7 +237,7 @@ describe('Host App Generator', () => {
expect(tree.exists('foo/remote3/project.json')).toBeTruthy();
expect(
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 () => {
@ -233,6 +247,7 @@ describe('Host App Generator', () => {
name: 'remote1',
typescriptConfiguration: true,
standalone: false,
skipFormat: true,
});
// ACT
@ -242,6 +257,7 @@ describe('Host App Generator', () => {
remotes: ['remote1', 'remote2', 'remote3'],
typescriptConfiguration: true,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -250,7 +266,7 @@ describe('Host App Generator', () => {
expect(tree.exists('foo/remote3/project.json')).toBeTruthy();
expect(
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 () => {
@ -261,6 +277,7 @@ describe('Host App Generator', () => {
await generateTestHostApplication(tree, {
name: 'host',
remotes: ['remote1'],
skipFormat: true,
});
// ASSERT
@ -279,6 +296,7 @@ describe('Host App Generator', () => {
await generateTestHostApplication(tree, {
name: 'host',
remotes: ['remote1'],
skipFormat: true,
});
// ASSERT
@ -296,6 +314,7 @@ describe('Host App Generator', () => {
name: 'dashboard',
remotes: ['remote1'],
directory: 'test/dashboard',
skipFormat: true,
});
// ASSERT
@ -314,6 +333,7 @@ describe('Host App Generator', () => {
remotes: ['remote1'],
e2eTestRunner: E2eTestRunner.None,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -369,6 +389,7 @@ describe('Host App Generator', () => {
ssr: true,
typescriptConfiguration: true,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -443,6 +464,7 @@ describe('Host App Generator', () => {
name: 'test',
ssr: true,
typescriptConfiguration: true,
skipFormat: true,
});
// 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();
});
@ -499,6 +525,7 @@ describe('Host App Generator', () => {
projectNameAndRootFormat: 'derived',
typescriptConfiguration: false,
standalone: false,
skipFormat: true,
});
// ACT
@ -508,6 +535,7 @@ describe('Host App Generator', () => {
projectNameAndRootFormat: 'derived',
typescriptConfiguration: false,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -516,7 +544,7 @@ describe('Host App Generator', () => {
expect(tree.exists('apps/remote3/project.json')).toBeTruthy();
expect(
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 () => {
@ -527,6 +555,7 @@ describe('Host App Generator', () => {
projectNameAndRootFormat: 'derived',
typescriptConfiguration: false,
standalone: false,
skipFormat: true,
});
// ACT
@ -537,6 +566,7 @@ describe('Host App Generator', () => {
projectNameAndRootFormat: 'derived',
typescriptConfiguration: false,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -545,7 +575,7 @@ describe('Host App Generator', () => {
expect(tree.exists('apps/foo/remote3/project.json')).toBeTruthy();
expect(
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 () => {
// ARRANGE
@ -555,6 +585,7 @@ describe('Host App Generator', () => {
projectNameAndRootFormat: 'derived',
typescriptConfiguration: true,
standalone: false,
skipFormat: true,
});
// ACT
@ -565,6 +596,7 @@ describe('Host App Generator', () => {
projectNameAndRootFormat: 'derived',
typescriptConfiguration: true,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -573,7 +605,7 @@ describe('Host App Generator', () => {
expect(tree.exists('apps/foo/remote3/project.json')).toBeTruthy();
expect(
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, {
unitTestRunner: UnitTestRunner.Jest,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
// ASSERT
@ -79,7 +79,7 @@ describe('init', () => {
}));
// ACT
await init(tree, {});
await init(tree, { skipFormat: true });
// ASSERT
const { dependencies, devDependencies } = readJson(tree, 'package.json');
@ -112,7 +112,7 @@ describe('init', () => {
}));
// ACT
await init(tree, {});
await init(tree, { skipFormat: true });
// ASSERT
const { dependencies } = readJson(tree, 'package.json');
@ -128,7 +128,7 @@ describe('init', () => {
await init(tree, {
unitTestRunner: UnitTestRunner.Jest,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
const { devDependencies } = readJson(tree, 'package.json');
@ -144,7 +144,7 @@ describe('init', () => {
await init(tree, {
unitTestRunner: UnitTestRunner.Jest,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
const hasJestConfigFile = tree.exists('jest.config.ts');
@ -158,7 +158,7 @@ describe('init', () => {
await init(tree, {
unitTestRunner: UnitTestRunner.Jest,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -182,7 +182,7 @@ describe('init', () => {
unitTestRunner: UnitTestRunner.None,
e2eTestRunner: E2eTestRunner.Playwright,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
expect(ensurePackage).toHaveBeenLastCalledWith(
@ -197,7 +197,7 @@ describe('init', () => {
unitTestRunner: UnitTestRunner.None,
e2eTestRunner: E2eTestRunner.Playwright,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -215,7 +215,7 @@ describe('init', () => {
unitTestRunner: UnitTestRunner.None,
e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
expect(ensurePackage).toHaveBeenLastCalledWith('@nx/cypress', '0.0.1');
@ -227,7 +227,7 @@ describe('init', () => {
unitTestRunner: UnitTestRunner.None,
e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -247,7 +247,7 @@ describe('init', () => {
await init(tree, {
unitTestRunner: UnitTestRunner.None,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -264,7 +264,7 @@ describe('init', () => {
await init(tree, {
unitTestRunner: UnitTestRunner.None,
linter: Linter.None,
skipFormat: false,
skipFormat: true,
});
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -284,7 +284,7 @@ describe('init', () => {
unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
expect(tree.read('.gitignore', 'utf-8')).toContain('.angular');
@ -305,7 +305,7 @@ bar
unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
const angularEntries = tree
@ -321,7 +321,7 @@ bar
unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
expect(tree.read('.prettierignore', 'utf-8')).toContain('.angular');
@ -342,7 +342,7 @@ bar
unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
const angularEntries = tree
@ -363,7 +363,7 @@ bar
unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
expect(tree.read('.gitignore', 'utf-8')).toContain(
@ -393,7 +393,7 @@ bar
await init(tree, {
unitTestRunner: UnitTestRunner.Jest,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
// ASSERT
@ -458,7 +458,7 @@ bar
}));
// ACT
await init(tree, {});
await init(tree, { skipFormat: true });
// ASSERT
const { dependencies, devDependencies } = readJson(tree, 'package.json');
@ -491,7 +491,7 @@ bar
}));
// ACT
await init(tree, {});
await init(tree, { skipFormat: true });
// ASSERT
const { dependencies } = readJson(tree, 'package.json');
@ -507,7 +507,7 @@ bar
await init(tree, {
unitTestRunner: UnitTestRunner.Jest,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
const { devDependencies } = readJson(tree, 'package.json');
@ -525,7 +525,7 @@ bar
await init(tree, {
unitTestRunner: UnitTestRunner.Jest,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
const hasJestConfigFile = tree.exists('jest.config.ts');
@ -539,7 +539,7 @@ bar
await init(tree, {
unitTestRunner: UnitTestRunner.Jest,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -562,7 +562,7 @@ bar
unitTestRunner: UnitTestRunner.None,
e2eTestRunner: E2eTestRunner.Playwright,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
expect(ensurePackage).toHaveBeenLastCalledWith(
@ -577,7 +577,7 @@ bar
unitTestRunner: UnitTestRunner.None,
e2eTestRunner: E2eTestRunner.Playwright,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -595,7 +595,7 @@ bar
unitTestRunner: UnitTestRunner.None,
e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
// ASSERT
expect(ensurePackage).toHaveBeenLastCalledWith(
@ -610,7 +610,7 @@ bar
unitTestRunner: UnitTestRunner.None,
e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -630,7 +630,7 @@ bar
await init(tree, {
unitTestRunner: UnitTestRunner.None,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -649,7 +649,7 @@ bar
await init(tree, {
unitTestRunner: UnitTestRunner.None,
linter: Linter.None,
skipFormat: false,
skipFormat: true,
});
const { generators } = readJson<NxJsonConfiguration>(tree, 'nx.json');
@ -669,7 +669,7 @@ bar
unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
expect(tree.read('.gitignore', 'utf-8')).toContain('.angular');
@ -690,7 +690,7 @@ bar
unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
const angularEntries = tree
@ -706,7 +706,7 @@ bar
unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
expect(tree.read('.prettierignore', 'utf-8')).toContain('.angular');
@ -727,7 +727,7 @@ bar
unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
const angularEntries = tree
@ -748,7 +748,7 @@ bar
unitTestRunner: UnitTestRunner.Jest,
e2eTestRunner: E2eTestRunner.Cypress,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
});
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`] = `
"export * from './lib/testing.module';
"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,9 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`lib --standalone should generate a library with a standalone component and have it flat 1`] = `
"export * from './lib/my-lib.component';
"
`;
exports[`lib --standalone should generate a library with a standalone component and have it flat 1`] = `"export * from './lib/my-lib.component';"`;
exports[`lib --standalone should generate a library with a standalone component and have it flat 2`] = `
"import { Component } from '@angular/core';
@ -14,7 +11,7 @@ import { CommonModule } from '@angular/common';
standalone: true,
imports: [CommonModule],
templateUrl: './my-lib.component.html',
styleUrl: './my-lib.component.css',
styleUrl: './my-lib.component.css'
})
export class MyLibComponent {}
"
@ -30,7 +27,7 @@ describe('MyLibComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MyLibComponent],
imports: [MyLibComponent]
}).compileComponents();
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`] = `
"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`] = `
@ -61,7 +57,7 @@ import { CommonModule } from '@angular/common';
standalone: true,
imports: [CommonModule],
templateUrl: './my-lib.component.html',
styleUrl: './my-lib.component.css',
styleUrl: './my-lib.component.css'
})
export class MyLibComponent {}
"
@ -77,7 +73,7 @@ describe('MyLibComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MyLibComponent],
imports: [MyLibComponent]
}).compileComponents();
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 { 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`] = `
"export * from './lib/my-lib/my-lib.component';
"
`;
exports[`lib --standalone should generate a library with a standalone component as entry point 1`] = `"export * from './lib/my-lib/my-lib.component';"`;
exports[`lib --standalone should generate a library with a standalone component as entry point 2`] = `
"import { Component } from '@angular/core';
@ -114,7 +109,7 @@ import { CommonModule } from '@angular/common';
standalone: true,
imports: [CommonModule],
templateUrl: './my-lib.component.html',
styleUrl: './my-lib.component.css',
styleUrl: './my-lib.component.css'
})
export class MyLibComponent {}
"
@ -130,7 +125,7 @@ describe('MyLibComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MyLibComponent],
imports: [MyLibComponent]
}).compileComponents();
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`] = `
"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 1`] = `"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`] = `
"import {
ChangeDetectionStrategy,
Component,
ViewEncapsulation,
} from '@angular/core';
"import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
@ -165,16 +153,13 @@ import { CommonModule } from '@angular/common';
template: \`<p>my-lib works!</p>\`,
styles: \`\`,
encapsulation: ViewEncapsulation.ShadowDom,
changeDetection: ChangeDetectionStrategy.OnPush,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MyLibComponent {}
"
`;
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';
"
`;
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';"`;
exports[`lib --standalone should generate a library with a standalone component as entry point and skip tests 2`] = `
"import { Component } from '@angular/core';
@ -185,16 +170,13 @@ import { CommonModule } from '@angular/common';
standalone: true,
imports: [CommonModule],
template: \`<p>my-lib works!</p>\`,
styles: \`\`,
styles: \`\`
})
export class MyLibComponent {}
"
`;
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';
"
`;
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';"`;
exports[`lib --standalone should generate a library with a standalone component as entry point following SFC pattern 2`] = `
"import { Component } from '@angular/core';
@ -205,7 +187,7 @@ import { CommonModule } from '@angular/common';
standalone: true,
imports: [CommonModule],
template: \`<p>my-lib works!</p>\`,
styles: \`\`,
styles: \`\`
})
export class MyLibComponent {}
"
@ -221,7 +203,7 @@ describe('MyLibComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MyLibComponent],
imports: [MyLibComponent]
}).compileComponents();
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`] = `
"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`] = `
"import { Route } from '@angular/router';
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,
imports: [CommonModule],
templateUrl: './my-lib.component.html',
styleUrl: './my-lib.component.css',
styleUrl: './my-lib.component.css'
})
export class MyLibComponent {}
"
@ -276,7 +259,7 @@ describe('MyLibComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MyLibComponent],
imports: [MyLibComponent]
}).compileComponents();
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`] = `
"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`] = `
"import { Route } from '@angular/router';
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';
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`] = `
"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`] = `
"import { Route } from '@angular/router';
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 { 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';
export const myLibRoutes: Route[] = [
{
path: 'second',
loadChildren: () => import('@proj/second').then((m) => m.secondRoutes),
},
{ path: '', component: MyLibComponent },
{ path: 'second', 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';
export const myLibRoutes: Route[] = [
{ path: 'second', children: secondRoutes },
{ path: '', component: MyLibComponent },
{ path: 'second', children: secondRoutes },
{ path: '', component: MyLibComponent }
];
"
`;
exports[`lib --standalone should generate a library with a standalone component in a directory 1`] = `
"export * from './lib/my-lib/my-lib.component';
"
`;
exports[`lib --standalone should generate a library with a standalone component in a directory 1`] = `"export * from './lib/my-lib/my-lib.component';"`;
exports[`lib --standalone should generate a library with a standalone component in a directory 2`] = `
"import { Component } from '@angular/core';
@ -381,7 +357,7 @@ import { CommonModule } from '@angular/common';
standalone: true,
imports: [CommonModule],
templateUrl: './my-lib.component.html',
styleUrl: './my-lib.component.css',
styleUrl: './my-lib.component.css'
})
export class MyLibComponent {}
"
@ -397,7 +373,7 @@ describe('MyLibComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MyLibComponent],
imports: [MyLibComponent]
}).compileComponents();
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`] = `
"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 1`] = `"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`] = `
"import { Component } from '@angular/core';
@ -426,7 +399,7 @@ import { CommonModule } from '@angular/common';
standalone: true,
imports: [CommonModule],
templateUrl: './my-lib.component.html',
styleUrl: './my-lib.component.css',
styleUrl: './my-lib.component.css'
})
export class MyLibComponent {}
"
@ -442,7 +415,7 @@ describe('MyLibComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MyLibComponent],
imports: [MyLibComponent]
}).compileComponents();
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`] = `
"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';
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';
export const <%= libPropertyName %>Routes: Route[] = [
{path: '', component: <%= libClassName %>Component}
{ path: '', component: <%= libClassName %>Component }
];

View File

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

View File

@ -37,7 +37,7 @@ describe('lib', () => {
publishable: false,
buildable: false,
linter: Linter.EsLint,
skipFormat: false,
skipFormat: true,
unitTestRunner: UnitTestRunner.Jest,
simpleName: false,
strict: true,
@ -151,7 +151,10 @@ describe('lib', () => {
const moduleFileExists = tree.exists('my-lib/src/lib/my-lib.module.ts');
expect(moduleFileExists).toBeFalsy();
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 () => {
@ -594,11 +597,17 @@ describe('lib', () => {
expect(tree.read('my-dir/my-lib/.eslintrc.json', 'utf-8'))
.toMatchInlineSnapshot(`
"{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"extends": [
"../../.eslintrc.json"
],
"ignorePatterns": [
"!**/*"
],
"overrides": [
{
"files": ["*.ts"],
"files": [
"*.ts"
],
"extends": [
"plugin:@nx/angular",
"plugin:@angular-eslint/template/process-inline-templates"
@ -623,12 +632,18 @@ describe('lib', () => {
}
},
{
"files": ["*.html"],
"extends": ["plugin:@nx/angular-template"],
"files": [
"*.html"
],
"extends": [
"plugin:@nx/angular-template"
],
"rules": {}
},
{
"files": ["*.json"],
"files": [
"*.json"
],
"parser": "jsonc-eslint-parser",
"rules": {
"@nx/dependency-checks": "error"
@ -721,6 +736,7 @@ describe('lib', () => {
routing: true,
lazy: true,
parent: 'myapp/src/app/app.module.ts',
skipFormat: false,
});
const moduleContents = tree
@ -737,6 +753,7 @@ describe('lib', () => {
lazy: true,
simpleName: true,
parent: 'myapp/src/app/app.module.ts',
skipFormat: false,
});
const moduleContents2 = tree
@ -753,6 +770,7 @@ describe('lib', () => {
lazy: true,
simpleName: true,
parent: 'myapp/src/app/app.module.ts',
skipFormat: false,
});
const moduleContents3 = tree
@ -1480,6 +1498,7 @@ describe('lib', () => {
await generateTestApplication(tree, {
name: 'app1',
routing: true,
skipFormat: true,
});
// ACT
@ -1504,6 +1523,7 @@ describe('lib', () => {
await generateTestApplication(tree, {
name: 'app1',
routing: true,
skipFormat: true,
});
// ACT
@ -1530,6 +1550,7 @@ describe('lib', () => {
name: 'app1',
routing: true,
standalone: true,
skipFormat: true,
});
// ACT
@ -1545,7 +1566,8 @@ describe('lib', () => {
"import { Route } from '@angular/router';
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',
routing: true,
standalone: true,
skipFormat: true,
});
// ACT
@ -1572,11 +1595,7 @@ describe('lib', () => {
"import { Route } from '@angular/router';
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,
publishable: false,
simpleName: true,
skipFormat: false,
skipFormat: true,
unitTestRunner: UnitTestRunner.Jest,
standalone: false,
});
@ -56,13 +56,18 @@ describe('@nx/angular:move', () => {
destination: 'mynewlib',
updateImportPath: true,
projectNameAndRootFormat: 'as-provided',
skipFormat: true,
});
expect(tree.exists('mynewlib/src/lib/mynewlib.module.ts')).toEqual(true);
});
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');
await angularMoveGenerator(tree, {
@ -70,6 +75,7 @@ describe('@nx/angular:move', () => {
destination: 'mynewlib2',
updateImportPath: true,
projectNameAndRootFormat: 'as-provided',
skipFormat: true,
});
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 () => {
await generateTestLibrary(tree, { name: 'mylib2', buildable: true });
await generateTestLibrary(tree, {
name: 'mylib2',
buildable: true,
skipFormat: true,
});
await librarySecondaryEntryPointGenerator(tree, {
library: 'mylib2',
name: 'testing',
skipFormat: true,
});
addProjectToGraph('mylib2');
@ -90,6 +101,7 @@ describe('@nx/angular:move', () => {
destination: 'mynewlib2',
updateImportPath: true,
projectNameAndRootFormat: 'as-provided',
skipFormat: true,
});
const readme = tree.read('mynewlib2/testing/README.md', 'utf-8');
@ -109,6 +121,7 @@ describe('@nx/angular:move', () => {
destination: 'my/lib',
updateImportPath: true,
projectNameAndRootFormat: 'as-provided',
skipFormat: 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,
publishable: false,
simpleName: true,
skipFormat: false,
skipFormat: true,
unitTestRunner: UnitTestRunner.Jest,
});
tree.write(
@ -173,6 +186,7 @@ describe('@nx/angular:move', () => {
destination: 'shared/my-lib',
updateImportPath: true,
projectNameAndRootFormat: 'as-provided',
skipFormat: true,
});
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',
updateImportPath: true,
projectNameAndRootFormat: 'as-provided',
skipFormat: true,
});
const importerFile = tree.read(
@ -234,6 +249,7 @@ describe('@nx/angular:move', () => {
destination: 'shared/my-lib',
updateImportPath: true,
projectNameAndRootFormat: 'as-provided',
skipFormat: true,
});
const indexFile = tree.read('shared/my-lib/src/index.ts', 'utf-8');
@ -251,7 +267,7 @@ describe('@nx/angular:move', () => {
linter: Linter.EsLint,
publishable: false,
simpleName: true,
skipFormat: false,
skipFormat: true,
unitTestRunner: UnitTestRunner.Jest,
});
@ -272,6 +288,7 @@ describe('@nx/angular:move', () => {
destination: 'my-destination',
updateImportPath: true,
projectNameAndRootFormat: 'as-provided',
skipFormat: true,
});
expect(
@ -294,6 +311,7 @@ describe('@nx/angular:move', () => {
destination: 'my-destination',
updateImportPath: true,
projectNameAndRootFormat: 'as-provided',
skipFormat: true,
});
const importerFile = tree.read(
@ -317,6 +335,7 @@ describe('@nx/angular:move', () => {
destination: 'my-destination',
updateImportPath: true,
projectNameAndRootFormat: 'as-provided',
skipFormat: true,
});
const indexFile = tree.read('my-destination/src/index.ts', 'utf-8');
@ -334,7 +353,7 @@ describe('@nx/angular:move', () => {
linter: Linter.EsLint,
publishable: false,
simpleName: true,
skipFormat: false,
skipFormat: true,
unitTestRunner: UnitTestRunner.Jest,
standalone: false,
});
@ -346,6 +365,7 @@ describe('@nx/angular:move', () => {
destination: 'my-destination',
updateImportPath: true,
projectNameAndRootFormat: 'as-provided',
skipFormat: true,
});
const moduleFile = tree.read(
@ -361,6 +381,7 @@ describe('@nx/angular:move', () => {
name: 'mylib2',
buildable: true,
standalone: false,
skipFormat: true,
});
addProjectToGraph('mylib2');
@ -369,6 +390,7 @@ describe('@nx/angular:move', () => {
destination: 'mynewlib',
updateImportPath: true,
projectNameAndRootFormat: 'derived',
skipFormat: true,
});
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({
ng: 'ng',
@ -208,35 +208,38 @@ describe('workspace', () => {
tree.write('/projects/myApp/e2e/protractor.conf.js', '// 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);
});
it('should set the default project correctly', async () => {
await migrateFromAngularCli(tree, {});
await migrateFromAngularCli(tree, { skipFormat: true });
expect(readJson(tree, 'nx.json').defaultProject).toBe('myApp');
});
it('should create nx.json', async () => {
await migrateFromAngularCli(tree, { defaultBase: 'main' });
await migrateFromAngularCli(tree, {
defaultBase: 'main',
skipFormat: true,
});
expect(readJson(tree, 'nx.json')).toMatchSnapshot();
});
it('should work if angular-cli workspace had tsconfig.base.json', async () => {
tree.rename('tsconfig.json', 'tsconfig.base.json');
await migrateFromAngularCli(tree, {});
await migrateFromAngularCli(tree, { skipFormat: true });
expect(readJson(tree, 'tsconfig.base.json')).toMatchSnapshot();
});
it('should update tsconfig.base.json if present', async () => {
await migrateFromAngularCli(tree, {});
await migrateFromAngularCli(tree, { skipFormat: true });
expect(readJson(tree, 'tsconfig.base.json')).toMatchSnapshot();
});
it('should work with existing .prettierignore file', async () => {
tree.write('/.prettierignore', '# existing ignore rules');
await migrateFromAngularCli(tree, {});
await migrateFromAngularCli(tree, { skipFormat: true });
const prettierIgnore = tree.read('/.prettierignore').toString();
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);
});
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);
});
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);
});
@ -332,13 +335,13 @@ describe('workspace', () => {
},
});
await migrateFromAngularCli(tree, {});
await migrateFromAngularCli(tree, { skipFormat: true });
expect(tree.exists('libs/.gitkeep')).toBe(false);
});
it('should create a root eslint config', async () => {
await migrateFromAngularCli(tree, {});
await migrateFromAngularCli(tree, { skipFormat: true });
expect(readJson(tree, '.eslintrc.json')).toMatchSnapshot();
});
@ -350,7 +353,7 @@ describe('workspace', () => {
return json;
});
await migrateFromAngularCli(tree, {});
await migrateFromAngularCli(tree, { skipFormat: true });
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('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('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 () => {
await ngAddGenerator(tree, {});
await ngAddGenerator(tree, { skipFormat: true });
expect(initGenerator.angularInitGenerator).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 () => {
tree.delete('nx.json');
await ngAddGenerator(tree, {});
await ngAddGenerator(tree, { skipFormat: true });
expect(angularCliMigrator.migrateFromAngularCli).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 { UsersEntity } from './users.models';
export const initUsers = createAction('[Users Page] Init');
export const initUsers = createAction(
'[Users Page] Init'
);
export const loadUsersSuccess = createAction(
'[Users/API] Load Users Success',
@ -39,16 +41,15 @@ import * as UsersFeature from './users.reducer';
export class UsersEffects {
private actions$ = inject(Actions);
init$ = createEffect(() =>
this.actions$.pipe(
ofType(UsersActions.initUsers),
switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))),
catchError((error) => {
init$ = createEffect(() => this.actions$.pipe(
ofType(UsersActions.initUsers),
switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))),
catchError((error) => {
console.error('Error', error);
return of(UsersActions.loadUsersFailure({ error }));
})
}
)
);
));
}
"
`;
@ -103,25 +104,24 @@ export interface UsersPartialState {
readonly [USERS_FEATURE_KEY]: UsersState;
}
export const usersAdapter: EntityAdapter<UsersEntity> =
createEntityAdapter<UsersEntity>();
export const usersAdapter: EntityAdapter<UsersEntity> = createEntityAdapter<UsersEntity>();
export const initialUsersState: UsersState = usersAdapter.getInitialState({
// set initial required properties
loaded: false,
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.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 })
),
on(UsersActions.loadUsersFailure, (state, { error }) => ({ ...state, error }))
);
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';
// Lookup the 'Users' feature state managed by NgRx
export const selectUsersState =
createFeatureSelector<UsersState>(USERS_FEATURE_KEY);
export const selectUsersState = createFeatureSelector<UsersState>(USERS_FEATURE_KEY);
const { selectAll, selectEntities } = usersAdapter.getSelectors();
@ -183,11 +182,7 @@ import { UsersEffects } from './+state/users/users.effects';
import { UsersFacade } from './+state/users/users.facade';
@NgModule({
imports: [
CommonModule,
StoreModule.forFeature(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
EffectsModule.forFeature([UsersEffects]),
],
imports: [CommonModule, StoreModule.forFeature(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer), EffectsModule.forFeature([UsersEffects])],
providers: [UsersFacade],
})
export class FeatureModuleModule {}
@ -717,7 +712,7 @@ import {
USERS_FEATURE_KEY,
UsersState,
initialUsersState,
usersReducer,
usersReducer
} from './users.reducer';
import * as UsersSelectors from './users.selectors';
@ -730,7 +725,7 @@ describe('UsersFacade', () => {
let store: Store<TestSchema>;
const createUsersEntity = (id: string, name = ''): UsersEntity => ({
id,
name: name || \`name-\${id}\`,
name: name || \`name-\${id}\`
});
describe('used in NgModule', () => {
@ -738,9 +733,9 @@ describe('UsersFacade', () => {
@NgModule({
imports: [
StoreModule.forFeature(USERS_FEATURE_KEY, usersReducer),
EffectsModule.forFeature([UsersEffects]),
EffectsModule.forFeature([UsersEffects])
],
providers: [UsersFacade],
providers: [UsersFacade]
})
class CustomFeatureModule {}
@ -749,7 +744,7 @@ describe('UsersFacade', () => {
StoreModule.forRoot({}),
EffectsModule.forRoot([]),
CustomFeatureModule,
],
]
})
class RootModule {}
TestBed.configureTestingModule({ imports: [RootModule] });
@ -787,10 +782,11 @@ describe('UsersFacade', () => {
expect(list.length).toBe(0);
expect(isLoaded).toBe(false);
store.dispatch(
UsersActions.loadUsersSuccess({
users: [createUsersEntity('AAA'), createUsersEntity('BBB')],
})
store.dispatch(UsersActions.loadUsersSuccess({
users: [
createUsersEntity('AAA'),
createUsersEntity('BBB')
]})
);
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 { UsersEntity } from './users.models';
export const initUsers = createAction('[Users Page] Init');
export const initUsers = createAction(
'[Users Page] Init'
);
export const loadUsersSuccess = createAction(
'[Users/API] Load Users Success',
@ -833,16 +831,15 @@ import * as UsersFeature from './users.reducer';
export class UsersEffects {
private actions$ = inject(Actions);
init$ = createEffect(() =>
this.actions$.pipe(
ofType(UsersActions.initUsers),
switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))),
catchError((error) => {
init$ = createEffect(() => this.actions$.pipe(
ofType(UsersActions.initUsers),
switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))),
catchError((error) => {
console.error('Error', error);
return of(UsersActions.loadUsersFailure({ error }));
})
}
)
);
));
}
"
`;
@ -868,7 +865,7 @@ describe('UsersEffects', () => {
providers: [
UsersEffects,
provideMockActions(() => actions),
provideMockStore(),
provideMockStore()
],
});
@ -879,9 +876,7 @@ describe('UsersEffects', () => {
it('should work', () => {
actions = hot('-a-|', { a: UsersActions.initUsers() });
const expected = hot('-a-|', {
a: UsersActions.loadUsersSuccess({ users: [] }),
});
const expected = hot('-a-|', { a: UsersActions.loadUsersSuccess({ users: [] }) });
expect(effects.init$).toBeObservable(expected);
});
@ -920,25 +915,24 @@ export interface UsersPartialState {
readonly [USERS_FEATURE_KEY]: UsersState;
}
export const usersAdapter: EntityAdapter<UsersEntity> =
createEntityAdapter<UsersEntity>();
export const usersAdapter: EntityAdapter<UsersEntity> = createEntityAdapter<UsersEntity>();
export const initialUsersState: UsersState = usersAdapter.getInitialState({
// set initial required properties
loaded: false,
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.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 })
),
on(UsersActions.loadUsersFailure, (state, { error }) => ({ ...state, error }))
);
export function usersReducer(state: UsersState | undefined, action: Action) {
@ -957,14 +951,14 @@ import { UsersState, initialUsersState, usersReducer } from './users.reducer';
describe('Users Reducer', () => {
const createUsersEntity = (id: string, name = ''): UsersEntity => ({
id,
name: name || \`name-\${id}\`,
name: name || \`name-\${id}\`
});
describe('valid Users actions', () => {
it('loadUsersSuccess should return the list of known Users', () => {
const users = [
createUsersEntity('PRODUCT-AAA'),
createUsersEntity('PRODUCT-zzz'),
createUsersEntity('PRODUCT-zzz')
];
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';
// Lookup the 'Users' feature state managed by NgRx
export const selectUsersState =
createFeatureSelector<UsersState>(USERS_FEATURE_KEY);
export const selectUsersState = createFeatureSelector<UsersState>(USERS_FEATURE_KEY);
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`] = `
"import { UsersEntity } from './users.models';
import {
usersAdapter,
UsersPartialState,
initialUsersState,
} from './users.reducer';
import { usersAdapter, UsersPartialState, initialUsersState } from './users.reducer';
import * as UsersSelectors from './users.selectors';
describe('Users Selectors', () => {
const ERROR_MSG = 'No Error Available';
const getUsersId = (it: UsersEntity) => it.id;
const createUsersEntity = (id: string, name = '') =>
({
id,
name: name || \`name-\${id}\`,
} as UsersEntity);
const createUsersEntity = (id: string, name = '') => ({
id,
name: name || \`name-\${id}\`
}) as UsersEntity;
let state: UsersPartialState;
beforeEach(() => {
state = {
users: usersAdapter.setAll(
[
createUsersEntity('PRODUCT-AAA'),
createUsersEntity('PRODUCT-BBB'),
createUsersEntity('PRODUCT-CCC'),
],
{
...initialUsersState,
selectedId: 'PRODUCT-BBB',
error: ERROR_MSG,
loaded: true,
}
),
users: usersAdapter.setAll([
createUsersEntity('PRODUCT-AAA'),
createUsersEntity('PRODUCT-BBB'),
createUsersEntity('PRODUCT-CCC')
], {
...initialUsersState,
selectedId: 'PRODUCT-BBB',
error: ERROR_MSG,
loaded: true
})
};
});
@ -1111,15 +1096,7 @@ import { UsersEffects } from './+state/users.effects';
import { UsersFacade } from './+state/users.facade';
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/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`] = `
@ -1150,6 +1126,5 @@ export * from './lib/+state/users.models';
export { UsersActions, UsersFeature, UsersSelectors };
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 {
id: string | number; // Primary ID
name: string;
};
}

View File

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

View File

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

View File

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

View File

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

View File

@ -21,7 +21,7 @@ describe('SuperUsersEffects', () => {
providers: [
SuperUsersEffects,
provideMockActions(() => actions),
provideMockStore(),
provideMockStore()
],
});
@ -32,9 +32,7 @@ describe('SuperUsersEffects', () => {
it('should work', () => {
actions = hot('-a-|', { a: SuperUsersActions.initSuperUsers() });
const expected = hot('-a-|', {
a: SuperUsersActions.loadSuperUsersSuccess({ superUsers: [] }),
});
const expected = hot('-a-|', { a: SuperUsersActions.loadSuperUsersSuccess({ superUsers: [] }) });
expect(effects.init$).toBeObservable(expected);
});
@ -58,7 +56,7 @@ import {
SUPER_USERS_FEATURE_KEY,
SuperUsersState,
initialSuperUsersState,
superUsersReducer,
superUsersReducer
} from './super-users.reducer';
import * as SuperUsersSelectors from './super-users.selectors';
@ -71,7 +69,7 @@ describe('SuperUsersFacade', () => {
let store: Store<TestSchema>;
const createSuperUsersEntity = (id: string, name = ''): SuperUsersEntity => ({
id,
name: name || \`name-\${id}\`,
name: name || \`name-\${id}\`
});
describe('used in NgModule', () => {
@ -79,9 +77,9 @@ describe('SuperUsersFacade', () => {
@NgModule({
imports: [
StoreModule.forFeature(SUPER_USERS_FEATURE_KEY, superUsersReducer),
EffectsModule.forFeature([SuperUsersEffects]),
EffectsModule.forFeature([SuperUsersEffects])
],
providers: [SuperUsersFacade],
providers: [SuperUsersFacade]
})
class CustomFeatureModule {}
@ -90,7 +88,7 @@ describe('SuperUsersFacade', () => {
StoreModule.forRoot({}),
EffectsModule.forRoot([]),
CustomFeatureModule,
],
]
})
class RootModule {}
TestBed.configureTestingModule({ imports: [RootModule] });
@ -128,13 +126,11 @@ describe('SuperUsersFacade', () => {
expect(list.length).toBe(0);
expect(isLoaded).toBe(false);
store.dispatch(
SuperUsersActions.loadSuperUsersSuccess({
superUsers: [
createSuperUsersEntity('AAA'),
createSuperUsersEntity('BBB'),
],
})
store.dispatch(SuperUsersActions.loadSuperUsersSuccess({
superUsers: [
createSuperUsersEntity('AAA'),
createSuperUsersEntity('BBB')
]})
);
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 { SuperUsersEntity } from './super-users.models';
import {
SuperUsersState,
initialSuperUsersState,
superUsersReducer,
} from './super-users.reducer';
import { SuperUsersState, initialSuperUsersState, superUsersReducer } from './super-users.reducer';
describe('SuperUsers Reducer', () => {
const createSuperUsersEntity = (id: string, name = ''): SuperUsersEntity => ({
id,
name: name || \`name-\${id}\`,
name: name || \`name-\${id}\`
});
describe('valid SuperUsers actions', () => {
it('loadSuperUsersSuccess should return the list of known SuperUsers', () => {
const superUsers = [
createSuperUsersEntity('PRODUCT-AAA'),
createSuperUsersEntity('PRODUCT-zzz'),
createSuperUsersEntity('PRODUCT-zzz')
];
const action = SuperUsersActions.loadSuperUsersSuccess({ superUsers });
const result: SuperUsersState = superUsersReducer(
initialSuperUsersState,
action
);
const result: SuperUsersState = superUsersReducer(initialSuperUsersState, action);
expect(result.loaded).toBe(true);
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`] = `
"import { SuperUsersEntity } from './super-users.models';
import {
superUsersAdapter,
SuperUsersPartialState,
initialSuperUsersState,
} from './super-users.reducer';
import { superUsersAdapter, SuperUsersPartialState, initialSuperUsersState } from './super-users.reducer';
import * as SuperUsersSelectors from './super-users.selectors';
describe('SuperUsers Selectors', () => {
const ERROR_MSG = 'No Error Available';
const getSuperUsersId = (it: SuperUsersEntity) => it.id;
const createSuperUsersEntity = (id: string, name = '') =>
({
id,
name: name || \`name-\${id}\`,
} as SuperUsersEntity);
const createSuperUsersEntity = (id: string, name = '') => ({
id,
name: name || \`name-\${id}\`
}) as SuperUsersEntity;
let state: SuperUsersPartialState;
beforeEach(() => {
state = {
superUsers: superUsersAdapter.setAll(
[
createSuperUsersEntity('PRODUCT-AAA'),
createSuperUsersEntity('PRODUCT-BBB'),
createSuperUsersEntity('PRODUCT-CCC'),
],
{
...initialSuperUsersState,
selectedId: 'PRODUCT-BBB',
error: ERROR_MSG,
loaded: true,
}
),
superUsers: superUsersAdapter.setAll([
createSuperUsersEntity('PRODUCT-AAA'),
createSuperUsersEntity('PRODUCT-BBB'),
createSuperUsersEntity('PRODUCT-CCC')
], {
...initialSuperUsersState,
selectedId: 'PRODUCT-BBB',
error: ERROR_MSG,
loaded: true
})
};
});
@ -244,9 +225,7 @@ describe('SuperUsers Selectors', () => {
});
it('selectEntity() should return the selected Entity', () => {
const result = SuperUsersSelectors.selectEntity(
state
) as SuperUsersEntity;
const result = SuperUsersSelectors.selectEntity(state) as SuperUsersEntity;
const selId = getSuperUsersId(result);
expect(selId).toBe('PRODUCT-BBB');
@ -279,25 +258,15 @@ import * as fromUsers from './+state/users.reducer';
import { UsersEffects } from './+state/users.effects';
import { StoreRouterConnectingModule } from '@ngrx/router-store';
@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot([]),
StoreModule.forRoot(
{},
{
metaReducers: [],
runtimeChecks: {
strictActionImmutability: true,
strictStateImmutability: true,
},
imports: [BrowserModule, RouterModule.forRoot([]), StoreModule.forRoot({}, {
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],
bootstrap: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
"
@ -314,25 +283,15 @@ import * as fromUsers from './+state/users.reducer';
import { UsersEffects } from './+state/users.effects';
import { StoreRouterConnectingModule } from '@ngrx/router-store';
@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot([]),
StoreModule.forRoot(
{},
{
metaReducers: [],
runtimeChecks: {
strictActionImmutability: true,
strictStateImmutability: true,
},
imports: [BrowserModule, RouterModule.forRoot([]), StoreModule.forRoot({}, {
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],
bootstrap: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
"
@ -346,22 +305,36 @@ import { AppComponent } from './app.component';
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
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({
imports: [
BrowserModule,
RouterModule.forRoot([]),
StoreModule.forRoot(
{},
{
metaReducers: [],
runtimeChecks: {
strictActionImmutability: true,
strictStateImmutability: true,
},
}
),
EffectsModule.forRoot([]),
StoreRouterConnectingModule.forRoot(),
StoreModule.forFeature(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
EffectsModule.forFeature([UsersEffects]),
],
declarations: [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`] = `
"/**
* 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 { UsersEntity } from './users.models';
export const initUsers = createAction('[Users Page] Init');
export const initUsers = createAction(
'[Users Page] Init'
);
export const loadUsersSuccess = createAction(
'[Users/API] Load Users Success',
@ -410,16 +528,15 @@ import * as UsersFeature from './users.reducer';
export class UsersEffects {
private actions$ = inject(Actions);
init$ = createEffect(() =>
this.actions$.pipe(
ofType(UsersActions.initUsers),
switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))),
catchError((error) => {
init$ = createEffect(() => this.actions$.pipe(
ofType(UsersActions.initUsers),
switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))),
catchError((error) => {
console.error('Error', error);
return of(UsersActions.loadUsersFailure({ error }));
})
}
)
);
));
}
"
`;
@ -474,25 +591,24 @@ export interface UsersPartialState {
readonly [USERS_FEATURE_KEY]: UsersState;
}
export const usersAdapter: EntityAdapter<UsersEntity> =
createEntityAdapter<UsersEntity>();
export const usersAdapter: EntityAdapter<UsersEntity> = createEntityAdapter<UsersEntity>();
export const initialUsersState: UsersState = usersAdapter.getInitialState({
// set initial required properties
loaded: false,
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.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 })
),
on(UsersActions.loadUsersFailure, (state, { error }) => ({ ...state, error }))
);
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';
// Lookup the 'Users' feature state managed by NgRx
export const selectUsersState =
createFeatureSelector<UsersState>(USERS_FEATURE_KEY);
export const selectUsersState = createFeatureSelector<UsersState>(USERS_FEATURE_KEY);
const { selectAll, selectEntities } = usersAdapter.getSelectors();
@ -552,7 +667,7 @@ import { AppComponent } from './app.component';
@NgModule({
imports: [BrowserModule, RouterModule.forRoot([])],
declarations: [AppComponent],
bootstrap: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
"
@ -570,7 +685,6 @@ export * from './lib/+state/super-users.facade';
export * from './lib/+state/super-users.models';
export { SuperUsersActions, SuperUsersFeature, SuperUsersSelectors };
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.reducer';
export * from './lib/+state/super-users.actions';
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.reducer';
export * from './lib/+state/super-users.actions';
export * from './lib/flights.module';
"
`;
@ -603,16 +715,8 @@ import { provideStore, provideState } from '@ngrx/store';
import { provideEffects } from '@ngrx/effects';
import * as fromUsers from './+state/users.reducer';
import { UsersEffects } from './+state/users.effects';
export const appRoutes: Routes = [
{
path: 'home',
component: NxWelcomeComponent,
providers: [
provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
provideEffects(UsersEffects),
],
},
];
export const appRoutes: Routes = [{ 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 * as fromUsers from './+state/users.reducer';
import { UsersEffects } from './+state/users.effects';
export const appRoutes: Routes = [
{
path: '',
component: NxWelcomeComponent,
providers: [
provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
provideEffects(UsersEffects),
],
},
];
export const appRoutes: Routes = [{ 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 * as fromUsers from './+state/users.reducer';
import { UsersEffects } from './+state/users.effects';
export const appRoutes: Routes = [
{
path: '',
component: NxWelcomeComponent,
providers: [
provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
provideEffects(UsersEffects),
],
},
];
export const appRoutes: Routes = [{ 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';
export const appConfig: ApplicationConfig = {
providers: [
provideEffects(UsersEffects),
provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
provideEffects(),
provideStore(),
provideRouter(appRoutes),
],
providers: [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';
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';
export const appConfig: ApplicationConfig = {
providers: [
provideEffects(UsersEffects),
provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
provideEffects(),
provideStore(),
UsersFacade,
provideRouter(appRoutes),
],
providers: [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 { UsersEffects } from './+state/users.effects';
import { UsersFacade } from './+state/users.facade';
export const appRoutes: Routes = [
{
path: '',
component: NxWelcomeComponent,
providers: [
UsersFacade,
provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
provideEffects(UsersEffects),
],
},
];
export const appRoutes: Routes = [{ 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 {
private actions$ = inject(Actions);
init$ = createEffect(() =>
this.actions$.pipe(
ofType(UsersActions.initUsers),
switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))),
catchError((error) => {
init$ = createEffect(() => this.actions$.pipe(
ofType(UsersActions.initUsers),
switchMap(() => of(UsersActions.loadUsersSuccess({ users: [] }))),
catchError((error) => {
console.error('Error', error);
return of(UsersActions.loadUsersFailure({ error }));
})
}
)
);
));
}
"
`;

View File

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

View File

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

View File

@ -25,6 +25,7 @@ describe('ngrx', () => {
minimal: true,
parent: 'myapp/src/app/app.module.ts',
name: 'users',
skipFormat: true,
};
const defaultStandaloneOptions: NgRxGeneratorOptions = {
@ -32,6 +33,7 @@ describe('ngrx', () => {
minimal: true,
parent: 'my-app/src/app/app.config.ts',
name: 'users',
skipFormat: true,
};
const defaultModuleOptions: NgRxGeneratorOptions = {
@ -39,6 +41,7 @@ describe('ngrx', () => {
minimal: true,
module: 'myapp/src/app/app.module.ts',
name: 'users',
skipFormat: true,
};
const expectFileToExist = (file: string) =>
@ -417,9 +420,27 @@ describe('ngrx', () => {
it('should format files', async () => {
jest.spyOn(devkit, 'formatFiles');
await ngrxGenerator(tree, defaultOptions);
await ngrxGenerator(tree, { ...defaultOptions, skipFormat: false });
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 () => {
@ -494,6 +515,7 @@ describe('ngrx', () => {
name: 'my-app',
standalone: true,
routing: true,
skipFormat: true,
});
tree.write(
'my-app/src/app/app.component.html',
@ -502,8 +524,10 @@ describe('ngrx', () => {
tree.write(
'my-app/src/app/app.routes.ts',
`import { Routes } from '@angular/router';
import { NxWelcomeComponent } from './nx-welcome.component';
export const appRoutes: Routes = [{ path: '', component: NxWelcomeComponent }];`
import { NxWelcomeComponent } from './nx-welcome.component';
export const appRoutes: Routes = [{ path: '', component: NxWelcomeComponent }];
`
);
});
@ -575,8 +599,10 @@ describe('ngrx', () => {
tree.write(
'my-app/src/app/app.routes.ts',
`import { Routes } from '@angular/router';
import { NxWelcomeComponent } from './nx-welcome.component';
export const appRoutes: Routes = [{ path: 'home', component: NxWelcomeComponent }];`
import { NxWelcomeComponent } from './nx-welcome.component';
export const appRoutes: Routes = [{ path: 'home', component: NxWelcomeComponent }];
`
);
await ngrxGenerator(tree, {
@ -637,7 +663,11 @@ describe('ngrx', () => {
beforeEach(async () => {
jest.clearAllMocks();
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) => ({
...json,
dependencies: {
@ -679,7 +709,11 @@ describe('ngrx', () => {
describe('rxjs v6 support', () => {
beforeEach(async () => {
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) => ({
...json,
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';
@Pipe({
name: 'test',
name: 'test'
})
export class TestPipe implements PipeTransform {
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';
@Pipe({
name: 'test',
name: 'test'
})
export class TestPipe implements PipeTransform {
transform(value: unknown, ...args: unknown[]): unknown {

View File

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

View File

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

View File

@ -27,7 +27,7 @@ export function app(): express.Express {
server.engine(
'html',
ngExpressEngine({
bootstrap,
bootstrap
})
);
@ -317,24 +317,15 @@ import { AppComponent } from './app.component';
declarations: [AppComponent],
imports: [
BrowserModule,
RouterModule.forRoot(
[
{
path: '',
loadChildren: () =>
import('./remote-entry/entry.module').then(
(m) => m.RemoteEntryModule
),
},
],
{ initialNavigation: 'enabledBlocking' }
),
RouterModule.forRoot([{
path: '',
loadChildren: () => import('./remote-entry/entry.module').then(m => m.RemoteEntryModule)
}], { initialNavigation: 'enabledBlocking' }),
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
"
export class AppModule {}"
`;
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`] = `
"import('./src/main.server');
"
`;
exports[`MF Remote App Generator --ssr should generate the correct files when --typescriptConfiguration=true 5`] = `"import('./src/main.server');"`;
exports[`MF Remote App Generator --ssr should generate the correct files when --typescriptConfiguration=true 6`] = `
"import { ModuleFederationConfig } from '@nx/webpack';
@ -461,7 +449,7 @@ exports[`MF Remote App Generator --ssr should generate the correct files when --
@Component({
selector: 'proj-test-entry',
template: \`<proj-nx-welcome></proj-nx-welcome>\`,
template: \`<proj-nx-welcome></proj-nx-welcome>\`
})
export class RemoteEntryComponent {}
"
@ -471,12 +459,7 @@ exports[`MF Remote App Generator --ssr should generate the correct files when --
"import { Route } from '@angular/router';
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 { RemoteEntryComponent } from './entry.component';
export const remoteRoutes: Route[] = [
{ path: '', component: RemoteEntryComponent },
];
"
export const remoteRoutes: Route[] = [{ path: '', component: RemoteEntryComponent }];"
`;
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 { RemoteEntryComponent } from './entry.component';
export const remoteRoutes: Route[] = [
{ path: '', component: RemoteEntryComponent },
];
"
export const remoteRoutes: Route[] = [{ path: '', component: RemoteEntryComponent }];"
`;
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,
imports: [CommonModule, NxWelcomeComponent],
selector: 'proj-test-entry',
template: \`<proj-nx-welcome></proj-nx-welcome>\`,
template: \`<proj-nx-welcome></proj-nx-welcome>\`
})
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';
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 { RemoteEntryComponent } from './entry.component';
export const remoteRoutes: Route[] = [
{ path: '', component: RemoteEntryComponent },
];
"
export const remoteRoutes: Route[] = [{ 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';
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('views', browserBundles);
// Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { });
// Serve static files from /browser
@ -41,7 +40,6 @@ export function app(): express.Express {
// All regular routes use the Universal engine
server.get('*', (req, res) => {
res.render(indexHtml, {
req,
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('views', browserBundles);
// Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { });
// Serve static files from /browser

View File

@ -24,6 +24,7 @@ describe('MF Remote App Generator', () => {
port: 4201,
typescriptConfiguration: false,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -44,6 +45,7 @@ describe('MF Remote App Generator', () => {
port: 4201,
typescriptConfiguration: true,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -58,6 +60,7 @@ describe('MF Remote App Generator', () => {
name: 'host',
typescriptConfiguration: false,
standalone: false,
skipFormat: true,
});
// ACT
@ -66,6 +69,7 @@ describe('MF Remote App Generator', () => {
host: 'host',
typescriptConfiguration: false,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -81,6 +85,7 @@ describe('MF Remote App Generator', () => {
name: 'host',
typescriptConfiguration: true,
standalone: false,
skipFormat: true,
});
// ACT
@ -89,6 +94,7 @@ describe('MF Remote App Generator', () => {
host: 'host',
typescriptConfiguration: true,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -106,6 +112,7 @@ describe('MF Remote App Generator', () => {
name: 'test',
host: 'host',
standalone: false,
skipFormat: true,
});
} catch (error) {
// ASSERT
@ -122,12 +129,14 @@ describe('MF Remote App Generator', () => {
name: 'existing',
port: 4201,
standalone: false,
skipFormat: true,
});
// ACT
await generateTestRemoteApplication(tree, {
name: 'test',
standalone: false,
skipFormat: true,
});
// ASSERT
@ -143,6 +152,7 @@ describe('MF Remote App Generator', () => {
await generateTestRemoteApplication(tree, {
name: 'test',
standalone: false,
skipFormat: true,
});
// ASSERT
@ -159,6 +169,7 @@ describe('MF Remote App Generator', () => {
name: 'test',
port: 4201,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -207,6 +218,7 @@ describe('MF Remote App Generator', () => {
await generateTestRemoteApplication(tree, {
name: 'test',
typescriptConfiguration: true,
skipFormat: true,
});
// ASSERT
@ -237,6 +249,7 @@ describe('MF Remote App Generator', () => {
name: 'remote1',
e2eTestRunner: E2eTestRunner.None,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -253,6 +266,7 @@ describe('MF Remote App Generator', () => {
name: 'test',
inlineTemplate: true,
standalone: false,
skipFormat: true,
});
// ASSERT
@ -262,10 +276,10 @@ describe('MF Remote App Generator', () => {
@Component({
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
await generateTestRemoteApplication(tree, {
name: 'test',
skipFormat: true,
});
// ASSERT
@ -346,6 +361,7 @@ describe('MF Remote App Generator', () => {
ssr: true,
typescriptConfiguration: true,
standalone: false,
skipFormat: true,
});
// 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();
});
@ -411,6 +431,7 @@ describe('MF Remote App Generator', () => {
projectNameAndRootFormat: 'derived',
typescriptConfiguration: false,
standalone: false,
skipFormat: true,
});
expect(tree.exists('apps/test/webpack.config.js')).toBe(true);
@ -427,6 +448,7 @@ describe('MF Remote App Generator', () => {
projectNameAndRootFormat: 'derived',
typescriptConfiguration: false,
standalone: false,
skipFormat: true,
});
expect(tree.exists('apps/shared/test/webpack.config.js')).toBe(true);

View File

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

View File

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

View File

@ -18,6 +18,7 @@ describe('SCAM Directive Generator', () => {
project: 'app1',
inlineScam: true,
flat: true,
skipFormat: true,
});
// ASSERT
@ -30,7 +31,7 @@ describe('SCAM Directive Generator', () => {
import { CommonModule } from '@angular/common';
@Directive({
selector: '[projExample]',
selector: '[projExample]'
})
export class ExampleDirective {
constructor() {}
@ -61,6 +62,7 @@ describe('SCAM Directive Generator', () => {
project: 'app1',
inlineScam: false,
flat: true,
skipFormat: true,
});
// ASSERT
@ -103,6 +105,7 @@ describe('SCAM Directive Generator', () => {
path: 'libs/lib1/feature/src/lib',
inlineScam: false,
export: true,
skipFormat: true,
});
// ASSERT
@ -129,8 +132,7 @@ describe('SCAM Directive Generator', () => {
);
expect(secondaryEntryPointSource).toMatchInlineSnapshot(`
"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',
inlineScam: true,
flat: false,
skipFormat: true,
});
// ASSERT
@ -163,7 +166,7 @@ describe('SCAM Directive Generator', () => {
import { CommonModule } from '@angular/common';
@Directive({
selector: '[projExample]',
selector: '[projExample]'
})
export class ExampleDirective {
constructor() {}
@ -195,6 +198,7 @@ describe('SCAM Directive Generator', () => {
path: '/apps/app1/src/app/random',
inlineScam: true,
flat: false,
skipFormat: true,
});
// ASSERT
@ -207,7 +211,7 @@ describe('SCAM Directive Generator', () => {
import { CommonModule } from '@angular/common';
@Directive({
selector: '[projExample]',
selector: '[projExample]'
})
export class ExampleDirective {
constructor() {}
@ -240,6 +244,7 @@ describe('SCAM Directive Generator', () => {
path: 'libs/proj/src/lib/random',
inlineScam: true,
flat: false,
skipFormat: true,
})
).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."`

View File

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

View File

@ -9,6 +9,7 @@ export interface Schema {
prefix?: string;
selector?: string;
export?: boolean;
skipFormat?: boolean;
/**
* @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.",
"default": true,
"x-priority": "important"
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
"default": false,
"x-priority": "internal"
}
},
"required": ["name"]

View File

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

View File

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

View File

@ -18,6 +18,7 @@ describe('SCAM Pipe Generator', () => {
project: 'app1',
inlineScam: true,
flat: false,
skipFormat: true,
});
// ASSERT
@ -30,7 +31,7 @@ describe('SCAM Pipe Generator', () => {
import { CommonModule } from '@angular/common';
@Pipe({
name: 'example',
name: 'example'
})
export class ExamplePipe implements PipeTransform {
transform(value: unknown, ...args: unknown[]): unknown {
@ -63,6 +64,7 @@ describe('SCAM Pipe Generator', () => {
project: 'app1',
inlineScam: false,
flat: false,
skipFormat: true,
});
// ASSERT
@ -105,6 +107,7 @@ describe('SCAM Pipe Generator', () => {
path: 'libs/lib1/feature/src/lib',
inlineScam: false,
export: true,
skipFormat: true,
});
// ASSERT
@ -131,8 +134,7 @@ describe('SCAM Pipe Generator', () => {
);
expect(secondaryEntryPointSource).toMatchInlineSnapshot(`
"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',
inlineScam: true,
flat: false,
skipFormat: true,
});
// ASSERT
@ -165,7 +168,7 @@ describe('SCAM Pipe Generator', () => {
import { CommonModule } from '@angular/common';
@Pipe({
name: 'example',
name: 'example'
})
export class ExamplePipe implements PipeTransform {
transform(value: unknown, ...args: unknown[]): unknown {
@ -199,6 +202,7 @@ describe('SCAM Pipe Generator', () => {
path: '/apps/app1/src/app/random',
inlineScam: true,
flat: false,
skipFormat: true,
});
// ASSERT
@ -211,7 +215,7 @@ describe('SCAM Pipe Generator', () => {
import { CommonModule } from '@angular/common';
@Pipe({
name: 'example',
name: 'example'
})
export class ExamplePipe implements PipeTransform {
transform(value: unknown, ...args: unknown[]): unknown {
@ -245,6 +249,7 @@ describe('SCAM Pipe Generator', () => {
project: 'app1',
path: 'libs/proj/src/lib/random',
inlineScam: true,
skipFormat: true,
})
).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."`

View File

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

View File

@ -7,6 +7,7 @@ export interface Schema {
skipTests?: boolean;
inlineScam?: boolean;
export?: boolean;
skipFormat?: boolean;
/**
* @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.",
"default": true,
"x-priority": "important"
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
"default": false,
"x-priority": "internal"
}
},
"required": ["name"]

View File

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

View File

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

View File

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

View File

@ -17,6 +17,7 @@ describe('SCAM Generator', () => {
name: 'example',
project: 'app1',
inlineScam: true,
skipFormat: true,
});
// ASSERT
@ -31,7 +32,7 @@ describe('SCAM Generator', () => {
@Component({
selector: 'proj-example',
templateUrl: './example.component.html',
styleUrl: './example.component.css',
styleUrl: './example.component.css'
})
export class ExampleComponent {}
@ -59,6 +60,7 @@ describe('SCAM Generator', () => {
name: 'example',
project: 'app1',
inlineScam: false,
skipFormat: true,
});
// ASSERT
@ -101,6 +103,7 @@ describe('SCAM Generator', () => {
path: 'libs/lib1/feature/src/lib',
inlineScam: false,
export: true,
skipFormat: true,
});
// ASSERT
@ -127,8 +130,7 @@ describe('SCAM Generator', () => {
);
expect(secondaryEntryPointSource).toMatchInlineSnapshot(`
"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',
path: 'apps/app1/src/app/random',
inlineScam: true,
skipFormat: true,
});
// ASSERT
@ -162,7 +165,7 @@ describe('SCAM Generator', () => {
@Component({
selector: 'proj-example',
templateUrl: './example.component.html',
styleUrl: './example.component.css',
styleUrl: './example.component.css'
})
export class ExampleComponent {}
@ -191,6 +194,7 @@ describe('SCAM Generator', () => {
project: 'app1',
path: '/apps/app1/src/app/random',
inlineScam: true,
skipFormat: true,
});
// ASSERT
@ -205,7 +209,7 @@ describe('SCAM Generator', () => {
@Component({
selector: 'proj-example',
templateUrl: './example.component.html',
styleUrl: './example.component.css',
styleUrl: './example.component.css'
})
export class ExampleComponent {}
@ -235,6 +239,7 @@ describe('SCAM Generator', () => {
project: 'app1',
path: 'libs/proj/src/lib/random',
inlineScam: true,
skipFormat: true,
})
).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."`

View File

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

View File

@ -37,6 +37,8 @@ describe('AppComponent', () => {
tick();
fixture.detectChanges();
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';
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';
export default withModuleFederation({
...config,
/*
* Remote overrides for production.
* Each entry is a pair of a unique name and the URL where it is deployed.
*
* e.g.
* remotes: [
* ['app1', 'https://app1.example.com'],
* ['app2', 'https://app2.example.com'],
* ]
*/
...config,
/*
* Remote overrides for production.
* Each entry is a pair of a unique name and the URL where it is deployed.
*
* e.g.
* remotes: [
* ['app1', 'https://app1.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 { %>
'./Module': '<%= projectRoot %>/src/app/remote-entry/entry.module.ts',<% } %>
},<% } %>
}
};

View File

@ -35,7 +35,7 @@ export function addRemoteEntry(
addRoute(
tree,
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(
0,
indexOfClosingMenuTag
)}<li><a routerLink='${options.appName}'>${
)}<li><a routerLink="${options.appName}">${
names(options.appName).className
}</a></li>\n${appComponent.slice(indexOfClosingMenuTag)}`;
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);
}
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';
fetch('/assets/module-federation.manifest.json')
fetch('/assets/module-federation.manifest.json')
.then((res) => res.json())
.then(definitions => setRemoteDefinitions(definitions))
.then(() => ${bootstrapImportCode})`;
@ -29,10 +29,11 @@ export function fixBootstrap(tree: Tree, appRoot: string, options: Schema) {
}
const standaloneBootstrapCode =
() => `import {bootstrapApplication} from "@angular/platform-browser";
import {appConfig} from './app/app.config';
import {RemoteEntryComponent} from './app/remote-entry/entry.component';
() => `import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { RemoteEntryComponent } from './app/remote-entry/entry.component';
bootstrapApplication(RemoteEntryComponent, appConfig).catch((err) =>
console.error(err)
);`;
);
`;

View File

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

View File

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

View File

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

View File

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

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