docs: add tests for lazy loading angularjs example (#30622)
PR Close #30622
This commit is contained in:
parent
81332150aa
commit
2b5d52fbdc
|
@ -0,0 +1,79 @@
|
|||
import { browser, element, by, ExpectedConditions } from 'protractor';
|
||||
|
||||
describe('Lazy Loading AngularJS Tests', function () {
|
||||
const pageElements = {
|
||||
homePageHref: element(by.cssContainingText('app-root nav a', 'Home')),
|
||||
homePageParagraph: element(by.css('app-root app-home p')),
|
||||
ajsUsersPageHref: element(by.cssContainingText('app-root nav a', 'Users')),
|
||||
ajsUsersPageParagraph: element(by.css('app-root app-angular-js div p')),
|
||||
notFoundPageHref: element(by.cssContainingText('app-root nav a', '404 Page')),
|
||||
notFoundPageParagraph: element(by.css('app-root app-app404 p')),
|
||||
};
|
||||
|
||||
beforeAll(async() => {
|
||||
await browser.get('/');
|
||||
});
|
||||
|
||||
it('should display \'Angular Home\' when visiting the home page', async() => {
|
||||
await pageElements.homePageHref.click();
|
||||
|
||||
const paragraphText = await pageElements.homePageParagraph.getText();
|
||||
|
||||
expect(paragraphText).toEqual('Angular Home');
|
||||
});
|
||||
|
||||
it('should display \'Users Page\' page when visiting the AngularJS page at /users', async() => {
|
||||
await pageElements.ajsUsersPageHref.click();
|
||||
await loadAngularJS();
|
||||
|
||||
const paragraphText = await pageElements.ajsUsersPageParagraph.getText();
|
||||
|
||||
expect(paragraphText).toEqual('Users Page');
|
||||
});
|
||||
|
||||
it('should display \'Angular 404\' when visiting an invalid URL', async() => {
|
||||
await pageElements.notFoundPageHref.click();
|
||||
|
||||
const paragraphText = await pageElements.notFoundPageParagraph.getText();
|
||||
|
||||
expect(paragraphText).toEqual('Angular 404');
|
||||
});
|
||||
|
||||
// Workaround for https://github.com/angular/protractor/issues/4724
|
||||
async function loadAngularJS() {
|
||||
// Abort if `resumeBootstrap` has already occured
|
||||
if (await browser.executeScript(`return '__TESTABILITY__NG1_APP_ROOT_INJECTOR__' in window;`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Might have to re-insert the 'NG_DEFER_BOOTSTRAP!' if the name has been changed since protractor loaded the page
|
||||
if (!await browser.executeScript('window.name.includes(\'NG_DEFER_BOOTSTRAP!\')')) {
|
||||
await browser.executeScript('window.name = \'NG_DEFER_BOOTSTRAP!\' + name');
|
||||
}
|
||||
|
||||
// Wait for the AngularJS bundle to download and initialize
|
||||
await browser.wait(ExpectedConditions.presenceOf(element(by.css('app-root app-angular-js'))), 5000, 'AngularJS app');
|
||||
|
||||
// Run the protractor pre-bootstrap logic and resumeBootstrap
|
||||
// Based on https://github.com/angular/protractor/blob/5.3.0/lib/browser.ts#L950-L969
|
||||
{
|
||||
let moduleNames = [];
|
||||
for (const {name, script, args} of browser.mockModules_) {
|
||||
moduleNames.push(name);
|
||||
await browser.executeScriptWithDescription(script, 'add mock module ' + name, ...args);
|
||||
}
|
||||
|
||||
await browser.executeScriptWithDescription(
|
||||
// TODO: must manually assign __TESTABILITY__NG1_APP_ROOT_INJECTOR__ (https://github.com/angular/angular/issues/22723)
|
||||
`window.__TESTABILITY__NG1_APP_ROOT_INJECTOR__ = angular.resumeBootstrap(arguments[0]) `
|
||||
+ `|| angular.element('app-angular-js').injector();`,
|
||||
'resume bootstrap',
|
||||
moduleNames
|
||||
);
|
||||
}
|
||||
|
||||
// Wait for the initial AngularJS page to finish loading
|
||||
await browser.waitForAngular();
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"projectType": "cli-ajs"
|
||||
}
|
|
@ -1,14 +1,22 @@
|
|||
import { Component, OnInit, ElementRef } from '@angular/core';
|
||||
import { Component, OnInit, OnDestroy, ElementRef } from '@angular/core';
|
||||
import { LazyLoaderService } from '../lazy-loader.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-angular-js',
|
||||
template: '<div ng-view></div>'
|
||||
})
|
||||
export class AngularJSComponent implements OnInit {
|
||||
constructor(private lazyLoader: LazyLoaderService, private elRef: ElementRef) {}
|
||||
export class AngularJSComponent implements OnInit, OnDestroy {
|
||||
constructor(
|
||||
private lazyLoader: LazyLoaderService,
|
||||
private elRef: ElementRef
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.lazyLoader.load(this.elRef.nativeElement);
|
||||
}
|
||||
|
||||
|
||||
ngOnDestroy() {
|
||||
this.lazyLoader.destroy();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ import { App404Component } from './app404/app404.component';
|
|||
BrowserModule,
|
||||
AppRoutingModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
||||
|
|
|
@ -1,23 +1,25 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import * as angular from 'angular';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class LazyLoaderService {
|
||||
bootstrapped = false;
|
||||
private app: angular.auto.IInjectorService;
|
||||
|
||||
load(el: HTMLElement): void {
|
||||
if (this.bootstrapped) {
|
||||
return;
|
||||
}
|
||||
|
||||
import('./angularjs-app').then(app => {
|
||||
try {
|
||||
app.bootstrap(el);
|
||||
this.bootstrapped = true;
|
||||
this.app = app.bootstrap(el);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (this.app) {
|
||||
this.app.get('$rootScope').$destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -868,6 +868,8 @@ As of Angular version 8, lazy loading code can be accomplished simply by using t
|
|||
|
||||
The service uses the `import()` method to load your bundled AngularJS application lazily. This decreases the initial bundle size of your application as you're not loading code your user doesn't need yet. You also need to provide a way to _bootstrap_ the application manually after it has been loaded. AngularJS provides a way to manually bootstrap an application using the [angular.bootstrap()](https://docs.angularjs.org/api/ng/function/angular.bootstrap) method with a provided HTML element. Your AngularJS app should also expose a `bootstrap` method that bootstraps the AngularJS app.
|
||||
|
||||
To ensure any necessary teardown is triggered in the AngularJS app, such as removal of global listeners, you also implement a method to call the `$rootScope.destroy()` method.
|
||||
|
||||
<code-example path="upgrade-lazy-load-ajs/src/app/angularjs-app/index.ts" header="angularjs-app">
|
||||
</code-example>
|
||||
|
||||
|
@ -886,7 +888,7 @@ In your Angular application, you need a component as a placeholder for your Angu
|
|||
<code-example path="upgrade-lazy-load-ajs/src/app/angular-js/angular-js.component.ts" header="src/app/angular-js/angular-js.component.ts">
|
||||
</code-example>
|
||||
|
||||
When the Angular Router matches a route that uses AngularJS, the `AngularJSComponent` is rendered, and the content is rendered within the AngularJS [`ng-view`](https://docs.angularjs.org/api/ngRoute/directive/ngView) directive.
|
||||
When the Angular Router matches a route that uses AngularJS, the `AngularJSComponent` is rendered, and the content is rendered within the AngularJS [`ng-view`](https://docs.angularjs.org/api/ngRoute/directive/ngView) directive. When the user navigates away from the route, the `$rootScope` is destroyed on the AngularJS application.
|
||||
|
||||
### Configure a custom route matcher for AngularJS routes
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"scripts": [
|
||||
{ "name": "ng", "command": "ng" },
|
||||
{ "name": "build", "command": "ng build --prod" },
|
||||
{ "name": "start", "command": "ng serve" },
|
||||
{ "name": "test", "command": "ng test" },
|
||||
{ "name": "lint", "command": "ng lint" },
|
||||
{ "name": "e2e", "command": "ng e2e" }
|
||||
],
|
||||
"dependencies": [
|
||||
"angular",
|
||||
"angular-route"
|
||||
],
|
||||
"devDependencies": [
|
||||
"@angular/cli",
|
||||
"@types/angular",
|
||||
"@types/angular-route",
|
||||
"@types/jasminewd2",
|
||||
"jasmine-spec-reporter",
|
||||
"karma-coverage-istanbul-reporter",
|
||||
"ts-node"
|
||||
]
|
||||
}
|
|
@ -57,6 +57,11 @@ BOILERPLATE_PATHS.schematics = [
|
|||
'angular.json'
|
||||
];
|
||||
|
||||
BOILERPLATE_PATHS['cli-ajs'] = [
|
||||
...cliRelativePath,
|
||||
'package.json'
|
||||
];
|
||||
|
||||
const EXAMPLE_CONFIG_FILENAME = 'example-config.json';
|
||||
|
||||
class ExampleBoilerPlate {
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
{
|
||||
"name": "angular.io-example",
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^8.0.0",
|
||||
"@angular/common": "^8.0.0",
|
||||
"@angular/compiler": "^8.0.0",
|
||||
"@angular/core": "^8.0.0",
|
||||
"@angular/forms": "^8.0.0",
|
||||
"@angular/platform-browser": "^8.0.0",
|
||||
"@angular/platform-browser-dynamic": "^8.0.0",
|
||||
"@angular/router": "^8.0.0",
|
||||
"angular": "1.7.8",
|
||||
"angular-in-memory-web-api": "^0.8.0",
|
||||
"angular-route": "1.7.8",
|
||||
"core-js": "^2.5.4",
|
||||
"rxjs": "^6.5.1",
|
||||
"tslib": "^1.9.0",
|
||||
"web-animations-js": "^2.3.1",
|
||||
"zone.js": "~0.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^0.800.0",
|
||||
"@angular/cli": "^8.0.0",
|
||||
"@angular/compiler-cli": "^8.0.0",
|
||||
"@angular/language-service": "^8.0.0",
|
||||
"@types/angular": "^1.6.47",
|
||||
"@types/angular-route": "^1.3.5",
|
||||
"@types/jasmine": "~3.3.8",
|
||||
"@types/jasminewd2": "~2.0.3",
|
||||
"@types/node": "~8.9.4",
|
||||
"codelyzer": "~5.0.0",
|
||||
"jasmine-core": "~2.99.1",
|
||||
"jasmine-marbles": "^0.5.0",
|
||||
"jasmine-spec-reporter": "~4.2.1",
|
||||
"karma": "~4.1.0",
|
||||
"karma-chrome-launcher": "~2.2.0",
|
||||
"karma-coverage-istanbul-reporter": "~2.0.1",
|
||||
"karma-jasmine": "~2.0.1",
|
||||
"karma-jasmine-html-reporter": "^0.2.2",
|
||||
"protractor": "~5.4.0",
|
||||
"ts-node": "~7.0.0",
|
||||
"tslint": "~5.15.0",
|
||||
"typescript": "~3.4.4"
|
||||
}
|
||||
}
|
|
@ -32,7 +32,9 @@
|
|||
"@nguniversal/common": "^8.0.0-rc.1",
|
||||
"@nguniversal/express-engine": "^8.0.0-rc.1",
|
||||
"@nguniversal/module-map-ngfactory-loader": "^8.0.0-rc.1",
|
||||
"angular": "1.7.8",
|
||||
"angular-in-memory-web-api": "github:brandonroberts/in-memory-web-api-bazel#50a34d8",
|
||||
"angular-route": "1.7.8",
|
||||
"core-js": "^2.5.4",
|
||||
"express": "^4.14.1",
|
||||
"rxjs": "^6.5.1",
|
||||
|
|
|
@ -801,6 +801,16 @@ amdefine@>=0.0.4:
|
|||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
angular-route@1.7.8:
|
||||
version "1.7.8"
|
||||
resolved "https://registry.yarnpkg.com/angular-route/-/angular-route-1.7.8.tgz#d502aa605dcbb253a93e844c0adf51c9bc36b9fa"
|
||||
integrity sha512-VVk89PH0fsY5kfbx+N7IVX1IwnaPWYhMGY0uA+rjej2v1sjvrTx1SLkxUK4E0UpW1hXeLJhN7ncBcwoBiPtAtA==
|
||||
|
||||
angular@1.7.8:
|
||||
version "1.7.8"
|
||||
resolved "https://registry.yarnpkg.com/angular/-/angular-1.7.8.tgz#b77ede272ce1b261e3be30c1451a0b346905a3c9"
|
||||
integrity sha512-wtef/y4COxM7ZVhddd7JtAAhyYObq9YXKar9tsW7558BImeVYteJiTxCKeJOL45lJ/+7B4wrAC49j8gTFYEthg==
|
||||
|
||||
ansi-colors@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.1.0.tgz#dcfaacc90ef9187de413ec3ef8d5eb981a98808f"
|
||||
|
|
Loading…
Reference in New Issue