Created
July 1, 2016 00:40
-
-
Save jashmenn/8638310d284afc3a9e6eb650f7495f60 to your computer and use it in GitHub Desktop.
ng-book 2 code diff between rc.2 and rc.4 - https://www.ng-book.com/2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/manuscript/code/advanced_components/app/ts/app.ts b/manuscript/code/advanced_components/app/ts/app.ts | |
index 6db6693..830beb2 100644 | |
--- a/manuscript/code/advanced_components/app/ts/app.ts | |
+++ b/manuscript/code/advanced_components/app/ts/app.ts | |
@@ -13,10 +13,10 @@ import { | |
import { bootstrap } from '@angular/platform-browser-dynamic'; | |
import { | |
ROUTER_DIRECTIVES, | |
- ROUTER_PROVIDERS, | |
- RouteDefinition, | |
+ RouterConfig, | |
+ provideRouter, | |
Router | |
-} from '@angular/router-deprecated'; | |
+} from '@angular/router'; | |
import { | |
APP_BASE_HREF, | |
LocationStrategy, | |
@@ -47,25 +47,31 @@ import './assets'; | |
* Here's the master list of our examples for this chapter. | |
*/ | |
let examples: ExampleDef[] = [ /* tslint:disable:max-line-length */ | |
- {label: 'Intro', name: 'Root', path: '/', component: IntroComponent}, | |
- {label: 'Styling', name: 'Styling', path: '/styling', component: StyleSampleApp }, | |
- {label: 'Modifying the Host (Step 1)', name: 'Host1', path: '/host-step-1', component: HostSampleApp1, dev: true}, | |
- {label: 'Modifying the Host (Step 2)', name: 'Host2', path: '/host-step-2', component: HostSampleApp2, dev: true}, | |
- {label: 'Modifying the Host (Step 3)', name: 'Host3', path: '/host-step-3', component: HostSampleApp3, dev: true}, | |
- {label: 'Modifying the Host (Step 4)', name: 'Host4', path: '/host-step-4', component: HostSampleApp4, dev: true}, | |
- {label: 'Modifying the Host', name: 'Host', path: '/host-final', component: HostSampleApp}, | |
- {label: 'Tabs - Component Querying', name: 'Tabs', path: '/tabs', component: TabsSampleApp}, | |
- {label: 'Lifecycle 1 - OnInit / OnDestroy', name: 'Lifecycle1', path: '/lifecycle-hooks-1', component: LifecycleSampleApp1 }, | |
- {label: 'Lifecycle 2 - OnChanges', name: 'Lifecycle2', path: '/lifecycle-hooks-2', component: LifecycleSampleApp2 }, | |
- {label: 'Lifecycle 3 - Differs', name: 'Lifecycle3', path: '/lifecycle-hooks-3', component: LifecycleSampleApp3 }, | |
- {label: 'Lifecycle 4 - Full', name: 'Lifecycle4', path: '/lifecycle-hooks-4', component: LifecycleSampleApp4 }, | |
- {label: 'ngBookFor', name: 'NgBookFor', path: '/ng-book-for', component: ForTemplateSampleApp }, | |
- {label: 'ngBookIf', name: 'NgBookIf', path: '/ng-book-if', component: IfTemplateSampleApp }, | |
- {label: 'Transclusion', name: 'Transclusion', path: '/transclusion', component: TransclusionSampleApp }, | |
+ {label: 'Intro', name: 'Root', path: '', component: IntroComponent}, | |
+ {label: 'Styling', name: 'Styling', path: 'styling', component: StyleSampleApp }, | |
+ {label: 'Modifying the Host (Step 1)', name: 'Host1', path: 'host-step-1', component: HostSampleApp1, dev: true}, | |
+ {label: 'Modifying the Host (Step 2)', name: 'Host2', path: 'host-step-2', component: HostSampleApp2, dev: true}, | |
+ {label: 'Modifying the Host (Step 3)', name: 'Host3', path: 'host-step-3', component: HostSampleApp3, dev: true}, | |
+ {label: 'Modifying the Host (Step 4)', name: 'Host4', path: 'host-step-4', component: HostSampleApp4, dev: true}, | |
+ {label: 'Modifying the Host', name: 'Host', path: 'host-final', component: HostSampleApp}, | |
+ {label: 'Tabs - Component Querying', name: 'Tabs', path: 'tabs', component: TabsSampleApp}, | |
+ {label: 'Lifecycle 1 - OnInit / OnDestroy', name: 'Lifecycle1', path: 'lifecycle-hooks-1', component: LifecycleSampleApp1 }, | |
+ {label: 'Lifecycle 2 - OnChanges', name: 'Lifecycle2', path: 'lifecycle-hooks-2', component: LifecycleSampleApp2 }, | |
+ {label: 'Lifecycle 3 - Differs', name: 'Lifecycle3', path: 'lifecycle-hooks-3', component: LifecycleSampleApp3 }, | |
+ {label: 'Lifecycle 4 - Full', name: 'Lifecycle4', path: 'lifecycle-hooks-4', component: LifecycleSampleApp4 }, | |
+ {label: 'ngBookFor', name: 'NgBookFor', path: 'ng-book-for', component: ForTemplateSampleApp }, | |
+ {label: 'ngBookIf', name: 'NgBookIf', path: 'ng-book-if', component: IfTemplateSampleApp }, | |
+ {label: 'Transclusion', name: 'Transclusion', path: 'transclusion', component: TransclusionSampleApp }, | |
{label: 'Change Detection - OnPush', name: 'ChangeDetectionOnPush', path: 'change-detection-onpush', component: OnPushChangeDetectionSampleApp }, | |
{label: 'Change Detection - Observables', name: 'ChangeDetectionObservables', path: 'change-detection-observ', component: ObservableChangeDetectionSampleApp }, | |
]; /* tslint:enable:max-line-length */ | |
+// dynamically configure the router based on our ExampleDefs | |
+const routes: RouterConfig = examples | |
+ .map( (example: ExampleDef) => ({ | |
+ path: example.path, component: example.component, terminal: true | |
+ })); | |
+ | |
@Component({ | |
selector: 'advanced-components-app', | |
directives: [ SidebarComponent, ROUTER_DIRECTIVES ], | |
@@ -102,19 +108,13 @@ class AdvancedComponentsApp { | |
constructor(private router: Router) { | |
this.examples = examples; // store the outer examples | |
- | |
- // dynamically configure the router based on our ExampleDefs | |
- let routeDefinitions: RouteDefinition[] = examples | |
- .map( (example: ExampleDef) => <RouteDefinition>({ | |
- path: example.path, name: example.name, component: example.component | |
- })); | |
- router.config(routeDefinitions); | |
} | |
} | |
bootstrap(AdvancedComponentsApp, [ | |
- ROUTER_PROVIDERS, | |
+ provideRouter(routes), | |
provide(APP_BASE_HREF, {useValue: '/'}), | |
provide(LocationStrategy, {useClass: HashLocationStrategy}) | |
]).catch((err: any) => console.error(err)); | |
+ | |
diff --git a/manuscript/code/advanced_components/app/ts/app/sidebar.ts b/manuscript/code/advanced_components/app/ts/app/sidebar.ts | |
index 071e670..e12719c 100644 | |
--- a/manuscript/code/advanced_components/app/ts/app/sidebar.ts | |
+++ b/manuscript/code/advanced_components/app/ts/app/sidebar.ts | |
@@ -9,10 +9,13 @@ import { | |
Component, | |
Input | |
} from '@angular/core'; | |
+import { Location } from '@angular/common'; | |
import { | |
ROUTER_DIRECTIVES, | |
- Router | |
-} from '@angular/router-deprecated'; | |
+ Router, | |
+ ActivatedRoute, | |
+ UrlPathWithParams | |
+} from '@angular/router'; | |
import { ExampleDef } from './example'; | |
/* | |
@@ -29,7 +32,7 @@ import { ExampleDef } from './example'; | |
template: ` | |
<a class="item" | |
[ngClass]="{ active: isActive() }" | |
- [routerLink]="[item.name]"> | |
+ [routerLink]="[item.path]"> | |
{{ item.label }} | |
</a> | |
` | |
@@ -37,17 +40,14 @@ import { ExampleDef } from './example'; | |
class SidebarItemComponent { | |
@Input('item') item: ExampleDef; | |
- constructor(private router: Router) { | |
+ constructor(private router: Router, | |
+ private route: ActivatedRoute, | |
+ private location: Location) { | |
} | |
// Checks if this current example is the selected one | |
isActive(): boolean { | |
- return this.isRouteActive(this.item.name); | |
- } | |
- | |
- // Here's how you determine if a current route is active in ng2 | |
- isRouteActive(route: string): boolean { | |
- return this.router.isRouteActive(this.router.generate([route])); | |
+ return `/${this.item.path}` === this.location.path(); | |
} | |
} | |
diff --git a/manuscript/code/advanced_components/package.json b/manuscript/code/advanced_components/package.json | |
index 4b6c7ec..6aad22d 100644 | |
--- a/manuscript/code/advanced_components/package.json | |
+++ b/manuscript/code/advanced_components/package.json | |
@@ -18,14 +18,14 @@ | |
], | |
"license": "MIT", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
- "@angular/router-deprecated": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"base64id": "0.1.0", | |
"core-js": "2.2.2", | |
"lodash": "3.10.1", | |
diff --git a/manuscript/code/built_in_components/ng_class/package.json b/manuscript/code/built_in_components/ng_class/package.json | |
index 96410eb..330197d 100644 | |
--- a/manuscript/code/built_in_components/ng_class/package.json | |
+++ b/manuscript/code/built_in_components/ng_class/package.json | |
@@ -11,13 +11,14 @@ | |
}, | |
"license": "ISC", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"core-js": "2.2.2", | |
"es6-shim": "0.35.0", | |
diff --git a/manuscript/code/built_in_components/ng_for/package.json b/manuscript/code/built_in_components/ng_for/package.json | |
index 96410eb..330197d 100644 | |
--- a/manuscript/code/built_in_components/ng_for/package.json | |
+++ b/manuscript/code/built_in_components/ng_for/package.json | |
@@ -11,13 +11,14 @@ | |
}, | |
"license": "ISC", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"core-js": "2.2.2", | |
"es6-shim": "0.35.0", | |
diff --git a/manuscript/code/built_in_components/ng_non_bindable/package.json b/manuscript/code/built_in_components/ng_non_bindable/package.json | |
index 96410eb..330197d 100644 | |
--- a/manuscript/code/built_in_components/ng_non_bindable/package.json | |
+++ b/manuscript/code/built_in_components/ng_non_bindable/package.json | |
@@ -11,13 +11,14 @@ | |
}, | |
"license": "ISC", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"core-js": "2.2.2", | |
"es6-shim": "0.35.0", | |
diff --git a/manuscript/code/built_in_components/ng_style/package.json b/manuscript/code/built_in_components/ng_style/package.json | |
index 96410eb..330197d 100644 | |
--- a/manuscript/code/built_in_components/ng_style/package.json | |
+++ b/manuscript/code/built_in_components/ng_style/package.json | |
@@ -11,13 +11,14 @@ | |
}, | |
"license": "ISC", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"core-js": "2.2.2", | |
"es6-shim": "0.35.0", | |
diff --git a/manuscript/code/built_in_components/ng_switch/package.json b/manuscript/code/built_in_components/ng_switch/package.json | |
index 96410eb..330197d 100644 | |
--- a/manuscript/code/built_in_components/ng_switch/package.json | |
+++ b/manuscript/code/built_in_components/ng_switch/package.json | |
@@ -11,13 +11,14 @@ | |
}, | |
"license": "ISC", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"core-js": "2.2.2", | |
"es6-shim": "0.35.0", | |
diff --git a/manuscript/code/conversion/hybrid/package.json b/manuscript/code/conversion/hybrid/package.json | |
index 8d7ad41..4759839 100644 | |
--- a/manuscript/code/conversion/hybrid/package.json | |
+++ b/manuscript/code/conversion/hybrid/package.json | |
@@ -16,13 +16,14 @@ | |
"go": "concurrent \"npm run tsc:w\" \"npm run serve\" " | |
}, | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"@angular/upgrade": "2.0.0-rc.2", | |
"core-js": "2.2.2", | |
diff --git a/manuscript/code/dependency_injection/complex/package.json b/manuscript/code/dependency_injection/complex/package.json | |
index 24be804..5b6395c 100644 | |
--- a/manuscript/code/dependency_injection/complex/package.json | |
+++ b/manuscript/code/dependency_injection/complex/package.json | |
@@ -11,13 +11,14 @@ | |
"author": "Nate Murray <[email protected]>", | |
"license": "MIT", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"base64id": "0.1.0", | |
"core-js": "2.2.2", | |
diff --git a/manuscript/code/dependency_injection/injector/package.json b/manuscript/code/dependency_injection/injector/package.json | |
index 3e1c94d..6d23703 100644 | |
--- a/manuscript/code/dependency_injection/injector/package.json | |
+++ b/manuscript/code/dependency_injection/injector/package.json | |
@@ -11,13 +11,14 @@ | |
"author": "Nate Murray <[email protected]>", | |
"license": "MIT", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"base64id": "0.1.0", | |
"core-js": "2.2.2", | |
diff --git a/manuscript/code/dependency_injection/misc/package.json b/manuscript/code/dependency_injection/misc/package.json | |
index fa725bb..947503b 100644 | |
--- a/manuscript/code/dependency_injection/misc/package.json | |
+++ b/manuscript/code/dependency_injection/misc/package.json | |
@@ -11,13 +11,14 @@ | |
"author": "Nate Murray <[email protected]>", | |
"license": "MIT", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"base64id": "0.1.0", | |
"core-js": "2.2.2", | |
diff --git a/manuscript/code/dependency_injection/simple/package.json b/manuscript/code/dependency_injection/simple/package.json | |
index 07c612d..e59e496 100644 | |
--- a/manuscript/code/dependency_injection/simple/package.json | |
+++ b/manuscript/code/dependency_injection/simple/package.json | |
@@ -11,13 +11,14 @@ | |
"author": "Nate Murray <[email protected]>", | |
"license": "MIT", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"base64id": "0.1.0", | |
"core-js": "2.2.2", | |
diff --git a/manuscript/code/dependency_injection/value/package.json b/manuscript/code/dependency_injection/value/package.json | |
index 8ab7814..6c904d4 100644 | |
--- a/manuscript/code/dependency_injection/value/package.json | |
+++ b/manuscript/code/dependency_injection/value/package.json | |
@@ -14,13 +14,14 @@ | |
], | |
"license": "MIT", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"base64id": "0.1.0", | |
"core-js": "2.2.2", | |
diff --git a/manuscript/code/first_app/angular2-reddit-base/package.json b/manuscript/code/first_app/angular2-reddit-base/package.json | |
index efad622..46513bf 100644 | |
--- a/manuscript/code/first_app/angular2-reddit-base/package.json | |
+++ b/manuscript/code/first_app/angular2-reddit-base/package.json | |
@@ -11,13 +11,14 @@ | |
}, | |
"license": "ISC", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"core-js": "2.2.2", | |
"es6-shim": "0.35.0", | |
diff --git a/manuscript/code/first_app/angular2-reddit-completed/package.json b/manuscript/code/first_app/angular2-reddit-completed/package.json | |
index efad622..46513bf 100644 | |
--- a/manuscript/code/first_app/angular2-reddit-completed/package.json | |
+++ b/manuscript/code/first_app/angular2-reddit-completed/package.json | |
@@ -11,13 +11,14 @@ | |
}, | |
"license": "ISC", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"core-js": "2.2.2", | |
"es6-shim": "0.35.0", | |
diff --git a/manuscript/code/first_app/hello-world/package.json b/manuscript/code/first_app/hello-world/package.json | |
index a39e0c2..ca429c8 100644 | |
--- a/manuscript/code/first_app/hello-world/package.json | |
+++ b/manuscript/code/first_app/hello-world/package.json | |
@@ -10,13 +10,14 @@ | |
}, | |
"license": "ISC", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"core-js": "2.2.2", | |
"es6-shim": "0.35.0", | |
diff --git a/manuscript/code/forms/app/ts/app.ts b/manuscript/code/forms/app/ts/app.ts | |
index c43a577..8ce37ac 100644 | |
--- a/manuscript/code/forms/app/ts/app.ts | |
+++ b/manuscript/code/forms/app/ts/app.ts | |
@@ -4,7 +4,8 @@ | |
import { | |
Component | |
} from '@angular/core'; | |
-import {bootstrap} from '@angular/platform-browser-dynamic'; | |
+import { bootstrap } from '@angular/platform-browser-dynamic'; | |
+import { disableDeprecatedForms, provideForms } from '@angular/forms'; | |
/* | |
* We're using Webpack to load our CSS which is why we use `require` instead of | |
@@ -45,7 +46,8 @@ import {DemoFormNgModel} from | |
DemoFormWithValidationsExplicit, | |
DemoFormWithCustomValidations, | |
DemoFormWithEvents, | |
- DemoFormNgModel], | |
+ DemoFormNgModel | |
+ ], | |
template: ` | |
<div> | |
<demo-form-ng-model></demo-form-ng-model> | |
@@ -61,4 +63,8 @@ import {DemoFormNgModel} from | |
class FormsDemoApp { | |
} | |
-bootstrap(FormsDemoApp); | |
+bootstrap(FormsDemoApp, [ | |
+ disableDeprecatedForms(), | |
+ provideForms() | |
+]) | |
+.catch((err: any) => console.error(err)); | |
diff --git a/manuscript/code/forms/app/ts/forms/demo_form_ng_model.ts b/manuscript/code/forms/app/ts/forms/demo_form_ng_model.ts | |
index 25edd03..d2037f3 100644 | |
--- a/manuscript/code/forms/app/ts/forms/demo_form_ng_model.ts | |
+++ b/manuscript/code/forms/app/ts/forms/demo_form_ng_model.ts | |
@@ -1,15 +1,15 @@ | |
import { Component } from '@angular/core'; | |
import { | |
- CORE_DIRECTIVES, | |
FORM_DIRECTIVES, | |
+ REACTIVE_FORM_DIRECTIVES, | |
FormBuilder, | |
- ControlGroup, | |
+ FormGroup, | |
Validators | |
-} from '@angular/common'; | |
+} from '@angular/forms'; | |
@Component({ | |
selector: 'demo-form-ng-model', | |
- directives: [CORE_DIRECTIVES, FORM_DIRECTIVES], | |
+ directives: [FORM_DIRECTIVES, REACTIVE_FORM_DIRECTIVES], | |
template: ` | |
<div class="ui raised segment"> | |
<h2 class="ui header">Demo Form: with ng-model</h2> | |
@@ -18,7 +18,7 @@ import { | |
The product name is: {{productName}} | |
</div> | |
- <form [ngFormModel]="myForm" | |
+ <form [formGroup]="myForm" | |
(ngSubmit)="onSubmit(myForm.value)" | |
class="ui form"> | |
@@ -27,7 +27,7 @@ import { | |
<input type="text" | |
id="productNameInput" | |
placeholder="Product Name" | |
- [ngFormControl]="myForm.find('productName')" | |
+ [formControl]="myForm.find('productName')" | |
[(ngModel)]="productName"> | |
</div> | |
@@ -40,7 +40,7 @@ import { | |
` | |
}) | |
export class DemoFormNgModel { | |
- myForm: ControlGroup; | |
+ myForm: FormGroup; | |
productName: string; | |
constructor(fb: FormBuilder) { | |
diff --git a/manuscript/code/forms/app/ts/forms/demo_form_sku.ts b/manuscript/code/forms/app/ts/forms/demo_form_sku.ts | |
index 57256bb..a244de2 100644 | |
--- a/manuscript/code/forms/app/ts/forms/demo_form_sku.ts | |
+++ b/manuscript/code/forms/app/ts/forms/demo_form_sku.ts | |
@@ -1,9 +1,9 @@ | |
import { Component } from '@angular/core'; | |
-import { FORM_DIRECTIVES } from '@angular/common'; | |
+ | |
@Component({ | |
selector: 'demo-form-sku', | |
- directives: [FORM_DIRECTIVES], | |
+ | |
template: ` | |
<div class="ui raised segment"> | |
<h2 class="ui header">Demo Form: Sku</h2> | |
@@ -16,7 +16,7 @@ import { FORM_DIRECTIVES } from '@angular/common'; | |
<input type="text" | |
id="skuInput" | |
placeholder="SKU" | |
- ngControl="sku"> | |
+ name="sku" ngModel> | |
</div> | |
<button type="submit" class="ui button">Submit</button> | |
diff --git a/manuscript/code/forms/app/ts/forms/demo_form_sku_with_builder.ts b/manuscript/code/forms/app/ts/forms/demo_form_sku_with_builder.ts | |
index 0af16b0..e17babf 100644 | |
--- a/manuscript/code/forms/app/ts/forms/demo_form_sku_with_builder.ts | |
+++ b/manuscript/code/forms/app/ts/forms/demo_form_sku_with_builder.ts | |
@@ -1,17 +1,18 @@ | |
import { Component } from '@angular/core'; | |
import { | |
FORM_DIRECTIVES, | |
+ REACTIVE_FORM_DIRECTIVES, | |
FormBuilder, | |
- ControlGroup | |
-} from '@angular/common'; | |
+ FormGroup | |
+} from '@angular/forms'; | |
@Component({ | |
selector: 'demo-form-sku-builder', | |
- directives: [FORM_DIRECTIVES], | |
+ directives: [FORM_DIRECTIVES, REACTIVE_FORM_DIRECTIVES], | |
template: ` | |
<div class="ui raised segment"> | |
<h2 class="ui header">Demo Form: Sku with Builder</h2> | |
- <form [ngFormModel]="myForm" | |
+ <form [formGroup]="myForm" | |
(ngSubmit)="onSubmit(myForm.value)" | |
class="ui form"> | |
@@ -20,7 +21,7 @@ import { | |
<input type="text" | |
id="skuInput" | |
placeholder="SKU" | |
- [ngFormControl]="myForm.controls['sku']"> | |
+ [formControl]="myForm.controls['sku']"> | |
</div> | |
<button type="submit" class="ui button">Submit</button> | |
@@ -29,7 +30,7 @@ import { | |
` | |
}) | |
export class DemoFormSkuBuilder { | |
- myForm: ControlGroup; | |
+ myForm: FormGroup; | |
constructor(fb: FormBuilder) { | |
this.myForm = fb.group({ | |
diff --git a/manuscript/code/forms/app/ts/forms/demo_form_with_custom_validations.ts b/manuscript/code/forms/app/ts/forms/demo_form_with_custom_validations.ts | |
index a01cca9..60675b1 100644 | |
--- a/manuscript/code/forms/app/ts/forms/demo_form_with_custom_validations.ts | |
+++ b/manuscript/code/forms/app/ts/forms/demo_form_with_custom_validations.ts | |
@@ -1,14 +1,14 @@ | |
/* tslint:disable:no-string-literal */ | |
import { Component } from '@angular/core'; | |
import { | |
- CORE_DIRECTIVES, | |
FORM_DIRECTIVES, | |
+ REACTIVE_FORM_DIRECTIVES, | |
FormBuilder, | |
- ControlGroup, | |
+ FormGroup, | |
Validators, | |
AbstractControl, | |
- Control | |
-} from '@angular/common'; | |
+ FormControl | |
+} from '@angular/forms'; | |
/** | |
* Our custom validator | |
@@ -18,7 +18,7 @@ import { | |
* - Returns a `StringMap<string, boolean>` where the key is "error code" and | |
* the value is `true` if it fails | |
*/ | |
-function skuValidator(control: Control): { [s: string]: boolean } { | |
+function skuValidator(control: FormControl): { [s: string]: boolean } { | |
if (!control.value.match(/^123/)) { | |
return {invalidSku: true}; | |
} | |
@@ -26,11 +26,11 @@ function skuValidator(control: Control): { [s: string]: boolean } { | |
@Component({ | |
selector: 'demo-form-with-custom-validations', | |
- directives: [CORE_DIRECTIVES, FORM_DIRECTIVES], | |
+ directives: [FORM_DIRECTIVES, REACTIVE_FORM_DIRECTIVES], | |
template: ` | |
<div class="ui raised segment"> | |
<h2 class="ui header">Demo Form: with custom validations</h2> | |
- <form [ngFormModel]="myForm" | |
+ <form [formGroup]="myForm" | |
(ngSubmit)="onSubmit(myForm.value)" | |
class="ui form"> | |
@@ -40,7 +40,7 @@ function skuValidator(control: Control): { [s: string]: boolean } { | |
<input type="text" | |
id="skuInput" | |
placeholder="SKU" | |
- [ngFormControl]="sku"> | |
+ [formControl]="sku"> | |
<div *ngIf="!sku.valid" | |
class="ui error message">SKU is invalid</div> | |
<div *ngIf="sku.hasError('required')" | |
@@ -57,7 +57,7 @@ function skuValidator(control: Control): { [s: string]: boolean } { | |
` | |
}) | |
export class DemoFormWithCustomValidations { | |
- myForm: ControlGroup; | |
+ myForm: FormGroup; | |
sku: AbstractControl; | |
constructor(fb: FormBuilder) { | |
diff --git a/manuscript/code/forms/app/ts/forms/demo_form_with_events.ts b/manuscript/code/forms/app/ts/forms/demo_form_with_events.ts | |
index 2e9e6de..d612b1c 100644 | |
--- a/manuscript/code/forms/app/ts/forms/demo_form_with_events.ts | |
+++ b/manuscript/code/forms/app/ts/forms/demo_form_with_events.ts | |
@@ -1,21 +1,20 @@ | |
-/* tslint:disable:no-string-literal */ | |
import { Component } from '@angular/core'; | |
import { | |
- CORE_DIRECTIVES, | |
FORM_DIRECTIVES, | |
+ REACTIVE_FORM_DIRECTIVES, | |
FormBuilder, | |
- ControlGroup, | |
+ FormGroup, | |
Validators, | |
AbstractControl | |
-} from '@angular/common'; | |
+} from '@angular/forms'; | |
@Component({ | |
selector: 'demo-form-with-events', | |
- directives: [CORE_DIRECTIVES, FORM_DIRECTIVES], | |
+ directives: [FORM_DIRECTIVES, REACTIVE_FORM_DIRECTIVES], | |
template: ` | |
<div class="ui raised segment"> | |
<h2 class="ui header">Demo Form: with events</h2> | |
- <form [ngFormModel]="myForm" | |
+ <form [formGroup]="myForm" | |
(ngSubmit)="onSubmit(myForm.value)" | |
class="ui form"> | |
@@ -26,7 +25,7 @@ import { | |
class="form-control" | |
id="skuInput" | |
placeholder="SKU" | |
- [ngFormControl]="sku"> | |
+ [formControl]="sku"> | |
<div *ngIf="!sku.valid" | |
class="ui error message">SKU is invalid</div> | |
<div *ngIf="sku.hasError('required')" | |
@@ -42,7 +41,7 @@ import { | |
` | |
}) | |
export class DemoFormWithEvents { | |
- myForm: ControlGroup; | |
+ myForm: FormGroup; | |
sku: AbstractControl; | |
constructor(fb: FormBuilder) { | |
diff --git a/manuscript/code/forms/app/ts/forms/demo_form_with_validations_explicit.ts b/manuscript/code/forms/app/ts/forms/demo_form_with_validations_explicit.ts | |
index 89725e1..bbc477f 100644 | |
--- a/manuscript/code/forms/app/ts/forms/demo_form_with_validations_explicit.ts | |
+++ b/manuscript/code/forms/app/ts/forms/demo_form_with_validations_explicit.ts | |
@@ -1,21 +1,21 @@ | |
/* tslint:disable:no-string-literal */ | |
import { Component } from '@angular/core'; | |
import { | |
- CORE_DIRECTIVES, | |
FORM_DIRECTIVES, | |
+ REACTIVE_FORM_DIRECTIVES, | |
FormBuilder, | |
- ControlGroup, | |
+ FormGroup, | |
Validators, | |
AbstractControl | |
-} from '@angular/common'; | |
+} from '@angular/forms'; | |
@Component({ | |
selector: 'demo-form-with-validations-explicit', | |
- directives: [CORE_DIRECTIVES, FORM_DIRECTIVES], | |
+ directives: [FORM_DIRECTIVES, REACTIVE_FORM_DIRECTIVES], | |
template: ` | |
<div class="ui raised segment"> | |
<h2 class="ui header">Demo Form: with validations (explicit)</h2> | |
- <form [ngFormModel]="myForm" | |
+ <form [formGroup]="myForm" | |
(ngSubmit)="onSubmit(myForm.value)" | |
class="ui form"> | |
@@ -25,7 +25,7 @@ import { | |
<input type="text" | |
id="skuInput" | |
placeholder="SKU" | |
- [ngFormControl]="sku"> | |
+ [formControl]="sku"> | |
<div *ngIf="!sku.valid" | |
class="ui error message">SKU is invalid</div> | |
<div *ngIf="sku.hasError('required')" | |
@@ -41,7 +41,7 @@ import { | |
` | |
}) | |
export class DemoFormWithValidationsExplicit { | |
- myForm: ControlGroup; | |
+ myForm: FormGroup; | |
sku: AbstractControl; | |
constructor(fb: FormBuilder) { | |
diff --git a/manuscript/code/forms/app/ts/forms/demo_form_with_validations_shorthand.ts b/manuscript/code/forms/app/ts/forms/demo_form_with_validations_shorthand.ts | |
index 5c6bc62..43c1a0f 100644 | |
--- a/manuscript/code/forms/app/ts/forms/demo_form_with_validations_shorthand.ts | |
+++ b/manuscript/code/forms/app/ts/forms/demo_form_with_validations_shorthand.ts | |
@@ -1,19 +1,19 @@ | |
import { Component } from '@angular/core'; | |
import { | |
- CORE_DIRECTIVES, | |
FORM_DIRECTIVES, | |
+ REACTIVE_FORM_DIRECTIVES, | |
FormBuilder, | |
- ControlGroup, | |
+ FormGroup, | |
Validators | |
-} from '@angular/common'; | |
+} from '@angular/forms'; | |
@Component({ | |
selector: 'demo-form-with-validations-shorthand', | |
- directives: [CORE_DIRECTIVES, FORM_DIRECTIVES], | |
+ directives: [FORM_DIRECTIVES, REACTIVE_FORM_DIRECTIVES], | |
template: ` | |
<div class="ui raised segment"> | |
<h2 class="ui header">Demo Form: with validations (shorthand)</h2> | |
- <form [ngFormModel]="myForm" | |
+ <form [formGroup]="myForm" | |
(ngSubmit)="onSubmit(myForm.value)" | |
class="ui form"> | |
@@ -23,11 +23,10 @@ import { | |
<input type="text" | |
id="skuInput" | |
placeholder="SKU" | |
- #sku="ngForm" | |
- [ngFormControl]="myForm.controls['sku']"> | |
- <div *ngIf="!sku.control.valid" | |
+ [formControl]="myForm.controls['sku']"> | |
+ <div *ngIf="!myForm.controls['sku'].valid" | |
class="ui error message">SKU is invalid</div> | |
- <div *ngIf="sku.control.hasError('required')" | |
+ <div *ngIf="myForm.controls['sku'].hasError('required')" | |
class="ui error message">SKU is required</div> | |
</div> | |
@@ -40,7 +39,7 @@ import { | |
` | |
}) | |
export class DemoFormWithValidationsShorthand { | |
- myForm: ControlGroup; | |
+ myForm: FormGroup; | |
constructor(fb: FormBuilder) { | |
this.myForm = fb.group({ | |
diff --git a/manuscript/code/forms/package.json b/manuscript/code/forms/package.json | |
index 29f1bde..59ee606 100644 | |
--- a/manuscript/code/forms/package.json | |
+++ b/manuscript/code/forms/package.json | |
@@ -6,18 +6,19 @@ | |
"scripts": { | |
"clean": "true", | |
"go": "./node_modules/.bin/webpack-dev-server", | |
- "test": "karma start" | |
+ "test": "karma start --single-run" | |
}, | |
"author": "Nate Murray <[email protected]>", | |
"license": "MIT", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"base64id": "0.1.0", | |
"bootstrap-sass": "3.3.5", | |
diff --git a/manuscript/code/forms/test/forms/demo_form_ng_model.spec.ts b/manuscript/code/forms/test/forms/demo_form_ng_model.spec.ts | |
index cd0d436..e1642ca 100644 | |
--- a/manuscript/code/forms/test/forms/demo_form_ng_model.spec.ts | |
+++ b/manuscript/code/forms/test/forms/demo_form_ng_model.spec.ts | |
@@ -1,30 +1,38 @@ | |
import { | |
it, | |
describe, | |
- | |
- expect, | |
- | |
async, | |
inject, | |
- beforeEachProviders | |
+ addProviders | |
} from '@angular/core/testing'; | |
-import { TestComponentBuilder } from '@angular/compiler/testing'; | |
-import { FormBuilder } from '@angular/common'; | |
- | |
+import { | |
+ disableDeprecatedForms, | |
+ provideForms, | |
+ FormBuilder | |
+} from '@angular/forms'; | |
+import { TestComponentBuilder } from '@angular/core/testing'; | |
import { DemoFormNgModel } from '../../app/ts/forms/demo_form_ng_model'; | |
-beforeEachProviders(() => { return [FormBuilder]; }); | |
- | |
describe('DemoFormNgModel', () => { | |
+ beforeEach(() => { | |
+ addProviders([ | |
+ disableDeprecatedForms(), | |
+ provideForms(), | |
+ FormBuilder | |
+ ]); | |
+ }); | |
+ | |
it('requires product name', async(inject([TestComponentBuilder], (tcb) => { | |
- return tcb.createAsync(DemoFormNgModel).then((fixture) => { | |
+ return tcb.createAsync(DemoFormNgModel) | |
+ .then((fixture) => { | |
let comp = fixture.debugElement.componentInstance; | |
let el = fixture.debugElement.nativeElement; | |
// error message is displayed when product name is empty | |
comp.productName = ''; | |
fixture.detectChanges(); | |
- expect(el.querySelector('.ui.error.message')).toHaveText('Form is invalid'); | |
+ expect(el.querySelector('.ui.error.message').innerHTML) | |
+ .toContain('Form is invalid'); | |
// error message is not present when product name has a value | |
comp.productName = 'something'; | |
diff --git a/manuscript/code/forms/test/forms/demo_form_sku.spec.ts b/manuscript/code/forms/test/forms/demo_form_sku.spec.ts | |
index 897ff94..08dde3f 100644 | |
--- a/manuscript/code/forms/test/forms/demo_form_sku.spec.ts | |
+++ b/manuscript/code/forms/test/forms/demo_form_sku.spec.ts | |
@@ -1,49 +1,42 @@ | |
import { | |
it, | |
describe, | |
- | |
expect, | |
inject, | |
- | |
fakeAsync, | |
tick, | |
- | |
- | |
- | |
} from '@angular/core/testing'; | |
-import { TestComponentBuilder, ComponentFixture } from '@angular/compiler/testing'; | |
-import { dispatchEvent } from '@angular/platform-browser/testing'; | |
+import { TestComponentBuilder, ComponentFixture } from '@angular/core/testing'; | |
import { By } from '@angular/platform-browser/src/dom/debug/by'; | |
- | |
import { DemoFormSku } from '../../app/ts/forms/demo_form_sku'; | |
- | |
-describe('DemoFormSku', () => { | |
- var _console; | |
- var fakeConsole; | |
- var el, input, form; | |
- | |
+import { | |
+ dispatchEvent, | |
+ ConsoleSpy | |
+} from '../util'; | |
+ | |
+describe('DemoFormSku Component', () => { | |
+ let originalConsole, fakeConsole; | |
+ let el, input, form; | |
+ | |
beforeEach(() => { | |
- // declare a fake console to track all the logs | |
- fakeConsole = {}; | |
- fakeConsole._logs = []; | |
- fakeConsole.log = (...theArgs) => fakeConsole._logs.push(theArgs.join(' ')); | |
- fakeConsole.warn = (...theArgs) => fakeConsole._logs.push(theArgs.join(' ')); | |
- // replace the real console with our fake version | |
- _console = window.console; | |
+ // replace the real window.console with our spy | |
+ fakeConsole = new ConsoleSpy(); | |
+ originalConsole = window.console; | |
(<any>window).console = fakeConsole; | |
}); | |
- // restores the real console | |
- afterAll(() => (<any>window).console = _console); | |
+ // restore real console | |
+ afterAll(() => (<any>window).console = originalConsole); | |
function createComponent(tcb: TestComponentBuilder): Promise<ComponentFixture<any>> { | |
- return tcb.createAsync(DemoFormSku).then((fixture) => { | |
- el = fixture.debugElement.nativeElement; | |
- input = fixture.debugElement.query(By.css("input")).nativeElement; | |
- form = fixture.debugElement.query(By.css("form")).nativeElement; | |
- fixture.detectChanges(); | |
+ return tcb.createAsync(DemoFormSku) | |
+ .then((fixture) => { | |
+ el = fixture.debugElement.nativeElement; | |
+ input = fixture.debugElement.query(By.css('input')).nativeElement; | |
+ form = fixture.debugElement.query(By.css('form')).nativeElement; | |
+ fixture.detectChanges(); | |
- return fixture; | |
+ return fixture; | |
}); | |
} | |
@@ -59,7 +52,7 @@ describe('DemoFormSku', () => { | |
dispatchEvent(form, 'submit'); | |
tick(); | |
- expect(fakeConsole._logs).toContain('you submitted value: [object Object]'); | |
+ expect(fakeConsole.logs).toContain('you submitted value: [object Object]'); | |
}); | |
}) | |
)); | |
diff --git a/manuscript/code/forms/test/forms/demo_form_sku_with_builder.spec.ts b/manuscript/code/forms/test/forms/demo_form_sku_with_builder.spec.ts | |
index 77ccc19..f12893c 100644 | |
--- a/manuscript/code/forms/test/forms/demo_form_sku_with_builder.spec.ts | |
+++ b/manuscript/code/forms/test/forms/demo_form_sku_with_builder.spec.ts | |
@@ -1,25 +1,33 @@ | |
import { | |
it, | |
describe, | |
- | |
expect, | |
- | |
inject, | |
- async, | |
- beforeEachProviders | |
+ async | |
} from '@angular/core/testing'; | |
-import { TestComponentBuilder } from '@angular/compiler/testing'; | |
-import { FormBuilder } from '@angular/common'; | |
- | |
+import { TestComponentBuilder } from '@angular/core/testing'; | |
+import { | |
+ disableDeprecatedForms, | |
+ provideForms, | |
+ FormBuilder | |
+} from '@angular/forms'; | |
import { DemoFormSkuBuilder } from '../../app/ts/forms/demo_form_sku_with_builder'; | |
-beforeEachProviders(() => { | |
- return [FormBuilder]; | |
-}); | |
- | |
describe('DemoFormSkuBuilder', () => { | |
+ let providerArr: any[]; | |
+ beforeEach(() => { | |
+ providerArr = [ | |
+ disableDeprecatedForms(), | |
+ provideForms(), | |
+ FormBuilder | |
+ ]; | |
+ }); | |
+ | |
it('initializes sku', async(inject([TestComponentBuilder], (tcb) => { | |
- return tcb.createAsync(DemoFormSkuBuilder).then((fixture) => { | |
+ let fb = new FormBuilder(); | |
+ return tcb.overrideProviders(DemoFormSkuBuilder, providerArr) | |
+ .createAsync(DemoFormSkuBuilder) | |
+ .then((fixture) => { | |
let comp = fixture.debugElement.componentInstance; | |
let el = fixture.debugElement.nativeElement; | |
@@ -32,4 +40,5 @@ describe('DemoFormSkuBuilder', () => { | |
expect(el.querySelector('form input').value).toEqual('ABC123'); | |
}); | |
}))); | |
+ | |
}); | |
diff --git a/manuscript/code/forms/test/forms/demo_form_with_custom_validations.spec.ts b/manuscript/code/forms/test/forms/demo_form_with_custom_validations.spec.ts | |
index 1632a71..adc3f05 100644 | |
--- a/manuscript/code/forms/test/forms/demo_form_with_custom_validations.spec.ts | |
+++ b/manuscript/code/forms/test/forms/demo_form_with_custom_validations.spec.ts | |
@@ -1,28 +1,41 @@ | |
import { | |
it, | |
describe, | |
- | |
- expect, | |
- | |
inject, | |
async, | |
- beforeEachProviders, | |
- | |
+ addProviders, | |
+} from '@angular/core/testing'; | |
+import { | |
+ disableDeprecatedForms, | |
+ provideForms, | |
+ FormBuilder | |
+} from '@angular/forms'; | |
+import { | |
+ TestComponentBuilder, | |
+ ComponentFixture | |
} from '@angular/core/testing'; | |
-import { TestComponentBuilder, ComponentFixture } from '@angular/compiler/testing'; | |
-import { dispatchEvent } from '@angular/platform-browser/testing'; | |
+import { dispatchEvent } from '../util'; | |
import { By } from '@angular/platform-browser/src/dom/debug/by'; | |
-import { FormBuilder } from '@angular/common'; | |
- | |
-import { DemoFormWithCustomValidations } from '../../app/ts/forms/demo_form_with_custom_validations'; | |
+import { | |
+ DemoFormWithCustomValidations | |
+} from '../../app/ts/forms/demo_form_with_custom_validations'; | |
describe('DemoFormWithCustomValidations', () => { | |
var el, input, form; | |
+ let providerArr: any[]; | |
- beforeEachProviders(() => { return [FormBuilder]; }); | |
+ beforeEach(() => { | |
+ addProviders([ | |
+ disableDeprecatedForms(), | |
+ provideForms(), | |
+ FormBuilder | |
+ ]); | |
+ }); | |
function createComponent(tcb: TestComponentBuilder): Promise<ComponentFixture<any>> { | |
- return tcb.createAsync(DemoFormWithCustomValidations).then((fixture) => { | |
+ return tcb.overrideProviders(DemoFormWithCustomValidations, providerArr) | |
+ .createAsync(DemoFormWithCustomValidations) | |
+ .then((fixture) => { | |
el = fixture.debugElement.nativeElement; | |
input = fixture.debugElement.query(By.css("input")).nativeElement; | |
form = fixture.debugElement.query(By.css("form")).nativeElement; | |
@@ -32,34 +45,37 @@ describe('DemoFormWithCustomValidations', () => { | |
}); | |
} | |
- it('displays errors with no sku', async(inject([TestComponentBuilder], (tcb) => { | |
+ it('displays errors with no sku', | |
+ async(inject([TestComponentBuilder], (tcb) => { | |
return createComponent(tcb).then((fixture) => { | |
input.value = ''; | |
dispatchEvent(input, 'input'); | |
fixture.detectChanges(); | |
let msgs = el.querySelectorAll('.ui.error.message'); | |
- expect(msgs[0]).toHaveText('SKU is invalid'); | |
- expect(msgs[1]).toHaveText('SKU is required'); | |
- expect(msgs[2]).toHaveText('SKU must begin with 123'); | |
- expect(msgs[3]).toHaveText('Form is invalid'); | |
+ expect(msgs[0].innerHTML).toContain('SKU is invalid'); | |
+ expect(msgs[1].innerHTML).toContain('SKU is required'); | |
+ expect(msgs[2].innerHTML).toContain('SKU must begin with <tt>123</tt>'); | |
+ expect(msgs[3].innerHTML).toContain('Form is invalid'); | |
}); | |
}))); | |
- it('removes the required error when sku has a value', async(inject([TestComponentBuilder], (tcb) => { | |
+ it('removes the required error when sku has a value', | |
+ async(inject([TestComponentBuilder], (tcb) => { | |
return createComponent(tcb).then((fixture) => { | |
input.value = 'ABC'; | |
dispatchEvent(input, 'input'); | |
fixture.detectChanges(); | |
let msgs = el.querySelectorAll('.ui.error.message'); | |
- expect(msgs[0]).toHaveText('SKU is invalid'); | |
- expect(msgs[1]).toHaveText('SKU must begin with 123'); | |
- expect(msgs[2]).toHaveText('Form is invalid'); | |
+ expect(msgs[0].innerHTML).toContain('SKU is invalid'); | |
+ expect(msgs[1].innerHTML).toContain('SKU must begin with <tt>123</tt>'); | |
+ expect(msgs[2].innerHTML).toContain('Form is invalid'); | |
}); | |
}))); | |
- it('removes all errors when sku starts with 123', async(inject([TestComponentBuilder], (tcb) => { | |
+ it('removes all errors when sku starts with 123', | |
+ async(inject([TestComponentBuilder], (tcb) => { | |
return createComponent(tcb).then((fixture) => { | |
input.value = '123ABC'; | |
dispatchEvent(input, 'input'); | |
diff --git a/manuscript/code/forms/test/forms/demo_form_with_events.spec.ts b/manuscript/code/forms/test/forms/demo_form_with_events.spec.ts | |
index b8e4a0c..ba20d0b 100644 | |
--- a/manuscript/code/forms/test/forms/demo_form_with_events.spec.ts | |
+++ b/manuscript/code/forms/test/forms/demo_form_with_events.spec.ts | |
@@ -1,58 +1,63 @@ | |
import { | |
it, | |
describe, | |
- | |
- expect, | |
inject, | |
async, | |
- | |
fakeAsync, | |
tick, | |
- beforeEachProviders, | |
- | |
+ addProviders | |
} from '@angular/core/testing'; | |
-import { TestComponentBuilder, ComponentFixture } from '@angular/compiler/testing'; | |
-import { dispatchEvent } from '@angular/platform-browser/testing'; | |
+import { | |
+ TestComponentBuilder, | |
+ ComponentFixture | |
+} from '@angular/core/testing'; | |
+import { | |
+ disableDeprecatedForms, | |
+ provideForms, | |
+ FormBuilder | |
+} from '@angular/forms'; | |
import { By } from '@angular/platform-browser/src/dom/debug/by'; | |
-import { FormBuilder } from '@angular/common'; | |
- | |
import { DemoFormWithEvents } from '../../app/ts/forms/demo_form_with_events'; | |
+import { | |
+ dispatchEvent, | |
+ ConsoleSpy | |
+} from '../util'; | |
describe('DemoFormWithEvents', () => { | |
- var _console; | |
- var fakeConsole; | |
- var el, input, form; | |
+ let originalConsole, fakeConsole; | |
+ let el, input, form; | |
beforeEach(() => { | |
- // declare a fake console to track all the logs | |
- fakeConsole = {}; | |
- fakeConsole._logs = []; | |
- fakeConsole.log = (...theArgs) => fakeConsole._logs.push(theArgs.join(' ')); | |
- | |
- // replace the real console with our fake version | |
- _console = window.console; | |
+ // replace the real window.console with our spy | |
+ fakeConsole = new ConsoleSpy(); | |
+ originalConsole = window.console; | |
(<any>window).console = fakeConsole; | |
+ | |
+ addProviders([ | |
+ disableDeprecatedForms(), | |
+ provideForms(), | |
+ FormBuilder | |
+ ]); | |
}); | |
// restores the real console | |
- afterAll(() => (<any>window).console = _console); | |
- | |
- beforeEachProviders(() => { | |
- return [FormBuilder]; | |
- }); | |
+ afterAll(() => (<any>window).console = originalConsole); | |
- function createComponent(tcb: TestComponentBuilder): Promise<ComponentFixture<any>> { | |
- return tcb.createAsync(DemoFormWithEvents).then((fixture) => { | |
+ function createComponent(tcb: TestComponentBuilder): | |
+ Promise<ComponentFixture<any>> { | |
+ return tcb.createAsync(DemoFormWithEvents) | |
+ .then((fixture) => { | |
el = fixture.debugElement.nativeElement; | |
- input = fixture.debugElement.query(By.css("input")).nativeElement; | |
- form = fixture.debugElement.query(By.css("form")).nativeElement; | |
+ input = fixture.debugElement.query(By.css('input')).nativeElement; | |
+ form = fixture.debugElement.query(By.css('form')).nativeElement; | |
fixture.detectChanges(); | |
return fixture; | |
}); | |
} | |
- it('displays errors with no sku', async(inject([TestComponentBuilder], (tcb) => { | |
+ it('displays errors with no sku', | |
+ async(inject([TestComponentBuilder], (tcb) => { | |
return createComponent(tcb).then((fixture) => { | |
input.value = ''; | |
dispatchEvent(input, 'input'); | |
@@ -60,12 +65,13 @@ describe('DemoFormWithEvents', () => { | |
// no value on sku field, all error messages are displayed | |
let msgs = el.querySelectorAll('.ui.error.message'); | |
- expect(msgs[0]).toHaveText('SKU is invalid'); | |
- expect(msgs[1]).toHaveText('SKU is required'); | |
+ expect(msgs[0].innerHTML).toContain('SKU is invalid'); | |
+ expect(msgs[1].innerHTML).toContain('SKU is required'); | |
}); | |
}))); | |
- it('displays no errors when sku has a value', async(inject([TestComponentBuilder], (tcb) => { | |
+ it('displays no errors when sku has a value', | |
+ async(inject([TestComponentBuilder], (tcb) => { | |
return createComponent(tcb).then((fixture) => { | |
input.value = 'XYZ'; | |
dispatchEvent(input, 'input'); | |
@@ -83,7 +89,7 @@ describe('DemoFormWithEvents', () => { | |
dispatchEvent(input, 'input'); | |
tick(); | |
- expect(fakeConsole._logs).toContain('sku changed to: XYZ'); | |
+ expect(fakeConsole.logs).toContain('sku changed to: XYZ'); | |
}); | |
}) | |
)); | |
@@ -95,7 +101,7 @@ describe('DemoFormWithEvents', () => { | |
dispatchEvent(input, 'input'); | |
tick(); | |
- expect(fakeConsole._logs).toContain('form changed to: [object Object]'); | |
+ expect(fakeConsole.logs).toContain('form changed to: [object Object]'); | |
}); | |
}) | |
)); | |
@@ -111,7 +117,7 @@ describe('DemoFormWithEvents', () => { | |
dispatchEvent(form, 'submit'); | |
tick(); | |
- expect(fakeConsole._logs).toContain('you submitted value: ABC'); | |
+ expect(fakeConsole.logs).toContain('you submitted value: ABC'); | |
}); | |
}) | |
)); | |
diff --git a/manuscript/code/forms/test/forms/demo_form_with_events_bad.spec.ts b/manuscript/code/forms/test/forms/demo_form_with_events_bad.spec.ts | |
index 76ef231..c5a0c75 100644 | |
--- a/manuscript/code/forms/test/forms/demo_form_with_events_bad.spec.ts | |
+++ b/manuscript/code/forms/test/forms/demo_form_with_events_bad.spec.ts | |
@@ -1,52 +1,55 @@ | |
import { | |
it, | |
describe, | |
- | |
expect, | |
inject, | |
- | |
- | |
fakeAsync, | |
tick, | |
- beforeEachProviders | |
- | |
+ addProviders | |
} from '@angular/core/testing'; | |
-import { TestComponentBuilder } from '@angular/compiler/testing'; | |
-import { dispatchEvent } from '@angular/platform-browser/testing'; | |
+import { | |
+ TestComponentBuilder, | |
+ ComponentFixture | |
+} from '@angular/core/testing'; | |
+import { | |
+ disableDeprecatedForms, | |
+ provideForms, | |
+ FormBuilder | |
+} from '@angular/forms'; | |
import { By } from '@angular/platform-browser/src/dom/debug/by'; | |
-import { FormBuilder } from '@angular/common'; | |
- | |
import { DemoFormWithEvents } from '../../app/ts/forms/demo_form_with_events'; | |
+import { | |
+ dispatchEvent, | |
+ ConsoleSpy | |
+} from '../util'; | |
describe('DemoFormWithEvents (bad)', () => { | |
- var _console; | |
- var fakeConsole; | |
+ var originalConsole, fakeConsole; | |
var el, input, form; | |
beforeEach(() => { | |
- // declare a fake console to track all the logs | |
- fakeConsole = {}; | |
- fakeConsole._logs = []; | |
- fakeConsole.log = (...theArgs) => fakeConsole._logs.push(theArgs.join(' ')); | |
- | |
- // replace the real console with our fake version | |
- _console = window.console; | |
+ // replace the real window.console with our spy | |
+ fakeConsole = new ConsoleSpy(); | |
+ originalConsole = window.console; | |
(<any>window).console = fakeConsole; | |
+ | |
+ addProviders([ | |
+ disableDeprecatedForms(), | |
+ provideForms(), | |
+ FormBuilder | |
+ ]); | |
}); | |
// restores the real console | |
- afterAll(() => (<any>window).console = _console); | |
- | |
- beforeEachProviders(() => { | |
- return [FormBuilder]; | |
- }); | |
+ afterAll(() => (<any>window).console = originalConsole); | |
- it('validates and trigger events', inject([TestComponentBuilder], | |
+ it('validates and triggers events', inject([TestComponentBuilder], | |
fakeAsync((tcb) => { | |
- tcb.createAsync(DemoFormWithEvents).then((fixture) => { | |
+ tcb.createAsync(DemoFormWithEvents) | |
+ .then((fixture) => { | |
let el = fixture.debugElement.nativeElement; | |
- let input = fixture.debugElement.query(By.css("input")).nativeElement; | |
- let form = fixture.debugElement.query(By.css("form")).nativeElement; | |
+ let input = fixture.debugElement.query(By.css('input')).nativeElement; | |
+ let form = fixture.debugElement.query(By.css('form')).nativeElement; | |
fixture.detectChanges(); | |
input.value = ''; | |
@@ -56,8 +59,8 @@ describe('DemoFormWithEvents (bad)', () => { | |
// no value on sku field, all error messages are displayed | |
let msgs = el.querySelectorAll('.ui.error.message'); | |
- expect(msgs[0]).toHaveText('SKU is invalid'); | |
- expect(msgs[1]).toHaveText('SKU is required'); | |
+ expect(msgs[0].innerHTML).toContain('SKU is invalid'); | |
+ expect(msgs[1].innerHTML).toContain('SKU is required'); | |
// displays no errors when sku has a value | |
input.value = 'XYZ'; | |
@@ -73,7 +76,7 @@ describe('DemoFormWithEvents (bad)', () => { | |
tick(); | |
// checks for the form submitted message | |
- expect(fakeConsole._logs).toContain('you submitted value: XYZ'); | |
+ expect(fakeConsole.logs).toContain('you submitted value: XYZ'); | |
}); | |
}) | |
)); | |
diff --git a/manuscript/code/forms/test/forms/demo_form_with_validations_explicit.spec.ts b/manuscript/code/forms/test/forms/demo_form_with_validations_explicit.spec.ts | |
index 6c68648..74e37e9 100644 | |
--- a/manuscript/code/forms/test/forms/demo_form_with_validations_explicit.spec.ts | |
+++ b/manuscript/code/forms/test/forms/demo_form_with_validations_explicit.spec.ts | |
@@ -1,32 +1,41 @@ | |
import { | |
it, | |
describe, | |
- | |
expect, | |
- | |
inject, | |
async, | |
- beforeEachProviders, | |
- | |
+ addProviders | |
} from '@angular/core/testing'; | |
import { | |
- CORE_DIRECTIVES, | |
- FORM_DIRECTIVES, | |
-} from '@angular/common'; | |
-import { TestComponentBuilder, ComponentFixture } from '@angular/compiler/testing'; | |
-import { dispatchEvent } from '@angular/platform-browser/testing'; | |
+ TestComponentBuilder, | |
+ ComponentFixture | |
+} from '@angular/core/testing'; | |
+import { | |
+ disableDeprecatedForms, | |
+ provideForms, | |
+ FormBuilder | |
+} from '@angular/forms'; | |
import { By } from '@angular/platform-browser/src/dom/debug/by'; | |
-import { FormBuilder } from '@angular/common'; | |
- | |
import { DemoFormWithValidationsExplicit } from '../../app/ts/forms/demo_form_with_validations_explicit'; | |
+import { | |
+ dispatchEvent, | |
+ ConsoleSpy | |
+} from '../util'; | |
describe('DemoFormWithValidationsExplicit', () => { | |
- var el, input, form; | |
+ let el, input, form; | |
- beforeEachProviders(() => { return [FormBuilder]; }); | |
+ beforeEach(() => { | |
+ addProviders([ | |
+ disableDeprecatedForms(), | |
+ provideForms(), | |
+ FormBuilder | |
+ ]); | |
+ }); | |
function createComponent(tcb: TestComponentBuilder): Promise<ComponentFixture<any>> { | |
- return tcb.createAsync(DemoFormWithValidationsExplicit).then((fixture) => { | |
+ return tcb.createAsync(DemoFormWithValidationsExplicit) | |
+ .then((fixture) => { | |
el = fixture.debugElement.nativeElement; | |
input = fixture.debugElement.query(By.css("input")).nativeElement; | |
form = fixture.debugElement.query(By.css("form")).nativeElement; | |
@@ -43,8 +52,8 @@ describe('DemoFormWithValidationsExplicit', () => { | |
fixture.detectChanges(); | |
let msgs = el.querySelectorAll('.ui.error.message'); | |
- expect(msgs[0]).toHaveText('SKU is invalid'); | |
- expect(msgs[1]).toHaveText('SKU is required'); | |
+ expect(msgs[0].innerHTML).toContain('SKU is invalid'); | |
+ expect(msgs[1].innerHTML).toContain('SKU is required'); | |
}); | |
}))); | |
diff --git a/manuscript/code/forms/test/forms/demo_form_with_validations_shorthand.spec.ts b/manuscript/code/forms/test/forms/demo_form_with_validations_shorthand.spec.ts | |
index 0c9bba7..24f5b59 100644 | |
--- a/manuscript/code/forms/test/forms/demo_form_with_validations_shorthand.spec.ts | |
+++ b/manuscript/code/forms/test/forms/demo_form_with_validations_shorthand.spec.ts | |
@@ -1,50 +1,52 @@ | |
import { | |
it, | |
describe, | |
- | |
expect, | |
inject, | |
async, | |
fakeAsync, | |
tick, | |
- | |
- beforeEachProviders, | |
- | |
+ addProviders | |
+} from '@angular/core/testing'; | |
+import { | |
+ TestComponentBuilder, | |
+ ComponentFixture | |
} from '@angular/core/testing'; | |
import { | |
- CORE_DIRECTIVES, | |
- FORM_DIRECTIVES, | |
-} from '@angular/common'; | |
-import { TestComponentBuilder, ComponentFixture } from '@angular/compiler/testing'; | |
-import { dispatchEvent } from '@angular/platform-browser/testing'; | |
+ disableDeprecatedForms, | |
+ provideForms, | |
+ FormBuilder | |
+} from '@angular/forms'; | |
import { By } from '@angular/platform-browser/src/dom/debug/by'; | |
-import { FormBuilder } from '@angular/common'; | |
- | |
import { DemoFormWithValidationsShorthand } from '../../app/ts/forms/demo_form_with_validations_shorthand'; | |
+import { | |
+ dispatchEvent, | |
+ ConsoleSpy | |
+} from '../util'; | |
describe('DemoFormWithValidationsShorthand', () => { | |
- var _console; | |
- var fakeConsole; | |
- var el, input, form; | |
+ let originalConsole, fakeConsole; | |
+ let el, input, form; | |
beforeEach(() => { | |
- // declare a fake console to track all the logs | |
- fakeConsole = {}; | |
- fakeConsole._logs = []; | |
- fakeConsole.log = (...theArgs) => fakeConsole._logs.push(theArgs.join(' ')); | |
- | |
- // replace the real console with our fake version | |
- _console = window.console; | |
+ // replace the real window.console with our spy | |
+ fakeConsole = new ConsoleSpy(); | |
+ originalConsole = window.console; | |
(<any>window).console = fakeConsole; | |
- }); | |
- // restores the real console | |
- afterAll(() => (<any>window).console = _console); | |
+ addProviders([ | |
+ disableDeprecatedForms(), | |
+ provideForms(), | |
+ FormBuilder | |
+ ]); | |
+ }); | |
- beforeEachProviders(() => { return [FormBuilder]; }); | |
+ // restore real console | |
+ afterAll(() => (<any>window).console = originalConsole); | |
function createComponent(tcb: TestComponentBuilder): Promise<ComponentFixture<any>> { | |
- return tcb.createAsync(DemoFormWithValidationsShorthand).then((fixture) => { | |
+ return tcb.createAsync(DemoFormWithValidationsShorthand) | |
+ .then((fixture) => { | |
el = fixture.debugElement.nativeElement; | |
input = fixture.debugElement.query(By.css("input")).nativeElement; | |
form = fixture.debugElement.query(By.css("form")).nativeElement; | |
@@ -62,8 +64,8 @@ describe('DemoFormWithValidationsShorthand', () => { | |
// no value on sku field, all error messages are displayed | |
let msgs = el.querySelectorAll('.ui.error.message'); | |
- expect(msgs[0]).toHaveText('SKU is invalid'); | |
- expect(msgs[1]).toHaveText('SKU is required'); | |
+ expect(msgs[0].innerHTML).toContain('SKU is invalid'); | |
+ expect(msgs[1].innerHTML).toContain('SKU is required'); | |
}); | |
}))); | |
@@ -89,7 +91,7 @@ describe('DemoFormWithValidationsShorthand', () => { | |
dispatchEvent(form, 'submit'); | |
tick(); | |
- expect(fakeConsole._logs).toContain('you submitted value: XYZ'); | |
+ expect(fakeConsole.logs).toContain('you submitted value: XYZ'); | |
}); | |
}) | |
)); | |
diff --git a/manuscript/code/forms/test/util.ts b/manuscript/code/forms/test/util.ts | |
new file mode 100644 | |
index 0000000..c5b1cb1 | |
--- /dev/null | |
+++ b/manuscript/code/forms/test/util.ts | |
@@ -0,0 +1,19 @@ | |
+/* | |
+ * Utility functions for our browser tests | |
+ */ | |
+import { getDOM } from '@angular/platform-browser/src/dom/dom_adapter'; | |
+ | |
+export function dispatchEvent(element: any, eventType: any) { | |
+ getDOM().dispatchEvent(element, getDOM().createEvent(eventType)); | |
+} | |
+ | |
+export class ConsoleSpy { | |
+ public logs: string[] = []; | |
+ log(...args) { | |
+ this.logs.push(args.join(' ')); | |
+ } | |
+ warn(...args) { | |
+ this.log(...args); | |
+ } | |
+} | |
+ | |
diff --git a/manuscript/code/how_angular_works/inventory_app/package.json b/manuscript/code/how_angular_works/inventory_app/package.json | |
index 7b1fd25..72843b3 100644 | |
--- a/manuscript/code/how_angular_works/inventory_app/package.json | |
+++ b/manuscript/code/how_angular_works/inventory_app/package.json | |
@@ -11,13 +11,14 @@ | |
}, | |
"license": "ISC", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"core-js": "2.2.2", | |
"es6-shim": "0.35.0", | |
diff --git a/manuscript/code/http/package.json b/manuscript/code/http/package.json | |
index 12b3819..42465f1 100644 | |
--- a/manuscript/code/http/package.json | |
+++ b/manuscript/code/http/package.json | |
@@ -6,18 +6,19 @@ | |
"scripts": { | |
"go": "./node_modules/.bin/webpack-dev-server --display-reasons --display-chunks", | |
"clean": "true", | |
- "test": "karma start" | |
+ "test": "karma start --single-run" | |
}, | |
"author": "Nate Murray <[email protected]>", | |
"license": "MIT", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"base64id": "0.1.0", | |
"core-js": "2.2.2", | |
diff --git a/manuscript/code/http/test/MoreHTTPRequests.spec.ts b/manuscript/code/http/test/MoreHTTPRequests.spec.ts | |
index c1c03f7..76c23d5 100644 | |
--- a/manuscript/code/http/test/MoreHTTPRequests.spec.ts | |
+++ b/manuscript/code/http/test/MoreHTTPRequests.spec.ts | |
@@ -1,44 +1,45 @@ | |
-import {provide} from '@angular/core'; | |
+import { provide } from '@angular/core'; | |
import { | |
it, | |
describe, | |
expect, | |
inject, | |
+ addProviders, | |
async, | |
- afterEach, | |
- beforeEachProviders, | |
+ TestComponentBuilder | |
} from '@angular/core/testing'; | |
-import {TestComponentBuilder} from '@angular/compiler/testing'; | |
import {MockBackend} from '@angular/http/testing'; | |
import { | |
Http, | |
ConnectionBackend, | |
BaseRequestOptions, | |
Response, | |
- ResponseOptions, | |
RequestMethod, | |
} from '@angular/http'; | |
import { MoreHTTPRequests } from '../app/ts/components/MoreHTTPRequests'; | |
-beforeEachProviders(() => { | |
- return [ | |
- BaseRequestOptions, | |
- MockBackend, | |
- provide(Http, {useFactory: (backend: ConnectionBackend, defaultOptions: BaseRequestOptions) => { | |
- return new Http(backend, defaultOptions); | |
- }, deps: [MockBackend, BaseRequestOptions]}), | |
- ] | |
-}); | |
- | |
describe('MoreHTTPRequests', () => { | |
+ beforeEach(() => { | |
+ addProviders([ | |
+ BaseRequestOptions, | |
+ MockBackend, | |
+ provide(Http, { | |
+ useFactory: (backend: ConnectionBackend, | |
+ defaultOptions: BaseRequestOptions) => { | |
+ return new Http(backend, defaultOptions); | |
+ }, deps: [MockBackend, BaseRequestOptions]}), | |
+ ]); | |
+ }); | |
+ | |
it('performs a POST', | |
async(inject([TestComponentBuilder, MockBackend], (tcb, backend) => { | |
return tcb.createAsync(MoreHTTPRequests).then((fixture) => { | |
let comp = fixture.debugElement.componentInstance; | |
backend.connections.subscribe(c => { | |
- expect(c.request.url).toBe('http://jsonplaceholder.typicode.com/posts'); | |
+ expect(c.request.url) | |
+ .toBe('http://jsonplaceholder.typicode.com/posts'); | |
expect(c.request.method).toBe(RequestMethod.Post); | |
c.mockRespond(new Response(<any>{body: '{"response": "OK"}'})); | |
}); | |
@@ -55,7 +56,8 @@ describe('MoreHTTPRequests', () => { | |
let comp = fixture.debugElement.componentInstance; | |
backend.connections.subscribe(c => { | |
- expect(c.request.url).toBe('http://jsonplaceholder.typicode.com/posts/1'); | |
+ expect(c.request.url) | |
+ .toBe('http://jsonplaceholder.typicode.com/posts/1'); | |
expect(c.request.method).toBe(RequestMethod.Delete); | |
c.mockRespond(new Response(<any>{body: '{"response": "OK"}'})); | |
}); | |
@@ -72,7 +74,8 @@ describe('MoreHTTPRequests', () => { | |
let comp = fixture.debugElement.componentInstance; | |
backend.connections.subscribe(c => { | |
- expect(c.request.url).toBe('http://jsonplaceholder.typicode.com/posts/1'); | |
+ expect(c.request.url) | |
+ .toBe('http://jsonplaceholder.typicode.com/posts/1'); | |
expect(c.request.headers.has('X-API-TOKEN')).toBeTruthy(); | |
expect(c.request.headers.get('X-API-TOKEN')).toEqual('ng-book'); | |
c.mockRespond(new Response(<any>{body: '{"response": "OK"}'})); | |
diff --git a/manuscript/code/http/test/YouTubeSearchComponentAfter.spec.ts b/manuscript/code/http/test/YouTubeSearchComponentAfter.spec.ts | |
index 2b68859..1fe8157 100644 | |
--- a/manuscript/code/http/test/YouTubeSearchComponentAfter.spec.ts | |
+++ b/manuscript/code/http/test/YouTubeSearchComponentAfter.spec.ts | |
@@ -11,7 +11,7 @@ import { | |
beforeEach, | |
beforeEachProviders | |
} from '@angular/core/testing'; | |
-import {TestComponentBuilder} from '@angular/compiler/testing'; | |
+import {TestComponentBuilder} from '@angular/core/testing'; | |
import {MockBackend} from '@angular/http/testing'; | |
import { | |
Http, | |
diff --git a/manuscript/code/http/test/YouTubeSearchComponentBefore.spec.ts b/manuscript/code/http/test/YouTubeSearchComponentBefore.spec.ts | |
index 76e6783..5e0bd1e 100644 | |
--- a/manuscript/code/http/test/YouTubeSearchComponentBefore.spec.ts | |
+++ b/manuscript/code/http/test/YouTubeSearchComponentBefore.spec.ts | |
@@ -6,18 +6,14 @@ import { | |
inject, | |
fakeAsync, | |
tick, | |
- afterEach, | |
- beforeEachProviders | |
+ addProviders | |
} from '@angular/core/testing'; | |
-import {TestComponentBuilder} from '@angular/compiler/testing'; | |
import {MockBackend} from '@angular/http/testing'; | |
import { | |
Http, | |
ConnectionBackend, | |
BaseRequestOptions, | |
- Response, | |
- ResponseOptions, | |
- RequestMethod, | |
+ Response | |
} from '@angular/http'; | |
import { | |
@@ -27,23 +23,27 @@ import { | |
} from '../app/ts/components/YouTubeSearchComponent'; | |
describe('MoreHTTPRequests (before)', () => { | |
- beforeEachProviders(() => { | |
- return [ | |
+ beforeEach(() => { | |
+ addProviders([ | |
YouTubeService, | |
BaseRequestOptions, | |
MockBackend, | |
provide(YOUTUBE_API_KEY, {useValue: 'YOUTUBE_API_KEY'}), | |
provide(YOUTUBE_API_URL, {useValue: 'YOUTUBE_API_URL'}), | |
- provide(Http, {useFactory: (backend: ConnectionBackend, defaultOptions: BaseRequestOptions) => { | |
- return new Http(backend, defaultOptions); | |
- }, deps: [MockBackend, BaseRequestOptions]}), | |
- ] | |
+ provide(Http, { | |
+ useFactory: (backend: ConnectionBackend, | |
+ defaultOptions: BaseRequestOptions) => { | |
+ return new Http(backend, defaultOptions); | |
+ }, | |
+ deps: [MockBackend, BaseRequestOptions] | |
+ }), | |
+ ]); | |
}); | |
describe('search', () => { | |
it('parses YouTube response', | |
inject([YouTubeService, MockBackend], fakeAsync((service, backend) => { | |
- var res; | |
+ let res; | |
backend.connections.subscribe(c => { | |
c.mockRespond(new Response(<any>{ | |
@@ -57,12 +57,7 @@ describe('MoreHTTPRequests (before)', () => { | |
"description": "DESCRIPTION", | |
"thumbnails": { | |
"high": { "url": "THUMBNAIL_URL" } | |
- } | |
- } | |
- } | |
- ] | |
- } | |
- ` | |
+ }}}]}` | |
})); | |
}); | |
diff --git a/manuscript/code/routes/auth/app/ts/app.ts b/manuscript/code/routes/auth/app/ts/app.ts | |
index 174eab8..57e6f10 100644 | |
--- a/manuscript/code/routes/auth/app/ts/app.ts | |
+++ b/manuscript/code/routes/auth/app/ts/app.ts | |
@@ -4,12 +4,12 @@ | |
import {provide, Component} from '@angular/core'; | |
import {bootstrap} from '@angular/platform-browser-dynamic'; | |
import { | |
+ provideRouter, | |
ROUTER_DIRECTIVES, | |
- ROUTER_PROVIDERS, | |
- | |
Router, | |
- RouteConfig, | |
-} from '@angular/router-deprecated'; | |
+ RouterConfig, | |
+} from '@angular/router'; | |
+import {provideForms} from '@angular/forms'; | |
import {LocationStrategy, HashLocationStrategy} from '@angular/common'; | |
/* | |
@@ -25,6 +25,7 @@ import {ProtectedComponent} from 'components/ProtectedComponent'; | |
* Services | |
*/ | |
import {AUTH_PROVIDERS} from 'services/AuthService'; | |
+import {LoggedInGuard} from 'guards/loggedIn.guard'; | |
/* | |
* Webpack | |
@@ -39,10 +40,10 @@ require('css/styles.scss'); | |
<div class="container"> | |
<h1>Router Sample</h1> | |
<div class="navLinks"> | |
- <a [routerLink]="['/Home']">Home</a> | |
- <a [routerLink]="['/About']">About</a> | |
- <a [routerLink]="['/Contact']">Contact us</a> | |
- <a [routerLink]="['/Protected']">Protected</a> | |
+ <a [routerLink]="['/home']">Home</a> | |
+ <a [routerLink]="['/about']">About</a> | |
+ <a [routerLink]="['/contact']">Contact us</a> | |
+ <a [routerLink]="['/protected']">Protected</a> | |
</div> | |
</div> | |
</div> | |
@@ -59,20 +60,24 @@ require('css/styles.scss'); | |
</div> | |
` | |
}) | |
-@RouteConfig([ | |
- { path: '/', name: 'root', redirectTo: ['Home'] }, | |
- { path: '/home', name: 'Home', component: HomeComponent }, | |
- { path: '/about', name: 'About', component: AboutComponent }, | |
- { path: '/contact', name: 'Contact', component: ContactComponent }, | |
- { path: '/protected', name: 'Protected', component: ProtectedComponent }, | |
-]) | |
class RoutesDemoApp { | |
constructor(public router: Router) { | |
} | |
} | |
+const routes: RouterConfig = [ | |
+ { path: '', redirectTo: 'home', terminal: true }, | |
+ { path: 'home', component: HomeComponent }, | |
+ { path: 'about', component: AboutComponent }, | |
+ { path: 'contact', component: ContactComponent }, | |
+ { path: 'protected', component: ProtectedComponent, | |
+ canActivate: [LoggedInGuard]} | |
+]; | |
+ | |
bootstrap(RoutesDemoApp, [ | |
- ROUTER_PROVIDERS, | |
+ provideRouter(routes), | |
AUTH_PROVIDERS, | |
- provide(LocationStrategy, {useClass: HashLocationStrategy}) | |
+ LoggedInGuard, | |
+ provide(LocationStrategy, {useClass: HashLocationStrategy}), | |
+ provideForms() | |
]); | |
diff --git a/manuscript/code/routes/auth/app/ts/components/LoginComponent.ts b/manuscript/code/routes/auth/app/ts/components/LoginComponent.ts | |
index 1255c30..56c700e 100644 | |
--- a/manuscript/code/routes/auth/app/ts/components/LoginComponent.ts | |
+++ b/manuscript/code/routes/auth/app/ts/components/LoginComponent.ts | |
@@ -48,11 +48,9 @@ export class LoginComponent { | |
this.message = ''; | |
if (!this.authService.login(username, password)) { | |
this.message = 'Incorrect credentials.'; | |
- /* tslint:disable */ | |
setTimeout(function() { | |
this.message = ''; | |
}.bind(this), 2500); | |
- /* tslint:enable */ | |
} | |
return false; | |
} | |
diff --git a/manuscript/code/routes/auth/app/ts/components/ProtectedComponent.ts b/manuscript/code/routes/auth/app/ts/components/ProtectedComponent.ts | |
index bed0ca2..16f26bd 100644 | |
--- a/manuscript/code/routes/auth/app/ts/components/ProtectedComponent.ts | |
+++ b/manuscript/code/routes/auth/app/ts/components/ProtectedComponent.ts | |
@@ -1,24 +1,11 @@ | |
/* | |
* Angular | |
*/ | |
-import {Component, ReflectiveInjector} from '@angular/core'; | |
-import {CanActivate} from '@angular/router-deprecated'; | |
- | |
-/* | |
- * Services | |
- */ | |
-import {AuthService} from 'services/AuthService'; | |
+import {Component} from '@angular/core'; | |
@Component({ | |
selector: 'protected', | |
template: `<h1>Protected content</h1>` | |
}) | |
-@CanActivate( | |
- (nextInstr: any, currInstr: any) => { | |
- let injector: any = ReflectiveInjector.resolveAndCreate([AuthService]); | |
- let authService: AuthService = injector.get(AuthService); | |
- return authService.isLogged(); | |
- } | |
-) | |
export class ProtectedComponent { | |
} | |
diff --git a/manuscript/code/routes/auth/app/ts/guards/loggedIn.guard.ts b/manuscript/code/routes/auth/app/ts/guards/loggedIn.guard.ts | |
new file mode 100644 | |
index 0000000..4f0b14a | |
--- /dev/null | |
+++ b/manuscript/code/routes/auth/app/ts/guards/loggedIn.guard.ts | |
@@ -0,0 +1,12 @@ | |
+import { Injectable } from '@angular/core'; | |
+import { CanActivate } from '@angular/router'; | |
+import { AuthService } from 'services/AuthService'; | |
+ | |
+@Injectable() | |
+export class LoggedInGuard implements CanActivate { | |
+ constructor(private authService: AuthService) {} | |
+ | |
+ canActivate(): boolean { | |
+ return this.authService.isLoggedIn(); | |
+ } | |
+} | |
diff --git a/manuscript/code/routes/auth/app/ts/services/AuthService.ts b/manuscript/code/routes/auth/app/ts/services/AuthService.ts | |
index b38aaa5..27124cd 100644 | |
--- a/manuscript/code/routes/auth/app/ts/services/AuthService.ts | |
+++ b/manuscript/code/routes/auth/app/ts/services/AuthService.ts | |
@@ -19,7 +19,7 @@ export class AuthService { | |
return localStorage.getItem('username'); | |
} | |
- isLogged(): boolean { | |
+ isLoggedIn(): boolean { | |
return this.getUser() !== null; | |
} | |
} | |
diff --git a/manuscript/code/routes/auth/package.json b/manuscript/code/routes/auth/package.json | |
index cfb9d8d..13a4109 100644 | |
--- a/manuscript/code/routes/auth/package.json | |
+++ b/manuscript/code/routes/auth/package.json | |
@@ -11,14 +11,14 @@ | |
"author": "Nate Murray <[email protected]>", | |
"license": "MIT", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
- "@angular/router-deprecated": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"base64id": "0.1.0", | |
"core-js": "2.2.2", | |
"lodash": "3.10.1", | |
diff --git a/manuscript/code/routes/basic/app/ts/app.html5.ts b/manuscript/code/routes/basic/app/ts/app.html5.ts | |
index 5366df3..9ea7870 100644 | |
--- a/manuscript/code/routes/basic/app/ts/app.html5.ts | |
+++ b/manuscript/code/routes/basic/app/ts/app.html5.ts | |
@@ -1,14 +1,13 @@ | |
/* | |
* Angular | |
*/ | |
-import {Component} from '@angular/core'; | |
+import {provide, Component} from '@angular/core'; | |
import {bootstrap} from '@angular/platform-browser-dynamic'; | |
import { | |
ROUTER_DIRECTIVES, | |
- ROUTER_PROVIDERS, | |
- Router, | |
- RouteConfig, | |
-} from '@angular/router-deprecated'; | |
+ provideRouter, | |
+ RouterConfig, | |
+} from '@angular/router'; | |
/* | |
* Components | |
@@ -40,18 +39,17 @@ require('css/styles.scss'); | |
</div> | |
` | |
}) | |
-@RouteConfig([ | |
- { path: '/', name: 'root', redirectTo: ['/Home'] }, | |
- { path: '/home', name: 'Home', component: HomeComponent }, | |
- { path: '/about', name: 'About', component: AboutComponent }, | |
- { path: '/contact', name: 'Contact', component: ContactComponent }, | |
- { path: '/contactus', name: 'ContactUs', redirectTo: ['/Contact'] }, | |
-]) | |
class RoutesDemoApp { | |
- constructor(public router: Router) { | |
- } | |
} | |
+const routes: RouterConfig = [ | |
+ { path: '', redirectTo: 'home', terminal: true }, | |
+ { path: 'home', component: HomeComponent }, | |
+ { path: 'about', component: AboutComponent }, | |
+ { path: 'contact', component: ContactComponent }, | |
+ { path: 'contactus', redirectTo: 'contact' }, | |
+]; | |
+ | |
bootstrap(RoutesDemoApp, [ | |
- ROUTER_PROVIDERS, | |
+ provideRouter(routes) | |
]); | |
diff --git a/manuscript/code/routes/basic/app/ts/app.ts b/manuscript/code/routes/basic/app/ts/app.ts | |
index 862cec5..4536456 100644 | |
--- a/manuscript/code/routes/basic/app/ts/app.ts | |
+++ b/manuscript/code/routes/basic/app/ts/app.ts | |
@@ -1,15 +1,13 @@ | |
/* | |
- * Angular | |
+ * Angular Imports | |
*/ | |
- | |
import {provide, Component} from '@angular/core'; | |
import {bootstrap} from '@angular/platform-browser-dynamic'; | |
import { | |
ROUTER_DIRECTIVES, | |
- ROUTER_PROVIDERS, | |
- RouteConfig, | |
-} from '@angular/router-deprecated'; | |
- | |
+ provideRouter, | |
+ RouterConfig, | |
+} from '@angular/router'; | |
import {LocationStrategy, HashLocationStrategy} from '@angular/common'; | |
/* | |
@@ -32,9 +30,9 @@ require('css/styles.scss'); | |
<nav> | |
<a>Navigation:</a> | |
<ul> | |
- <li><a [routerLink]="['/Home']">Home</a></li> | |
- <li><a [routerLink]="['/About']">About</a></li> | |
- <li><a [routerLink]="['/Contact']">Contact us</a></li> | |
+ <li><a [routerLink]="['home']">Home</a></li> | |
+ <li><a [routerLink]="['about']">About</a></li> | |
+ <li><a [routerLink]="['contact']">Contact us</a></li> | |
</ul> | |
</nav> | |
@@ -42,17 +40,18 @@ require('css/styles.scss'); | |
</div> | |
` | |
}) | |
-@RouteConfig([ | |
- { path: '/', name: 'root', redirectTo: ['/Home'] }, | |
- { path: '/home', name: 'Home', component: HomeComponent }, | |
- { path: '/about', name: 'About', component: AboutComponent }, | |
- { path: '/contact', name: 'Contact', component: ContactComponent }, | |
- { path: '/contactus', name: 'ContactUs', redirectTo: ['/Contact'] }, | |
-]) | |
class RoutesDemoApp { | |
} | |
+const routes: RouterConfig = [ | |
+ { path: '', redirectTo: 'home', terminal: true }, | |
+ { path: 'home', component: HomeComponent }, | |
+ { path: 'about', component: AboutComponent }, | |
+ { path: 'contact', component: ContactComponent }, | |
+ { path: 'contactus', redirectTo: 'contact' }, | |
+]; | |
+ | |
bootstrap(RoutesDemoApp, [ | |
- ROUTER_PROVIDERS, | |
+ provideRouter(routes), // <-- installs our routes | |
provide(LocationStrategy, {useClass: HashLocationStrategy}) | |
]); | |
diff --git a/manuscript/code/routes/basic/package.json b/manuscript/code/routes/basic/package.json | |
index 103b7f6..aa1fdcc 100644 | |
--- a/manuscript/code/routes/basic/package.json | |
+++ b/manuscript/code/routes/basic/package.json | |
@@ -10,13 +10,14 @@ | |
"author": "Nate Murray <[email protected]>", | |
"license": "MIT", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"base64id": "0.1.0", | |
"bootstrap-sass": "3.3.5", | |
@@ -41,7 +42,7 @@ | |
"ts-helpers": "1.1.1", | |
"tslint": "3.7.0-dev.2", | |
"typescript": "1.9.0-dev.20160409", | |
- "typings": "0.8.1", | |
+ "typings": "1.3.0", | |
"url-loader": "0.5.6", | |
"uuid": "2.0.1", | |
"val-loader": "0.5.0", | |
diff --git a/manuscript/code/routes/basic/tsconfig.json b/manuscript/code/routes/basic/tsconfig.json | |
index 88e8d4a..74d48c7 100644 | |
--- a/manuscript/code/routes/basic/tsconfig.json | |
+++ b/manuscript/code/routes/basic/tsconfig.json | |
@@ -21,6 +21,6 @@ | |
"node_modules" | |
], | |
"atom": { | |
- "rewriteTsconfig": true | |
+ "rewriteTsconfig": false | |
} | |
} | |
diff --git a/manuscript/code/routes/basic/tslint.json b/manuscript/code/routes/basic/tslint.json | |
index ae663cb..23bf2f3 100644 | |
--- a/manuscript/code/routes/basic/tslint.json | |
+++ b/manuscript/code/routes/basic/tslint.json | |
@@ -39,7 +39,6 @@ | |
"no-shadowed-variable": true, | |
"no-string-literal": true, | |
"no-switch-case-fall-through": true, | |
- "no-trailing-comma": true, | |
"no-trailing-whitespace": true, | |
"no-unused-expression": true, | |
"no-unused-variable": true, | |
@@ -55,7 +54,6 @@ | |
"quotemark": [true, "single"], | |
"radix": true, | |
"semicolon": true, | |
- "sort-object-literal-keys": false, | |
"triple-equals": [true, "allow-null-check"], | |
"typedef": [true, | |
"call-signature", | |
diff --git a/manuscript/code/routes/basic/typings/index.d.ts b/manuscript/code/routes/basic/typings/index.d.ts | |
new file mode 100644 | |
index 0000000..e69de29 | |
diff --git a/manuscript/code/routes/music/app/ts/app.ts b/manuscript/code/routes/music/app/ts/app.ts | |
index 6b31c6b..68d06bc 100644 | |
--- a/manuscript/code/routes/music/app/ts/app.ts | |
+++ b/manuscript/code/routes/music/app/ts/app.ts | |
@@ -1,5 +1,5 @@ | |
/* | |
- * Angular | |
+ * Angular Imports | |
*/ | |
import { | |
Component, | |
@@ -8,15 +8,15 @@ import { | |
import {bootstrap} from '@angular/platform-browser-dynamic'; | |
import {HTTP_PROVIDERS} from '@angular/http'; | |
import { | |
- | |
ROUTER_DIRECTIVES, | |
- ROUTER_PROVIDERS, | |
- ROUTER_PRIMARY_COMPONENT, | |
- | |
- Router, | |
- RouteConfig, | |
-} from '@angular/router-deprecated'; | |
-import {LocationStrategy, HashLocationStrategy, APP_BASE_HREF} from '@angular/common'; | |
+ provideRouter, | |
+ RouterConfig | |
+} from '@angular/router'; | |
+import { | |
+ LocationStrategy, | |
+ HashLocationStrategy, | |
+ APP_BASE_HREF | |
+} from '@angular/common'; | |
/* | |
* Components | |
@@ -30,6 +30,7 @@ import {AlbumComponent} from 'components/AlbumComponent'; | |
* Services | |
*/ | |
import {SPOTIFY_PROVIDERS} from 'services/SpotifyService'; | |
+import {provideForms} from '@angular/forms'; | |
/* | |
* Webpack | |
@@ -43,25 +44,25 @@ require('css/styles.scss'); | |
<router-outlet></router-outlet> | |
` | |
}) | |
-@RouteConfig([ | |
- { path: '/', name: 'root', redirectTo: ['Search'] }, | |
- { path: '/search', name: 'Search', component: SearchComponent }, | |
- { path: '/artists/:id', name: 'Artists', component: ArtistComponent }, | |
- { path: '/tracks/:id', name: 'Tracks', component: TrackComponent }, | |
- { path: '/albums/:id', name: 'Albums', component: AlbumComponent }, | |
-]) | |
class RoutesDemoApp { | |
query: string; | |
- | |
- constructor(public router: Router) { | |
- } | |
} | |
+const routes: RouterConfig = [ | |
+ { path: '', redirectTo: 'search', terminal: true }, | |
+ { path: 'search', component: SearchComponent }, | |
+ { path: 'artists/:id', component: ArtistComponent }, | |
+ { path: 'tracks/:id', component: TrackComponent }, | |
+ { path: 'albums/:id', component: AlbumComponent }, | |
+]; | |
+ | |
+const ROUTER_PROVIDER = provideRouter(routes); | |
+ | |
bootstrap(RoutesDemoApp, [ | |
- ROUTER_PROVIDERS, | |
+ ROUTER_PROVIDER, | |
HTTP_PROVIDERS, | |
SPOTIFY_PROVIDERS, | |
- provide(ROUTER_PRIMARY_COMPONENT, {useValue: RoutesDemoApp}), | |
provide(APP_BASE_HREF, {useValue: '/'}), | |
- provide(LocationStrategy, {useClass: HashLocationStrategy}) | |
+ provide(LocationStrategy, {useClass: HashLocationStrategy}), | |
+ provideForms() | |
]).catch((err: any) => console.error(err)); | |
diff --git a/manuscript/code/routes/music/app/ts/components/AlbumComponent.ts b/manuscript/code/routes/music/app/ts/components/AlbumComponent.ts | |
index ae3a302..80a512d 100644 | |
--- a/manuscript/code/routes/music/app/ts/components/AlbumComponent.ts | |
+++ b/manuscript/code/routes/music/app/ts/components/AlbumComponent.ts | |
@@ -3,8 +3,8 @@ | |
*/ | |
import {Component, OnInit} from '@angular/core'; | |
import {CORE_DIRECTIVES} from '@angular/common'; | |
-import {RouteParams, RouterLink} from '@angular/router-deprecated'; | |
-import {LocationStrategy} from '@angular/common'; | |
+import {ActivatedRoute, ROUTER_DIRECTIVES} from '@angular/router'; | |
+import {Location} from '@angular/common'; | |
/* | |
* Services | |
@@ -13,7 +13,7 @@ import {SpotifyService} from 'services/SpotifyService'; | |
@Component({ | |
selector: 'album', | |
- directives: [RouterLink, CORE_DIRECTIVES], | |
+ directives: [ROUTER_DIRECTIVES, CORE_DIRECTIVES], | |
template: ` | |
<div *ngIf="album"> | |
<h1>{{ album.name }}</h1> | |
@@ -26,7 +26,7 @@ import {SpotifyService} from 'services/SpotifyService'; | |
<h3>Tracks</h3> | |
<ol> | |
<li *ngFor="let t of album.tracks.items"> | |
- <a [routerLink]="['/Tracks', {id: t.id}]"> | |
+ <a [routerLink]="['/tracks', t.id]"> | |
{{ t.name }} | |
</a> | |
</li> | |
@@ -40,9 +40,9 @@ export class AlbumComponent implements OnInit { | |
id: string; | |
album: Object; | |
- constructor(public routeParams: RouteParams, public spotify: SpotifyService, | |
- public locationStrategy: LocationStrategy) { | |
- this.id = routeParams.get('id'); | |
+ constructor(public route: ActivatedRoute, public spotify: SpotifyService, | |
+ public location: Location) { | |
+ route.params.subscribe(params => { this.id = params['id']; }); | |
} | |
ngOnInit(): void { | |
@@ -52,7 +52,7 @@ export class AlbumComponent implements OnInit { | |
} | |
back(): void { | |
- this.locationStrategy.back(); | |
+ this.location.back(); | |
} | |
renderAlbum(res: any): void { | |
diff --git a/manuscript/code/routes/music/app/ts/components/ArtistComponent.ts b/manuscript/code/routes/music/app/ts/components/ArtistComponent.ts | |
index ff8f897..8912b44 100644 | |
--- a/manuscript/code/routes/music/app/ts/components/ArtistComponent.ts | |
+++ b/manuscript/code/routes/music/app/ts/components/ArtistComponent.ts | |
@@ -3,8 +3,8 @@ | |
*/ | |
import {Component, OnInit} from '@angular/core'; | |
import {CORE_DIRECTIVES} from '@angular/common'; | |
-import {RouteParams} from '@angular/router-deprecated'; | |
-import {LocationStrategy} from '@angular/common'; | |
+import {ActivatedRoute} from '@angular/router'; | |
+import {Location} from '@angular/common'; | |
/* | |
* Services | |
@@ -30,9 +30,9 @@ export class ArtistComponent implements OnInit { | |
id: string; | |
artist: Object; | |
- constructor(public routeParams: RouteParams, public spotify: SpotifyService, | |
- public locationStrategy: LocationStrategy) { | |
- this.id = routeParams.get('id'); | |
+ constructor(public route: ActivatedRoute, public spotify: SpotifyService, | |
+ public location: Location) { | |
+ route.params.subscribe(params => { this.id = params['id']; }); | |
} | |
ngOnInit(): void { | |
@@ -42,7 +42,7 @@ export class ArtistComponent implements OnInit { | |
} | |
back(): void { | |
- this.locationStrategy.back(); | |
+ this.location.back(); | |
} | |
renderArtist(res: any): void { | |
diff --git a/manuscript/code/routes/music/app/ts/components/SearchComponent.ts b/manuscript/code/routes/music/app/ts/components/SearchComponent.ts | |
index dd4b572..c55e64e 100644 | |
--- a/manuscript/code/routes/music/app/ts/components/SearchComponent.ts | |
+++ b/manuscript/code/routes/music/app/ts/components/SearchComponent.ts | |
@@ -6,9 +6,9 @@ import {Component, OnInit} from '@angular/core'; | |
import {CORE_DIRECTIVES} from '@angular/common'; | |
import { | |
Router, | |
- RouterLink, | |
- RouteParams, | |
-} from '@angular/router-deprecated'; | |
+ ROUTER_DIRECTIVES, | |
+ ActivatedRoute, | |
+} from '@angular/router'; | |
/* | |
* Services | |
@@ -17,7 +17,7 @@ import {SpotifyService} from 'services/SpotifyService'; | |
@Component({ | |
selector: 'search', | |
- directives: [RouterLink, CORE_DIRECTIVES], | |
+ directives: [ROUTER_DIRECTIVES, CORE_DIRECTIVES], | |
template: ` | |
<h1>Search</h1> | |
@@ -43,20 +43,20 @@ import {SpotifyService} from 'services/SpotifyService'; | |
<img src="{{ t.album.images[0].url }}" class="img-responsive"> | |
<div class="caption"> | |
<h3> | |
- <a [routerLink]="['/Artists', {id: t.artists[0].id}]"> | |
+ <a [routerLink]="['/artists', t.artists[0].id]"> | |
{{ t.artists[0].name }} | |
</a> | |
</h3> | |
<br> | |
<p> | |
- <a [routerLink]="['/Tracks', {id: t.id}]"> | |
+ <a [routerLink]="['/tracks', t.id]"> | |
{{ t.name }} | |
</a> | |
</p> | |
</div> | |
<div class="attribution"> | |
<h4> | |
- <a [routerLink]="['/Albums', {id: t.album.id}]"> | |
+ <a [routerLink]="['/albums', t.album.id]"> | |
{{ t.album.name }} | |
</a> | |
</h4> | |
@@ -73,8 +73,10 @@ export class SearchComponent implements OnInit { | |
query: string; | |
results: Object; | |
- constructor(public spotify: SpotifyService, public router: Router, | |
- public routeParams: RouteParams) { | |
+ constructor(private spotify: SpotifyService, private router: Router, | |
+ private route: ActivatedRoute) { | |
+ router.routerState.queryParams | |
+ .subscribe(params => { this.query = params['query'] || ''; }); | |
} | |
ngOnInit(): void { | |
@@ -82,12 +84,11 @@ export class SearchComponent implements OnInit { | |
} | |
submit(query: string): void { | |
- this.router.navigate(['/Search', {query: query}]); | |
- this.search(); | |
+ this.router.navigate(['search'], { queryParams: { query: query } }) | |
+ .then(_ => this.search() ); | |
} | |
search(): void { | |
- this.query = this.routeParams.get('query'); | |
if (!this.query) { | |
return; | |
} | |
diff --git a/manuscript/code/routes/music/app/ts/components/TrackComponent.ts b/manuscript/code/routes/music/app/ts/components/TrackComponent.ts | |
index 43690e6..0d48197 100644 | |
--- a/manuscript/code/routes/music/app/ts/components/TrackComponent.ts | |
+++ b/manuscript/code/routes/music/app/ts/components/TrackComponent.ts | |
@@ -4,8 +4,8 @@ | |
import {Component, OnInit} from '@angular/core'; | |
import {CORE_DIRECTIVES} from '@angular/common'; | |
-import {RouteParams} from '@angular/router-deprecated'; | |
-import {LocationStrategy} from '@angular/common'; | |
+import {ActivatedRoute} from '@angular/router'; | |
+import {Location} from '@angular/common'; | |
/* | |
* Services | |
@@ -39,9 +39,9 @@ export class TrackComponent implements OnInit { | |
id: string; | |
track: Object; | |
- constructor(public routeParams: RouteParams, public spotify: SpotifyService, | |
- public locationStrategy: LocationStrategy) { | |
- this.id = routeParams.get('id'); | |
+ constructor(public route: ActivatedRoute, public spotify: SpotifyService, | |
+ public location: Location) { | |
+ route.params.subscribe(params => { this.id = params['id']; }); | |
} | |
ngOnInit(): void { | |
@@ -51,7 +51,7 @@ export class TrackComponent implements OnInit { | |
} | |
back(): void { | |
- this.locationStrategy.back(); | |
+ this.location.back(); | |
} | |
renderTrack(res: any): void { | |
diff --git a/manuscript/code/routes/music/app/ts/vendor.ts b/manuscript/code/routes/music/app/ts/vendor.ts | |
index 9fdc3a7..926724b 100644 | |
--- a/manuscript/code/routes/music/app/ts/vendor.ts | |
+++ b/manuscript/code/routes/music/app/ts/vendor.ts | |
@@ -10,7 +10,7 @@ import 'zone.js/dist/long-stack-trace-zone'; | |
import '@angular/platform-browser-dynamic'; | |
import '@angular/common'; | |
import '@angular/core'; | |
-import '@angular/router-deprecated'; | |
+import '@angular/router'; | |
import '@angular/http'; | |
// RxJS | |
diff --git a/manuscript/code/routes/music/karma.conf.js b/manuscript/code/routes/music/karma.conf.js | |
index aeaef77..fb1058c 100644 | |
--- a/manuscript/code/routes/music/karma.conf.js | |
+++ b/manuscript/code/routes/music/karma.conf.js | |
@@ -23,10 +23,11 @@ module.exports = function(config) { | |
// preprocess matching files before serving them to the browser | |
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor | |
preprocessors: { | |
- 'test.bundle.js': ['webpack'] | |
+ 'test.bundle.js': ['webpack', 'sourcemap'] | |
}, | |
webpack: { | |
+ devtool: 'inline-source-map', | |
resolve: { | |
root: [path.resolve(cwd)], | |
modulesDirectories: ['node_modules', 'app', 'app/ts', 'test', '.'], | |
diff --git a/manuscript/code/routes/music/package.json b/manuscript/code/routes/music/package.json | |
index 1321d20..aceab89 100644 | |
--- a/manuscript/code/routes/music/package.json | |
+++ b/manuscript/code/routes/music/package.json | |
@@ -6,19 +6,19 @@ | |
"scripts": { | |
"go": "./node_modules/.bin/webpack-dev-server", | |
"clean": "true", | |
- "test": "karma start" | |
+ "test": "karma start --single-run" | |
}, | |
"author": "Nate Murray <[email protected]>", | |
"license": "MIT", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
- "@angular/router-deprecated": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"base64id": "0.1.0", | |
"core-js": "2.2.2", | |
"lodash": "3.10.1", | |
diff --git a/manuscript/code/routes/music/test/MusicTestHelpers.ts b/manuscript/code/routes/music/test/MusicTestHelpers.ts | |
new file mode 100644 | |
index 0000000..5c6f399 | |
--- /dev/null | |
+++ b/manuscript/code/routes/music/test/MusicTestHelpers.ts | |
@@ -0,0 +1,105 @@ | |
+import { | |
+ Component, | |
+ ComponentResolver, | |
+ Injector | |
+} from '@angular/core'; | |
+import { tick } from '@angular/core/testing'; | |
+import { TestComponentBuilder, ComponentFixture } from '@angular/core/testing'; | |
+import { BrowserPlatformLocation } from '@angular/platform-browser'; | |
+import { | |
+ ROUTER_DIRECTIVES, | |
+ ActivatedRoute, | |
+ Router, | |
+ RouterConfig, | |
+ RouterOutletMap, | |
+ DefaultUrlSerializer, | |
+ UrlSerializer | |
+} from '@angular/router'; | |
+import { | |
+ PlatformLocation, | |
+ Location, | |
+ LocationStrategy, | |
+ HashLocationStrategy | |
+} from '@angular/common'; | |
+import { SpyLocation } from '@angular/common/testing'; | |
+import { AlbumComponent } from '../app/ts/components/AlbumComponent'; | |
+import { ArtistComponent } from '../app/ts/components/ArtistComponent'; | |
+import { SearchComponent } from '../app/ts/components/SearchComponent'; | |
+import { TrackComponent } from '../app/ts/components/TrackComponent'; | |
+import { MockSpotifyService } from './mocks/spotify'; | |
+ | |
+export function advance(fixture: ComponentFixture<any>): void { | |
+ tick(); | |
+ fixture.detectChanges(); | |
+} | |
+ | |
+@Component({ | |
+ selector: 'blank-cmp', | |
+ template: ``, | |
+ directives: [ROUTER_DIRECTIVES] | |
+}) | |
+export class BlankCmp { | |
+} | |
+ | |
+@Component({ | |
+ selector: 'root-cmp', | |
+ template: `<router-outlet></router-outlet>`, | |
+ directives: [ROUTER_DIRECTIVES], | |
+ precompile: [BlankCmp, SearchComponent, ArtistComponent, | |
+ TrackComponent, AlbumComponent] | |
+}) | |
+export class RootCmp { | |
+} | |
+ | |
+export function createRoot(tcb: TestComponentBuilder, | |
+ router: Router, | |
+ type: any): ComponentFixture<any> { | |
+ const f = tcb.createFakeAsync(type); | |
+ advance(f); | |
+ (<any>router).initialNavigation(); | |
+ advance(f); | |
+ return f; | |
+} | |
+ | |
+export const routerConfig: RouterConfig = [ | |
+ { path: '', component: BlankCmp }, | |
+ { path: 'search', component: SearchComponent }, | |
+ { path: 'artists/:id', component: ArtistComponent }, | |
+ { path: 'tracks/:id', component: TrackComponent }, | |
+ { path: 'albums/:id', component: AlbumComponent } | |
+]; | |
+ | |
+export function musicTestProviders() { | |
+ const mockSpotifyService: MockSpotifyService = new MockSpotifyService(); | |
+ | |
+ return [ | |
+ RouterOutletMap, | |
+ {provide: UrlSerializer, useClass: DefaultUrlSerializer}, | |
+ {provide: Location, useClass: SpyLocation}, | |
+ {provide: LocationStrategy, useClass: HashLocationStrategy}, | |
+ {provide: PlatformLocation, useClass: BrowserPlatformLocation}, | |
+ { | |
+ provide: Router, | |
+ useFactory: (resolver: ComponentResolver, urlSerializer: UrlSerializer, | |
+ outletMap: RouterOutletMap, location: Location, | |
+ injector: Injector) => { | |
+ return new Router( | |
+ RootCmp, resolver, urlSerializer, outletMap, | |
+ location, injector, routerConfig); | |
+ }, | |
+ deps: [ | |
+ ComponentResolver, | |
+ UrlSerializer, | |
+ RouterOutletMap, | |
+ Location, | |
+ Injector | |
+ ] | |
+ }, | |
+ { | |
+ provide: ActivatedRoute, | |
+ useFactory: (r: Router) => r.routerState.root, deps: [Router] | |
+ }, | |
+ mockSpotifyService.getProviders(), | |
+ ]; | |
+}; | |
+ | |
diff --git a/manuscript/code/routes/music/test/components/AlbumComponent.spec.ts b/manuscript/code/routes/music/test/components/AlbumComponent.spec.ts | |
index 1d15f01..dc6f03a 100644 | |
--- a/manuscript/code/routes/music/test/components/AlbumComponent.spec.ts | |
+++ b/manuscript/code/routes/music/test/components/AlbumComponent.spec.ts | |
@@ -1,61 +1,67 @@ | |
import { | |
it, | |
describe, | |
- fdescribe, | |
- expect, | |
inject, | |
- injectAsync, | |
- afterEach, | |
- beforeEachProviders, | |
+ fakeAsync, | |
+ addProviders | |
} from '@angular/core/testing'; | |
-import {TestComponentBuilder} from '@angular/compiler/testing'; | |
- | |
-import {MockRouterProvider} from '../mocks/routes'; | |
-import {MockSpotifyService} from '../mocks/spotify'; | |
- | |
-import {AlbumComponent} from '../../app/ts/components/AlbumComponent'; | |
+import { Router } from '@angular/router'; | |
+import { Location } from '@angular/common'; | |
+import { TestComponentBuilder } from '@angular/core/testing'; | |
+import { MockSpotifyService } from '../mocks/spotify'; | |
+import { SpotifyService } from '../../app/ts/services/SpotifyService'; | |
+import { | |
+ musicTestProviders, | |
+ advance, | |
+ createRoot, | |
+ RootCmp | |
+} from '../MusicTestHelpers'; | |
describe('AlbumComponent', () => { | |
- var mockSpotifyService: MockSpotifyService; | |
- var mockRouterProvider: MockRouterProvider; | |
- | |
- beforeEachProviders(() => { | |
- mockSpotifyService = new MockSpotifyService(); | |
- mockRouterProvider = new MockRouterProvider(); | |
- | |
- return [ | |
- mockSpotifyService.getProviders(), mockRouterProvider.getProviders() | |
- ]; | |
+ beforeEach(() => { | |
+ addProviders(musicTestProviders()); | |
}); | |
describe('initialization', () => { | |
- it('retrieves the album', injectAsync([TestComponentBuilder], (tcb) => { | |
- // makes the RouteParams return 1 as the album id | |
- mockRouterProvider.setRouteParam('id', 1); | |
- | |
- return tcb.createAsync(AlbumComponent).then((fixture) => { | |
- fixture.detectChanges(); | |
- expect(mockSpotifyService.getAlbumSpy).toHaveBeenCalledWith(1); | |
- }); | |
- })); | |
+ it('retrieves the album', fakeAsync( | |
+ inject([Router, TestComponentBuilder, SpotifyService], | |
+ (router: Router, tcb: TestComponentBuilder, | |
+ mockSpotifyService: MockSpotifyService) => { | |
+ const fixture = createRoot(tcb, router, RootCmp); | |
+ | |
+ router.navigateByUrl('/albums/1'); | |
+ advance(fixture); | |
+ | |
+ expect(mockSpotifyService.getAlbumSpy).toHaveBeenCalledWith('1'); | |
+ }))); | |
}); | |
describe('back', () => { | |
- it('returns to the previous location', injectAsync([TestComponentBuilder], (tcb) => { | |
- return tcb.createAsync(AlbumComponent).then((fixture) => { | |
- let albumComponent = fixture.debugElement.componentInstance; | |
- let backSpy = mockRouterProvider.mockLocationStrategy.spy('back'); | |
- | |
- albumComponent.back(); | |
- expect(backSpy).toHaveBeenCalled(); | |
- }); | |
- })); | |
+ it('returns to the previous location', fakeAsync( | |
+ inject([Router, TestComponentBuilder, Location], | |
+ (router: Router, tcb: TestComponentBuilder, location: Location) => { | |
+ const fixture = createRoot(tcb, router, RootCmp); | |
+ expect(location.path()).toEqual('/'); | |
+ | |
+ router.navigateByUrl('/albums/1'); | |
+ advance(fixture); | |
+ expect(location.path()).toEqual('/albums/1'); | |
+ | |
+ const album = fixture.debugElement.children[1].componentInstance; | |
+ album.back(); | |
+ advance(fixture); | |
+ | |
+ expect(location.path()).toEqual('/'); | |
+ }))); | |
}); | |
describe('renderAlbum', () => { | |
- it('renders album info', injectAsync([TestComponentBuilder], (tcb) => { | |
- return tcb.createAsync(AlbumComponent).then((fixture) => { | |
- let albumComponent = fixture.debugElement.componentInstance; | |
+ it('renders album info', fakeAsync( | |
+ inject([Router, TestComponentBuilder, SpotifyService], | |
+ (router: Router, tcb: TestComponentBuilder, | |
+ mockSpotifyService: MockSpotifyService) => { | |
+ const fixture = createRoot(tcb, router, RootCmp); | |
+ | |
let album = { | |
name: 'ALBUM NAME', | |
artists: [{name: 'ARTIST NAME'}], | |
@@ -64,18 +70,21 @@ describe('AlbumComponent', () => { | |
items: [{id: 1, name: 'TRACK 1'},{id: 2, name: 'TRACK 2'}] | |
} | |
}; | |
- | |
mockSpotifyService.setResponse(album); | |
- fixture.detectChanges(); | |
- var compiled = fixture.debugElement.nativeElement; | |
- expect(compiled.querySelector('h1')).toHaveText('ALBUM NAME'); | |
- expect(compiled.querySelector('h2')).toHaveText('ARTIST NAME'); | |
+ router.navigateByUrl('/albums/1'); | |
+ advance(fixture); | |
+ | |
+ const compiled = fixture.debugElement.nativeElement; | |
+ | |
+ expect(compiled.querySelector('h1').innerHTML).toContain('ALBUM NAME'); | |
+ expect(compiled.querySelector('h2').innerHTML).toContain('ARTIST NAME'); | |
var links = compiled.querySelectorAll('a'); | |
expect(links[0].innerText).toContain('TRACK 1'); | |
expect(links[1].innerText).toContain('TRACK 2'); | |
- }); | |
- })); | |
+ }))); | |
}); | |
}); | |
+ | |
+ | |
diff --git a/manuscript/code/routes/music/test/components/ArtistComponent.spec.ts b/manuscript/code/routes/music/test/components/ArtistComponent.spec.ts | |
index 620d3c7..64b39ca 100644 | |
--- a/manuscript/code/routes/music/test/components/ArtistComponent.spec.ts | |
+++ b/manuscript/code/routes/music/test/components/ArtistComponent.spec.ts | |
@@ -1,70 +1,78 @@ | |
import { | |
it, | |
describe, | |
- expect, | |
inject, | |
- async, | |
- afterEach, | |
- beforeEachProviders, | |
+ fakeAsync, | |
+ addProviders | |
} from '@angular/core/testing'; | |
-import {TestComponentBuilder} from '@angular/compiler/testing'; | |
- | |
-import {MockRouterProvider} from "../mocks/routes"; | |
-import {MockSpotifyService} from "../mocks/spotify"; | |
-import {TestHelper} from "../mocks/helper"; | |
+import { Router } from '@angular/router'; | |
+import { Location } from '@angular/common'; | |
+import { TestComponentBuilder } from '@angular/compiler/testing'; | |
+import { MockSpotifyService } from '../mocks/spotify'; | |
+import { SpotifyService } from '../../app/ts/services/SpotifyService'; | |
+import { | |
+ musicTestProviders, | |
+ advance, | |
+ createRoot, | |
+ RootCmp | |
+} from '../MusicTestHelpers'; | |
-import {ArtistComponent} from "../../app/ts/components/ArtistComponent"; | |
+describe('ArtistComponent', () => { | |
+ beforeEach(() => { | |
+ addProviders(musicTestProviders()); | |
+ }); | |
-describe("ArtistComponent", () => { | |
- var mockSpotifyService: MockSpotifyService; | |
- var mockRouterProvider: MockRouterProvider; | |
+ describe('initialization', () => { | |
+ it('retrieves the artist', fakeAsync( | |
+ inject([Router, SpotifyService, TestComponentBuilder], | |
+ (router: Router, | |
+ mockSpotifyService: MockSpotifyService, | |
+ tcb: TestComponentBuilder) => { | |
+ const fixture = createRoot(tcb, router, RootCmp); | |
- beforeEachProviders(() => { | |
- mockSpotifyService = new MockSpotifyService(); | |
- mockRouterProvider = new MockRouterProvider(); | |
+ router.navigateByUrl('/artists/2'); | |
+ advance(fixture); | |
- return [ | |
- mockSpotifyService.getProviders(), mockRouterProvider.getProviders() | |
- ]; | |
+ expect(mockSpotifyService.getArtistSpy).toHaveBeenCalledWith('2'); | |
+ }))); | |
}); | |
- describe("initialization", () => { | |
- it("retrieves the artist", async(inject([TestComponentBuilder], (tcb) => { | |
- // makes the RouteParams return 2 as the artist id | |
- mockRouterProvider.setRouteParam('id', 2); | |
+ describe('back', () => { | |
+ it('returns to the previous location', fakeAsync( | |
+ inject([Router, TestComponentBuilder, Location], | |
+ (router: Router, tcb: TestComponentBuilder, location: Location) => { | |
+ const fixture = createRoot(tcb, router, RootCmp); | |
+ expect(location.path()).toEqual('/'); | |
- return tcb.createAsync(ArtistComponent).then((fixture) => { | |
- fixture.detectChanges(); | |
- expect(mockSpotifyService.getArtistSpy).toHaveBeenCalledWith(2); | |
- }); | |
- }))); | |
- }); | |
+ router.navigateByUrl('/artists/2'); | |
+ advance(fixture); | |
+ expect(location.path()).toEqual('/artists/2'); | |
- describe('back', () => { | |
- it('returns to the previous location', async(inject([TestComponentBuilder], (tcb) => { | |
- return tcb.createAsync(ArtistComponent).then((fixture) => { | |
- let artistComponent = fixture.debugElement.componentInstance; | |
- let backSpy = mockRouterProvider.mockLocationStrategy.spy('back'); | |
+ const artist = fixture.debugElement.children[1].componentInstance; | |
+ artist.back(); | |
+ advance(fixture); | |
- artistComponent.back(); | |
- expect(backSpy).toHaveBeenCalled(); | |
- }); | |
- }))); | |
+ expect(location.path()).toEqual('/'); | |
+ }))); | |
}); | |
describe('renderArtist', () => { | |
- it('renders artist info', async(inject([TestComponentBuilder], (tcb) => { | |
- return tcb.createAsync(ArtistComponent).then((fixture) => { | |
- let artistComponent = fixture.debugElement.componentInstance; | |
- let artist = {name: 'ARTIST NAME', images: [{url: 'IMAGE_1'}]}; | |
+ it('renders album info', fakeAsync( | |
+ inject([Router, TestComponentBuilder, SpotifyService], | |
+ (router: Router, tcb: TestComponentBuilder, | |
+ mockSpotifyService: MockSpotifyService) => { | |
+ const fixture = createRoot(tcb, router, RootCmp); | |
+ let artist = {name: 'ARTIST NAME', images: [{url: 'IMAGE_1'}]}; | |
mockSpotifyService.setResponse(artist); | |
- fixture.detectChanges(); | |
- var compiled = fixture.debugElement.nativeElement; | |
- expect(compiled.querySelector('h1')).toHaveText('ARTIST NAME'); | |
+ router.navigateByUrl('/artists/2'); | |
+ advance(fixture); | |
+ | |
+ const compiled = fixture.debugElement.nativeElement; | |
+ | |
+ expect(compiled.querySelector('h1').innerHTML).toContain('ARTIST NAME'); | |
expect(compiled.querySelector('img').src).toContain('IMAGE_1'); | |
- }); | |
- }))); | |
+ }))); | |
}); | |
}); | |
diff --git a/manuscript/code/routes/music/test/components/SearchComponent.spec.ts b/manuscript/code/routes/music/test/components/SearchComponent.spec.ts | |
index 314a853..32240af 100644 | |
--- a/manuscript/code/routes/music/test/components/SearchComponent.spec.ts | |
+++ b/manuscript/code/routes/music/test/components/SearchComponent.spec.ts | |
@@ -1,165 +1,124 @@ | |
import { | |
it, | |
- fdescribe, | |
describe, | |
- expect, | |
inject, | |
- async, | |
- afterEach, | |
- beforeEachProviders, | |
+ fakeAsync, | |
+ addProviders | |
} from '@angular/core/testing'; | |
-import {TestComponentBuilder} from '@angular/compiler/testing'; | |
-import {Router} from "@angular/router-deprecated"; | |
-import {DebugElement} from '@angular/core/src/debug/debug_node'; | |
- | |
-import {MockRouterProvider} from '../mocks/routes'; | |
-import {MockSpotifyService} from '../mocks/spotify'; | |
-import {TestHelper} from '../mocks/helper'; | |
- | |
-import {SearchComponent} from '../../app/ts/components/SearchComponent'; | |
+import { Router } from '@angular/router'; | |
+import { Location } from '@angular/common'; | |
+import { TestComponentBuilder } from '@angular/core/testing'; | |
+import { MockSpotifyService } from '../mocks/spotify'; | |
+import { SpotifyService } from '../../app/ts/services/SpotifyService'; | |
+import { | |
+ musicTestProviders, | |
+ advance, | |
+ createRoot, | |
+ RootCmp | |
+} from '../MusicTestHelpers'; | |
describe('SearchComponent', () => { | |
- var mockSpotifyService: MockSpotifyService; | |
- var mockRouterProvider: MockRouterProvider; | |
- | |
- beforeEachProviders(() => { | |
- mockSpotifyService = new MockSpotifyService(); | |
- mockRouterProvider = new MockRouterProvider(); | |
- | |
- return [ | |
- mockSpotifyService.getProviders(), mockRouterProvider.getProviders() | |
- ]; | |
+ beforeEach(() => { | |
+ addProviders(musicTestProviders()); | |
}); | |
describe('initialization', () => { | |
- it(`doesn\'t search for a track without a query`, | |
- async(inject([TestComponentBuilder], (tcb) => { | |
- var search = mockSpotifyService.spy('searchTrack'); | |
- return tcb.createAsync(SearchComponent).then((fixture) => { | |
- fixture.detectChanges(); | |
- expect(search).not.toHaveBeenCalled(); | |
- }); | |
- })) | |
- ); | |
- | |
- it('searches for a track if a query is provided', | |
- async(inject([TestComponentBuilder], (tcb) => { | |
- var search = mockSpotifyService.spy('searchTrack'); | |
- mockRouterProvider.setRouteParam('query', 'QUERY'); | |
- | |
- return tcb.createAsync(SearchComponent).then((rootTC) => { | |
- rootTC.detectChanges(); | |
- expect(search).toHaveBeenCalled(); | |
- }); | |
- })) | |
- ); | |
- }); | |
- | |
- describe('submit', () => { | |
- describe('testing the method', () => { | |
- it('navigates to the Search route', | |
- async(inject([TestComponentBuilder], (tcb) => { | |
- var navigate = mockRouterProvider.mockRouter.spy('navigate'); | |
- | |
- return tcb.createAsync(SearchComponent).then((fixture) => { | |
- let searchComponent = fixture.debugElement.componentInstance; | |
- searchComponent.submit("QUERY"); | |
- expect(navigate).toHaveBeenCalledWith(["/Search", {query: "QUERY"}]); | |
- }); | |
- })) | |
- ); | |
- | |
- it('performs the search', | |
- async(inject([TestComponentBuilder], (tcb) => { | |
- return tcb.createAsync(SearchComponent).then((fixture) => { | |
- let searchComponent = fixture.debugElement.componentInstance; | |
- let search = spyOn(searchComponent, 'search'); | |
- | |
- searchComponent.submit("QUERY"); | |
- expect(search).toHaveBeenCalled(); | |
- }); | |
- })) | |
- ); | |
- }); | |
- | |
- describe('testing the interaction', () => { | |
- it('navigates to the Search route', | |
- async(inject([TestComponentBuilder], (tcb) => { | |
- let navigate = mockRouterProvider.mockRouter.spy('navigate'); | |
- | |
- return tcb.createAsync(SearchComponent).then((fixture) => { | |
- var compiled = fixture.debugElement.nativeElement; | |
- var input = compiled.querySelector('input'); | |
- var button = compiled.querySelector('button'); | |
- | |
- fixture.detectChanges(); | |
- | |
- // sets the value of the search field to "QUERY" | |
- // and clicks the search button | |
- input.value = "QUERY"; | |
- button.click(); | |
- | |
- expect(navigate).toHaveBeenCalledWith(["/Search", {query: "QUERY"}]); | |
- }); | |
- })) | |
- ); | |
- }); | |
+ it(`doesn't search for a track without a query`, fakeAsync( | |
+ inject([Router, TestComponentBuilder, SpotifyService], | |
+ (router: Router, tcb: TestComponentBuilder, | |
+ mockSpotifyService: MockSpotifyService) => { | |
+ const searchSpy = mockSpotifyService.spy('searchTrack'); | |
+ const fixture = createRoot(tcb, router, RootCmp); | |
+ router.navigateByUrl('/search'); | |
+ advance(fixture); | |
+ expect(searchSpy).not.toHaveBeenCalled(); | |
+ }))); | |
+ | |
+ it(`searches for a track if a query is provided`, fakeAsync( | |
+ inject([Router, TestComponentBuilder, SpotifyService], | |
+ (router: Router, tcb: TestComponentBuilder, | |
+ mockSpotifyService: MockSpotifyService) => { | |
+ const searchSpy = mockSpotifyService.spy('searchTrack'); | |
+ const fixture = createRoot(tcb, router, RootCmp); | |
+ router.navigateByUrl('/search?query=cats'); | |
+ advance(fixture); | |
+ expect(searchSpy).toHaveBeenCalled(); | |
+ }))); | |
}); | |
- describe('search', () => { | |
- it('searches when a query is present', | |
- async(inject([TestComponentBuilder], (tcb) => { | |
- return tcb.createAsync(SearchComponent).then((fixture) => { | |
- var searchComponent = fixture.debugElement.componentInstance; | |
- mockRouterProvider.setRouteParam('query', 'QUERY') | |
- | |
- searchComponent.search(); | |
- expect(mockSpotifyService.searchTrackSpy).toHaveBeenCalledWith("QUERY") | |
- }) | |
- })) | |
- ); | |
- | |
- it(`doesn\'t search when a query is absent`, | |
- async(inject([TestComponentBuilder], (tcb) => { | |
- return tcb.createAsync(SearchComponent).then((fixture) => { | |
- var searchComponent = fixture.debugElement.componentInstance; | |
- | |
- searchComponent.search(); | |
- expect(mockSpotifyService.searchTrackSpy).not.toHaveBeenCalled(); | |
- }); | |
- })) | |
- ); | |
+ describe('submitting a search', () => { | |
+ it('navigates to the Search route', fakeAsync( | |
+ inject([Router, TestComponentBuilder, Location], | |
+ (router: Router, tcb: TestComponentBuilder, location: Location) => { | |
+ const fixture = createRoot(tcb, router, RootCmp); | |
+ expect(location.path()).toEqual('/'); | |
+ | |
+ router.navigateByUrl('/search'); | |
+ advance(fixture); | |
+ | |
+ const searchComponent = fixture.debugElement.children[1].componentInstance; | |
+ const searchSpy = spyOn(searchComponent, 'search'); | |
+ searchComponent.submit('cats'); | |
+ advance(fixture); | |
+ | |
+ expect(location.path()).toEqual('/search?query=cats'); | |
+ expect(searchSpy).toHaveBeenCalled(); | |
+ }))); | |
+ | |
+ it('can search with a button', fakeAsync( | |
+ inject([Router, TestComponentBuilder, Location], | |
+ (router: Router, tcb: TestComponentBuilder, location: Location) => { | |
+ const fixture = createRoot(tcb, router, RootCmp); | |
+ router.navigateByUrl('/search'); | |
+ advance(fixture); | |
+ expect(location.path()).toEqual('/search'); | |
+ | |
+ const compiled = fixture.debugElement.nativeElement; | |
+ const searchComponent = fixture.debugElement.children[1].componentInstance; | |
+ const searchSpy = spyOn(searchComponent, 'search'); | |
+ const input = compiled.querySelector('input'); | |
+ const button = compiled.querySelector('button'); | |
+ | |
+ input.value = 'cats'; | |
+ button.click(); | |
+ advance(fixture); | |
+ | |
+ expect(location.path()).toEqual('/search?query=cats'); | |
+ expect(searchSpy).toHaveBeenCalled(); | |
+ }))); | |
}); | |
describe('renderResults', () => { | |
- it('display a message when no results are found', | |
- async(inject([Router, TestComponentBuilder], (router, tcb) => { | |
- return tcb.createAsync(SearchComponent).then((fixture) => { | |
- mockSpotifyService.setResponse({tracks: {items: []}}); | |
- mockRouterProvider.setRouteParam('query', 'QUERY'); | |
- | |
- var searchComponent = fixture.debugElement.componentInstance; | |
- var compiled = fixture.debugElement.nativeElement; | |
- var input = compiled.querySelector('input'); | |
- var button = compiled.querySelector('button'); | |
- | |
- fixture.detectChanges(); | |
- | |
- // sets the value of the search field to "QUERY" | |
- // and clicks the search button | |
- input.value = "QUERY"; | |
- button.click(); | |
- | |
- expect(compiled.innerText) | |
- .toContain("No tracks were found with the term 'QUERY'"); | |
- }); | |
- })) | |
- ); | |
- | |
- it('display results', | |
- async(inject([Router, TestComponentBuilder], (router, tcb) => { | |
- return tcb.createAsync(SearchComponent).then((fixture) => { | |
- var searchComponent = fixture.debugElement.componentInstance; | |
+ it('displays a message when no results are found', fakeAsync( | |
+ inject([Router, TestComponentBuilder, Location, SpotifyService], | |
+ (router: Router, tcb: TestComponentBuilder, | |
+ location: Location, mockSpotifyService: MockSpotifyService) => { | |
+ const fixture = createRoot(tcb, router, RootCmp); | |
+ router.navigateByUrl('/search'); | |
+ advance(fixture); | |
+ | |
+ mockSpotifyService.setResponse({tracks: {items: []}}); | |
+ | |
+ const compiled = fixture.debugElement.nativeElement; | |
+ const input = compiled.querySelector('input'); | |
+ const button = compiled.querySelector('button'); | |
+ | |
+ input.value = 'cats'; | |
+ button.click(); | |
+ advance(fixture); | |
+ | |
+ expect(compiled.innerText) | |
+ .toContain(`No tracks were found with the term 'cats'`); | |
+ }))); | |
+ | |
+ it('displays results', fakeAsync( | |
+ inject([Router, TestComponentBuilder, Location, SpotifyService], | |
+ (router: Router, tcb: TestComponentBuilder, | |
+ location: Location, mockSpotifyService: MockSpotifyService) => { | |
+ const fixture = createRoot(tcb, router, RootCmp); | |
+ router.navigateByUrl('/search'); | |
+ advance(fixture); | |
+ | |
var response = { | |
tracks: { | |
items: [ | |
@@ -167,27 +126,26 @@ describe('SearchComponent', () => { | |
id: 1, | |
name: 'TRACK', | |
album: { id: 2, name: 'ALBUM', images: [{url: 'IMAGE_1'}] }, | |
- artists: [ {id: 3, name: 'ARTIST'} ] | |
- } | |
- ] | |
- } | |
- }; | |
- | |
- searchComponent.renderResults(response); | |
- fixture.detectChanges(); | |
- | |
- // checks the album URL matches | |
- var compiled = fixture.debugElement.nativeElement; | |
- expect(compiled.querySelector('img').src).toContain('IMAGE_1'); | |
- | |
- // checks the artist, track and album information | |
- var links = compiled.querySelectorAll('a'); | |
- expect(links.length).toEqual(3); | |
- expect(links[0].innerText).toEqual('ARTIST'); | |
- expect(links[1].innerText).toEqual('TRACK'); | |
- expect(links[2].innerText).toEqual('ALBUM'); | |
- }) | |
- })) | |
- ); | |
+ artists: [ {id: 3, name: 'ARTIST'} ]}]}}; | |
+ | |
+ mockSpotifyService.setResponse(response); | |
+ | |
+ const compiled = fixture.debugElement.nativeElement; | |
+ const input = compiled.querySelector('input'); | |
+ const button = compiled.querySelector('button'); | |
+ | |
+ input.value = 'cats'; | |
+ button.click(); | |
+ advance(fixture); | |
+ | |
+ expect(compiled.querySelector('img').src).toContain('IMAGE_1'); | |
+ | |
+ // checks the artist, track and album information | |
+ var links = compiled.querySelectorAll('a'); | |
+ expect(links.length).toEqual(3); | |
+ expect(links[0].innerText).toEqual('ARTIST'); | |
+ expect(links[1].innerText).toEqual('TRACK'); | |
+ expect(links[2].innerText).toEqual('ALBUM'); | |
+ }))); | |
}); | |
}); | |
diff --git a/manuscript/code/routes/music/test/components/TrackComponent.spec.ts b/manuscript/code/routes/music/test/components/TrackComponent.spec.ts | |
index 4767890..012521c 100644 | |
--- a/manuscript/code/routes/music/test/components/TrackComponent.spec.ts | |
+++ b/manuscript/code/routes/music/test/components/TrackComponent.spec.ts | |
@@ -3,75 +3,78 @@ import { | |
describe, | |
expect, | |
inject, | |
- injectAsync, | |
- afterEach, | |
- beforeEachProviders, | |
+ fakeAsync, | |
+ addProviders | |
} from '@angular/core/testing'; | |
-import { TestComponentBuilder } from '@angular/compiler/testing'; | |
- | |
-import {MockRouterProvider} from "../mocks/routes"; | |
-import {MockSpotifyService} from "../mocks/spotify"; | |
-import {TestHelper} from "../mocks/helper"; | |
- | |
-import {TrackComponent} from "../../app/ts/components/TrackComponent"; | |
- | |
-let mockSpotifyService: MockSpotifyService = new MockSpotifyService(); | |
-let mockRouterProvider: MockRouterProvider = new MockRouterProvider(); | |
+import { Router } from '@angular/router'; | |
+import { Location } from '@angular/common'; | |
+import { TestComponentBuilder } from '@angular/core/testing'; | |
+import { MockSpotifyService } from '../mocks/spotify'; | |
+import { SpotifyService } from '../../app/ts/services/SpotifyService'; | |
+import { | |
+ musicTestProviders, | |
+ advance, | |
+ createRoot, | |
+ RootCmp | |
+} from '../MusicTestHelpers'; | |
describe("TrackComponent", () => { | |
- var mockSpotifyService: MockSpotifyService; | |
- var mockRouterProvider: MockRouterProvider; | |
- var template = `<h1 *ngIf="track">{{track.name}}</h1>`; | |
- | |
- beforeEachProviders(() => { | |
- mockSpotifyService = new MockSpotifyService(); | |
- mockRouterProvider = new MockRouterProvider(); | |
- | |
- return [ | |
- mockSpotifyService.getProviders(), mockRouterProvider.getProviders() | |
- ]; | |
+ beforeEach(() => { | |
+ addProviders(musicTestProviders()); | |
}); | |
- describe("initialization", () => { | |
- it("retrieves the track", injectAsync([TestComponentBuilder], (tcb) => { | |
- // makes the RouteParams return 1 as the track id | |
- mockRouterProvider.setRouteParam('id', 1); | |
+ describe('initialization', () => { | |
+ it('retrieves the track', fakeAsync( | |
+ inject([Router, TestComponentBuilder, SpotifyService], | |
+ (router: Router, tcb: TestComponentBuilder, | |
+ mockSpotifyService: MockSpotifyService) => { | |
+ const fixture = createRoot(tcb, router, RootCmp); | |
+ advance(fixture); | |
- return tcb.overrideTemplate(TrackComponent, template) | |
- .createAsync(TrackComponent).then((fixture) => { | |
- fixture.detectChanges(); | |
- expect(mockSpotifyService.getTrackSpy).toHaveBeenCalledWith(1); | |
- }); | |
- })); | |
+ router.navigateByUrl('/tracks/1'); | |
+ advance(fixture); | |
+ | |
+ expect(mockSpotifyService.getTrackSpy).toHaveBeenCalledWith('1'); | |
+ }))); | |
}); | |
+ | |
describe('back', () => { | |
- it('returns to the previous location', | |
- injectAsync([TestComponentBuilder], (tcb) => { | |
- return tcb.overrideTemplate(TrackComponent, template) | |
- .createAsync(TrackComponent).then((fixture) => { | |
- var trackComponent = fixture.debugElement.componentInstance; | |
- var backSpy = mockRouterProvider.mockLocationStrategy.spy('back'); | |
+ it('returns to the previous location', fakeAsync( | |
+ inject([Router, TestComponentBuilder, Location], | |
+ (router: Router, tcb: TestComponentBuilder, location: Location) => { | |
+ const fixture = createRoot(tcb, router, RootCmp); | |
+ expect(location.path()).toEqual('/'); | |
+ | |
+ router.navigateByUrl('/tracks/1'); | |
+ advance(fixture); | |
+ expect(location.path()).toEqual('/tracks/1'); | |
- trackComponent.back(); | |
- expect(backSpy).toHaveBeenCalled(); | |
- }); | |
- }) | |
- ); | |
+ const album = fixture.debugElement.children[1].componentInstance; | |
+ album.back(); | |
+ advance(fixture); | |
+ | |
+ expect(location.path()).toEqual('/'); | |
+ }))); | |
}); | |
describe('renderTrack', () => { | |
- it('renders track info', injectAsync([TestComponentBuilder], (tcb) => { | |
- return tcb.overrideTemplate(TrackComponent, template) | |
- .createAsync(TrackComponent).then((fixture) => { | |
- var trackComponent = fixture.debugElement.componentInstance; | |
- mockSpotifyService.setResponse({name: 'TRACK NAME'}); | |
+ it('renders track info', fakeAsync( | |
+ inject([Router, TestComponentBuilder, SpotifyService], | |
+ (router: Router, tcb: TestComponentBuilder, | |
+ mockSpotifyService: MockSpotifyService) => { | |
+ const fixture = createRoot(tcb, router, RootCmp); | |
+ | |
+ let response = { | |
+ name: 'TRACK NAME', | |
+ album: { images: [{url: 'IMAGE_0.png'}, {url: 'IMAGE_1.png'}] } }; | |
+ mockSpotifyService.setResponse(response); | |
- fixture.detectChanges(); | |
+ router.navigateByUrl('/tracks/1'); | |
+ advance(fixture); | |
- var compiled = fixture.debugElement.nativeElement; | |
- expect(compiled.querySelector('h1')).toHaveText('TRACK NAME'); | |
- }); | |
- })); | |
+ const compiled = fixture.debugElement.nativeElement; | |
+ expect(compiled.querySelector('h1').innerText).toContain('TRACK NAME'); | |
+ }))); | |
}); | |
}); | |
diff --git a/manuscript/code/routes/music/test/mocks/routes.ts b/manuscript/code/routes/music/test/mocks/routes.ts | |
deleted file mode 100644 | |
index 5b3b491..0000000 | |
--- a/manuscript/code/routes/music/test/mocks/routes.ts | |
+++ /dev/null | |
@@ -1,63 +0,0 @@ | |
-import {provide} from '@angular/core'; | |
-import { | |
- | |
- | |
- | |
- ComponentInstruction, | |
- Router, | |
- RouteParams | |
-} from '@angular/router-deprecated'; | |
-import {Location, LocationStrategy} from '@angular/common'; | |
-import {ResolvedInstruction} from '@angular/router-deprecated/src/instruction'; | |
-import {SpyObject} from './helper'; | |
- | |
- | |
-export class MockRouteParams extends SpyObject { | |
- private ROUTE_PARAMS = {}; | |
- | |
- constructor() { super(RouteParams); } | |
- | |
- set(key: string, value: string) { | |
- this.ROUTE_PARAMS[key] = value; | |
- } | |
- | |
- get(key: string) { | |
- return this.ROUTE_PARAMS[key]; | |
- } | |
-} | |
- | |
-export class MockRouter extends SpyObject { | |
- constructor() { super(Router); } | |
- isRouteActive(s) { return true; } | |
- generate(s) { | |
- let klass: any = ComponentInstruction; // hack b/c ComponentInstruction constructor typing isn't exposed | |
- let instruction: ComponentInstruction = new klass('detail', [], null, null, true, '0', null, 'Detail'); | |
- return new ResolvedInstruction(instruction, null, {}); | |
- } | |
-} | |
-export class MockLocationStrategy extends SpyObject { | |
- constructor() { super(LocationStrategy); } | |
-} | |
-export class MockLocation extends SpyObject { | |
- constructor() { super(Location); } | |
-} | |
- | |
-export class MockRouterProvider { | |
- mockRouter: MockRouter = new MockRouter(); | |
- mockRouteParams: MockRouteParams = new MockRouteParams(); | |
- mockLocationStrategy: MockLocationStrategy = new MockLocationStrategy(); | |
- mockLocation: MockLocation = new MockLocation(); | |
- | |
- setRouteParam(key: string, value: any) { | |
- this.mockRouteParams.set(key, value); | |
- } | |
- | |
- getProviders(): Array<any> { | |
- return [ | |
- provide(Router, {useValue: this.mockRouter}), | |
- provide(RouteParams, {useValue: this.mockRouteParams}), | |
- provide(Location, {useValue: this.mockLocation}), | |
- provide(LocationStrategy, {useValue: this.mockLocationStrategy}) | |
- ]; | |
- } | |
-} | |
diff --git a/manuscript/code/routes/music/test/mocks/spotify.ts b/manuscript/code/routes/music/test/mocks/spotify.ts | |
index 36fafba..7bef2ba 100644 | |
--- a/manuscript/code/routes/music/test/mocks/spotify.ts | |
+++ b/manuscript/code/routes/music/test/mocks/spotify.ts | |
@@ -1,6 +1,5 @@ | |
import {provide} from '@angular/core'; | |
import {SpyObject} from './helper'; | |
- | |
import {SpotifyService} from '../../app/ts/services/SpotifyService'; | |
export class MockSpotifyService extends SpyObject { | |
diff --git a/manuscript/code/routes/music/test/services/SpotifyService.spec.ts b/manuscript/code/routes/music/test/services/SpotifyService.spec.ts | |
index d8b6ada..66728bc 100644 | |
--- a/manuscript/code/routes/music/test/services/SpotifyService.spec.ts | |
+++ b/manuscript/code/routes/music/test/services/SpotifyService.spec.ts | |
@@ -4,9 +4,8 @@ import { | |
expect, | |
inject, | |
fakeAsync, | |
- afterEach, | |
- beforeEachProviders, | |
tick, | |
+ addProviders | |
} from '@angular/core/testing'; | |
import {MockBackend} from '@angular/http/testing'; | |
import {provide} from '@angular/core'; | |
@@ -21,15 +20,17 @@ import { | |
import {SpotifyService} from '../../app/ts/services/SpotifyService'; | |
describe('SpotifyService', () => { | |
- beforeEachProviders(() => { | |
- return [ | |
+ beforeEach(() => { | |
+ addProviders([ | |
BaseRequestOptions, | |
MockBackend, | |
SpotifyService, | |
- provide(Http, {useFactory: (backend: ConnectionBackend, defaultOptions: BaseRequestOptions) => { | |
+ provide(Http, { | |
+ useFactory: (backend: ConnectionBackend, | |
+ defaultOptions: BaseRequestOptions) => { | |
return new Http(backend, defaultOptions); | |
}, deps: [MockBackend, BaseRequestOptions]}), | |
- ] | |
+ ]); | |
}); | |
// sets up an expectation that the correct URL will being requested | |
diff --git a/manuscript/code/routes/nested/app/ts/app.ts b/manuscript/code/routes/nested/app/ts/app.ts | |
index f47ff14..f60a2fa 100644 | |
--- a/manuscript/code/routes/nested/app/ts/app.ts | |
+++ b/manuscript/code/routes/nested/app/ts/app.ts | |
@@ -5,10 +5,10 @@ import {bind, Component} from '@angular/core'; | |
import {bootstrap} from '@angular/platform-browser-dynamic'; | |
import { | |
ROUTER_DIRECTIVES, | |
- ROUTER_BINDINGS, | |
+ provideRouter, | |
Router, | |
- RouteConfig, | |
-} from '@angular/router-deprecated'; | |
+ RouterConfig | |
+} from '@angular/router'; | |
import {LocationStrategy, HashLocationStrategy} from '@angular/common'; | |
@@ -16,7 +16,10 @@ import {LocationStrategy, HashLocationStrategy} from '@angular/common'; | |
* Components | |
*/ | |
import {HomeComponent} from 'components/HomeComponent'; | |
-import {ProductsComponent} from 'components/ProductsComponent'; | |
+import { | |
+ routes as childRoutes, | |
+ ProductsComponent | |
+} from 'components/ProductsComponent'; | |
/* | |
* Webpack | |
@@ -31,8 +34,8 @@ require('css/styles.scss'); | |
<div class="container"> | |
<h1>Router Sample</h1> | |
<div class="navLinks"> | |
- <a [routerLink]="['Home']">Home</a> | |
- <a [routerLink]="['Products']">Products</a> | |
+ <a [routerLink]="['/home']">Home</a> | |
+ <a [routerLink]="['/products']">Products</a> | |
</div> | |
</div> | |
</div> | |
@@ -44,16 +47,18 @@ require('css/styles.scss'); | |
</div> | |
` | |
}) | |
-@RouteConfig([ | |
- { path: '/home', name: 'Home', component: HomeComponent, useAsDefault: true }, | |
- { path: '/products/...', name: 'Products', component: ProductsComponent }, | |
-]) | |
class RoutesDemoApp { | |
constructor(public router: Router) { | |
} | |
} | |
+const routes: RouterConfig = [ | |
+ { path: '', redirectTo: 'home', terminal: true }, | |
+ { path: 'home', component: HomeComponent }, | |
+ { path: 'products', component: ProductsComponent, children: childRoutes } | |
+]; | |
+ | |
bootstrap(RoutesDemoApp, [ | |
- ROUTER_BINDINGS, | |
+ provideRouter(routes), | |
bind(LocationStrategy).toClass(HashLocationStrategy) | |
]); | |
diff --git a/manuscript/code/routes/nested/app/ts/components/ProductsComponent.ts b/manuscript/code/routes/nested/app/ts/components/ProductsComponent.ts | |
index d01dc7a..7927945 100644 | |
--- a/manuscript/code/routes/nested/app/ts/components/ProductsComponent.ts | |
+++ b/manuscript/code/routes/nested/app/ts/components/ProductsComponent.ts | |
@@ -3,11 +3,11 @@ | |
*/ | |
import {Component} from '@angular/core'; | |
import { | |
+ ActivatedRoute, | |
+ ROUTER_DIRECTIVES, | |
Router, | |
- RouterOutlet, | |
- RouteConfig, | |
- RouterLink | |
-} from '@angular/router-deprecated'; | |
+ RouterConfig | |
+} from '@angular/router'; | |
/* | |
* Components | |
@@ -19,14 +19,14 @@ import {ByIdComponent} from 'components/products/ByIdComponent'; | |
@Component({ | |
selector: 'products', | |
- directives: [RouterOutlet, RouterLink], | |
+ directives: [ROUTER_DIRECTIVES], | |
template: ` | |
<h2>Products</h2> | |
<div class="navLinks"> | |
- <a [routerLink]="['./Main']">Main</a> | | |
- <a [routerLink]="['./Interest']">Interest</a> | | |
- <a [routerLink]="['./Sportify']">Sportify</a> | | |
+ <a [routerLink]="['./main']">Main</a> | | |
+ <a [routerLink]="['./interest']">Interest</a> | | |
+ <a [routerLink]="['./sportify']">Sportify</a> | | |
Enter id: <input #id size="6"> | |
<button (click)="goToProduct(id.value)">Go</button> | |
</div> | |
@@ -36,17 +36,20 @@ import {ByIdComponent} from 'components/products/ByIdComponent'; | |
</div> | |
` | |
}) | |
-@RouteConfig([ | |
- { path: '/main', name: 'Main', component: MainComponent, useAsDefault: true }, | |
- { path: '/:id', name: 'ById', component: ByIdComponent }, | |
- { path: '/interest', name: 'Interest', component: InterestComponent }, | |
- { path: '/sportify', name: 'Sportify', component: SportifyComponent }, | |
-]) | |
+ | |
export class ProductsComponent { | |
- constructor(public router: Router) { | |
+ constructor(private router: Router, private route: ActivatedRoute) { | |
} | |
- goToProduct(id: string): void { | |
- this.router.navigate(['./ById', {id: id}]); | |
+ goToProduct(id:string): void { | |
+ this.router.navigate(['./', id], {relativeTo: this.route}); | |
} | |
} | |
+ | |
+export const routes: RouterConfig = [ | |
+ { path: '', redirectTo: 'main' }, | |
+ { path: 'main', component: MainComponent }, | |
+ { path: ':id', component: ByIdComponent }, | |
+ { path: 'interest', component: InterestComponent }, | |
+ { path: 'sportify', component: SportifyComponent }, | |
+]; | |
diff --git a/manuscript/code/routes/nested/app/ts/components/products/ByIdComponent.ts b/manuscript/code/routes/nested/app/ts/components/products/ByIdComponent.ts | |
index 19dccee..e7e270f 100644 | |
--- a/manuscript/code/routes/nested/app/ts/components/products/ByIdComponent.ts | |
+++ b/manuscript/code/routes/nested/app/ts/components/products/ByIdComponent.ts | |
@@ -1,8 +1,8 @@ | |
/* | |
* Angular | |
*/ | |
-import {Component} from '@angular/core'; | |
-import {RouteParams} from '@angular/router-deprecated'; | |
+import { Component } from '@angular/core'; | |
+import { ActivatedRoute } from '@angular/router'; | |
@Component({ | |
selector: 'byid', | |
@@ -11,7 +11,7 @@ import {RouteParams} from '@angular/router-deprecated'; | |
export class ByIdComponent { | |
id: string; | |
- constructor(public routeParams: RouteParams) { | |
- this.id = routeParams.get('id'); | |
+ constructor(public route: ActivatedRoute) { | |
+ route.params.subscribe(params => { this.id = params['id']; }); | |
} | |
} | |
diff --git a/manuscript/code/routes/nested/package.json b/manuscript/code/routes/nested/package.json | |
index 0659e9a..81db4dd 100644 | |
--- a/manuscript/code/routes/nested/package.json | |
+++ b/manuscript/code/routes/nested/package.json | |
@@ -11,13 +11,14 @@ | |
"author": "Nate Murray <[email protected]>", | |
"license": "MIT", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"@angular/router-deprecated": "2.0.0-rc.2", | |
"base64id": "0.1.0", | |
"bootstrap-sass": "3.3.5", | |
diff --git a/manuscript/code/rxjs/chat/package.json b/manuscript/code/rxjs/chat/package.json | |
index 5f821c8..4b0ad18 100644 | |
--- a/manuscript/code/rxjs/chat/package.json | |
+++ b/manuscript/code/rxjs/chat/package.json | |
@@ -6,7 +6,7 @@ | |
"scripts": { | |
"go": "./node_modules/.bin/webpack-dev-server --display-reasons --display-chunks", | |
"clean": "true", | |
- "test": "karma start" | |
+ "test": "karma start --single-run" | |
}, | |
"repository": { | |
"type": "git", | |
@@ -15,15 +15,16 @@ | |
"author": "Nate Murray <[email protected]>", | |
"license": "MIT", | |
"dependencies": { | |
- "@angular/common": "2.0.0-rc.2", | |
- "@angular/compiler": "2.0.0-rc.2", | |
- "@angular/core": "2.0.0-rc.2", | |
- "@angular/http": "2.0.0-rc.2", | |
- "@angular/platform-browser": "2.0.0-rc.2", | |
- "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
- "@angular/router": "2.0.0-rc.2", | |
+ "@angular/common": "2.0.0-rc.4", | |
+ "@angular/compiler": "2.0.0-rc.4", | |
+ "@angular/core": "2.0.0-rc.4", | |
+ "@angular/forms": "0.2.0", | |
+ "@angular/http": "2.0.0-rc.4", | |
+ "@angular/platform-browser": "2.0.0-rc.4", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.4", | |
+ "@angular/router": "3.0.0-beta.1", | |
"base64id": "0.1.0", | |
- "core-js": "^2.2.2", | |
+ "core-js": "2.2.2", | |
"lodash": "3.10.1", | |
"moment": "2.10.6", | |
"optimist": "0.6.1", | |
@@ -64,7 +65,7 @@ | |
"script-loader": "0.6.1", | |
"style-loader": "0.12.3", | |
"traceur-loader": "0.6.3", | |
- "ts-helpers": "^1.1.1", | |
+ "ts-helpers": "1.1.1", | |
"ts-loader": "0.7.2", | |
"tslint-loader": "1.0.1", | |
"typescript": "1.7.3", | |
diff --git a/manuscript/code/rxjs/chat/package.json.orig b/manuscript/code/rxjs/chat/package.json.orig | |
new file mode 100644 | |
index 0000000..5f534d3 | |
--- /dev/null | |
+++ b/manuscript/code/rxjs/chat/package.json.orig | |
@@ -0,0 +1,82 @@ | |
+{ | |
+ "name": "angular2-rxjs-chat", | |
+ "version": "1.0.0", | |
+ "description": "Chat App with Angular 2 and RxJS", | |
+ "main": "index.js", | |
+ "scripts": { | |
+ "go": "./node_modules/.bin/webpack-dev-server --display-reasons --display-chunks", | |
+ "clean": "true", | |
+ "test": "karma start" | |
+ }, | |
+ "repository": { | |
+ "type": "git", | |
+ "url": "https://github.com/ng-book/angular2-rxjs-chat.git" | |
+ }, | |
+ "author": "Nate Murray <[email protected]>", | |
+ "license": "MIT", | |
+ "dependencies": { | |
+ "@angular/common": "2.0.0-rc.2", | |
+ "@angular/compiler": "2.0.0-rc.2", | |
+ "@angular/core": "2.0.0-rc.2", | |
+ "@angular/http": "2.0.0-rc.2", | |
+ "@angular/platform-browser": "2.0.0-rc.2", | |
+ "@angular/platform-browser-dynamic": "2.0.0-rc.2", | |
+ "@angular/router": "2.0.0-rc.2", | |
+<<<<<<< HEAD | |
+ "@angular/router-deprecated": "2.0.0-rc.2", | |
+======= | |
+>>>>>>> 70d6a7f38c5ed937f5676bcc79fbc05ae93fde2a | |
+ "base64id": "0.1.0", | |
+ "core-js": "2.2.2", | |
+ "lodash": "3.10.1", | |
+ "moment": "2.10.6", | |
+ "optimist": "0.6.1", | |
+ "reflect-metadata": "0.1.3", | |
+ "rxjs": "5.0.0-beta.6", | |
+ "tslint": "3.7.0-dev.2", | |
+ "typescript": "1.9.0-dev.20160409", | |
+ "typings": "0.8.1", | |
+ "underscore": "1.8.3", | |
+ "uuid": "2.0.1", | |
+ "zone.js": "0.6.12" | |
+ }, | |
+ "devDependencies": { | |
+ "bootstrap-sass": "3.3.5", | |
+ "chunk-manifest-webpack-plugin": "0.0.1", | |
+ "css-loader": "0.15.5", | |
+ "exports-loader": "0.6.2", | |
+ "expose-loader": "0.7.1", | |
+ "extract-text-webpack-plugin": "0.8.2", | |
+ "file-loader": "0.8.4", | |
+ "html-webpack-plugin": "1.6.0", | |
+ "imports-loader": "0.6.4", | |
+ "jasmine-core": "2.3.4", | |
+ "karma": "0.13.9", | |
+ "karma-chrome-launcher": "0.2.0", | |
+ "karma-jasmine": "0.3.6", | |
+ "karma-phantomjs-launcher": "0.2.1", | |
+ "karma-sourcemap-loader": "0.3.5", | |
+ "karma-spec-reporter": "0.0.20", | |
+ "karma-webpack": "1.7.0", | |
+ "live-server": "0.7.1", | |
+ "node-sass": "3.4.2", | |
+ "on-build-webpack": "0.1.0", | |
+ "phantomjs": "1.9.18", | |
+ "phantomjs-polyfill": "0.0.1", | |
+ "raw-loader": "0.5.1", | |
+ "sass-loader": "1.0.2", | |
+ "script-loader": "0.6.1", | |
+ "style-loader": "0.12.3", | |
+ "traceur-loader": "0.6.3", | |
+ "ts-helpers": "1.1.1", | |
+ "ts-loader": "0.7.2", | |
+ "tslint-loader": "1.0.1", | |
+ "typescript": "1.7.3", | |
+ "url-loader": "0.5.6", | |
+ "val-loader": "0.5.0", | |
+ "webpack": "1.12.9", | |
+ "webpack-dev-server": "1.12.1", | |
+ "webpack-notifier": "1.2.1", | |
+ "webpack-reload-plugin": "0.1.2" | |
+ } | |
+} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment