178 lines
5.6 KiB
TypeScript
178 lines
5.6 KiB
TypeScript
import { names } from '@nx/devkit';
|
|
import {
|
|
checkFilesExist,
|
|
cleanupProject,
|
|
killProcessAndPorts,
|
|
newProject,
|
|
readFile,
|
|
runCLI,
|
|
runCommandUntil,
|
|
uniq,
|
|
updateFile,
|
|
updateJson,
|
|
} from '@nx/e2e/utils';
|
|
import { join } from 'path';
|
|
|
|
describe('Angular Module Federation', () => {
|
|
let proj: string;
|
|
let oldVerboseLoggingValue: string;
|
|
|
|
beforeAll(() => {
|
|
proj = newProject({ packages: ['@nx/angular'] });
|
|
oldVerboseLoggingValue = process.env.NX_E2E_VERBOSE_LOGGING;
|
|
process.env.NX_E2E_VERBOSE_LOGGING = 'true';
|
|
});
|
|
afterAll(() => {
|
|
cleanupProject();
|
|
process.env.NX_E2E_VERBOSE_LOGGING = oldVerboseLoggingValue;
|
|
});
|
|
|
|
it('should generate valid host and remote apps', async () => {
|
|
const hostApp = uniq('app');
|
|
const remoteApp1 = uniq('remote');
|
|
const sharedLib = uniq('shared-lib');
|
|
const wildcardLib = uniq('wildcard-lib');
|
|
const secondaryEntry = uniq('secondary');
|
|
const hostPort = 4300;
|
|
const remotePort = 4301;
|
|
|
|
// generate host app
|
|
runCLI(
|
|
`generate @nx/angular:host ${hostApp} --style=css --bundler=rspack --no-standalone --no-interactive`
|
|
);
|
|
let rspackConfigFileContents = readFile(join(hostApp, 'rspack.config.ts'));
|
|
let updatedConfigFileContents = rspackConfigFileContents.replace(
|
|
`maximumError: '1mb'`,
|
|
`maximumError: '3mb'`
|
|
);
|
|
updateFile(join(hostApp, 'rspack.config.ts'), updatedConfigFileContents);
|
|
|
|
// generate remote app
|
|
runCLI(
|
|
`generate @nx/angular:remote ${remoteApp1} --host=${hostApp} --bundler=rspack --port=${remotePort} --style=css --no-standalone --no-interactive`
|
|
);
|
|
rspackConfigFileContents = readFile(join(remoteApp1, 'rspack.config.ts'));
|
|
updatedConfigFileContents = rspackConfigFileContents.replace(
|
|
`maximumError: '1mb'`,
|
|
`maximumError: '3mb'`
|
|
);
|
|
updateFile(join(remoteApp1, 'rspack.config.ts'), updatedConfigFileContents);
|
|
|
|
// check files are generated without the layout directory ("apps/")
|
|
checkFilesExist(
|
|
`${hostApp}/src/app/app-module.ts`,
|
|
`${remoteApp1}/src/app/app-module.ts`
|
|
);
|
|
|
|
// check default generated host is built successfully
|
|
const buildOutput = runCLI(`build ${hostApp}`, {
|
|
env: { NODE_ENV: 'production' },
|
|
});
|
|
expect(buildOutput).toContain('Successfully ran target build');
|
|
|
|
// generate a shared lib with a seconary entry point
|
|
runCLI(
|
|
`generate @nx/angular:library ${sharedLib} --buildable --no-standalone --no-interactive`
|
|
);
|
|
runCLI(
|
|
`generate @nx/angular:library-secondary-entry-point --library=${sharedLib} --name=${secondaryEntry} --no-interactive`
|
|
);
|
|
|
|
// Add a library that will be accessed via a wildcard in tspath mappings
|
|
runCLI(
|
|
`generate @nx/angular:library ${wildcardLib} --buildable --no-standalone --no-interactive`
|
|
);
|
|
|
|
updateJson('tsconfig.base.json', (json) => {
|
|
delete json.compilerOptions.paths[`@${proj}/${wildcardLib}`];
|
|
json.compilerOptions.paths[`@${proj}/${wildcardLib}/*`] = [
|
|
`${wildcardLib}/src/lib/*`,
|
|
];
|
|
return json;
|
|
});
|
|
|
|
// update host & remote files to use shared library
|
|
updateFile(
|
|
`${hostApp}/src/app/app-module.ts`,
|
|
`import { NgModule } from '@angular/core';
|
|
import { BrowserModule } from '@angular/platform-browser';
|
|
import { ${
|
|
names(wildcardLib).className
|
|
}Module } from '@${proj}/${wildcardLib}/${
|
|
names(secondaryEntry).fileName
|
|
}-module';
|
|
import { ${
|
|
names(sharedLib).className
|
|
}Module } from '@${proj}/${sharedLib}';
|
|
import { ${
|
|
names(secondaryEntry).className
|
|
}Module } from '@${proj}/${sharedLib}/${secondaryEntry}';
|
|
import { App } from './app';
|
|
import { NxWelcome } from './nx-welcome';
|
|
import { RouterModule } from '@angular/router';
|
|
|
|
@NgModule({
|
|
declarations: [App, NxWelcome],
|
|
imports: [
|
|
BrowserModule,
|
|
${names(sharedLib).className}Module,
|
|
${names(wildcardLib).className}Module,
|
|
RouterModule.forRoot(
|
|
[
|
|
{
|
|
path: '${remoteApp1}',
|
|
loadChildren: () =>
|
|
import('${remoteApp1}/Module').then(
|
|
(m) => m.RemoteEntryModule
|
|
),
|
|
},
|
|
],
|
|
{ initialNavigation: 'enabledBlocking' }
|
|
),
|
|
],
|
|
providers: [],
|
|
bootstrap: [App],
|
|
})
|
|
export class AppModule {}
|
|
`
|
|
);
|
|
updateFile(
|
|
`${remoteApp1}/src/app/remote-entry/entry-module.ts`,
|
|
`import { NgModule } from '@angular/core';
|
|
import { CommonModule } from '@angular/common';
|
|
import { RouterModule } from '@angular/router';
|
|
import { ${names(sharedLib).className}Module } from '@${proj}/${sharedLib}';
|
|
import { ${
|
|
names(secondaryEntry).className
|
|
}Module } from '@${proj}/${sharedLib}/${secondaryEntry}';
|
|
import { RemoteEntry } from './entry';
|
|
import { NxWelcome } from './nx-welcome';
|
|
|
|
@NgModule({
|
|
declarations: [RemoteEntry, NxWelcome],
|
|
imports: [
|
|
CommonModule,
|
|
${names(sharedLib).className}Module,
|
|
RouterModule.forChild([
|
|
{
|
|
path: '',
|
|
component: RemoteEntry,
|
|
},
|
|
]),
|
|
],
|
|
providers: [],
|
|
})
|
|
export class RemoteEntryModule {}
|
|
`
|
|
);
|
|
|
|
const processSwc = await runCommandUntil(
|
|
`serve ${remoteApp1}`,
|
|
(output) =>
|
|
!output.includes(`Remote '${remoteApp1}' failed to serve correctly`) &&
|
|
output.includes(`Build at:`)
|
|
);
|
|
await killProcessAndPorts(processSwc.pid, remotePort);
|
|
}, 20_000_000);
|
|
});
|