/** * @license * Copyright Google Inc. 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 */ import {AnimationBuilder, animate, style, transition, trigger} from '@angular/animations'; import {APP_BASE_HREF, PlatformLocation, isPlatformServer} from '@angular/common'; import {HttpClient, HttpClientModule} from '@angular/common/http'; import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing'; import {ApplicationRef, CompilerFactory, Component, HostListener, Input, NgModule, NgModuleRef, NgZone, PLATFORM_ID, PlatformRef, ViewEncapsulation, destroyPlatform, getPlatform} from '@angular/core'; import {TestBed, async, inject} from '@angular/core/testing'; import {Http, HttpModule, Response, ResponseOptions, XHRBackend} from '@angular/http'; import {MockBackend, MockConnection} from '@angular/http/testing'; import {BrowserModule, DOCUMENT, StateKey, Title, TransferState, makeStateKey} from '@angular/platform-browser'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; import {BEFORE_APP_SERIALIZED, INITIAL_CONFIG, PlatformState, ServerModule, ServerTransferStateModule, platformDynamicServer, renderModule, renderModuleFactory} from '@angular/platform-server'; import {Subscription} from 'rxjs/Subscription'; import {filter} from 'rxjs/operator/filter'; import {first} from 'rxjs/operator/first'; import {toPromise} from 'rxjs/operator/toPromise'; @Component({selector: 'app', template: `Works!`}) class MyServerApp { } @NgModule({ bootstrap: [MyServerApp], declarations: [MyServerApp], imports: [ServerModule], providers: [ MockBackend, {provide: XHRBackend, useExisting: MockBackend}, ] }) class ExampleModule { } function getTitleRenderHook(doc: any) { return () => { // Set the title as part of the render hook. doc.title = 'RenderHook'; }; } function exceptionRenderHook() { throw new Error('error'); } function getMetaRenderHook(doc: any) { return () => { // Add a meta tag before rendering the document. const metaElement = doc.createElement('meta'); metaElement.setAttribute('name', 'description'); doc.head.appendChild(metaElement); }; } @NgModule({ bootstrap: [MyServerApp], declarations: [MyServerApp], imports: [BrowserModule.withServerTransition({appId: 'render-hook'}), ServerModule], providers: [ {provide: BEFORE_APP_SERIALIZED, useFactory: getTitleRenderHook, multi: true, deps: [DOCUMENT]}, ] }) class RenderHookModule { } @NgModule({ bootstrap: [MyServerApp], declarations: [MyServerApp], imports: [BrowserModule.withServerTransition({appId: 'render-hook'}), ServerModule], providers: [ {provide: BEFORE_APP_SERIALIZED, useFactory: getTitleRenderHook, multi: true, deps: [DOCUMENT]}, {provide: BEFORE_APP_SERIALIZED, useValue: exceptionRenderHook, multi: true}, {provide: BEFORE_APP_SERIALIZED, useFactory: getMetaRenderHook, multi: true, deps: [DOCUMENT]}, ] }) class MultiRenderHookModule { } @Component({selector: 'app', template: `Works too!`}) class MyServerApp2 { } @NgModule({declarations: [MyServerApp2], imports: [ServerModule], bootstrap: [MyServerApp2]}) class ExampleModule2 { } @Component({selector: 'app', template: ``}) class TitleApp { constructor(private title: Title) {} ngOnInit() { this.title.setTitle('Test App Title'); } } @NgModule({declarations: [TitleApp], imports: [ServerModule], bootstrap: [TitleApp]}) class TitleAppModule { } @Component({selector: 'app', template: '{{text}}

'}) class MyAsyncServerApp { text = ''; h1 = ''; @HostListener('window:scroll') track() { console.error('scroll'); } ngOnInit() { Promise.resolve(null).then(() => setTimeout(() => { this.text = 'Works!'; this.h1 = 'fine'; }, 10)); } } @NgModule({ declarations: [MyAsyncServerApp], imports: [BrowserModule.withServerTransition({appId: 'async-server'}), ServerModule], bootstrap: [MyAsyncServerApp] }) class AsyncServerModule { } @Component({selector: 'app', template: ''}) class SVGComponent { } @NgModule({ declarations: [SVGComponent], imports: [BrowserModule.withServerTransition({appId: 'svg-server'}), ServerModule], bootstrap: [SVGComponent] }) class SVGServerModule { } @Component({ selector: 'app', template: '
{{text}}
', animations: [trigger( 'myAnimation', [transition('void => *', [style({'opacity': '0'}), animate(500, style({'opacity': '1'}))])])], }) class MyAnimationApp { constructor(private builder: AnimationBuilder) {} text = 'Works!'; } @NgModule({ declarations: [MyAnimationApp], imports: [BrowserModule.withServerTransition({appId: 'anim-server'}), ServerModule], bootstrap: [MyAnimationApp] }) class AnimationServerModule { } @Component({selector: 'app', template: `Works!`, styles: [':host { color: red; }']}) class MyStylesApp { } @NgModule({ declarations: [MyStylesApp], imports: [BrowserModule.withServerTransition({appId: 'example-styles'}), ServerModule], bootstrap: [MyStylesApp] }) class ExampleStylesModule { } @NgModule({ bootstrap: [MyServerApp], declarations: [MyServerApp], imports: [HttpModule, ServerModule], providers: [ MockBackend, {provide: XHRBackend, useExisting: MockBackend}, ] }) export class HttpBeforeExampleModule { } @NgModule({ bootstrap: [MyServerApp], declarations: [MyServerApp], imports: [ServerModule, HttpModule], providers: [ MockBackend, {provide: XHRBackend, useExisting: MockBackend}, ] }) export class HttpAfterExampleModule { } @NgModule({ bootstrap: [MyServerApp], declarations: [MyServerApp], imports: [ServerModule, HttpClientModule, HttpClientTestingModule], }) export class HttpClientExmapleModule { } @Component({selector: 'app', template: ``}) class ImageApp { } @NgModule({declarations: [ImageApp], imports: [ServerModule], bootstrap: [ImageApp]}) class ImageExampleModule { } @Component({ selector: 'app', template: 'Native works', encapsulation: ViewEncapsulation.Native, styles: [':host { color: red; }'] }) class NativeEncapsulationApp { } @NgModule({ declarations: [NativeEncapsulationApp], imports: [BrowserModule.withServerTransition({appId: 'test'}), ServerModule], bootstrap: [NativeEncapsulationApp] }) class NativeExampleModule { } @Component({selector: 'my-child', template: 'Works!'}) class MyChildComponent { @Input() public attr: boolean; } @Component({selector: 'app', template: ''}) class MyHostComponent { } @NgModule({ declarations: [MyHostComponent, MyChildComponent], bootstrap: [MyHostComponent], imports: [ServerModule, BrowserModule.withServerTransition({appId: 'false-attributes'})] }) class FalseAttributesModule { } @Component({selector: 'app', template: ''}) class MyInputComponent { @Input() name = ''; } @NgModule({ declarations: [MyInputComponent], bootstrap: [MyInputComponent], imports: [ServerModule, BrowserModule.withServerTransition({appId: 'name-attributes'})] }) class NameModule { } const TEST_KEY = makeStateKey('test'); const STRING_KEY = makeStateKey('testString'); @Component({selector: 'app', template: 'Works!'}) class TransferComponent { constructor(private transferStore: TransferState) {} ngOnInit() { this.transferStore.set(TEST_KEY, 10); } } @Component({selector: 'esc-app', template: 'Works!'}) class EscapedComponent { constructor(private transferStore: TransferState) {} ngOnInit() { this.transferStore.set(STRING_KEY, ''; beforeEach(() => { called = false; }); afterEach(() => { expect(called).toBe(true); }); it('adds transfer script tag when using renderModule', async(() => { renderModule(TransferStoreModule, {document: ''}).then(output => { expect(output).toBe(defaultExpectedOutput); called = true; }); })); it('adds transfer script tag when using renderModuleFactory', async(inject([PlatformRef], (defaultPlatform: PlatformRef) => { const compilerFactory: CompilerFactory = defaultPlatform.injector.get(CompilerFactory, null); const moduleFactory = compilerFactory.createCompiler().compileModuleSync(TransferStoreModule); renderModuleFactory(moduleFactory, {document: ''}).then(output => { expect(output).toBe(defaultExpectedOutput); called = true; }); }))); it('cannot break out of '); called = true; }); })); }); }); })();