@ -10,13 +10,12 @@
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {createAngularJSTestingModule, createAngularTestingModule} from '@angular/upgrade/static/testing';
|
||||
|
||||
import {HeroesService, Ng2AppModule, ng1AppModule} from './module';
|
||||
import {HeroesService, ng1AppModule, Ng2AppModule} from './module';
|
||||
|
||||
const {module, inject} = (window as any).angular.mock;
|
||||
|
||||
// #enddocregion angular-setup
|
||||
describe('HeroesService (from Angular)', () => {
|
||||
|
||||
// #docregion angular-setup
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule(
|
||||
@ -40,7 +39,8 @@ describe('HeroesService (from AngularJS)', () => {
|
||||
// #enddocregion angularjs-setup
|
||||
|
||||
// #docregion angularjs-spec
|
||||
it('should have access to the HeroesService',
|
||||
inject((heroesService: HeroesService) => { expect(heroesService).toBeDefined(); }));
|
||||
it('should have access to the HeroesService', inject((heroesService: HeroesService) => {
|
||||
expect(heroesService).toBeDefined();
|
||||
}));
|
||||
// #enddocregion angularjs-spec
|
||||
});
|
||||
|
@ -9,7 +9,7 @@
|
||||
import {Component, Directive, ElementRef, EventEmitter, Injectable, Injector, Input, NgModule, Output} from '@angular/core';
|
||||
import {BrowserModule} from '@angular/platform-browser';
|
||||
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
||||
import {UpgradeComponent, UpgradeModule, downgradeComponent, downgradeInjectable} from '@angular/upgrade/static';
|
||||
import {downgradeComponent, downgradeInjectable, UpgradeComponent, UpgradeModule} from '@angular/upgrade/static';
|
||||
|
||||
declare var angular: ng.IAngularStatic;
|
||||
|
||||
@ -20,7 +20,9 @@ export interface Hero {
|
||||
|
||||
// #docregion ng1-text-formatter-service
|
||||
export class TextFormatter {
|
||||
titleCase(value: string) { return value.replace(/((^|\s)[a-z])/g, (_, c) => c.toUpperCase()); }
|
||||
titleCase(value: string) {
|
||||
return value.replace(/((^|\s)[a-z])/g, (_, c) => c.toUpperCase());
|
||||
}
|
||||
}
|
||||
|
||||
// #enddocregion
|
||||
@ -39,7 +41,7 @@ export class TextFormatter {
|
||||
<button (click)="addHero.emit()">Add Hero</button>`,
|
||||
})
|
||||
export class Ng2HeroesComponent {
|
||||
@Input() heroes !: Hero[];
|
||||
@Input() heroes!: Hero[];
|
||||
@Output() addHero = new EventEmitter();
|
||||
@Output() removeHero = new EventEmitter();
|
||||
}
|
||||
@ -67,7 +69,9 @@ export class HeroesService {
|
||||
this.heroes.concat([{name: 'Kamala Khan', description: 'Epic shape-shifting healer'}]);
|
||||
}
|
||||
|
||||
removeHero(hero: Hero) { this.heroes = this.heroes.filter((item: Hero) => item !== hero); }
|
||||
removeHero(hero: Hero) {
|
||||
this.heroes = this.heroes.filter((item: Hero) => item !== hero);
|
||||
}
|
||||
}
|
||||
// #enddocregion
|
||||
|
||||
@ -77,8 +81,8 @@ export class HeroesService {
|
||||
export class Ng1HeroComponentWrapper extends UpgradeComponent {
|
||||
// The names of the input and output properties here must match the names of the
|
||||
// `<` and `&` bindings in the AngularJS component that is being wrapped
|
||||
@Input() hero !: Hero;
|
||||
@Output() onRemove !: EventEmitter<void>;
|
||||
@Input() hero!: Hero;
|
||||
@Output() onRemove!: EventEmitter<void>;
|
||||
|
||||
constructor(elementRef: ElementRef, injector: Injector) {
|
||||
// We must pass the name of the directive as used by AngularJS to the super
|
||||
@ -159,7 +163,10 @@ ng1AppModule.component('exampleApp', {
|
||||
// (We don't need the `HeroesService` type for AngularJS DI - it just helps with TypeScript
|
||||
// compilation)
|
||||
controller: [
|
||||
'heroesService', function(heroesService: HeroesService) { this.heroesService = heroesService; }
|
||||
'heroesService',
|
||||
function(heroesService: HeroesService) {
|
||||
this.heroesService = heroesService;
|
||||
}
|
||||
],
|
||||
// This template makes use of the downgraded `ng2-heroes` component
|
||||
// Note that because its element is compiled by AngularJS we must use kebab-case attributes
|
||||
|
@ -24,6 +24,7 @@ describe('upgrade/static (lite with multiple downgraded modules and shared root
|
||||
expect(compB.getText()).toBe('Component B (Service ID: 2)');
|
||||
});
|
||||
|
||||
it('should use a different injectable instance on downgraded module C',
|
||||
() => { expect(compC.getText()).toBe('Component C (Service ID: 1)'); });
|
||||
it('should use a different injectable instance on downgraded module C', () => {
|
||||
expect(compC.getText()).toBe('Component C (Service ID: 1)');
|
||||
});
|
||||
});
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Compiler, Component, Injectable, Injector, NgModule, StaticProvider, getPlatform} from '@angular/core';
|
||||
import {Compiler, Component, getPlatform, Injectable, Injector, NgModule, StaticProvider} from '@angular/core';
|
||||
import {BrowserModule} from '@angular/platform-browser';
|
||||
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
||||
import {downgradeComponent, downgradeModule} from '@angular/upgrade/static';
|
||||
@ -100,12 +100,12 @@ const getRootInjector = (extraProviders: StaticProvider[]) => {
|
||||
return rootInjectorPromise;
|
||||
};
|
||||
|
||||
const downgradedNg2AModule = downgradeModule(async(extraProviders: StaticProvider[]) => {
|
||||
const downgradedNg2AModule = downgradeModule(async (extraProviders: StaticProvider[]) => {
|
||||
const rootInjector = await getRootInjector(extraProviders);
|
||||
const moduleAFactory = await rootInjector.get(Compiler).compileModuleAsync(Ng2AModule);
|
||||
return moduleAFactory.create(rootInjector);
|
||||
});
|
||||
const downgradedNg2BModule = downgradeModule(async(extraProviders: StaticProvider[]) => {
|
||||
const downgradedNg2BModule = downgradeModule(async (extraProviders: StaticProvider[]) => {
|
||||
const rootInjector = await getRootInjector(extraProviders);
|
||||
const moduleBFactory = await rootInjector.get(Compiler).compileModuleAsync(Ng2BModule);
|
||||
return moduleBFactory.create(rootInjector);
|
||||
|
@ -7,10 +7,10 @@
|
||||
*/
|
||||
|
||||
// #docplaster
|
||||
import {Component, Directive, ElementRef, Injectable, Injector, NgModule, StaticProvider, getPlatform} from '@angular/core';
|
||||
import {Component, Directive, ElementRef, getPlatform, Injectable, Injector, NgModule, StaticProvider} from '@angular/core';
|
||||
import {BrowserModule} from '@angular/platform-browser';
|
||||
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
||||
import {UpgradeComponent, downgradeComponent, downgradeInjectable, downgradeModule} from '@angular/upgrade/static';
|
||||
import {downgradeComponent, downgradeInjectable, downgradeModule, UpgradeComponent} from '@angular/upgrade/static';
|
||||
|
||||
|
||||
declare var angular: ng.IAngularStatic;
|
||||
@ -28,12 +28,16 @@ export class Ng2AComponent {
|
||||
selector: 'ng1A',
|
||||
})
|
||||
export class Ng1AComponentFacade extends UpgradeComponent {
|
||||
constructor(elementRef: ElementRef, injector: Injector) { super('ng1A', elementRef, injector); }
|
||||
constructor(elementRef: ElementRef, injector: Injector) {
|
||||
super('ng1A', elementRef, injector);
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class Ng2AService {
|
||||
getValue() { return 'ng2'; }
|
||||
getValue() {
|
||||
return 'ng2';
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
@ -91,13 +95,17 @@ const appModule =
|
||||
<ng2-b ng-switch-when="B"></ng2-b>
|
||||
</main>
|
||||
`,
|
||||
controller: class ExampleAppController{page = 'A';},
|
||||
controller: class ExampleAppController {
|
||||
page = 'A';
|
||||
},
|
||||
})
|
||||
.component('ng1A', {
|
||||
template: 'ng1({{ $ctrl.value }})',
|
||||
controller: [
|
||||
'ng2AService', class Ng1AController{
|
||||
value = this.ng2AService.getValue(); constructor(private ng2AService: Ng2AService) {}
|
||||
'ng2AService',
|
||||
class Ng1AController {
|
||||
value = this.ng2AService.getValue();
|
||||
constructor(private ng2AService: Ng2AService) {}
|
||||
}
|
||||
],
|
||||
})
|
||||
|
@ -6,14 +6,14 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ElementFinder, by} from 'protractor';
|
||||
import {by, ElementFinder} from 'protractor';
|
||||
|
||||
declare global {
|
||||
namespace jasmine {
|
||||
interface Matchers<T> {
|
||||
toBeAHero(): Promise<void>;
|
||||
toHaveName(exectedName: string): Promise<void>;
|
||||
}
|
||||
interface Matchers<T> {
|
||||
toBeAHero(): Promise<void>;
|
||||
toHaveName(exectedName: string): Promise<void>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,43 +22,41 @@ const isTitleCased = (text: string) =>
|
||||
|
||||
export function addCustomMatchers() {
|
||||
jasmine.addMatchers({
|
||||
toBeAHero:
|
||||
() => ({
|
||||
compare(actualNg1Hero: ElementFinder | undefined) {
|
||||
const getText = (selector: string) =>
|
||||
actualNg1Hero !.element(by.css(selector)).getText();
|
||||
const result = {
|
||||
message: 'Expected undefined to be an `ng1Hero` ElementFinder.',
|
||||
pass: !!actualNg1Hero &&
|
||||
Promise.all(['.title', 'h2', 'p'].map(getText) as PromiseLike<string>[])
|
||||
.then(([actualTitle, actualName, actualDescription]) => {
|
||||
const pass = (actualTitle === 'Super Hero') && isTitleCased(actualName) &&
|
||||
(actualDescription.length > 0);
|
||||
toBeAHero: () => ({
|
||||
compare(actualNg1Hero: ElementFinder|undefined) {
|
||||
const getText = (selector: string) => actualNg1Hero!.element(by.css(selector)).getText();
|
||||
const result = {
|
||||
message: 'Expected undefined to be an `ng1Hero` ElementFinder.',
|
||||
pass: !!actualNg1Hero &&
|
||||
Promise.all(['.title', 'h2', 'p'].map(getText) as PromiseLike<string>[])
|
||||
.then(([actualTitle, actualName, actualDescription]) => {
|
||||
const pass = (actualTitle === 'Super Hero') && isTitleCased(actualName) &&
|
||||
(actualDescription.length > 0);
|
||||
|
||||
const actualHero =
|
||||
`Hero(${actualTitle}, ${actualName}, ${actualDescription})`;
|
||||
result.message =
|
||||
`Expected ${actualHero}'${pass ? ' not' : ''} to be a real hero.`;
|
||||
const actualHero = `Hero(${actualTitle}, ${actualName}, ${actualDescription})`;
|
||||
result.message =
|
||||
`Expected ${actualHero}'${pass ? ' not' : ''} to be a real hero.`;
|
||||
|
||||
return pass;
|
||||
})
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}),
|
||||
toHaveName: () => ({
|
||||
compare(actualNg1Hero: ElementFinder | undefined, expectedName: string) {
|
||||
const result = {
|
||||
message: 'Expected undefined to be an `ng1Hero` ElementFinder.',
|
||||
pass: !!actualNg1Hero && actualNg1Hero.element(by.css('h2')).getText().then(actualName => {
|
||||
return pass;
|
||||
})
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}),
|
||||
toHaveName: () => ({
|
||||
compare(actualNg1Hero: ElementFinder|undefined, expectedName: string) {
|
||||
const result = {
|
||||
message: 'Expected undefined to be an `ng1Hero` ElementFinder.',
|
||||
pass:
|
||||
!!actualNg1Hero && actualNg1Hero.element(by.css('h2')).getText().then(actualName => {
|
||||
const pass = actualName === expectedName;
|
||||
result.message =
|
||||
`Expected Hero(${actualName})${pass ? ' not' : ''} to have name '${expectedName}'.`;
|
||||
result.message = `Expected Hero(${actualName})${pass ? ' not' : ''} to have name '${
|
||||
expectedName}'.`;
|
||||
return pass;
|
||||
})
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}),
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}),
|
||||
} as any);
|
||||
}
|
||||
|
@ -6,7 +6,8 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ElementArrayFinder, ElementFinder, browser, by, element} from 'protractor';
|
||||
import {browser, by, element, ElementArrayFinder, ElementFinder} from 'protractor';
|
||||
|
||||
import {verifyNoBrowserErrors} from '../../../../../test-utils';
|
||||
|
||||
import {addCustomMatchers} from './e2e_util';
|
||||
|
@ -51,7 +51,9 @@ class HeroesService {
|
||||
return newHero;
|
||||
}
|
||||
|
||||
removeHero(hero: Hero) { this.heroes = this.heroes.filter((item: Hero) => item !== hero); }
|
||||
removeHero(hero: Hero) {
|
||||
this.heroes = this.heroes.filter((item: Hero) => item !== hero);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -103,8 +105,8 @@ class Ng2HeroesComponent {
|
||||
class Ng1HeroComponentWrapper extends UpgradeComponent {
|
||||
// The names of the input and output properties here must match the names of the
|
||||
// `<` and `&` bindings in the AngularJS component that is being wrapped.
|
||||
@Input() hero !: Hero;
|
||||
@Output() onRemove !: EventEmitter<void>;
|
||||
@Input() hero!: Hero;
|
||||
@Output() onRemove!: EventEmitter<void>;
|
||||
|
||||
constructor(elementRef: ElementRef, injector: Injector) {
|
||||
// We must pass the name of the directive as used by AngularJS to the super.
|
||||
|
Reference in New Issue
Block a user