diff --git a/public/docs/_examples/testing/ts/app/app.component.ts b/public/docs/_examples/testing/ts/app/app.component.ts
index bf10177937..f2da2da067 100644
--- a/public/docs/_examples/testing/ts/app/app.component.ts
+++ b/public/docs/_examples/testing/ts/app/app.component.ts
@@ -13,6 +13,8 @@ import { HeroesComponent } from './heroes.component';
import { HeroDetailComponent } from './hero-detail.component';
import { HeroService } from './hero.service';
+import { BAG_DIRECTIVES, BAG_PROVIDERS } from './bag';
+
@Component({
selector: 'my-app',
template: `
@@ -22,12 +24,23 @@ import { HeroService } from './hero.service';
Heroes
+
+ Bag-a-specs
+
+ External Template Comp
+
+ Comp With External Template Comp
+
`,
+ /*
+
+ */
styleUrls: ['app/app.component.css'],
- directives: [RouterLink, RouterOutlet],
+ directives: [RouterLink, RouterOutlet, BAG_DIRECTIVES],
providers: [
ROUTER_PROVIDERS,
- HeroService
+ HeroService,
+ BAG_PROVIDERS
]
})
@RouteConfig([
diff --git a/public/docs/_examples/testing/ts/app/bad-tests.spec.ts b/public/docs/_examples/testing/ts/app/bad-tests.spec.ts
index eaeab08128..6521bb2e38 100644
--- a/public/docs/_examples/testing/ts/app/bad-tests.spec.ts
+++ b/public/docs/_examples/testing/ts/app/bad-tests.spec.ts
@@ -4,7 +4,7 @@
* Tests that show what goes wrong when the tests are incorrectly written or have a problem
*/
import {
- BadTemplateUrl, ButtonComp,
+ BadTemplateUrlComp, ButtonComp,
ChildChildComp, ChildComp, ChildWithChildComp,
ExternalTemplateComp,
FancyService, MockFancyService,
@@ -134,7 +134,7 @@ xdescribe('async & inject testing errors', () => {
it('should fail with an error from a promise',
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
- tcb.createAsync(BadTemplateUrl);
+ tcb.createAsync(BadTemplateUrlComp);
})));
itPromise.then(
diff --git a/public/docs/_examples/testing/ts/app/bag.spec.ts b/public/docs/_examples/testing/ts/app/bag.spec.ts
index c6eae1bc77..2ad3e13341 100644
--- a/public/docs/_examples/testing/ts/app/bag.spec.ts
+++ b/public/docs/_examples/testing/ts/app/bag.spec.ts
@@ -1,9 +1,9 @@
// Based on https://github.com/angular/angular/blob/master/modules/angular2/test/testing/testing_public_spec.ts
/* tslint:disable:no-unused-variable */
import {
- BadTemplateUrl, ButtonComp,
+ BadTemplateUrlComp, ButtonComp,
ChildChildComp, ChildComp, ChildWithChildComp,
- ExternalTemplateComp,
+ CompWithCompWithExternalTemplate, ExternalTemplateComp,
FancyService, MockFancyService,
InputComp,
MyIfComp, MyIfChildComp, MyIfParentComp,
@@ -18,14 +18,16 @@ import { By } from '@angular/platform-browser';
import {
beforeEach, beforeEachProviders,
describe, ddescribe, xdescribe,
- expect, it, iit, xit,
+ it, iit, xit,
async, inject,
fakeAsync, tick, withProviders
} from '@angular/core/testing';
+// https://github.com/angular/angular/issues/9017
+import {expect} from './expect-proper';
+
import { ComponentFixture, TestComponentBuilder } from '@angular/compiler/testing';
-import { provide } from '@angular/core';
import { ViewMetadata } from '@angular/core';
import { Observable } from 'rxjs/Rx';
@@ -116,7 +118,7 @@ describe('using the test injector with the inject helper', () => {
describe('setting up Providers with FancyService', () => {
beforeEachProviders(() => [
- provide(FancyService, {useValue: new FancyService()})
+ {provide: FancyService, useValue: new FancyService()}
]);
it('should use FancyService',
@@ -183,16 +185,42 @@ describe('using the test injector with the inject helper', () => {
describe('using `withProviders` for per-test provision', () => {
it('should inject test-local FancyService for this test',
// `withProviders`: set up providers at individual test level
- withProviders(() => [provide(FancyService, {useValue: {value: 'fake value'}})])
+ withProviders(() => [{provide: FancyService, useValue: {value: 'fake value'}}])
// now inject and test
.inject([FancyService], (service: FancyService) => {
expect(service.value).toEqual('fake value');
}));
});
+
+
+ describe('can spy on FancyService', () => {
+
+ let spy: jasmine.Spy;
+ let value: string;
+
+ beforeEachProviders(() => [
+ {provide: FancyService, useValue: new FancyService()}
+ ]);
+
+ beforeEach(inject([FancyService], (service: FancyService) => {
+ spy = spyOn(service, 'getValue').and.callFake(() => 'fake value');
+ value = service.getValue();
+ }));
+
+ it('FancyService.getValue spy should return fake', () => {
+ expect(value).toBe('fake value');
+ });
+
+ it('FancyService.getValue spy should have been called', () => {
+ expect(spy.calls.count()).toBe(1, 'should be called once');
+ });
+ });
});
describe('test component builder', function() {
+ beforeEachProviders(() => [ FancyService ]);
+
it('should instantiate a component with valid DOM',
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
@@ -314,7 +342,7 @@ describe('test component builder', function() {
tcb.overrideProviders(
TestProvidersComp,
- [provide(FancyService, {useClass: MockFancyService})]
+ [{provide: FancyService, useClass: MockFancyService}]
)
.createAsync(TestProvidersComp)
.then(fixture => {
@@ -329,7 +357,7 @@ describe('test component builder', function() {
tcb.overrideViewProviders(
TestViewProvidersComp,
- [provide(FancyService, {useClass: MockFancyService})]
+ [{provide: FancyService, useClass: MockFancyService}]
)
.createAsync(TestViewProvidersComp)
.then(fixture => {
@@ -339,7 +367,7 @@ describe('test component builder', function() {
});
})));
- it('should allow an external templateUrl',
+ it('should allow an external template',
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
tcb.createAsync(ExternalTemplateComp)
@@ -348,130 +376,201 @@ describe('test component builder', function() {
expect(fixture.nativeElement)
.toHaveText('from external template\n');
});
- })), 10000); // Long timeout because this test makes an actual XHR.
+ })), 10000); // Long timeout because of actual XHR to fetch template.
- describe('(lifecycle hooks w/ MyIfParentComp)', () => {
- let fixture: ComponentFixture;
- let parent: MyIfParentComp;
- let child: MyIfChildComp;
+ it('should create a component with a component that has an external template',
+ async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
+ tcb.createAsync(CompWithCompWithExternalTemplate)
+ .then(fixture => {
+ fixture.detectChanges();
+ let h3 = fixture.debugElement.query(By.css('h3'));
+ expect(h3).not.toBeNull('should create CompWithExtComp component');
+ })
+ .catch((err) => {
+ // console.error(err);
+ throw (err);
+ });
+ })), 10000); // Long timeout because of actual XHR to fetch template.
- /**
- * Get the MyIfChildComp from parent; fail w/ good message if cannot.
- */
- function getChild() {
- let childDe: DebugElement; // DebugElement that should hold the MyIfChildComp
+ it('should spy on injected component service',
+ async(inject([TestComponentBuilder, FancyService],
+ (tcb: TestComponentBuilder, service: FancyService) => {
- // The Hard Way: requires detailed knowledge of the parent template
- try {
- childDe = fixture.debugElement.children[4].children[0];
- } catch (err) { /* we'll report the error */ }
+ let spy = spyOn(service, 'getValue').and.callThrough();
- // DebugElement.queryAll: if we wanted all of many instances:
- childDe = fixture.debugElement
- .queryAll(function (de) { return de.componentInstance instanceof MyIfChildComp; })[0];
+ tcb
+ .createAsync(ExternalTemplateComp)
+ .then(fixture => {
- // WE'LL USE THIS APPROACH !
- // DebugElement.query: find first instance (if any)
- childDe = fixture.debugElement
- .query(function (de) { return de.componentInstance instanceof MyIfChildComp; });
+ // let spy = spyOn(service, 'getValue').and.callThrough();
- if (childDe && childDe.componentInstance) {
- child = childDe.componentInstance;
- } else {
- fail('Unable to find MyIfChildComp within MyIfParentComp');
- }
+ fixture.detectChanges();
+ expect(spy.calls.count()).toBe(1, 'should be called once');
+ });
+ })), 10000); // Long timeout because of actual XHR to fetch template.
- return child;
+ describe('(lifecycle hooks w/ MyIfParentComp)', () => {
+ let fixture: ComponentFixture;
+ let parent: MyIfParentComp;
+ let child: MyIfChildComp;
+
+ /**
+ * Get the MyIfChildComp from parent; fail w/ good message if cannot.
+ */
+ function getChild() {
+
+ let childDe: DebugElement; // DebugElement that should hold the MyIfChildComp
+
+ // The Hard Way: requires detailed knowledge of the parent template
+ try {
+ childDe = fixture.debugElement.children[4].children[0];
+ } catch (err) { /* we'll report the error */ }
+
+ // DebugElement.queryAll: if we wanted all of many instances:
+ childDe = fixture.debugElement
+ .queryAll(function (de) { return de.componentInstance instanceof MyIfChildComp; })[0];
+
+ // WE'LL USE THIS APPROACH !
+ // DebugElement.query: find first instance (if any)
+ childDe = fixture.debugElement
+ .query(function (de) { return de.componentInstance instanceof MyIfChildComp; });
+
+ if (childDe && childDe.componentInstance) {
+ child = childDe.componentInstance;
+ } else {
+ fail('Unable to find MyIfChildComp within MyIfParentComp');
}
- // Create MyIfParentComp TCB and component instance before each test (async beforeEach)
- beforeEach(async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
- tcb.createAsync(MyIfParentComp)
- .then(fix => {
- fixture = fix;
- parent = fixture.debugElement.componentInstance;
- });
- })));
+ return child;
+ }
- it('should instantiate parent component', () => {
- expect(parent).not.toBeNull('parent component should exist');
- });
+ // Create MyIfParentComp TCB and component instance before each test (async beforeEach)
+ beforeEach(async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
+ tcb.createAsync(MyIfParentComp)
+ .then(fix => {
+ fixture = fix;
+ parent = fixture.debugElement.componentInstance;
+ });
+ })));
- it('parent component OnInit should NOT be called before first detectChanges()', () => {
- expect(parent.ngOnInitCalled).toEqual(false);
- });
+ it('should instantiate parent component', () => {
+ expect(parent).not.toBeNull('parent component should exist');
+ });
- it('parent component OnInit should be called after first detectChanges()', () => {
- fixture.detectChanges();
- expect(parent.ngOnInitCalled).toEqual(true);
- });
+ it('parent component OnInit should NOT be called before first detectChanges()', () => {
+ expect(parent.ngOnInitCalled).toEqual(false);
+ });
- it('child component should exist after OnInit', () => {
- fixture.detectChanges();
- getChild();
- expect(child instanceof MyIfChildComp).toEqual(true, 'should create child');
- });
+ it('parent component OnInit should be called after first detectChanges()', () => {
+ fixture.detectChanges();
+ expect(parent.ngOnInitCalled).toEqual(true);
+ });
- it('should have called child component\'s OnInit ', () => {
- fixture.detectChanges();
- getChild();
- expect(child.ngOnInitCalled).toEqual(true);
- });
+ it('child component should exist after OnInit', () => {
+ fixture.detectChanges();
+ getChild();
+ expect(child instanceof MyIfChildComp).toEqual(true, 'should create child');
+ });
- it('child component called OnChanges once', () => {
- fixture.detectChanges();
- getChild();
- expect(child.ngOnChangesCounter).toEqual(1);
- });
+ it('should have called child component\'s OnInit ', () => {
+ fixture.detectChanges();
+ getChild();
+ expect(child.ngOnInitCalled).toEqual(true);
+ });
- it('changed parent value flows to child', () => {
- fixture.detectChanges();
- getChild();
+ it('child component called OnChanges once', () => {
+ fixture.detectChanges();
+ getChild();
+ expect(child.ngOnChangesCounter).toEqual(1);
+ });
- parent.parentValue = 'foo';
+ it('changed parent value flows to child', () => {
+ fixture.detectChanges();
+ getChild();
+
+ parent.parentValue = 'foo';
+ fixture.detectChanges();
+
+ expect(child.ngOnChangesCounter).toEqual(2,
+ 'expected 2 changes: initial value and changed value');
+ expect(child.childValue).toEqual('foo',
+ 'childValue should eq changed parent value');
+ });
+
+ it('changed child value flows to parent', async(() => {
+ fixture.detectChanges();
+ getChild();
+
+ child.childValue = 'bar';
+
+ return new Promise(resolve => {
+ // Wait one JS engine turn!
+ setTimeout(() => resolve(), 0);
+ }).then(() => {
fixture.detectChanges();
expect(child.ngOnChangesCounter).toEqual(2,
'expected 2 changes: initial value and changed value');
- expect(child.childValue).toEqual('foo',
- 'childValue should eq changed parent value');
+ expect(parent.parentValue).toEqual('bar',
+ 'parentValue should eq changed parent value');
});
- it('changed child value flows to parent', async(() => {
- fixture.detectChanges();
- getChild();
+ }));
- child.childValue = 'bar';
+ it('clicking "Close Child" triggers child OnDestroy', () => {
+ fixture.detectChanges();
+ getChild();
- return new Promise(resolve => {
- // Wait one JS engine turn!
- setTimeout(() => resolve(), 0);
- }).then(() => {
- fixture.detectChanges();
-
- expect(child.ngOnChangesCounter).toEqual(2,
- 'expected 2 changes: initial value and changed value');
- expect(parent.parentValue).toEqual('bar',
- 'parentValue should eq changed parent value');
- });
-
- }));
-
- it('clicking "Close Child" triggers child OnDestroy', () => {
- fixture.detectChanges();
- getChild();
-
- let btn = fixture.debugElement.query(By.css('button'));
- btn.triggerEventHandler('click', null);
-
- fixture.detectChanges();
- expect(child.ngOnDestroyCalled).toEqual(true);
- });
+ let btn = fixture.debugElement.query(By.css('button'));
+ btn.triggerEventHandler('click', null);
+ fixture.detectChanges();
+ expect(child.ngOnDestroyCalled).toEqual(true);
});
+
+ });
});
+describe('test component builder in beforeEach (comp w/ external template)', function() {
+ let fixture: ComponentFixture;
+
+ beforeEach(async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
+ tcb.createAsync(ExternalTemplateComp).then(fix => fixture = fix);
+ }))
+ );
+ // May need Long timeout because this test makes an actual XHR to get template
+ // , 10000); WHY CAN'T I ADD TIMEOUT OVERRIDE
+
+ it('should allow an external template', () => {
+ fixture.detectChanges();
+ expect(fixture.nativeElement)
+ .toHaveText('from external template\n');
+ });
+
+});
+
+describe('test component builder in beforeEach (comp w/ internal comp w/ external template)', function() {
+ let fixture: ComponentFixture;
+
+ beforeEach(async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
+ tcb.createAsync(CompWithCompWithExternalTemplate).then(fix => fixture = fix)
+ .catch((err) => {
+ // console.error(err);
+ throw (err);
+ });
+ }))
+ );
+ // May need Long timeout because this test makes an actual XHR to get template
+ // , 10000); WHY CAN'T I ADD TIMEOUT OVERRIDE
+
+ it('should allow an external template', () => {
+ fixture.detectChanges();
+ let h3 = fixture.debugElement.query(By.css('h3'));
+ expect(h3).not.toBeNull('should create CompWithExtComp component');
+ });
+
+});
//////// Testing Framework Bugs? /////
import { HeroService } from './hero.service';
@@ -495,7 +594,7 @@ describe('tcb.overrideProviders', () => {
tcb.overrideProviders(
AnotherProvidersComp,
- [provide(HeroService, {useValue: {}})]
+ [{provide: HeroService, useValue: {}}]
)
.createAsync(AnotherProvidersComp);
})));
diff --git a/public/docs/_examples/testing/ts/app/bag.ts b/public/docs/_examples/testing/ts/app/bag.ts
index 0da4d7fb20..94be448e7e 100644
--- a/public/docs/_examples/testing/ts/app/bag.ts
+++ b/public/docs/_examples/testing/ts/app/bag.ts
@@ -1,6 +1,6 @@
// Based on https://github.com/angular/angular/blob/master/modules/angular2/test/testing/testing_public_spec.ts
/* tslint:disable:forin */
-import { Component, EventEmitter, Injectable, Input, Output,
+import { Component, EventEmitter, Injectable, Input, Output, Optional,
OnInit, OnChanges, OnDestroy, SimpleChange } from '@angular/core';
import { Observable } from 'rxjs/Rx';
@@ -13,6 +13,8 @@ import { Observable } from 'rxjs/Rx';
export class FancyService {
value: string = 'real value';
+ getValue() { return this.value; }
+
getAsyncValue() { return Promise.resolve('async value'); }
getObservableValue() { return Observable.of('observable value'); }
@@ -123,20 +125,36 @@ export class TestViewProvidersComp {
constructor(private fancyService: FancyService) {}
}
-
@Component({
moduleId: module.id,
selector: 'external-template-comp',
templateUrl: 'bag-external-template.html'
})
-export class ExternalTemplateComp { }
+export class ExternalTemplateComp {
+ serviceValue: string;
+ constructor(@Optional() private service: FancyService) { }
+
+ ngOnInit() {
+ if (this.service) { this.serviceValue = this.service.getValue(); }
+ }
+}
+
+@Component({
+ selector: 'comp-w-ext-comp',
+ template: `
+ comp-w-ext-comp
+
+ `,
+ directives: [ExternalTemplateComp]
+})
+export class CompWithCompWithExternalTemplate { }
@Component({
selector: 'bad-template-comp',
templateUrl: 'non-existant.html'
})
-export class BadTemplateUrl { }
+export class BadTemplateUrlComp { }
///////// MyIfChildComp ////////
@@ -222,3 +240,16 @@ export class MyIfParentComp implements OnInit {
this.toggleLabel = this.showChild ? 'Close' : 'Show';
}
}
+
+export const BAG_PROVIDERS = [FancyService];
+
+export const BAG_DIRECTIVES = [
+ ButtonComp,
+ ChildChildComp, ChildComp, ChildWithChildComp,
+ ExternalTemplateComp, CompWithCompWithExternalTemplate,
+ InputComp,
+ MyIfComp, MyIfChildComp, MyIfParentComp,
+ MockChildComp, MockChildChildComp,
+ ParentComp,
+ TestProvidersComp, TestViewProvidersComp
+];
diff --git a/public/docs/_examples/testing/ts/app/expect-proper.ts b/public/docs/_examples/testing/ts/app/expect-proper.ts
new file mode 100644
index 0000000000..6712b879d1
--- /dev/null
+++ b/public/docs/_examples/testing/ts/app/expect-proper.ts
@@ -0,0 +1,9 @@
+// See https://github.com/angular/angular/issues/9017
+import { expect as expectCore} from '@angular/core/testing';
+import { NgMatchers } from '@angular/platform-browser/testing';
+
+export function expect(spy: Function): NgMatchers;
+export function expect(actual: any): NgMatchers;
+export function expect(actual: any): NgMatchers {
+ return expectCore(actual) as NgMatchers;
+}
diff --git a/public/docs/_examples/testing/ts/app/main.ts b/public/docs/_examples/testing/ts/app/main.ts
index 33b9c2b641..5f185788a3 100644
--- a/public/docs/_examples/testing/ts/app/main.ts
+++ b/public/docs/_examples/testing/ts/app/main.ts
@@ -1,6 +1,5 @@
import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from './app.component';
-import { MyIfParentComp } from './bag';
bootstrap(AppComponent);
-bootstrap(MyIfParentComp);
+
diff --git a/public/docs/_examples/testing/ts/index.html b/public/docs/_examples/testing/ts/index.html
index 02b11078c5..bfde80afe3 100644
--- a/public/docs/_examples/testing/ts/index.html
+++ b/public/docs/_examples/testing/ts/index.html
@@ -22,7 +22,5 @@
Loading...
-
- Loading MyIfParentComp ...