mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-15 10:11:50 +08:00
test: move builder testing infrastructure to separate bazel target module
The builder testing infrastructure and harness has been moved out of the `@angular-devkit/build-angular` package and into a separate bazel only module. This allows the testing code to be shared with other packages within the repository. It also removes test only code from within the package that is not specific any of the included builders.
This commit is contained in:
parent
63dab464a4
commit
631303664e
@ -15,6 +15,7 @@
|
||||
"bazel-out",
|
||||
"dist-schema",
|
||||
"goldens/public-api",
|
||||
"modules/testing/builder/projects",
|
||||
"packages/angular_devkit/build_angular/src/babel-bazel.d.ts",
|
||||
"packages/angular_devkit/build_angular/test",
|
||||
"packages/angular_devkit/build_webpack/test",
|
||||
|
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@ -103,7 +103,9 @@ jobs:
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@f8b2efa171f4ebec4d0cb3d5c5d4f7cb680f2af9
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Run tests
|
||||
- name: Run module tests
|
||||
run: yarn bazel test //modules/...
|
||||
- name: Run package tests
|
||||
run: yarn bazel test //packages/...
|
||||
|
||||
e2e:
|
||||
|
@ -2,6 +2,7 @@
|
||||
/docs/design/analytics.md
|
||||
/dist-schema/
|
||||
/goldens/public-api
|
||||
/modules/testing/builder/projects/
|
||||
/packages/angular_devkit/build_angular/test/
|
||||
/packages/angular_devkit/core/src/workspace/json/test/
|
||||
/packages/angular_devkit/schematics_cli/blank/project-files/
|
||||
|
45
modules/testing/builder/BUILD.bazel
Normal file
45
modules/testing/builder/BUILD.bazel
Normal file
@ -0,0 +1,45 @@
|
||||
load("@npm//@bazel/jasmine:index.bzl", "jasmine_node_test")
|
||||
load("//tools:defaults.bzl", "ts_library")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
ts_library(
|
||||
name = "builder",
|
||||
testonly = True,
|
||||
srcs = glob(
|
||||
include = [
|
||||
"src/**/*.ts",
|
||||
],
|
||||
exclude = [
|
||||
"src/**/*_spec.ts",
|
||||
],
|
||||
),
|
||||
data = glob(["projects/**/*"]),
|
||||
deps = [
|
||||
"//packages/angular_devkit/architect",
|
||||
"//packages/angular_devkit/architect/node",
|
||||
"//packages/angular_devkit/architect/testing",
|
||||
"//packages/angular_devkit/core",
|
||||
"//packages/angular_devkit/core/node",
|
||||
"@npm//rxjs",
|
||||
],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "unit_test_lib",
|
||||
testonly = True,
|
||||
srcs = glob(
|
||||
include = [
|
||||
"src/**/*_spec.ts",
|
||||
],
|
||||
),
|
||||
deps = [
|
||||
":builder",
|
||||
"//packages/angular_devkit/architect/testing",
|
||||
],
|
||||
)
|
||||
|
||||
jasmine_node_test(
|
||||
name = "unit_test",
|
||||
srcs = [":unit_test_lib"],
|
||||
)
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
@ -6,6 +6,8 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
|
||||
import {
|
||||
BuilderContext,
|
||||
BuilderHandlerFn,
|
@ -6,6 +6,8 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
|
||||
import { TestProjectHost } from '@angular-devkit/architect/testing';
|
||||
import { BuilderHarness } from './builder-harness';
|
||||
|
@ -6,10 +6,17 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {
|
||||
BuilderWatcherCallback,
|
||||
BuilderWatcherFactory,
|
||||
} from '../tools/webpack/plugins/builder-watch-plugin';
|
||||
type BuilderWatcherCallback = (
|
||||
events: Array<{ path: string; type: 'created' | 'modified' | 'deleted'; time?: number }>,
|
||||
) => void;
|
||||
|
||||
interface BuilderWatcherFactory {
|
||||
watch(
|
||||
files: Iterable<string>,
|
||||
directories: Iterable<string>,
|
||||
callback: BuilderWatcherCallback,
|
||||
): { close(): void };
|
||||
}
|
||||
|
||||
class WatcherDescriptor {
|
||||
constructor(
|
15
modules/testing/builder/src/index.ts
Normal file
15
modules/testing/builder/src/index.ts
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
export {
|
||||
BuilderHarness,
|
||||
BuilderHarnessExecutionOptions,
|
||||
BuilderHarnessExecutionResult,
|
||||
} from './builder-harness';
|
||||
export { HarnessFileMatchers, JasmineBuilderHarness, describeBuilder } from './jasmine-helpers';
|
||||
export * from './test-utils';
|
176
modules/testing/builder/src/test-utils.ts
Normal file
176
modules/testing/builder/src/test-utils.ts
Normal file
@ -0,0 +1,176 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
|
||||
import { Architect, BuilderOutput, ScheduleOptions, Target } from '@angular-devkit/architect';
|
||||
import { WorkspaceNodeModulesArchitectHost } from '@angular-devkit/architect/node';
|
||||
import { TestProjectHost, TestingArchitectHost } from '@angular-devkit/architect/testing';
|
||||
import {
|
||||
Path,
|
||||
getSystemPath,
|
||||
join,
|
||||
json,
|
||||
normalize,
|
||||
schema,
|
||||
virtualFs,
|
||||
workspaces,
|
||||
} from '@angular-devkit/core';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
// Default timeout for large specs is 2.5 minutes.
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 150000;
|
||||
|
||||
export const workspaceRoot = join(normalize(__dirname), `../projects/hello-world-app/`);
|
||||
export const host = new TestProjectHost(workspaceRoot);
|
||||
export const outputPath: Path = normalize('dist');
|
||||
|
||||
export const browserTargetSpec = { project: 'app', target: 'build' };
|
||||
export const devServerTargetSpec = { project: 'app', target: 'serve' };
|
||||
export const extractI18nTargetSpec = { project: 'app', target: 'extract-i18n' };
|
||||
export const karmaTargetSpec = { project: 'app', target: 'test' };
|
||||
export const tslintTargetSpec = { project: 'app', target: 'lint' };
|
||||
export const protractorTargetSpec = { project: 'app-e2e', target: 'e2e' };
|
||||
|
||||
export async function createArchitect(workspaceRoot: Path) {
|
||||
const registry = new schema.CoreSchemaRegistry();
|
||||
registry.addPostTransform(schema.transforms.addUndefinedDefaults);
|
||||
const workspaceSysPath = getSystemPath(workspaceRoot);
|
||||
|
||||
const { workspace } = await workspaces.readWorkspace(
|
||||
workspaceSysPath,
|
||||
workspaces.createWorkspaceHost(host),
|
||||
);
|
||||
const architectHost = new TestingArchitectHost(
|
||||
workspaceSysPath,
|
||||
workspaceSysPath,
|
||||
new WorkspaceNodeModulesArchitectHost(workspace, workspaceSysPath),
|
||||
);
|
||||
const architect = new Architect(architectHost, registry);
|
||||
|
||||
return {
|
||||
workspace,
|
||||
architectHost,
|
||||
architect,
|
||||
};
|
||||
}
|
||||
|
||||
export interface BrowserBuildOutput {
|
||||
output: BuilderOutput;
|
||||
files: { [file: string]: Promise<string> };
|
||||
}
|
||||
|
||||
export async function browserBuild(
|
||||
architect: Architect,
|
||||
host: virtualFs.Host,
|
||||
target: Target,
|
||||
overrides?: json.JsonObject,
|
||||
scheduleOptions?: ScheduleOptions,
|
||||
): Promise<BrowserBuildOutput> {
|
||||
const run = await architect.scheduleTarget(target, overrides, scheduleOptions);
|
||||
const output = (await run.result) as BuilderOutput & { outputs: { path: string }[] };
|
||||
expect(output.success).toBe(true);
|
||||
|
||||
if (!output.success) {
|
||||
await run.stop();
|
||||
|
||||
return {
|
||||
output,
|
||||
files: {},
|
||||
};
|
||||
}
|
||||
|
||||
const [{ path }] = output.outputs;
|
||||
expect(path).toBeTruthy();
|
||||
const outputPath = normalize(path);
|
||||
|
||||
const fileNames = await firstValueFrom(host.list(outputPath));
|
||||
const files = fileNames.reduce((acc: { [name: string]: Promise<string> }, path) => {
|
||||
let cache: Promise<string> | null = null;
|
||||
Object.defineProperty(acc, path, {
|
||||
enumerable: true,
|
||||
get() {
|
||||
if (cache) {
|
||||
return cache;
|
||||
}
|
||||
if (!fileNames.includes(path)) {
|
||||
return Promise.reject('No file named ' + path);
|
||||
}
|
||||
cache = firstValueFrom(host.read(join(outputPath, path))).then((content) =>
|
||||
virtualFs.fileBufferToString(content),
|
||||
);
|
||||
|
||||
return cache;
|
||||
},
|
||||
});
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
await run.stop();
|
||||
|
||||
return {
|
||||
output,
|
||||
files,
|
||||
};
|
||||
}
|
||||
|
||||
export const lazyModuleFiles: { [path: string]: string } = {
|
||||
'src/app/lazy/lazy-routing.module.ts': `
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
const routes: Routes = [];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class LazyRoutingModule { }
|
||||
`,
|
||||
'src/app/lazy/lazy.module.ts': `
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { LazyRoutingModule } from './lazy-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
LazyRoutingModule
|
||||
],
|
||||
declarations: []
|
||||
})
|
||||
export class LazyModule { }
|
||||
`,
|
||||
};
|
||||
|
||||
export const lazyModuleFnImport: { [path: string]: string } = {
|
||||
'src/app/app.module.ts': `
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
RouterModule.forRoot([
|
||||
{ path: 'lazy', loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule) }
|
||||
])
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
||||
`,
|
||||
};
|
@ -3,10 +3,10 @@
|
||||
# Use of this source code is governed by an MIT-style license that can be
|
||||
# found in the LICENSE file at https://angular.io/license
|
||||
|
||||
load("@npm//@angular/build-tooling/bazel/api-golden:index.bzl", "api_golden_test_npm_package")
|
||||
load("@npm//@bazel/jasmine:index.bzl", "jasmine_node_test")
|
||||
load("//tools:defaults.bzl", "pkg_npm", "ts_library")
|
||||
load("//tools:ts_json_schema.bzl", "ts_json_schema")
|
||||
load("@npm//@angular/build-tooling/bazel/api-golden:index.bzl", "api_golden_test_npm_package")
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
@ -285,7 +285,6 @@ ts_library(
|
||||
testonly = True,
|
||||
srcs = glob(
|
||||
include = [
|
||||
"src/test-utils.ts",
|
||||
"src/testing/**/*.ts",
|
||||
"src/**/tests/*.ts",
|
||||
],
|
||||
@ -297,6 +296,7 @@ ts_library(
|
||||
tsconfig = "//:tsconfig-test.json",
|
||||
deps = [
|
||||
":build_angular",
|
||||
"//modules/testing/builder",
|
||||
"//packages/angular_devkit/architect",
|
||||
"//packages/angular_devkit/architect/node",
|
||||
"//packages/angular_devkit/architect/testing",
|
||||
@ -394,6 +394,7 @@ LARGE_SPECS = {
|
||||
# Dependencies needed to compile and run the specs themselves.
|
||||
":build_angular",
|
||||
":build_angular_test_utils",
|
||||
"//modules/testing/builder",
|
||||
"//packages/angular_devkit/architect",
|
||||
"//packages/angular_devkit/architect/node",
|
||||
"//packages/angular_devkit/architect/testing",
|
||||
|
@ -11,7 +11,7 @@ import { BASE_OPTIONS, BROWSER_BUILDER_INFO, describeBuilder } from '../setup';
|
||||
|
||||
const MAIN_OUTPUT = 'dist/main.js';
|
||||
const NAMED_LAZY_OUTPUT = 'dist/src_lazy-module_ts.js';
|
||||
const UNNAMED_LAZY_OUTPUT = 'dist/28.js';
|
||||
const UNNAMED_LAZY_OUTPUT = 'dist/358.js';
|
||||
|
||||
describeBuilder(buildWebpackBrowser, BROWSER_BUILDER_INFO, (harness) => {
|
||||
describe('Option: "namedChunks"', () => {
|
||||
@ -61,7 +61,7 @@ describeBuilder(buildWebpackBrowser, BROWSER_BUILDER_INFO, (harness) => {
|
||||
const { result } = await harness.executeOnce();
|
||||
|
||||
expect(result?.success).toBe(true);
|
||||
|
||||
debugger;
|
||||
harness.expectFile(MAIN_OUTPUT).toExist();
|
||||
harness.expectFile(NAMED_LAZY_OUTPUT).toNotExist();
|
||||
harness.expectFile(UNNAMED_LAZY_OUTPUT).toExist();
|
||||
|
@ -12,7 +12,7 @@ import {
|
||||
BuilderHarness,
|
||||
BuilderHarnessExecutionOptions,
|
||||
BuilderHarnessExecutionResult,
|
||||
} from '../../../testing/builder-harness';
|
||||
} from '../../../testing';
|
||||
|
||||
export async function executeOnceAndFetch<T>(
|
||||
harness: BuilderHarness<T>,
|
||||
|
@ -9,7 +9,7 @@
|
||||
import { BuilderHandlerFn } from '@angular-devkit/architect';
|
||||
import { json } from '@angular-devkit/core';
|
||||
import { readFileSync } from 'fs';
|
||||
import { JasmineBuilderHarness } from '../../../testing/jasmine-helpers';
|
||||
import { JasmineBuilderHarness } from '../../../testing';
|
||||
import { host } from '../../../testing/test-utils';
|
||||
import { setupApplicationTarget, setupBrowserTarget } from './setup';
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import { createServer } from 'node:http';
|
||||
import { JasmineBuilderHarness } from '../../../../testing/jasmine-helpers';
|
||||
import { BuilderHarness } from '../../../../testing';
|
||||
import { executeDevServer } from '../../index';
|
||||
import { executeOnceAndFetch } from '../execute-fetch';
|
||||
import { describeServeBuilder } from '../jasmine-helpers';
|
||||
@ -275,7 +275,7 @@ async function createProxyServer() {
|
||||
/**
|
||||
* Vite specific tests
|
||||
*/
|
||||
function viteOnlyTests(harness: JasmineBuilderHarness<unknown>): void {
|
||||
function viteOnlyTests(harness: BuilderHarness<unknown>): void {
|
||||
it('proxies support regexp as context', async () => {
|
||||
harness.useTarget('serve', {
|
||||
...BASE_OPTIONS,
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
import { json } from '@angular-devkit/core';
|
||||
import { readFileSync } from 'fs';
|
||||
import { BuilderHarness } from '../../../testing/builder-harness';
|
||||
import { BuilderHarness } from '../../../testing';
|
||||
import { buildApplication } from '../../application';
|
||||
import { Schema as AppilicationSchema } from '../../application/schema';
|
||||
import {
|
||||
|
@ -6,5 +6,6 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
export { BuilderHarnessExecutionOptions, BuilderHarnessExecutionResult } from './builder-harness';
|
||||
export { HarnessFileMatchers, describeBuilder } from './jasmine-helpers';
|
||||
// TODO: Consider using package.json imports field instead of relative path
|
||||
// after the switch to rules_js.
|
||||
export * from '../../../../../modules/testing/builder/src';
|
||||
|
@ -6,170 +6,4 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import { Architect, BuilderOutput, ScheduleOptions, Target } from '@angular-devkit/architect';
|
||||
import { WorkspaceNodeModulesArchitectHost } from '@angular-devkit/architect/node';
|
||||
import { TestProjectHost, TestingArchitectHost } from '@angular-devkit/architect/testing';
|
||||
import { BrowserBuilderOutput } from '@angular-devkit/build-angular';
|
||||
import {
|
||||
Path,
|
||||
getSystemPath,
|
||||
join,
|
||||
json,
|
||||
normalize,
|
||||
schema,
|
||||
virtualFs,
|
||||
workspaces,
|
||||
} from '@angular-devkit/core';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
// Default timeout for large specs is 2.5 minutes.
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 150000;
|
||||
|
||||
export const workspaceRoot = join(normalize(__dirname), `../../test/hello-world-app/`);
|
||||
export const host = new TestProjectHost(workspaceRoot);
|
||||
export const outputPath: Path = normalize('dist');
|
||||
|
||||
export const browserTargetSpec = { project: 'app', target: 'build' };
|
||||
export const devServerTargetSpec = { project: 'app', target: 'serve' };
|
||||
export const extractI18nTargetSpec = { project: 'app', target: 'extract-i18n' };
|
||||
export const karmaTargetSpec = { project: 'app', target: 'test' };
|
||||
export const tslintTargetSpec = { project: 'app', target: 'lint' };
|
||||
export const protractorTargetSpec = { project: 'app-e2e', target: 'e2e' };
|
||||
|
||||
export async function createArchitect(workspaceRoot: Path) {
|
||||
const registry = new schema.CoreSchemaRegistry();
|
||||
registry.addPostTransform(schema.transforms.addUndefinedDefaults);
|
||||
const workspaceSysPath = getSystemPath(workspaceRoot);
|
||||
|
||||
const { workspace } = await workspaces.readWorkspace(
|
||||
workspaceSysPath,
|
||||
workspaces.createWorkspaceHost(host),
|
||||
);
|
||||
const architectHost = new TestingArchitectHost(
|
||||
workspaceSysPath,
|
||||
workspaceSysPath,
|
||||
new WorkspaceNodeModulesArchitectHost(workspace, workspaceSysPath),
|
||||
);
|
||||
const architect = new Architect(architectHost, registry);
|
||||
|
||||
return {
|
||||
workspace,
|
||||
architectHost,
|
||||
architect,
|
||||
};
|
||||
}
|
||||
|
||||
export interface BrowserBuildOutput {
|
||||
output: BuilderOutput;
|
||||
files: { [file: string]: Promise<string> };
|
||||
}
|
||||
|
||||
export async function browserBuild(
|
||||
architect: Architect,
|
||||
host: virtualFs.Host,
|
||||
target: Target,
|
||||
overrides?: json.JsonObject,
|
||||
scheduleOptions?: ScheduleOptions,
|
||||
): Promise<BrowserBuildOutput> {
|
||||
const run = await architect.scheduleTarget(target, overrides, scheduleOptions);
|
||||
const output = (await run.result) as BrowserBuilderOutput;
|
||||
expect(output.success).toBe(true);
|
||||
|
||||
if (!output.success) {
|
||||
await run.stop();
|
||||
|
||||
return {
|
||||
output,
|
||||
files: {},
|
||||
};
|
||||
}
|
||||
|
||||
const [{ path }] = output.outputs;
|
||||
expect(path).toBeTruthy();
|
||||
const outputPath = normalize(path);
|
||||
|
||||
const fileNames = await firstValueFrom(host.list(outputPath));
|
||||
const files = fileNames.reduce((acc: { [name: string]: Promise<string> }, path) => {
|
||||
let cache: Promise<string> | null = null;
|
||||
Object.defineProperty(acc, path, {
|
||||
enumerable: true,
|
||||
get() {
|
||||
if (cache) {
|
||||
return cache;
|
||||
}
|
||||
if (!fileNames.includes(path)) {
|
||||
return Promise.reject('No file named ' + path);
|
||||
}
|
||||
cache = firstValueFrom(host.read(join(outputPath, path))).then((content) =>
|
||||
virtualFs.fileBufferToString(content),
|
||||
);
|
||||
|
||||
return cache;
|
||||
},
|
||||
});
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
await run.stop();
|
||||
|
||||
return {
|
||||
output,
|
||||
files,
|
||||
};
|
||||
}
|
||||
|
||||
export const lazyModuleFiles: { [path: string]: string } = {
|
||||
'src/app/lazy/lazy-routing.module.ts': `
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
const routes: Routes = [];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class LazyRoutingModule { }
|
||||
`,
|
||||
'src/app/lazy/lazy.module.ts': `
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { LazyRoutingModule } from './lazy-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
LazyRoutingModule
|
||||
],
|
||||
declarations: []
|
||||
})
|
||||
export class LazyModule { }
|
||||
`,
|
||||
};
|
||||
|
||||
export const lazyModuleFnImport: { [path: string]: string } = {
|
||||
'src/app/app.module.ts': `
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
RouterModule.forRoot([
|
||||
{ path: 'lazy', loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule) }
|
||||
])
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
||||
`,
|
||||
};
|
||||
export * from '../../../../../modules/testing/builder/src';
|
||||
|
Loading…
x
Reference in New Issue
Block a user