docs(upgrade): update NgUpgrade with AoT, router, unit tests (#2803)
Followup from #2781
|
@ -15,4 +15,3 @@ protractor-helpers.js
|
||||||
**/ts/**/*.js
|
**/ts/**/*.js
|
||||||
**/js-es6*/**/*.js
|
**/js-es6*/**/*.js
|
||||||
**/ts-snippets/**/*.js
|
**/ts-snippets/**/*.js
|
||||||
!**/systemjs.config.extras.js
|
|
||||||
|
|
|
@ -23,8 +23,6 @@
|
||||||
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
|
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
|
||||||
'@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js',
|
'@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js',
|
||||||
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
|
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
|
||||||
'@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js',
|
|
||||||
'@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js',
|
|
||||||
|
|
||||||
// other libraries
|
// other libraries
|
||||||
'rxjs': 'npm:rxjs',
|
'rxjs': 'npm:rxjs',
|
||||||
|
|
|
@ -98,7 +98,7 @@ describe('Upgrade Tests', function () {
|
||||||
expect(element.all(by.css('h2')).first().getText()).toEqual('Windstorm details!');
|
expect(element.all(by.css('h2')).first().getText()).toEqual('Windstorm details!');
|
||||||
});
|
});
|
||||||
|
|
||||||
xit('has outputs', function () {
|
it('has outputs', function () {
|
||||||
element.all(by.buttonText('Delete')).first().click();
|
element.all(by.buttonText('Delete')).first().click();
|
||||||
expect(element.all(by.css('h2')).first().getText()).toEqual('Ex-Windstorm details!');
|
expect(element.all(by.css('h2')).first().getText()).toEqual('Ex-Windstorm details!');
|
||||||
});
|
});
|
||||||
|
@ -161,4 +161,22 @@ describe('Upgrade Tests', function () {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Dividing routes', function() {
|
||||||
|
|
||||||
|
beforeAll(function () {
|
||||||
|
browser.get('/index-divide-routes.html');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows ng1 routes', function () {
|
||||||
|
browser.get('/index-divide-routes.html#/villain');
|
||||||
|
expect(element(by.css('h2')).getText()).toBe('Mr. Nice - No More Mr. Nice Guy');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows ng2 routes', function () {
|
||||||
|
browser.get('/index-divide-routes.html#/hero');
|
||||||
|
expect(element(by.css('h2')).getText()).toBe('Windstorm - Specific powers of controlling winds');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
**/*.js
|
||||||
|
aot/**/*
|
||||||
|
!aot/bs-config.json
|
||||||
|
!aot/index.html
|
||||||
|
!copy-dist-files.js
|
||||||
|
!rollup-config.js
|
||||||
|
!systemjs.config.1.js
|
|
@ -0,0 +1,12 @@
|
||||||
|
// #docregion
|
||||||
|
import { HeroesService } from './heroes.service';
|
||||||
|
|
||||||
|
export function heroesServiceFactory(i: any) {
|
||||||
|
return i.get('heroes');
|
||||||
|
}
|
||||||
|
|
||||||
|
export const heroesServiceProvider = {
|
||||||
|
provide: HeroesService,
|
||||||
|
useFactory: heroesServiceFactory,
|
||||||
|
deps: ['$injector']
|
||||||
|
};
|
|
@ -6,18 +6,17 @@ import { UpgradeModule, downgradeComponent } from '@angular/upgrade/static';
|
||||||
|
|
||||||
import { HeroDetailComponent } from './hero-detail.component';
|
import { HeroDetailComponent } from './hero-detail.component';
|
||||||
import { HeroesService } from './heroes.service';
|
import { HeroesService } from './heroes.service';
|
||||||
|
|
||||||
// #docregion register
|
// #docregion register
|
||||||
|
import { heroesServiceProvider } from './ajs-upgraded-providers';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
UpgradeModule
|
UpgradeModule
|
||||||
],
|
],
|
||||||
providers: [{
|
providers: [
|
||||||
provide: 'heroes',
|
heroesServiceProvider
|
||||||
useFactory: (i: any) => i.get('heroes'),
|
],
|
||||||
deps: ['$injector']
|
|
||||||
}],
|
|
||||||
// #enddocregion register
|
// #enddocregion register
|
||||||
declarations: [
|
declarations: [
|
||||||
HeroDetailComponent
|
HeroDetailComponent
|
||||||
|
@ -39,7 +38,6 @@ angular.module('heroApp', [])
|
||||||
downgradeComponent({component: HeroDetailComponent}) as angular.IDirectiveFactory
|
downgradeComponent({component: HeroDetailComponent}) as angular.IDirectiveFactory
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
|
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
|
||||||
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
|
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
|
||||||
upgrade.bootstrap(document.body, ['heroApp'], {strictDi: true});
|
upgrade.bootstrap(document.body, ['heroApp'], {strictDi: true});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// #docregion
|
// #docregion
|
||||||
import { Component, Inject } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { HeroesService } from './heroes.service';
|
import { HeroesService } from './heroes.service';
|
||||||
import { Hero } from '../hero';
|
import { Hero } from '../hero';
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import { Hero } from '../hero';
|
||||||
})
|
})
|
||||||
export class HeroDetailComponent {
|
export class HeroDetailComponent {
|
||||||
hero: Hero;
|
hero: Hero;
|
||||||
constructor(@Inject('heroes') heroes: HeroesService) {
|
constructor(heroes: HeroesService) {
|
||||||
this.hero = heroes.get()[0];
|
this.hero = heroes.get()[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
// #docregion
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-app',
|
||||||
|
template: `
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
<div ng-view></div>
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
export class AppComponent { }
|
|
@ -0,0 +1,62 @@
|
||||||
|
// #docregion
|
||||||
|
declare var angular: angular.IAngularStatic;
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { UpgradeModule } from '@angular/upgrade/static';
|
||||||
|
|
||||||
|
import { HeroModule } from './hero.module';
|
||||||
|
|
||||||
|
// #docregion router-config
|
||||||
|
import { HashLocationStrategy, LocationStrategy } from '@angular/common';
|
||||||
|
import { RouterModule, UrlHandlingStrategy, UrlTree } from '@angular/router';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
|
class HybridUrlHandlingStrategy implements UrlHandlingStrategy {
|
||||||
|
// use only process the `/hero` url
|
||||||
|
shouldProcessUrl(url: UrlTree) { return url.toString().startsWith('/hero'); }
|
||||||
|
extract(url: UrlTree) { return url; }
|
||||||
|
merge(url: UrlTree, whole: UrlTree) { return url; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
UpgradeModule,
|
||||||
|
HeroModule,
|
||||||
|
RouterModule.forRoot([])
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
// use hash location strategy
|
||||||
|
{ provide: LocationStrategy, useClass: HashLocationStrategy },
|
||||||
|
// use custom url handling strategy
|
||||||
|
{ provide: UrlHandlingStrategy, useClass: HybridUrlHandlingStrategy }
|
||||||
|
],
|
||||||
|
declarations: [ AppComponent ],
|
||||||
|
bootstrap: [ AppComponent ]
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
||||||
|
// #enddocregion router-config
|
||||||
|
|
||||||
|
import { Villain } from '../villain';
|
||||||
|
|
||||||
|
export const villainDetail = {
|
||||||
|
template: `
|
||||||
|
<h1>Villain detail</h1>
|
||||||
|
<h2>{{$ctrl.villain.name}} - {{$ctrl.villain.description}}</h2>
|
||||||
|
`,
|
||||||
|
controller: function() {
|
||||||
|
this.villain = new Villain(1, 'Mr. Nice', 'No More Mr. Nice Guy');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
angular.module('heroApp', ['ngRoute'])
|
||||||
|
.component('villainDetail', villainDetail)
|
||||||
|
.config(['$locationProvider', '$routeProvider',
|
||||||
|
function config($locationProvider: angular.ILocationProvider,
|
||||||
|
$routeProvider: angular.route.IRouteProvider) {
|
||||||
|
// #docregion ajs-route
|
||||||
|
$routeProvider
|
||||||
|
.when('/villain', { template: '<villain-detail></villain-detail>' });
|
||||||
|
// #enddocregion ajs-route
|
||||||
|
}
|
||||||
|
]);
|
|
@ -0,0 +1,32 @@
|
||||||
|
// #docregion
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { Hero } from '../hero';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: `
|
||||||
|
<h1>Hero detail</h1>
|
||||||
|
<h2>{{hero.name}} - {{hero.description}}</h2>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
export class HeroDetailComponent {
|
||||||
|
hero = new Hero(1, 'Windstorm', 'Specific powers of controlling winds');
|
||||||
|
}
|
||||||
|
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
// #docregion a-route
|
||||||
|
RouterModule.forChild([
|
||||||
|
{ path: 'hero', children: [
|
||||||
|
{ path: '', component: HeroDetailComponent },
|
||||||
|
] },
|
||||||
|
])
|
||||||
|
// #enddocregion a-route
|
||||||
|
],
|
||||||
|
declarations: [ HeroDetailComponent ]
|
||||||
|
})
|
||||||
|
export class HeroModule {}
|
|
@ -0,0 +1,10 @@
|
||||||
|
// #docregion
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
import { UpgradeModule } from '@angular/upgrade/static';
|
||||||
|
|
||||||
|
import { AppModule } from './app.module';
|
||||||
|
|
||||||
|
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
|
||||||
|
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
|
||||||
|
upgrade.bootstrap(document.body, ['heroApp'], {strictDi: true});
|
||||||
|
});
|
|
@ -0,0 +1,5 @@
|
||||||
|
export class Villain {
|
||||||
|
constructor(public id: number,
|
||||||
|
public name: string,
|
||||||
|
public description?: string) { }
|
||||||
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
<script>
|
<script>
|
||||||
System.import('app/a-to-ajs-providers/app.module')
|
System.import('app/a-to-ajs-providers/app.module')
|
||||||
.then(null, console.error.bind(console));
|
.then(null, console.error.bind(console));
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
<script>
|
<script>
|
||||||
System.import('app/a-to-ajs-transclusion/app.module')
|
System.import('app/a-to-ajs-transclusion/app.module')
|
||||||
.then(null, console.error.bind(console));
|
.then(null, console.error.bind(console));
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
<script>
|
<script>
|
||||||
System.import('app/ajs-a-hybrid-bootstrap/app.module')
|
System.import('app/ajs-a-hybrid-bootstrap/app.module')
|
||||||
.then(null, console.error.bind(console));
|
.then(null, console.error.bind(console));
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
<script>
|
<script>
|
||||||
System.import('app/ajs-to-a-projection/app.module')
|
System.import('app/ajs-to-a-projection/app.module')
|
||||||
.then(null, console.error.bind(console));
|
.then(null, console.error.bind(console));
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
<script>
|
<script>
|
||||||
System.import('app/ajs-to-a-providers/app.module')
|
System.import('app/ajs-to-a-providers/app.module')
|
||||||
.then(null, console.error.bind(console));
|
.then(null, console.error.bind(console));
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Angular 2 Upgrade</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
|
||||||
|
<script src="https://code.angularjs.org/1.5.5/angular.js"></script>
|
||||||
|
<script src="https://code.angularjs.org/1.5.5/angular-route.js"></script>
|
||||||
|
|
||||||
|
<!-- Polyfills for older browsers -->
|
||||||
|
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||||
|
|
||||||
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
|
<script src="node_modules/reflect-metadata/Reflect.js"></script>
|
||||||
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
|
<script src="systemjs.config.1.js"></script>
|
||||||
|
<script>
|
||||||
|
System.import('app/divide-routes/main')
|
||||||
|
.then(null, console.error.bind(console));
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<!--#docregion body-->
|
||||||
|
<body>
|
||||||
|
<my-app>Loading...</my-app>
|
||||||
|
</body>
|
||||||
|
<!--#enddocregion body-->
|
||||||
|
</html>
|
|
@ -15,7 +15,7 @@
|
||||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
<script>
|
<script>
|
||||||
System.import('app/downgrade-io/app.module')
|
System.import('app/downgrade-io/app.module')
|
||||||
.then(null, console.error.bind(console));
|
.then(null, console.error.bind(console));
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
<script>
|
<script>
|
||||||
System.import('app/downgrade-static/app.module')
|
System.import('app/downgrade-static/app.module')
|
||||||
.then(null, console.error.bind(console));
|
.then(null, console.error.bind(console));
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
<script>
|
<script>
|
||||||
System.import('app/upgrade-io/app.module')
|
System.import('app/upgrade-io/app.module')
|
||||||
.then(null, console.error.bind(console));
|
.then(null, console.error.bind(console));
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
<script>
|
<script>
|
||||||
System.import('app/upgrade-static/app.module')
|
System.import('app/upgrade-static/app.module')
|
||||||
.then(null, console.error.bind(console));
|
.then(null, console.error.bind(console));
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* System configuration for Angular samples
|
||||||
|
* Adjust as necessary for your application needs.
|
||||||
|
*/
|
||||||
|
(function (global) {
|
||||||
|
System.config({
|
||||||
|
paths: {
|
||||||
|
// paths serve as alias
|
||||||
|
'npm:': 'node_modules/'
|
||||||
|
},
|
||||||
|
// map tells the System loader where to look for things
|
||||||
|
map: {
|
||||||
|
// our app is within the app folder
|
||||||
|
app: 'app',
|
||||||
|
// angular bundles
|
||||||
|
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
|
||||||
|
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
|
||||||
|
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
|
||||||
|
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
|
||||||
|
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
|
||||||
|
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
|
||||||
|
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
|
||||||
|
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
|
||||||
|
// #docregion upgrade-static-umd
|
||||||
|
'@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js',
|
||||||
|
// #enddocregion upgrade-static-umd
|
||||||
|
|
||||||
|
// other libraries
|
||||||
|
'rxjs': 'npm:rxjs',
|
||||||
|
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
|
||||||
|
},
|
||||||
|
// packages tells the System loader how to load when no filename and/or no extension
|
||||||
|
packages: {
|
||||||
|
app: {
|
||||||
|
main: './main.js',
|
||||||
|
defaultExtension: 'js'
|
||||||
|
},
|
||||||
|
rxjs: {
|
||||||
|
defaultExtension: 'js'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})(this);
|
|
@ -16,6 +16,7 @@
|
||||||
"compileOnSave": true,
|
"compileOnSave": true,
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules/*",
|
"node_modules/*",
|
||||||
"**/*-aot.ts"
|
"**/*-aot.ts",
|
||||||
|
"aot/**/*"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ describe('PhoneCat Application', function() {
|
||||||
expect(browser.getLocationAbsUrl()).toBe('/phones');
|
expect(browser.getLocationAbsUrl()).toBe('/phones');
|
||||||
});
|
});
|
||||||
|
|
||||||
xdescribe('View: Phone list', function() {
|
describe('View: Phone list', function() {
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
browser.get('index.html#!/phones');
|
browser.get('index.html#!/phones');
|
||||||
|
@ -75,7 +75,7 @@ describe('PhoneCat Application', function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
xdescribe('View: Phone detail', function() {
|
describe('View: Phone detail', function() {
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
browser.get('index.html#!/phones/nexus-s');
|
browser.get('index.html#!/phones/nexus-s');
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
aot/**/*.ts
|
aot/**/*
|
||||||
**/*.ngfactory.ts
|
!aot/index.html
|
||||||
**/*.ngsummary.json
|
|
||||||
**/*.metadata.json
|
|
||||||
**/*.js
|
|
||||||
dist
|
dist
|
||||||
!app/tsconfig.json
|
!app/tsconfig.json
|
||||||
!rollup-config.js
|
!rollup-config.js
|
||||||
!karma.conf.ajs.js
|
!karma.conf.ajs.js
|
||||||
|
!copy-dist-files.js
|
||||||
|
!systemjs.config.1.js
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
<!-- #docregion -->
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
|
||||||
|
<base href="/app/">
|
||||||
|
|
||||||
|
<title>Google Phone Gallery</title>
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
|
||||||
|
<link rel="stylesheet" href="app.css" />
|
||||||
|
<link rel="stylesheet" href="app.animations.css" />
|
||||||
|
|
||||||
|
<script src="https://code.jquery.com/jquery-2.2.4.js"></script>
|
||||||
|
<script src="https://code.angularjs.org/1.5.5/angular.js"></script>
|
||||||
|
<script src="https://code.angularjs.org/1.5.5/angular-animate.js"></script>
|
||||||
|
<script src="https://code.angularjs.org/1.5.5/angular-resource.js"></script>
|
||||||
|
<script src="https://code.angularjs.org/1.5.5/angular-route.js"></script>
|
||||||
|
|
||||||
|
<script src="app.module.ajs.js"></script>
|
||||||
|
<script src="app.config.js"></script>
|
||||||
|
<script src="app.animations.js"></script>
|
||||||
|
<script src="core/core.module.js"></script>
|
||||||
|
<script src="core/phone/phone.module.js"></script>
|
||||||
|
<script src="phone-list/phone-list.module.js"></script>
|
||||||
|
<script src="phone-detail/phone-detail.module.js"></script>
|
||||||
|
|
||||||
|
<script src="/node_modules/core-js/client/shim.min.js"></script>
|
||||||
|
<script src="/node_modules/zone.js/dist/zone.min.js"></script>
|
||||||
|
|
||||||
|
<script>window.module = 'aot';</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="view-container">
|
||||||
|
<div ng-view class="view-frame"></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script src="/dist/build.js"></script>
|
||||||
|
</html>
|
|
@ -0,0 +1,14 @@
|
||||||
|
// #docregion
|
||||||
|
export abstract class RouteParams {
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function routeParamsFactory(i: any) {
|
||||||
|
return i.get('$routeParams');
|
||||||
|
}
|
||||||
|
|
||||||
|
export const routeParamsProvider = {
|
||||||
|
provide: RouteParams,
|
||||||
|
useFactory: routeParamsFactory,
|
||||||
|
deps: ['$injector']
|
||||||
|
};
|
|
@ -21,6 +21,9 @@ import { CheckmarkPipe } from './core/checkmark/checkmark.pipe';
|
||||||
// #docregion phonelist
|
// #docregion phonelist
|
||||||
import { PhoneListComponent } from './phone-list/phone-list.component';
|
import { PhoneListComponent } from './phone-list/phone-list.component';
|
||||||
// #enddocregion phonelist
|
// #enddocregion phonelist
|
||||||
|
// #docregion routeparams
|
||||||
|
import { routeParamsProvider } from './ajs-upgraded-providers';
|
||||||
|
// #enddocregion routeparams
|
||||||
// #docregion phonedetail
|
// #docregion phonedetail
|
||||||
import { PhoneDetailComponent } from './phone-detail/phone-detail.component';
|
import { PhoneDetailComponent } from './phone-detail/phone-detail.component';
|
||||||
// #enddocregion phonedetail
|
// #enddocregion phonedetail
|
||||||
|
@ -57,11 +60,7 @@ import { PhoneDetailComponent } from './phone-detail/phone-detail.component';
|
||||||
providers: [
|
providers: [
|
||||||
Phone,
|
Phone,
|
||||||
// #enddocregion phone
|
// #enddocregion phone
|
||||||
{
|
routeParamsProvider
|
||||||
provide: '$routeParams',
|
|
||||||
useFactory: routeParamsFactory,
|
|
||||||
deps: ['$injector']
|
|
||||||
}
|
|
||||||
// #docregion phone
|
// #docregion phone
|
||||||
]
|
]
|
||||||
// #enddocregion routeparams
|
// #enddocregion routeparams
|
||||||
|
@ -73,9 +72,3 @@ export class AppModule {
|
||||||
// #docregion bare
|
// #docregion bare
|
||||||
}
|
}
|
||||||
// #enddocregion bare, upgrademodule, httpmodule, phone, phonelist, phonedetail, checkmarkpipe
|
// #enddocregion bare, upgrademodule, httpmodule, phone, phonelist, phonedetail, checkmarkpipe
|
||||||
|
|
||||||
// #docregion routeparams
|
|
||||||
export function routeParamsFactory(i: any) {
|
|
||||||
return i.get('$routeParams');
|
|
||||||
}
|
|
||||||
// #enddocregion routeparams
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// #docregion bootstrap
|
// #docregion
|
||||||
import { platformBrowser } from '@angular/platform-browser';
|
import { platformBrowser } from '@angular/platform-browser';
|
||||||
import { UpgradeModule } from '@angular/upgrade/static';
|
import { UpgradeModule } from '@angular/upgrade/static';
|
||||||
|
|
||||||
|
@ -8,4 +8,3 @@ platformBrowser().bootstrapModuleFactory(AppModuleNgFactory).then(platformRef =>
|
||||||
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
|
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
|
||||||
upgrade.bootstrap(document.documentElement, ['phonecatApp']);
|
upgrade.bootstrap(document.documentElement, ['phonecatApp']);
|
||||||
});
|
});
|
||||||
// #enddocregion bootstrap
|
|
||||||
|
|
|
@ -4,11 +4,11 @@ declare var angular: angular.IAngularStatic;
|
||||||
import { downgradeComponent } from '@angular/upgrade/static';
|
import { downgradeComponent } from '@angular/upgrade/static';
|
||||||
|
|
||||||
// #docregion initialclass
|
// #docregion initialclass
|
||||||
import { Component, Inject } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
import { Phone, PhoneData } from '../core/phone/phone.service';
|
import { Phone, PhoneData } from '../core/phone/phone.service';
|
||||||
// #enddocregion initialclass
|
// #enddocregion initialclass
|
||||||
// #docregion checkmark-pipe
|
import { RouteParams } from '../ajs-upgraded-providers';
|
||||||
|
|
||||||
// #docregion initialclass
|
// #docregion initialclass
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -18,13 +18,12 @@ import { Phone, PhoneData } from '../core/phone/phone.service';
|
||||||
// #enddocregion initialclass
|
// #enddocregion initialclass
|
||||||
// #docregion initialclass
|
// #docregion initialclass
|
||||||
})
|
})
|
||||||
// #enddocregion checkmark-pipe
|
|
||||||
export class PhoneDetailComponent {
|
export class PhoneDetailComponent {
|
||||||
phone: PhoneData;
|
phone: PhoneData;
|
||||||
mainImageUrl: string;
|
mainImageUrl: string;
|
||||||
|
|
||||||
constructor(@Inject('$routeParams') $routeParams: any, phone: Phone) {
|
constructor(routeParams: RouteParams, phone: Phone) {
|
||||||
phone.get($routeParams['phoneId']).subscribe(phone => {
|
phone.get(routeParams['phoneId']).subscribe(phone => {
|
||||||
this.phone = phone;
|
this.phone = phone;
|
||||||
this.setImage(phone.images[0]);
|
this.setImage(phone.images[0]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"open": false,
|
||||||
|
"logLevel": "silent",
|
||||||
|
"port": 8080,
|
||||||
|
"server": {
|
||||||
|
"baseDir": "aot",
|
||||||
|
"routes": {
|
||||||
|
"/node_modules": "node_modules"
|
||||||
|
},
|
||||||
|
"middleware": {
|
||||||
|
"0": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
// #docregion
|
||||||
|
var fsExtra = require('fs-extra');
|
||||||
|
var resources = [
|
||||||
|
// polyfills
|
||||||
|
'node_modules/core-js/client/shim.min.js',
|
||||||
|
'node_modules/zone.js/dist/zone.min.js',
|
||||||
|
// css
|
||||||
|
'app/app.css',
|
||||||
|
'app/app.animations.css',
|
||||||
|
// images and json files
|
||||||
|
'app/img/',
|
||||||
|
'app/phones/',
|
||||||
|
// app files
|
||||||
|
'app/app.module.ajs.js',
|
||||||
|
'app/app.config.js',
|
||||||
|
'app/app.animations.js',
|
||||||
|
'app/core/core.module.js',
|
||||||
|
'app/core/phone/phone.module.js',
|
||||||
|
'app/phone-list/phone-list.module.js',
|
||||||
|
'app/phone-detail/phone-detail.module.js'
|
||||||
|
];
|
||||||
|
resources.map(function(sourcePath) {
|
||||||
|
var destPath = `aot/${sourcePath}`;
|
||||||
|
fsExtra.copySync(sourcePath, destPath);
|
||||||
|
});
|
|
@ -22,8 +22,9 @@
|
||||||
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
|
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
|
||||||
'@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js',
|
'@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js',
|
||||||
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
|
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
|
||||||
'@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js',
|
// #docregion paths
|
||||||
'@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js',
|
'@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js',
|
||||||
|
// #enddocregion paths
|
||||||
|
|
||||||
// other libraries
|
// other libraries
|
||||||
'rxjs': 'npm:rxjs',
|
'rxjs': 'npm:rxjs',
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
|
"lib": ["es2015", "dom"],
|
||||||
"removeComments": false,
|
"removeComments": false,
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"suppressImplicitAnyIndexErrors": true,
|
"suppressImplicitAnyIndexErrors": true,
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
This is the Angular Phonecat application adjusted to fit our boilerplate project
|
||||||
|
structure.
|
||||||
|
|
||||||
|
The following changes from vanilla Phonecat are applied:
|
||||||
|
|
||||||
|
* Karma config for unit tests is in karma.conf.ng1.js because the boilerplate
|
||||||
|
Karma config is not compatible with the way Angular 1 tests need to be run.
|
||||||
|
The shell script run-unit-tests.sh can be used to run the unit tests.
|
||||||
|
* There's a `package.ng1.json`, which is not used to run anything but only to
|
||||||
|
show an example of changing the PhoneCat http-server root path.
|
||||||
|
* Also for the Karma shim, there is a `karma-test-shim.1.js` file which isn't
|
||||||
|
used but is shown in the test appendix.
|
||||||
|
* Instead of using Bower, Angular 1 and its dependencies are fetched from a CDN
|
||||||
|
in index.html and karma.conf.ng1.js.
|
||||||
|
* E2E tests have been moved to the parent directory, where `run-e2e-tests` can
|
||||||
|
discover and run them along with all the other examples.
|
||||||
|
* Most of the phone JSON and image data removed in the interest of keeping
|
||||||
|
repo weight down. Keeping enough to retain testability of the app.
|
||||||
|
|
||||||
|
## Running the app
|
||||||
|
|
||||||
|
Start like any example
|
||||||
|
|
||||||
|
npm run start
|
||||||
|
|
||||||
|
## Running unit tests
|
||||||
|
|
||||||
|
./run-unit-tests.sh
|
||||||
|
|
||||||
|
## Running E2E tests
|
||||||
|
|
||||||
|
Like for any example (at the project root):
|
||||||
|
|
||||||
|
gulp run-e2e-tests --filter=phonecat-2
|
|
@ -0,0 +1,107 @@
|
||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
|
import { browser, element, by } from 'protractor';
|
||||||
|
import { setProtractorToHybridMode } from '../protractor-helpers';
|
||||||
|
|
||||||
|
// Angular E2E Testing Guide:
|
||||||
|
// https://docs.angularjs.org/guide/e2e-testing
|
||||||
|
|
||||||
|
describe('PhoneCat Application', function() {
|
||||||
|
|
||||||
|
beforeAll(function () {
|
||||||
|
setProtractorToHybridMode();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should redirect `index.html` to `index.html#!/phones', function() {
|
||||||
|
browser.get('index.html');
|
||||||
|
expect(browser.getLocationAbsUrl()).toBe('/phones');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('View: Phone list', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
browser.get('index.html#!/phones');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should filter the phone list as a user types into the search box', function() {
|
||||||
|
let phoneList = element.all(by.css('.phones li'));
|
||||||
|
let query = element(by.css('input'));
|
||||||
|
|
||||||
|
expect(phoneList.count()).toBe(20);
|
||||||
|
|
||||||
|
query.sendKeys('nexus');
|
||||||
|
expect(phoneList.count()).toBe(1);
|
||||||
|
|
||||||
|
query.clear();
|
||||||
|
query.sendKeys('motorola');
|
||||||
|
expect(phoneList.count()).toBe(8);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be possible to control phone order via the drop-down menu', function() {
|
||||||
|
let queryField = element(by.css('input'));
|
||||||
|
let orderSelect = element(by.css('select'));
|
||||||
|
let nameOption = orderSelect.element(by.css('option[value="name"]'));
|
||||||
|
let phoneNameColumn = element.all(by.css('.phones .name'));
|
||||||
|
|
||||||
|
function getNames() {
|
||||||
|
return phoneNameColumn.map(function(elem) {
|
||||||
|
return elem.getText();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
queryField.sendKeys('tablet'); // Let's narrow the dataset to make the assertions shorter
|
||||||
|
|
||||||
|
expect(getNames()).toEqual([
|
||||||
|
'Motorola XOOM\u2122 with Wi-Fi',
|
||||||
|
'MOTOROLA XOOM\u2122'
|
||||||
|
]);
|
||||||
|
|
||||||
|
nameOption.click();
|
||||||
|
|
||||||
|
expect(getNames()).toEqual([
|
||||||
|
'MOTOROLA XOOM\u2122',
|
||||||
|
'Motorola XOOM\u2122 with Wi-Fi'
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render phone specific links', function() {
|
||||||
|
let query = element(by.css('input'));
|
||||||
|
query.sendKeys('nexus');
|
||||||
|
|
||||||
|
element.all(by.css('.phones li a')).first().click();
|
||||||
|
browser.sleep(200); // Not sure why this is needed but it is. The route change works fine.
|
||||||
|
expect(browser.getLocationAbsUrl()).toBe('/phones/nexus-s');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('View: Phone detail', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
browser.get('index.html#!/phones/nexus-s');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display the `nexus-s` page', function() {
|
||||||
|
expect(element(by.css('h1')).getText()).toBe('Nexus S');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display the first phone image as the main phone image', function() {
|
||||||
|
let mainImage = element(by.css('img.phone.selected'));
|
||||||
|
|
||||||
|
expect(mainImage.getAttribute('src')).toMatch(/img\/phones\/nexus-s.0.jpg/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should swap the main image when clicking on a thumbnail image', function() {
|
||||||
|
let mainImage = element(by.css('img.phone.selected'));
|
||||||
|
let thumbnails = element.all(by.css('.phone-thumbs img'));
|
||||||
|
|
||||||
|
thumbnails.get(2).click();
|
||||||
|
expect(mainImage.getAttribute('src')).toMatch(/img\/phones\/nexus-s.2.jpg/);
|
||||||
|
|
||||||
|
thumbnails.get(0).click();
|
||||||
|
expect(mainImage.getAttribute('src')).toMatch(/img\/phones\/nexus-s.0.jpg/);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,7 @@
|
||||||
|
**/*.js
|
||||||
|
aot/**/*
|
||||||
|
!aot/bs-config.json
|
||||||
|
!aot/index.html
|
||||||
|
!copy-dist-files.js
|
||||||
|
!rollup-config.js
|
||||||
|
!systemjs.config.1.js
|
|
@ -1,12 +1,15 @@
|
||||||
<!-- #docregion -->
|
<!-- #docregion -->
|
||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html>
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<base href="/">
|
<meta charset="utf-8">
|
||||||
<title>Angular Tour of Heroes</title>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="styles.css">
|
<base href="/app/">
|
||||||
|
|
||||||
|
<title>Google Phone Gallery</title>
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
|
||||||
|
<link rel="stylesheet" href="app.css" />
|
||||||
|
<link rel="stylesheet" href="app.animations.css" />
|
||||||
|
|
||||||
<script src="https://code.jquery.com/jquery-2.2.4.js"></script>
|
<script src="https://code.jquery.com/jquery-2.2.4.js"></script>
|
||||||
<script src="https://code.angularjs.org/1.5.5/angular.js"></script>
|
<script src="https://code.angularjs.org/1.5.5/angular.js"></script>
|
||||||
|
@ -14,7 +17,7 @@
|
||||||
<script src="https://code.angularjs.org/1.5.5/angular-resource.js"></script>
|
<script src="https://code.angularjs.org/1.5.5/angular-resource.js"></script>
|
||||||
<script src="https://code.angularjs.org/1.5.5/angular-route.js"></script>
|
<script src="https://code.angularjs.org/1.5.5/angular-route.js"></script>
|
||||||
|
|
||||||
<script src="app.module.ng1.js"></script>
|
<script src="app.module.ajs.js"></script>
|
||||||
<script src="app.config.js"></script>
|
<script src="app.config.js"></script>
|
||||||
<script src="app.animations.js"></script>
|
<script src="app.animations.js"></script>
|
||||||
<script src="core/core.module.js"></script>
|
<script src="core/core.module.js"></script>
|
||||||
|
@ -22,15 +25,14 @@
|
||||||
<script src="phone-list/phone-list.module.js"></script>
|
<script src="phone-list/phone-list.module.js"></script>
|
||||||
<script src="phone-detail/phone-detail.module.js"></script>
|
<script src="phone-detail/phone-detail.module.js"></script>
|
||||||
|
|
||||||
<script src="shim.min.js"></script>
|
<script src="/node_modules/core-js/client/shim.min.js"></script>
|
||||||
<script src="zone.min.js"></script>
|
<script src="/node_modules/zone.js/dist/zone.min.js"></script>
|
||||||
<!-- #docregion moduleId -->
|
|
||||||
<script>window.module = 'aot';</script>
|
<script>window.module = 'aot';</script>
|
||||||
<!-- #enddocregion moduleId -->
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<my-app>Loading...</my-app>
|
<phonecat-app></phonecat-app>
|
||||||
</body>
|
</body>
|
||||||
<script src="dist/build.js"></script>
|
<script src="/dist/build.js"></script>
|
||||||
</html>
|
</html>
|
|
@ -0,0 +1,14 @@
|
||||||
|
// #docregion
|
||||||
|
export abstract class RouteParams {
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function routeParamsFactory(i: any) {
|
||||||
|
return i.get('$routeParams');
|
||||||
|
}
|
||||||
|
|
||||||
|
export const routeParamsProvider = {
|
||||||
|
provide: RouteParams,
|
||||||
|
useFactory: routeParamsFactory,
|
||||||
|
deps: ['$injector']
|
||||||
|
};
|
|
@ -0,0 +1,30 @@
|
||||||
|
// #docregion
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { Routes, RouterModule, UrlHandlingStrategy, UrlTree } from '@angular/router';
|
||||||
|
import { APP_BASE_HREF, HashLocationStrategy, LocationStrategy } from '@angular/common';
|
||||||
|
|
||||||
|
import { PhoneListComponent } from './phone-list/phone-list.component';
|
||||||
|
|
||||||
|
export class Ng1Ng2UrlHandlingStrategy implements UrlHandlingStrategy {
|
||||||
|
shouldProcessUrl(url: UrlTree) {
|
||||||
|
return url.toString() === '/' || url.toString() === '/phones';
|
||||||
|
}
|
||||||
|
extract(url: UrlTree) { return url; }
|
||||||
|
merge(url: UrlTree, whole: UrlTree) { return url; }
|
||||||
|
}
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{ path: '', redirectTo: 'phones', pathMatch: 'full' },
|
||||||
|
{ path: 'phones', component: PhoneListComponent }
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [ RouterModule.forRoot(routes) ],
|
||||||
|
exports: [ RouterModule ],
|
||||||
|
providers: [
|
||||||
|
{ provide: APP_BASE_HREF, useValue: '!' },
|
||||||
|
{ provide: LocationStrategy, useClass: HashLocationStrategy },
|
||||||
|
{ provide: UrlHandlingStrategy, useClass: Ng1Ng2UrlHandlingStrategy }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class AppRoutingModule { }
|
|
@ -0,0 +1,67 @@
|
||||||
|
/* Animate `ngRepeat` in `phoneList` component */
|
||||||
|
.phone-list-item.ng-enter,
|
||||||
|
.phone-list-item.ng-leave,
|
||||||
|
.phone-list-item.ng-move {
|
||||||
|
overflow: hidden;
|
||||||
|
transition: 0.5s linear all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-list-item.ng-enter,
|
||||||
|
.phone-list-item.ng-leave.ng-leave-active,
|
||||||
|
.phone-list-item.ng-move {
|
||||||
|
height: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
opacity: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-list-item.ng-enter.ng-enter-active,
|
||||||
|
.phone-list-item.ng-leave,
|
||||||
|
.phone-list-item.ng-move.ng-move-active {
|
||||||
|
height: 120px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
opacity: 1;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
padding-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animate view transitions with `ngView` */
|
||||||
|
.view-container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-frame {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-frame.ng-enter,
|
||||||
|
.view-frame.ng-leave {
|
||||||
|
background: white;
|
||||||
|
left: 0;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-frame.ng-enter {
|
||||||
|
animation: 1s fade-in;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-frame.ng-leave {
|
||||||
|
animation: 1s fade-out;
|
||||||
|
z-index: 99;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade-in {
|
||||||
|
from { opacity: 0; }
|
||||||
|
to { opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade-out {
|
||||||
|
from { opacity: 1; }
|
||||||
|
to { opacity: 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Older browsers might need vendor-prefixes for keyframes and animation! */
|
|
@ -0,0 +1,43 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.
|
||||||
|
module('phonecatApp').
|
||||||
|
animation('.phone', function phoneAnimationFactory() {
|
||||||
|
return {
|
||||||
|
addClass: animateIn,
|
||||||
|
removeClass: animateOut
|
||||||
|
};
|
||||||
|
|
||||||
|
function animateIn(element: JQuery, className: string, done: () => void) {
|
||||||
|
if (className !== 'selected') { return; }
|
||||||
|
|
||||||
|
element.css({
|
||||||
|
display: 'block',
|
||||||
|
position: 'absolute',
|
||||||
|
top: 500,
|
||||||
|
left: 0
|
||||||
|
}).animate({
|
||||||
|
top: 0
|
||||||
|
}, done);
|
||||||
|
|
||||||
|
return function animateInEnd(wasCanceled: boolean) {
|
||||||
|
if (wasCanceled) { element.stop(); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function animateOut(element: JQuery, className: string, done: () => void) {
|
||||||
|
if (className !== 'selected') { return; }
|
||||||
|
|
||||||
|
element.css({
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0
|
||||||
|
}).animate({
|
||||||
|
top: -500
|
||||||
|
}, done);
|
||||||
|
|
||||||
|
return function animateOutEnd(wasCanceled: boolean) {
|
||||||
|
if (wasCanceled) { element.stop(); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,13 @@
|
||||||
|
// #docregion
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'phonecat-app',
|
||||||
|
template: `
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
<div class="view-container">
|
||||||
|
<div ng-view class="view-frame"></div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
export class AppComponent { }
|
|
@ -0,0 +1,16 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.
|
||||||
|
module('phonecatApp').
|
||||||
|
config(['$locationProvider', '$routeProvider',
|
||||||
|
function config($locationProvider: angular.ILocationProvider,
|
||||||
|
$routeProvider: angular.route.IRouteProvider) {
|
||||||
|
$locationProvider.hashPrefix('!');
|
||||||
|
// #docregion ajs-routes
|
||||||
|
$routeProvider
|
||||||
|
.when('/phones/:phoneId', {
|
||||||
|
template: '<phone-detail></phone-detail>'
|
||||||
|
});
|
||||||
|
// #enddocregion ajs-routes
|
||||||
|
}
|
||||||
|
]);
|
|
@ -0,0 +1,11 @@
|
||||||
|
// #docregion
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// Define the `phonecatApp` Angular 1 module
|
||||||
|
angular.module('phonecatApp', [
|
||||||
|
'ngAnimate',
|
||||||
|
'ngRoute',
|
||||||
|
'core',
|
||||||
|
'phoneDetail',
|
||||||
|
'phoneList',
|
||||||
|
]);
|
|
@ -0,0 +1,42 @@
|
||||||
|
// #docregion
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { UpgradeModule } from '@angular/upgrade/static';
|
||||||
|
import { HttpModule } from '@angular/http';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
import { Phone } from './core/phone/phone.service';
|
||||||
|
import { CheckmarkPipe } from './core/checkmark/checkmark.pipe';
|
||||||
|
import { PhoneListComponent } from './phone-list/phone-list.component';
|
||||||
|
import { PhoneDetailComponent } from './phone-detail/phone-detail.component';
|
||||||
|
import { routeParamsProvider } from './ajs-upgraded-providers';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
UpgradeModule,
|
||||||
|
HttpModule,
|
||||||
|
FormsModule,
|
||||||
|
AppRoutingModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
AppComponent,
|
||||||
|
PhoneListComponent,
|
||||||
|
PhoneDetailComponent,
|
||||||
|
CheckmarkPipe
|
||||||
|
],
|
||||||
|
entryComponents: [
|
||||||
|
PhoneListComponent,
|
||||||
|
PhoneDetailComponent
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
Phone,
|
||||||
|
routeParamsProvider
|
||||||
|
],
|
||||||
|
// #docregion bootstrap
|
||||||
|
bootstrap: [ AppComponent ]
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
||||||
|
// #enddocregion bootstrap
|
|
@ -0,0 +1,11 @@
|
||||||
|
// #docregion
|
||||||
|
import { CheckmarkPipe } from './checkmark.pipe';
|
||||||
|
|
||||||
|
describe('CheckmarkPipe', function() {
|
||||||
|
|
||||||
|
it('should convert boolean values to unicode checkmark or cross', function () {
|
||||||
|
const checkmarkPipe = new CheckmarkPipe();
|
||||||
|
expect(checkmarkPipe.transform(true)).toBe('\u2713');
|
||||||
|
expect(checkmarkPipe.transform(false)).toBe('\u2718');
|
||||||
|
});
|
||||||
|
});
|
|
@ -3,9 +3,7 @@ import { Pipe, PipeTransform } from '@angular/core';
|
||||||
|
|
||||||
@Pipe({name: 'checkmark'})
|
@Pipe({name: 'checkmark'})
|
||||||
export class CheckmarkPipe implements PipeTransform {
|
export class CheckmarkPipe implements PipeTransform {
|
||||||
|
|
||||||
transform(input: boolean) {
|
transform(input: boolean) {
|
||||||
return input ? '\u2713' : '\u2718';
|
return input ? '\u2713' : '\u2718';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// Define the `core` module
|
||||||
|
angular.module('core', ['core.phone']);
|
|
@ -0,0 +1,4 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// Define the `core.phone` module
|
||||||
|
angular.module('core.phone', ['ngResource']);
|
|
@ -0,0 +1,51 @@
|
||||||
|
// #docregion
|
||||||
|
import { inject, TestBed } from '@angular/core/testing';
|
||||||
|
import {
|
||||||
|
Http,
|
||||||
|
BaseRequestOptions,
|
||||||
|
ResponseOptions,
|
||||||
|
Response
|
||||||
|
} from '@angular/http';
|
||||||
|
import { MockBackend, MockConnection } from '@angular/http/testing';
|
||||||
|
import { Phone, PhoneData } from './phone.service';
|
||||||
|
|
||||||
|
describe('Phone', function() {
|
||||||
|
let phone: Phone;
|
||||||
|
let phonesData: PhoneData[] = [
|
||||||
|
{name: 'Phone X', snippet: '', images: []},
|
||||||
|
{name: 'Phone Y', snippet: '', images: []},
|
||||||
|
{name: 'Phone Z', snippet: '', images: []}
|
||||||
|
];
|
||||||
|
let mockBackend: MockBackend;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [
|
||||||
|
Phone,
|
||||||
|
MockBackend,
|
||||||
|
BaseRequestOptions,
|
||||||
|
{ provide: Http,
|
||||||
|
useFactory: (backend: MockBackend, options: BaseRequestOptions) => new Http(backend, options),
|
||||||
|
deps: [MockBackend, BaseRequestOptions]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(inject([MockBackend, Phone], (_mockBackend_: MockBackend, _phone_: Phone) => {
|
||||||
|
mockBackend = _mockBackend_;
|
||||||
|
phone = _phone_;
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should fetch the phones data from `/phones/phones.json`', (done: () => void) => {
|
||||||
|
mockBackend.connections.subscribe((conn: MockConnection) => {
|
||||||
|
conn.mockRespond(new Response(new ResponseOptions({body: JSON.stringify(phonesData)})));
|
||||||
|
});
|
||||||
|
phone.query().subscribe(result => {
|
||||||
|
expect(result).toEqual(phonesData);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
|
@ -3,21 +3,19 @@ import { Injectable } from '@angular/core';
|
||||||
import { Http, Response } from '@angular/http';
|
import { Http, Response } from '@angular/http';
|
||||||
import { Observable } from 'rxjs/Rx';
|
import { Observable } from 'rxjs/Rx';
|
||||||
|
|
||||||
|
declare var angular: angular.IAngularStatic;
|
||||||
|
import { downgradeInjectable } from '@angular/upgrade/static';
|
||||||
|
|
||||||
import 'rxjs/add/operator/map';
|
import 'rxjs/add/operator/map';
|
||||||
|
|
||||||
// #docregion phonedata-interface
|
|
||||||
export interface PhoneData {
|
export interface PhoneData {
|
||||||
name: string;
|
name: string;
|
||||||
snippet: string;
|
snippet: string;
|
||||||
images: string[];
|
images: string[];
|
||||||
}
|
}
|
||||||
// #enddocregion phonedata-interface
|
|
||||||
|
|
||||||
// #docregion fullclass
|
|
||||||
// #docregion classdef
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class Phone {
|
export class Phone {
|
||||||
// #enddocregion classdef
|
|
||||||
constructor(private http: Http) { }
|
constructor(private http: Http) { }
|
||||||
query(): Observable<PhoneData[]> {
|
query(): Observable<PhoneData[]> {
|
||||||
return this.http.get(`phones/phones.json`)
|
return this.http.get(`phones/phones.json`)
|
||||||
|
@ -27,7 +25,8 @@ export class Phone {
|
||||||
return this.http.get(`phones/${id}.json`)
|
return this.http.get(`phones/${id}.json`)
|
||||||
.map((res: Response) => res.json());
|
.map((res: Response) => res.json());
|
||||||
}
|
}
|
||||||
// #docregion classdef
|
|
||||||
}
|
}
|
||||||
// #enddocregion classdef
|
|
||||||
// #enddocregion fullclass
|
angular.module('core.phone')
|
||||||
|
.factory('phone', downgradeInjectable(Phone));
|
||||||
|
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
@ -0,0 +1,10 @@
|
||||||
|
// #docregion
|
||||||
|
import { platformBrowser } from '@angular/platform-browser';
|
||||||
|
import { UpgradeModule } from '@angular/upgrade/static';
|
||||||
|
|
||||||
|
import { AppModuleNgFactory } from '../aot/app/app.module.ngfactory';
|
||||||
|
|
||||||
|
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory).then(platformRef => {
|
||||||
|
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
|
||||||
|
upgrade.bootstrap(document.documentElement, ['phonecatApp']);
|
||||||
|
});
|
|
@ -0,0 +1,10 @@
|
||||||
|
// #docregion
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
import { UpgradeModule } from '@angular/upgrade/static';
|
||||||
|
|
||||||
|
import { AppModule } from './app.module';
|
||||||
|
|
||||||
|
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
|
||||||
|
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
|
||||||
|
upgrade.bootstrap(document.documentElement, ['phonecatApp']);
|
||||||
|
});
|
|
@ -0,0 +1,34 @@
|
||||||
|
// #docplaster
|
||||||
|
// #docregion
|
||||||
|
declare var angular: angular.IAngularStatic;
|
||||||
|
import { downgradeComponent } from '@angular/upgrade/static';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
import { Phone, PhoneData } from '../core/phone/phone.service';
|
||||||
|
import { RouteParams } from '../ajs-upgraded-providers';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
moduleId: module.id,
|
||||||
|
templateUrl: 'phone-detail.template.html',
|
||||||
|
})
|
||||||
|
export class PhoneDetailComponent {
|
||||||
|
phone: PhoneData;
|
||||||
|
mainImageUrl: string;
|
||||||
|
|
||||||
|
constructor(routeParams: RouteParams, phone: Phone) {
|
||||||
|
phone.get(routeParams['phoneId']).subscribe(phone => {
|
||||||
|
this.phone = phone;
|
||||||
|
this.setImage(phone.images[0]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setImage(imageUrl: string) {
|
||||||
|
this.mainImageUrl = imageUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
angular.module('phoneDetail')
|
||||||
|
.directive(
|
||||||
|
'phoneDetail',
|
||||||
|
downgradeComponent({component: PhoneDetailComponent}) as angular.IDirectiveFactory
|
||||||
|
);
|
|
@ -0,0 +1,7 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// Define the `phoneDetail` module
|
||||||
|
angular.module('phoneDetail', [
|
||||||
|
'ngRoute',
|
||||||
|
'core.phone'
|
||||||
|
]);
|
|
@ -0,0 +1,66 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
// #docregion
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { Observable } from 'rxjs/Rx';
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { SpyLocation } from '@angular/common/testing';
|
||||||
|
|
||||||
|
import { PhoneListComponent } from './phone-list.component';
|
||||||
|
import { Phone, PhoneData } from '../core/phone/phone.service';
|
||||||
|
|
||||||
|
class ActivatedRouteMock {
|
||||||
|
constructor(public snapshot: any) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockPhone {
|
||||||
|
query(): Observable<PhoneData[]> {
|
||||||
|
return Observable.of([
|
||||||
|
{name: 'Nexus S', snippet: '', images: []},
|
||||||
|
{name: 'Motorola DROID', snippet: '', images: []}
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let fixture: ComponentFixture<PhoneListComponent>;
|
||||||
|
|
||||||
|
describe('PhoneList', () => {
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ PhoneListComponent ],
|
||||||
|
providers: [
|
||||||
|
{ provide: ActivatedRoute, useValue: new ActivatedRouteMock({ params: { 'phoneId': 1 } }) },
|
||||||
|
{ provide: Location, useClass: SpyLocation },
|
||||||
|
{ provide: Phone, useClass: MockPhone },
|
||||||
|
],
|
||||||
|
schemas: [ NO_ERRORS_SCHEMA ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(PhoneListComponent);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create "phones" model with 2 phones fetched from xhr', () => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
let compiled = fixture.debugElement.nativeElement;
|
||||||
|
expect(compiled.querySelectorAll('.phone-list-item').length).toBe(2);
|
||||||
|
expect(
|
||||||
|
compiled.querySelector('.phone-list-item:nth-child(1)').textContent
|
||||||
|
).toContain('Motorola DROID');
|
||||||
|
expect(
|
||||||
|
compiled.querySelector('.phone-list-item:nth-child(2)').textContent
|
||||||
|
).toContain('Nexus S');
|
||||||
|
});
|
||||||
|
|
||||||
|
xit('should set the default value of orderProp model', () => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
let compiled = fixture.debugElement.nativeElement;
|
||||||
|
expect(
|
||||||
|
compiled.querySelector('select option:last-child').selected
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|