docs(testing) adapt sample code to beta.16 breaking changes
This commit is contained in:
parent
097505b4e8
commit
4bbaac127d
|
@ -20,24 +20,30 @@ module.exports = function(config) {
|
||||||
flags: ['--no-sandbox']
|
flags: ['--no-sandbox']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
files: [
|
files: [
|
||||||
// Angular and shim libraries loaded by Karma
|
// System.js for module loading
|
||||||
{ pattern: 'node_modules/systemjs/dist/system-polyfills.js', included: true, watched: true },
|
'node_modules/systemjs/dist/system-polyfills.js',
|
||||||
{ pattern: 'node_modules/systemjs/dist/system.src.js', included: true, watched: true },
|
'node_modules/systemjs/dist/system.src.js',
|
||||||
{ pattern: 'node_modules/es6-shim/es6-shim.js', included: true, watched: true },
|
|
||||||
{ pattern: 'node_modules/angular2/bundles/angular2-polyfills.js', included: true, watched: true },
|
|
||||||
{ pattern: 'node_modules/rxjs/bundles/Rx.js', included: true, watched: true },
|
|
||||||
{ pattern: 'node_modules/angular2/bundles/angular2.js', included: true, watched: true },
|
|
||||||
{ pattern: 'node_modules/angular2/bundles/testing.dev.js', included: true, watched: true },
|
|
||||||
|
|
||||||
// External libraries loaded by Karma
|
// Polyfills
|
||||||
{ pattern: 'node_modules/angular2/bundles/http.dev.js', included: true, watched: true },
|
'node_modules/es6-shim/es6-shim.js',
|
||||||
{ pattern: 'node_modules/angular2/bundles/router.dev.js', included: true, watched: true },
|
'node_modules/angular2/bundles/angular2-polyfills.js',
|
||||||
{ pattern: 'node_modules/a2-in-memory-web-api/web-api.js', included: true, watched: true },
|
|
||||||
|
|
||||||
// Configures module loader w/ app and specs, then launch karma
|
// Zone.js dependencies
|
||||||
{ pattern: 'karma-test-shim.js', included: true, watched: true },
|
// Note - do not include zone.js itself or long-stack-trace-zone.js` here as
|
||||||
|
// they are included already in angular2-polyfills
|
||||||
|
'node_modules/zone.js/dist/jasmine-patch.js',
|
||||||
|
'node_modules/zone.js/dist/async-test.js',
|
||||||
|
'node_modules/zone.js/dist/fake-async-test.js',
|
||||||
|
|
||||||
|
// RxJs
|
||||||
|
'node_modules/rxjs/bundles/Rx.js',
|
||||||
|
|
||||||
|
// Angular 2 itself and the testing library
|
||||||
|
'node_modules/angular2/bundles/angular2.js',
|
||||||
|
'node_modules/angular2/bundles/testing.dev.js',
|
||||||
|
|
||||||
|
'karma-test-shim.js',
|
||||||
|
|
||||||
// transpiled application & spec code paths loaded via module imports
|
// transpiled application & spec code paths loaded via module imports
|
||||||
{pattern: appBase + '**/*.js', included: false, watched: true},
|
{pattern: appBase + '**/*.js', included: false, watched: true},
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
/* tslint:disable:no-unused-variable */
|
/* tslint:disable:no-unused-variable */
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
import { By } from 'angular2/platform/browser';
|
import { By } from 'angular2/platform/browser';
|
||||||
import { provide } from 'angular2/core';
|
import { DebugElement, provide } from 'angular2/core';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
beforeEach, beforeEachProviders,
|
beforeEach, beforeEachProviders,
|
||||||
describe, ddescribe, xdescribe,
|
describe, ddescribe, xdescribe,
|
||||||
expect, it, iit, xit,
|
expect, it, iit, xit,
|
||||||
inject, injectAsync,
|
async, inject, ComponentFixture, TestComponentBuilder
|
||||||
ComponentFixture, TestComponentBuilder
|
|
||||||
} from 'angular2/testing';
|
} from 'angular2/testing';
|
||||||
|
|
||||||
import { Hero, HeroService, MockHeroService } from './mock-hero.service';
|
import { Hero, HeroService, MockHeroService } from './mock-hero.service';
|
||||||
|
@ -22,8 +21,8 @@ describe('AppComponent', () => {
|
||||||
let fixture: ComponentFixture;
|
let fixture: ComponentFixture;
|
||||||
let comp: AppComponent;
|
let comp: AppComponent;
|
||||||
|
|
||||||
beforeEach(injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
beforeEach(async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
return tcb
|
tcb
|
||||||
.overrideDirective(AppComponent, RouterLink, MockRouterLink)
|
.overrideDirective(AppComponent, RouterLink, MockRouterLink)
|
||||||
.overrideDirective(AppComponent, RouterOutlet, MockRouterOutlet)
|
.overrideDirective(AppComponent, RouterOutlet, MockRouterOutlet)
|
||||||
.overrideProviders(AppComponent, [
|
.overrideProviders(AppComponent, [
|
||||||
|
@ -35,7 +34,7 @@ describe('AppComponent', () => {
|
||||||
fixture = fix;
|
fixture = fix;
|
||||||
comp = fixture.debugElement.componentInstance;
|
comp = fixture.debugElement.componentInstance;
|
||||||
});
|
});
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('can instantiate it', () => {
|
it('can instantiate it', () => {
|
||||||
expect(comp).not.toBeNull();
|
expect(comp).not.toBeNull();
|
||||||
|
@ -51,8 +50,8 @@ describe('AppComponent', () => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
let links = fixture.debugElement
|
let links = fixture.debugElement
|
||||||
.queryAll(function (de) { return de.componentInstance instanceof MockRouterLink; })
|
.queryAll(By.directive(MockRouterLink))
|
||||||
.map(de => <MockRouterLink> de.componentInstance);
|
.map(de => <MockRouterLink> extractDirective(de, MockRouterLink));
|
||||||
|
|
||||||
expect(links.length).toEqual(2, 'should have 2 links');
|
expect(links.length).toEqual(2, 'should have 2 links');
|
||||||
expect(links[0].routeParams[0]).toEqual('Dashboard', '1st link should go to Dashboard');
|
expect(links[0].routeParams[0]).toEqual('Dashboard', '1st link should go to Dashboard');
|
||||||
|
@ -67,11 +66,12 @@ describe('AppComponent', () => {
|
||||||
|
|
||||||
// Heroes RouterLink DebugElement
|
// Heroes RouterLink DebugElement
|
||||||
let heroesDe = fixture.debugElement
|
let heroesDe = fixture.debugElement
|
||||||
.queryAll(function (de) { return de.componentInstance instanceof MockRouterLink; })[1];
|
.queryAll(By.directive(MockRouterLink))[1];
|
||||||
|
|
||||||
expect(heroesDe).not.toBeNull('should 2nd link');
|
expect(heroesDe).toBeDefined('should have a 2nd RouterLink');
|
||||||
|
|
||||||
|
let link = <MockRouterLink> extractDirective(heroesDe, MockRouterLink);
|
||||||
|
|
||||||
let link = <MockRouterLink> heroesDe.componentInstance;
|
|
||||||
expect(link.navigatedTo).toBeNull('link should not have navigate yet');
|
expect(link.navigatedTo).toBeNull('link should not have navigate yet');
|
||||||
|
|
||||||
heroesDe.triggerEventHandler('click', null);
|
heroesDe.triggerEventHandler('click', null);
|
||||||
|
@ -82,3 +82,15 @@ describe('AppComponent', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
///////////// Helpers ////////////////////
|
||||||
|
|
||||||
|
import { Type } from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the directive instance from the DebugElement to which it is attached
|
||||||
|
*/
|
||||||
|
function extractDirective(de: DebugElement, directive: Type): any {
|
||||||
|
return de.injector.get(
|
||||||
|
de.providerTokens[de.providerTokens.indexOf(directive)]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
// Based on https://github.com/angular/angular/blob/master/modules/angular2/test/testing/testing_public_spec.ts
|
||||||
|
/* tslint:disable:no-unused-variable */
|
||||||
|
/**
|
||||||
|
* Tests that show what goes wrong when the tests are incorrectly written or have a problem
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
BadTemplateUrl, ButtonComp,
|
||||||
|
ChildChildComp, ChildComp, ChildWithChildComp,
|
||||||
|
ExternalTemplateComp,
|
||||||
|
FancyService, MockFancyService,
|
||||||
|
InputComp,
|
||||||
|
MyIfComp, MyIfChildComp, MyIfParentComp,
|
||||||
|
MockChildComp, MockChildChildComp,
|
||||||
|
ParentComp,
|
||||||
|
TestProvidersComp, TestViewProvidersComp
|
||||||
|
} from './bag';
|
||||||
|
|
||||||
|
import { DebugElement } from 'angular2/core';
|
||||||
|
import { By } from 'angular2/platform/browser';
|
||||||
|
|
||||||
|
import {
|
||||||
|
beforeEach, beforeEachProviders, withProviders,
|
||||||
|
describe, ddescribe, xdescribe,
|
||||||
|
expect, it, iit, xit,
|
||||||
|
async, inject, fakeAsync, tick,
|
||||||
|
ComponentFixture, TestComponentBuilder
|
||||||
|
} from 'angular2/testing';
|
||||||
|
|
||||||
|
import { provide } from 'angular2/core';
|
||||||
|
import { ViewMetadata } from 'angular2/core';
|
||||||
|
import { PromiseWrapper } from 'angular2/src/facade/promise';
|
||||||
|
import { XHR } from 'angular2/src/compiler/xhr';
|
||||||
|
import { XHRImpl } from 'angular2/src/platform/browser/xhr_impl';
|
||||||
|
import { Observable } from 'rxjs/Rx';
|
||||||
|
|
||||||
|
//////// SPECS /////////////
|
||||||
|
|
||||||
|
xdescribe('async & inject testing errors', () => {
|
||||||
|
let originalJasmineIt: any;
|
||||||
|
let originalJasmineBeforeEach: any;
|
||||||
|
|
||||||
|
let patchJasmineIt = () => {
|
||||||
|
let deferred = PromiseWrapper.completer();
|
||||||
|
originalJasmineIt = jasmine.getEnv().it;
|
||||||
|
jasmine.getEnv().it = (description: string, fn: Function): jasmine.Spec => {
|
||||||
|
let done = () => { deferred.resolve(); };
|
||||||
|
(<any>done).fail = (err: any) => { deferred.reject(err); };
|
||||||
|
fn(done);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
return deferred.promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
let restoreJasmineIt = () => { jasmine.getEnv().it = originalJasmineIt; };
|
||||||
|
|
||||||
|
let patchJasmineBeforeEach = () => {
|
||||||
|
let deferred = PromiseWrapper.completer();
|
||||||
|
originalJasmineBeforeEach = jasmine.getEnv().beforeEach;
|
||||||
|
jasmine.getEnv().beforeEach = (fn: any): void => {
|
||||||
|
let done = () => { deferred.resolve(); };
|
||||||
|
(<any>done).fail = (err: any) => { deferred.reject(err); };
|
||||||
|
fn(done);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
return deferred.promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
let restoreJasmineBeforeEach =
|
||||||
|
() => { jasmine.getEnv().beforeEach = originalJasmineBeforeEach; };
|
||||||
|
|
||||||
|
const shouldNotSucceed =
|
||||||
|
(done: DoneFn) => () => done.fail( 'Expected an error, but did not get one.');
|
||||||
|
|
||||||
|
const shouldFail =
|
||||||
|
(done: DoneFn, emsg: string) => (err: any) => { expect(err).toEqual(emsg); done(); };
|
||||||
|
|
||||||
|
it('should fail when an asynchronous error is thrown', (done: DoneFn) => {
|
||||||
|
let itPromise = patchJasmineIt();
|
||||||
|
|
||||||
|
it('throws an async error',
|
||||||
|
async(inject([], () => { setTimeout(() => { throw new Error('bar'); }, 0); })));
|
||||||
|
|
||||||
|
itPromise.then(
|
||||||
|
shouldNotSucceed(done),
|
||||||
|
err => {
|
||||||
|
expect(err).toEqual('bar');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
restoreJasmineIt();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail when a returned promise is rejected', (done: DoneFn) => {
|
||||||
|
let itPromise = patchJasmineIt();
|
||||||
|
|
||||||
|
it('should fail with an error from a promise', async(inject([], () => {
|
||||||
|
let deferred = PromiseWrapper.completer();
|
||||||
|
let p = deferred.promise.then(() => { expect(1).toEqual(2); });
|
||||||
|
|
||||||
|
deferred.reject('baz');
|
||||||
|
return p;
|
||||||
|
})));
|
||||||
|
|
||||||
|
itPromise.then(
|
||||||
|
shouldNotSucceed(done),
|
||||||
|
err => {
|
||||||
|
expect(err).toEqual('Uncaught (in promise): baz');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
restoreJasmineIt();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail when an error occurs inside inject', (done: DoneFn) => {
|
||||||
|
let itPromise = patchJasmineIt();
|
||||||
|
|
||||||
|
it('throws an error', inject([], () => { throw new Error('foo'); }));
|
||||||
|
|
||||||
|
itPromise.then(
|
||||||
|
shouldNotSucceed(done),
|
||||||
|
shouldFail(done, 'foo')
|
||||||
|
);
|
||||||
|
restoreJasmineIt();
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO(juliemr): reenable this test when we are using a test zone and can capture this error.
|
||||||
|
it('should fail when an asynchronous error is thrown', (done: DoneFn) => {
|
||||||
|
let itPromise = patchJasmineIt();
|
||||||
|
|
||||||
|
it('throws an async error',
|
||||||
|
async(inject([], () => { setTimeout(() => { throw new Error('bar'); }, 0); })));
|
||||||
|
|
||||||
|
itPromise.then(
|
||||||
|
shouldNotSucceed(done),
|
||||||
|
shouldFail(done, 'bar')
|
||||||
|
);
|
||||||
|
restoreJasmineIt();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail when XHR loading of a template fails', (done: DoneFn) => {
|
||||||
|
let itPromise = patchJasmineIt();
|
||||||
|
|
||||||
|
it('should fail with an error from a promise',
|
||||||
|
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
|
tcb.createAsync(BadTemplateUrl);
|
||||||
|
})));
|
||||||
|
|
||||||
|
itPromise.then(
|
||||||
|
shouldNotSucceed(done),
|
||||||
|
shouldFail(done, 'Uncaught (in promise): Failed to load non-existant.html')
|
||||||
|
);
|
||||||
|
restoreJasmineIt();
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
describe('using beforeEachProviders', () => {
|
||||||
|
beforeEachProviders(() => [provide(FancyService, {useValue: new FancyService()})]);
|
||||||
|
|
||||||
|
beforeEach(
|
||||||
|
inject([FancyService], (service: FancyService) => { expect(service.value).toEqual('real value'); }));
|
||||||
|
|
||||||
|
describe('nested beforeEachProviders', () => {
|
||||||
|
|
||||||
|
it('should fail when the injector has already been used', () => {
|
||||||
|
patchJasmineBeforeEach();
|
||||||
|
expect(() => {
|
||||||
|
beforeEachProviders(() => [provide(FancyService, {useValue: new FancyService()})]);
|
||||||
|
})
|
||||||
|
.toThrowError('beforeEachProviders was called after the injector had been used ' +
|
||||||
|
'in a beforeEach or it block. This invalidates the test injector');
|
||||||
|
restoreJasmineBeforeEach();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -19,7 +19,7 @@ import {
|
||||||
beforeEach, beforeEachProviders, withProviders,
|
beforeEach, beforeEachProviders, withProviders,
|
||||||
describe, ddescribe, xdescribe,
|
describe, ddescribe, xdescribe,
|
||||||
expect, it, iit, xit,
|
expect, it, iit, xit,
|
||||||
inject, injectAsync, fakeAsync, tick,
|
async, inject, fakeAsync, tick,
|
||||||
ComponentFixture, TestComponentBuilder
|
ComponentFixture, TestComponentBuilder
|
||||||
} from 'angular2/testing';
|
} from 'angular2/testing';
|
||||||
|
|
||||||
|
@ -28,12 +28,7 @@ import { ViewMetadata } from 'angular2/core';
|
||||||
import { PromiseWrapper } from 'angular2/src/facade/promise';
|
import { PromiseWrapper } from 'angular2/src/facade/promise';
|
||||||
import { XHR } from 'angular2/src/compiler/xhr';
|
import { XHR } from 'angular2/src/compiler/xhr';
|
||||||
import { XHRImpl } from 'angular2/src/platform/browser/xhr_impl';
|
import { XHRImpl } from 'angular2/src/platform/browser/xhr_impl';
|
||||||
|
import { Observable } from 'rxjs/Rx';
|
||||||
/////////// Module Preparation ///////////////////////
|
|
||||||
interface Done {
|
|
||||||
(): void;
|
|
||||||
fail: (err: any) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////// SPECS /////////////
|
//////// SPECS /////////////
|
||||||
|
|
||||||
|
@ -78,16 +73,47 @@ describe('angular2 jasmine matchers', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('using the test injector with the inject helper', () => {
|
describe('using the async helper', () => {
|
||||||
it('should run normal tests', () => { expect(true).toEqual(true); });
|
let actuallyDone = false;
|
||||||
|
|
||||||
it('should run normal async tests', (done: Done) => {
|
beforeEach(() => { actuallyDone = false; });
|
||||||
|
|
||||||
|
afterEach(() => { expect(actuallyDone).toEqual(true); });
|
||||||
|
|
||||||
|
it('should run normal test', () => { actuallyDone = true; });
|
||||||
|
|
||||||
|
it('should run normal async test', (done: DoneFn) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
expect(true).toEqual(true);
|
actuallyDone = true;
|
||||||
done();
|
done();
|
||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should run async test with task',
|
||||||
|
async(() => { setTimeout(() => { actuallyDone = true; }, 0); }));
|
||||||
|
|
||||||
|
it('should run async test with successful promise', async(() => {
|
||||||
|
let p = new Promise(resolve => { setTimeout(resolve, 10); });
|
||||||
|
p.then(() => { actuallyDone = true; });
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should run async test with failed promise', async(() => {
|
||||||
|
let p = new Promise((resolve, reject) => { setTimeout(reject, 10); });
|
||||||
|
p.catch(() => { actuallyDone = true; });
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should run async test with successful Observable', async(() => {
|
||||||
|
let source = Observable.of(true).delay(10);
|
||||||
|
source.subscribe(
|
||||||
|
val => {},
|
||||||
|
err => fail(err),
|
||||||
|
() => { actuallyDone = true; } // completed
|
||||||
|
);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('using the test injector with the inject helper', () => {
|
||||||
|
|
||||||
it('provides a real XHR instance',
|
it('provides a real XHR instance',
|
||||||
inject([XHR], (xhr: any) => { expect(xhr).toBeAnInstanceOf(XHRImpl); }));
|
inject([XHR], (xhr: any) => { expect(xhr).toBeAnInstanceOf(XHRImpl); }));
|
||||||
|
|
||||||
|
@ -102,14 +128,33 @@ describe('using the test injector with the inject helper', () => {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('test should wait for FancyService.getAsyncValue',
|
it('test should wait for FancyService.getAsyncValue',
|
||||||
injectAsync([FancyService], (service: FancyService) => {
|
async(inject([FancyService], (service: FancyService) => {
|
||||||
return service.getAsyncValue().then(
|
service.getAsyncValue().then(
|
||||||
(value) => { expect(value).toEqual('async value'); });
|
value => { expect(value).toEqual('async value'); });
|
||||||
}));
|
})));
|
||||||
|
|
||||||
|
it('test should wait for FancyService.getTimeoutValue',
|
||||||
|
async(inject([FancyService], (service: FancyService) => {
|
||||||
|
service.getTimeoutValue().then(
|
||||||
|
value => { expect(value).toEqual('timeout value'); });
|
||||||
|
})));
|
||||||
|
|
||||||
|
it('test should wait for FancyService.getObservableValue',
|
||||||
|
async(inject([FancyService], (service: FancyService) => {
|
||||||
|
service.getObservableValue().subscribe(
|
||||||
|
value => { expect(value).toEqual('observable value'); }
|
||||||
|
);
|
||||||
|
})));
|
||||||
|
|
||||||
|
it('test should wait for FancyService.getObservableDelayValue',
|
||||||
|
async(inject([FancyService], (service: FancyService) => {
|
||||||
|
service.getObservableDelayValue().subscribe(
|
||||||
|
value => { expect(value).toEqual('observable delay value'); }
|
||||||
|
);
|
||||||
|
})));
|
||||||
|
|
||||||
// Experimental: write async tests synchonously by faking async processing
|
|
||||||
it('should allow the use of fakeAsync (Experimental)',
|
it('should allow the use of fakeAsync (Experimental)',
|
||||||
inject([FancyService], fakeAsync((service: FancyService) => {
|
fakeAsync(inject([FancyService], (service: FancyService) => {
|
||||||
let value: any;
|
let value: any;
|
||||||
service.getAsyncValue().then((val: any) => value = val);
|
service.getAsyncValue().then((val: any) => value = val);
|
||||||
tick(); // Trigger JS engine cycle until all promises resolve.
|
tick(); // Trigger JS engine cycle until all promises resolve.
|
||||||
|
@ -128,9 +173,9 @@ describe('using the test injector with the inject helper', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('using async within beforeEach', () => {
|
describe('using async within beforeEach', () => {
|
||||||
beforeEach(injectAsync([FancyService], (service: FancyService) => {
|
beforeEach(async(inject([FancyService], (service: FancyService) => {
|
||||||
return service.getAsyncValue().then(value => { service.value = value; });
|
service.getAsyncValue().then(value => { service.value = value; });
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('should use asynchronously modified value ... in synchronous test',
|
it('should use asynchronously modified value ... in synchronous test',
|
||||||
inject([FancyService], (service: FancyService) => {
|
inject([FancyService], (service: FancyService) => {
|
||||||
|
@ -152,18 +197,18 @@ describe('using the test injector with the inject helper', () => {
|
||||||
|
|
||||||
describe('test component builder', function() {
|
describe('test component builder', function() {
|
||||||
it('should instantiate a component with valid DOM',
|
it('should instantiate a component with valid DOM',
|
||||||
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
|
|
||||||
return tcb.createAsync(ChildComp).then(fixture => {
|
tcb.createAsync(ChildComp).then(fixture => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(fixture.nativeElement).toHaveText('Original Child');
|
expect(fixture.nativeElement).toHaveText('Original Child');
|
||||||
});
|
});
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('should allow changing members of the component',
|
it('should allow changing members of the component',
|
||||||
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
|
|
||||||
return tcb.createAsync(MyIfComp).then(fixture => {
|
tcb.createAsync(MyIfComp).then(fixture => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(fixture.nativeElement).toHaveText('MyIf()');
|
expect(fixture.nativeElement).toHaveText('MyIf()');
|
||||||
|
|
||||||
|
@ -171,12 +216,12 @@ describe('test component builder', function() {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(fixture.nativeElement).toHaveText('MyIf(More)');
|
expect(fixture.nativeElement).toHaveText('MyIf(More)');
|
||||||
});
|
});
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('should support clicking a button',
|
it('should support clicking a button',
|
||||||
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
|
|
||||||
return tcb.createAsync(ButtonComp).then(fixture => {
|
tcb.createAsync(ButtonComp).then(fixture => {
|
||||||
|
|
||||||
let comp = <ButtonComp> fixture.componentInstance;
|
let comp = <ButtonComp> fixture.componentInstance;
|
||||||
expect(comp.wasClicked).toEqual(false, 'wasClicked should be false at start');
|
expect(comp.wasClicked).toEqual(false, 'wasClicked should be false at start');
|
||||||
|
@ -188,14 +233,14 @@ describe('test component builder', function() {
|
||||||
// btn.nativeElement.click(); // this often works too ... but not all the time!
|
// btn.nativeElement.click(); // this often works too ... but not all the time!
|
||||||
expect(comp.wasClicked).toEqual(true, 'wasClicked should be true after click');
|
expect(comp.wasClicked).toEqual(true, 'wasClicked should be true after click');
|
||||||
});
|
});
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('should support entering text in input box (ngModel)',
|
it('should support entering text in input box (ngModel)',
|
||||||
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
let origName = 'John';
|
let origName = 'John';
|
||||||
let newName = 'Sally';
|
let newName = 'Sally';
|
||||||
|
|
||||||
return tcb.createAsync(InputComp).then(fixture => {
|
tcb.createAsync(InputComp).then(fixture => {
|
||||||
|
|
||||||
let comp = <InputComp> fixture.componentInstance;
|
let comp = <InputComp> fixture.componentInstance;
|
||||||
expect(comp.name).toEqual(origName, `At start name should be ${origName} `);
|
expect(comp.name).toEqual(origName, `At start name should be ${origName} `);
|
||||||
|
@ -212,23 +257,23 @@ describe('test component builder', function() {
|
||||||
expect(inputBox.value).toEqual(newName,
|
expect(inputBox.value).toEqual(newName,
|
||||||
`After value change and detectChanges, name should now be ${newName} `);
|
`After value change and detectChanges, name should now be ${newName} `);
|
||||||
});
|
});
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('should override a template',
|
it('should override a template',
|
||||||
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
|
|
||||||
return tcb.overrideTemplate(MockChildComp, '<span>Mock</span>')
|
tcb.overrideTemplate(MockChildComp, '<span>Mock</span>')
|
||||||
.createAsync(MockChildComp)
|
.createAsync(MockChildComp)
|
||||||
.then(fixture => {
|
.then(fixture => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(fixture.nativeElement).toHaveText('Mock');
|
expect(fixture.nativeElement).toHaveText('Mock');
|
||||||
});
|
});
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('should override a view',
|
it('should override a view',
|
||||||
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
|
|
||||||
return tcb.overrideView(
|
tcb.overrideView(
|
||||||
ChildComp,
|
ChildComp,
|
||||||
new ViewMetadata({template: '<span>Modified {{childBinding}}</span>'})
|
new ViewMetadata({template: '<span>Modified {{childBinding}}</span>'})
|
||||||
)
|
)
|
||||||
|
@ -238,25 +283,25 @@ describe('test component builder', function() {
|
||||||
expect(fixture.nativeElement).toHaveText('Modified Child');
|
expect(fixture.nativeElement).toHaveText('Modified Child');
|
||||||
|
|
||||||
});
|
});
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('should override component directives',
|
it('should override component directives',
|
||||||
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
|
|
||||||
return tcb.overrideDirective(ParentComp, ChildComp, MockChildComp)
|
tcb.overrideDirective(ParentComp, ChildComp, MockChildComp)
|
||||||
.createAsync(ParentComp)
|
.createAsync(ParentComp)
|
||||||
.then(fixture => {
|
.then(fixture => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(fixture.nativeElement).toHaveText('Parent(Mock)');
|
expect(fixture.nativeElement).toHaveText('Parent(Mock)');
|
||||||
|
|
||||||
});
|
});
|
||||||
}));
|
})));
|
||||||
|
|
||||||
|
|
||||||
it('should override child component\'s directives',
|
it('should override child component\'s directives',
|
||||||
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
|
|
||||||
return tcb.overrideDirective(ParentComp, ChildComp, ChildWithChildComp)
|
tcb.overrideDirective(ParentComp, ChildComp, ChildWithChildComp)
|
||||||
.overrideDirective(ChildWithChildComp, ChildChildComp, MockChildChildComp)
|
.overrideDirective(ChildWithChildComp, ChildChildComp, MockChildChildComp)
|
||||||
.createAsync(ParentComp)
|
.createAsync(ParentComp)
|
||||||
.then(fixture => {
|
.then(fixture => {
|
||||||
|
@ -265,12 +310,12 @@ describe('test component builder', function() {
|
||||||
.toHaveText('Parent(Original Child(ChildChild Mock))');
|
.toHaveText('Parent(Original Child(ChildChild Mock))');
|
||||||
|
|
||||||
});
|
});
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('should override a provider',
|
it('should override a provider',
|
||||||
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
|
|
||||||
return tcb.overrideProviders(
|
tcb.overrideProviders(
|
||||||
TestProvidersComp,
|
TestProvidersComp,
|
||||||
[provide(FancyService, {useClass: MockFancyService})]
|
[provide(FancyService, {useClass: MockFancyService})]
|
||||||
)
|
)
|
||||||
|
@ -280,12 +325,12 @@ describe('test component builder', function() {
|
||||||
expect(fixture.nativeElement)
|
expect(fixture.nativeElement)
|
||||||
.toHaveText('injected value: mocked out value');
|
.toHaveText('injected value: mocked out value');
|
||||||
});
|
});
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('should override a viewProvider',
|
it('should override a viewProvider',
|
||||||
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
|
|
||||||
return tcb.overrideViewProviders(
|
tcb.overrideViewProviders(
|
||||||
TestViewProvidersComp,
|
TestViewProvidersComp,
|
||||||
[provide(FancyService, {useClass: MockFancyService})]
|
[provide(FancyService, {useClass: MockFancyService})]
|
||||||
)
|
)
|
||||||
|
@ -295,18 +340,18 @@ describe('test component builder', function() {
|
||||||
expect(fixture.nativeElement)
|
expect(fixture.nativeElement)
|
||||||
.toHaveText('injected value: mocked out value');
|
.toHaveText('injected value: mocked out value');
|
||||||
});
|
});
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('should allow an external templateUrl',
|
it('should allow an external templateUrl',
|
||||||
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
|
|
||||||
return tcb.createAsync(ExternalTemplateComp)
|
tcb.createAsync(ExternalTemplateComp)
|
||||||
.then(fixture => {
|
.then(fixture => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(fixture.nativeElement)
|
expect(fixture.nativeElement)
|
||||||
.toHaveText('from external template\n');
|
.toHaveText('from external template\n');
|
||||||
});
|
});
|
||||||
}), 10000); // Long timeout because this test makes an actual XHR.
|
})), 10000); // Long timeout because this test makes an actual XHR.
|
||||||
|
|
||||||
describe('(lifecycle hooks w/ MyIfParentComp)', () => {
|
describe('(lifecycle hooks w/ MyIfParentComp)', () => {
|
||||||
let fixture: ComponentFixture;
|
let fixture: ComponentFixture;
|
||||||
|
@ -344,13 +389,13 @@ describe('test component builder', function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create MyIfParentComp TCB and component instance before each test (async beforeEach)
|
// Create MyIfParentComp TCB and component instance before each test (async beforeEach)
|
||||||
beforeEach(injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
beforeEach(async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
return tcb.createAsync(MyIfParentComp)
|
tcb.createAsync(MyIfParentComp)
|
||||||
.then(fix => {
|
.then(fix => {
|
||||||
fixture = fix;
|
fixture = fix;
|
||||||
parent = fixture.debugElement.componentInstance;
|
parent = fixture.debugElement.componentInstance;
|
||||||
});
|
});
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('should instantiate parent component', () => {
|
it('should instantiate parent component', () => {
|
||||||
expect(parent).not.toBeNull('parent component should exist');
|
expect(parent).not.toBeNull('parent component should exist');
|
||||||
|
@ -396,7 +441,7 @@ describe('test component builder', function() {
|
||||||
'childValue should eq changed parent value');
|
'childValue should eq changed parent value');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('changed child value flows to parent', injectAsync([], () => {
|
it('changed child value flows to parent', async(() => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
getChild();
|
getChild();
|
||||||
|
|
||||||
|
@ -419,24 +464,6 @@ describe('test component builder', function() {
|
||||||
return p;
|
return p;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
/* Will soon be able to write it like this:
|
|
||||||
it('changed child value flows to parent', async(() => {
|
|
||||||
fixture.detectChanges();
|
|
||||||
getChild();
|
|
||||||
|
|
||||||
child.childValue = 'bar';
|
|
||||||
|
|
||||||
// Wait one JS engine turn!
|
|
||||||
setTimeout(() => {
|
|
||||||
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');
|
|
||||||
}, 0);
|
|
||||||
}));
|
|
||||||
*/
|
|
||||||
|
|
||||||
it('clicking "Close Child" triggers child OnDestroy', () => {
|
it('clicking "Close Child" triggers child OnDestroy', () => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
getChild();
|
getChild();
|
||||||
|
@ -451,173 +478,6 @@ describe('test component builder', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('inject/async testing errors', () => {
|
|
||||||
let originalJasmineIt: any;
|
|
||||||
let originalJasmineBeforeEach: any;
|
|
||||||
|
|
||||||
let patchJasmineIt = () => {
|
|
||||||
let deferred = PromiseWrapper.completer();
|
|
||||||
originalJasmineIt = jasmine.getEnv().it;
|
|
||||||
jasmine.getEnv().it = (description: string, fn: Function): jasmine.Spec => {
|
|
||||||
let done = () => { deferred.resolve(); };
|
|
||||||
(<any>done).fail = (err: any) => { deferred.reject(err); };
|
|
||||||
fn(done);
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
|
|
||||||
let restoreJasmineIt = () => { jasmine.getEnv().it = originalJasmineIt; };
|
|
||||||
|
|
||||||
let patchJasmineBeforeEach = () => {
|
|
||||||
let deferred = PromiseWrapper.completer();
|
|
||||||
originalJasmineBeforeEach = jasmine.getEnv().beforeEach;
|
|
||||||
jasmine.getEnv().beforeEach = (fn: any): void => {
|
|
||||||
let done = () => { deferred.resolve(); };
|
|
||||||
(<any>done).fail = (err: any) => { deferred.reject(err); };
|
|
||||||
fn(done);
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
|
|
||||||
let restoreJasmineBeforeEach =
|
|
||||||
() => { jasmine.getEnv().beforeEach = originalJasmineBeforeEach; };
|
|
||||||
|
|
||||||
const shouldNotSucceed =
|
|
||||||
(done: Done) => () => done.fail( 'Expected function to throw, but it did not');
|
|
||||||
|
|
||||||
const shouldFail =
|
|
||||||
(done: Done, emsg: string) => (err: any) => { expect(err).toEqual(emsg); done(); };
|
|
||||||
|
|
||||||
it('injectAsync should fail when return was forgotten in it', (done: Done) => {
|
|
||||||
let itPromise = patchJasmineIt();
|
|
||||||
it('forgets to return a proimse', injectAsync([], () => { return true; }));
|
|
||||||
|
|
||||||
itPromise.then(
|
|
||||||
shouldNotSucceed(done),
|
|
||||||
shouldFail(done,
|
|
||||||
'Error: injectAsync was expected to return a promise, but the returned value was: true')
|
|
||||||
);
|
|
||||||
restoreJasmineIt();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('inject should fail if a value was returned', (done: Done) => {
|
|
||||||
let itPromise = patchJasmineIt();
|
|
||||||
it('returns a value', inject([], () => { return true; }));
|
|
||||||
|
|
||||||
itPromise.then(
|
|
||||||
shouldNotSucceed(done),
|
|
||||||
shouldFail(done,
|
|
||||||
'Error: inject returned a value. Did you mean to use injectAsync? Returned value was: true')
|
|
||||||
);
|
|
||||||
restoreJasmineIt();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('injectAsync should fail when return was forgotten in beforeEach', (done: Done) => {
|
|
||||||
let beforeEachPromise = patchJasmineBeforeEach();
|
|
||||||
beforeEach(injectAsync([], () => { return true; }));
|
|
||||||
|
|
||||||
beforeEachPromise.then(
|
|
||||||
shouldNotSucceed(done),
|
|
||||||
shouldFail(done,
|
|
||||||
'Error: injectAsync was expected to return a promise, but the returned value was: true')
|
|
||||||
);
|
|
||||||
restoreJasmineBeforeEach();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('inject should fail if a value was returned in beforeEach', (done: Done) => {
|
|
||||||
let beforeEachPromise = patchJasmineBeforeEach();
|
|
||||||
beforeEach(inject([], () => { return true; }));
|
|
||||||
|
|
||||||
beforeEachPromise.then(
|
|
||||||
shouldNotSucceed(done),
|
|
||||||
shouldFail(done,
|
|
||||||
'Error: inject returned a value. Did you mean to use injectAsync? Returned value was: true')
|
|
||||||
);
|
|
||||||
restoreJasmineBeforeEach();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fail when an error occurs inside inject', (done: Done) => {
|
|
||||||
let itPromise = patchJasmineIt();
|
|
||||||
|
|
||||||
it('throws an error', inject([], () => { throw new Error('foo'); }));
|
|
||||||
|
|
||||||
itPromise.then(
|
|
||||||
shouldNotSucceed(done),
|
|
||||||
err => { expect(err.message).toEqual('foo'); done(); }
|
|
||||||
);
|
|
||||||
restoreJasmineIt();
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO(juliemr): reenable this test when we are using a test zone and can capture this error.
|
|
||||||
xit('should fail when an asynchronous error is thrown', (done: Done) => {
|
|
||||||
let itPromise = patchJasmineIt();
|
|
||||||
|
|
||||||
it('throws an async error',
|
|
||||||
injectAsync([], () => { setTimeout(() => { throw new Error('bar'); }, 0); }));
|
|
||||||
|
|
||||||
itPromise.then(
|
|
||||||
shouldNotSucceed(done),
|
|
||||||
err => { expect(err.message).toEqual('bar'); done(); }
|
|
||||||
);
|
|
||||||
restoreJasmineIt();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fail when a returned promise is rejected', (done: Done) => {
|
|
||||||
let itPromise = patchJasmineIt();
|
|
||||||
|
|
||||||
it('should fail with an error from a promise', injectAsync([], () => {
|
|
||||||
let deferred = PromiseWrapper.completer();
|
|
||||||
let p = deferred.promise.then(() => { expect(1).toEqual(2); });
|
|
||||||
|
|
||||||
deferred.reject('baz');
|
|
||||||
return p;
|
|
||||||
}));
|
|
||||||
|
|
||||||
itPromise.then(
|
|
||||||
shouldNotSucceed(done),
|
|
||||||
shouldFail(done, 'baz')
|
|
||||||
);
|
|
||||||
restoreJasmineIt();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fail when an XHR fails', (done: Done) => {
|
|
||||||
let itPromise = patchJasmineIt();
|
|
||||||
|
|
||||||
it('should fail with an error from a promise',
|
|
||||||
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
|
||||||
return tcb.createAsync(BadTemplateUrl);
|
|
||||||
}));
|
|
||||||
|
|
||||||
itPromise.then(
|
|
||||||
shouldNotSucceed(done),
|
|
||||||
shouldFail(done, 'Failed to load non-existant.html')
|
|
||||||
);
|
|
||||||
restoreJasmineIt();
|
|
||||||
}, 10000);
|
|
||||||
|
|
||||||
describe('using beforeEachProviders', () => {
|
|
||||||
beforeEachProviders(() => [provide(FancyService, {useValue: new FancyService()})]);
|
|
||||||
|
|
||||||
beforeEach(
|
|
||||||
inject([FancyService], (service: FancyService) => { expect(service.value).toEqual('real value'); }));
|
|
||||||
|
|
||||||
describe('nested beforeEachProviders', () => {
|
|
||||||
|
|
||||||
it('should fail when the injector has already been used', () => {
|
|
||||||
patchJasmineBeforeEach();
|
|
||||||
expect(() => {
|
|
||||||
beforeEachProviders(() => [provide(FancyService, {useValue: new FancyService()})]);
|
|
||||||
})
|
|
||||||
.toThrowError('beforeEachProviders was called after the injector had been used ' +
|
|
||||||
'in a beforeEach or it block. This invalidates the test injector');
|
|
||||||
restoreJasmineBeforeEach();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
//////// Testing Framework Bugs? /////
|
//////// Testing Framework Bugs? /////
|
||||||
import { HeroService } from './hero.service';
|
import { HeroService } from './hero.service';
|
||||||
|
@ -637,12 +497,12 @@ export class AnotherProvidersComp {
|
||||||
|
|
||||||
describe('tcb.overrideProviders', () => {
|
describe('tcb.overrideProviders', () => {
|
||||||
it('Component must have at least one provider else crash',
|
it('Component must have at least one provider else crash',
|
||||||
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
|
|
||||||
return tcb.overrideProviders(
|
tcb.overrideProviders(
|
||||||
AnotherProvidersComp,
|
AnotherProvidersComp,
|
||||||
[provide(HeroService, {useValue: {}})]
|
[provide(HeroService, {useValue: {}})]
|
||||||
)
|
)
|
||||||
.createAsync(AnotherProvidersComp);
|
.createAsync(AnotherProvidersComp);
|
||||||
}));
|
})));
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
import { Component, EventEmitter, Injectable, Input, Output,
|
import { Component, EventEmitter, Injectable, Input, Output,
|
||||||
OnInit, OnChanges, OnDestroy, SimpleChange } from 'angular2/core';
|
OnInit, OnChanges, OnDestroy, SimpleChange } from 'angular2/core';
|
||||||
|
|
||||||
|
import { Observable } from 'rxjs/Rx';
|
||||||
|
|
||||||
// Let TypeScript know about the special SystemJS __moduleName variable
|
// Let TypeScript know about the special SystemJS __moduleName variable
|
||||||
declare var __moduleName: string;
|
declare var __moduleName: string;
|
||||||
|
|
||||||
|
@ -21,7 +23,16 @@ if (!__moduleName) {
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FancyService {
|
export class FancyService {
|
||||||
value: string = 'real value';
|
value: string = 'real value';
|
||||||
|
|
||||||
getAsyncValue() { return Promise.resolve('async value'); }
|
getAsyncValue() { return Promise.resolve('async value'); }
|
||||||
|
|
||||||
|
getObservableValue() { return Observable.of('observable value'); }
|
||||||
|
|
||||||
|
getTimeoutValue() {
|
||||||
|
return new Promise((resolve, reject) => { setTimeout(() => {resolve('timeout value'); }, 10); });
|
||||||
|
}
|
||||||
|
|
||||||
|
getObservableDelayValue() { return Observable.of('observable delay value').delay(10); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|
|
@ -8,18 +8,12 @@ import {
|
||||||
beforeEach, beforeEachProviders,
|
beforeEach, beforeEachProviders,
|
||||||
describe, ddescribe, xdescribe,
|
describe, ddescribe, xdescribe,
|
||||||
expect, it, iit, xit,
|
expect, it, iit, xit,
|
||||||
inject, injectAsync,
|
async, inject, TestComponentBuilder
|
||||||
TestComponentBuilder
|
|
||||||
} from 'angular2/testing';
|
} from 'angular2/testing';
|
||||||
|
|
||||||
import { Hero, HeroService, MockHeroService } from './mock-hero.service';
|
import { Hero, HeroService, MockHeroService } from './mock-hero.service';
|
||||||
import { Router, MockRouter } from './mock-router';
|
import { Router, MockRouter } from './mock-router';
|
||||||
|
|
||||||
interface Done {
|
|
||||||
(): void;
|
|
||||||
fail: (err: any) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('DashboardComponent', () => {
|
describe('DashboardComponent', () => {
|
||||||
|
|
||||||
//////// WITHOUT ANGULAR INVOLVED ///////
|
//////// WITHOUT ANGULAR INVOLVED ///////
|
||||||
|
@ -45,7 +39,7 @@ describe('DashboardComponent', () => {
|
||||||
'should not have heroes until service promise resolves');
|
'should not have heroes until service promise resolves');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should HAVE heroes after HeroService gets them', (done: Done) => {
|
it('should HAVE heroes after HeroService gets them', (done: DoneFn) => {
|
||||||
comp.ngOnInit(); // ngOnInit -> getHeroes
|
comp.ngOnInit(); // ngOnInit -> getHeroes
|
||||||
mockHeroService.lastPromise // the one from getHeroes
|
mockHeroService.lastPromise // the one from getHeroes
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -85,55 +79,55 @@ describe('DashboardComponent', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can instantiate it',
|
it('can instantiate it',
|
||||||
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
return tcb.createAsync(DashboardComponent);
|
tcb.createAsync(DashboardComponent);
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('should NOT have heroes before OnInit',
|
it('should NOT have heroes before OnInit',
|
||||||
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
return tcb.createAsync(DashboardComponent).then(fixture => {
|
tcb.createAsync(DashboardComponent).then(fixture => {
|
||||||
comp = fixture.debugElement.componentInstance;
|
comp = fixture.debugElement.componentInstance;
|
||||||
|
|
||||||
expect(comp.heroes.length).toEqual(0,
|
expect(comp.heroes.length).toEqual(0,
|
||||||
'should not have heroes before OnInit');
|
'should not have heroes before OnInit');
|
||||||
});
|
});
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('should NOT have heroes immediately after OnInit',
|
it('should NOT have heroes immediately after OnInit',
|
||||||
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
return tcb.createAsync(DashboardComponent).then(fixture => {
|
tcb.createAsync(DashboardComponent).then(fixture => {
|
||||||
comp = fixture.debugElement.componentInstance;
|
comp = fixture.debugElement.componentInstance;
|
||||||
fixture.detectChanges(); // runs initial lifecycle hooks
|
fixture.detectChanges(); // runs initial lifecycle hooks
|
||||||
|
|
||||||
expect(comp.heroes.length).toEqual(0,
|
expect(comp.heroes.length).toEqual(0,
|
||||||
'should not have heroes until service promise resolves');
|
'should not have heroes until service promise resolves');
|
||||||
});
|
});
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('should HAVE heroes after HeroService gets them',
|
it('should HAVE heroes after HeroService gets them',
|
||||||
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
|
|
||||||
return tcb.createAsync(DashboardComponent).then(fixture => {
|
tcb.createAsync(DashboardComponent).then(fixture => {
|
||||||
comp = fixture.debugElement.componentInstance;
|
comp = fixture.debugElement.componentInstance;
|
||||||
fixture.detectChanges(); // runs ngOnInit -> getHeroes
|
fixture.detectChanges(); // runs ngOnInit -> getHeroes
|
||||||
|
|
||||||
return mockHeroService.lastPromise // the one from getHeroes
|
mockHeroService.lastPromise // the one from getHeroes
|
||||||
.then(() => {
|
.then(() => {
|
||||||
expect(comp.heroes.length).toBeGreaterThan(0,
|
expect(comp.heroes.length).toBeGreaterThan(0,
|
||||||
'should have heroes after service promise resolves');
|
'should have heroes after service promise resolves');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('should DISPLAY heroes after HeroService gets them',
|
it('should DISPLAY heroes after HeroService gets them',
|
||||||
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||||
|
|
||||||
return tcb.createAsync(DashboardComponent).then(fixture => {
|
tcb.createAsync(DashboardComponent).then(fixture => {
|
||||||
comp = fixture.debugElement.componentInstance;
|
comp = fixture.debugElement.componentInstance;
|
||||||
fixture.detectChanges(); // runs ngOnInit -> getHeroes
|
fixture.detectChanges(); // runs ngOnInit -> getHeroes
|
||||||
|
|
||||||
return mockHeroService.lastPromise // the one from getHeroes
|
mockHeroService.lastPromise // the one from getHeroes
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|
||||||
// Find and examine the displayed heroes
|
// Find and examine the displayed heroes
|
||||||
|
@ -148,15 +142,15 @@ describe('DashboardComponent', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('should tell ROUTER to navigate by hero id',
|
it('should tell ROUTER to navigate by hero id',
|
||||||
injectAsync([TestComponentBuilder, Router],
|
async(inject([TestComponentBuilder, Router],
|
||||||
(tcb: TestComponentBuilder, router: MockRouter) => {
|
(tcb: TestComponentBuilder, router: MockRouter) => {
|
||||||
|
|
||||||
let spy = spyOn(router, 'navigate').and.callThrough();
|
let spy = spyOn(router, 'navigate').and.callThrough();
|
||||||
|
|
||||||
return tcb.createAsync(DashboardComponent).then(fixture => {
|
tcb.createAsync(DashboardComponent).then(fixture => {
|
||||||
let hero: Hero = {id: 42, name: 'Abbracadabra' };
|
let hero: Hero = {id: 42, name: 'Abbracadabra' };
|
||||||
comp = fixture.debugElement.componentInstance;
|
comp = fixture.debugElement.componentInstance;
|
||||||
comp.gotoDetail(hero);
|
comp.gotoDetail(hero);
|
||||||
|
@ -166,6 +160,6 @@ describe('DashboardComponent', () => {
|
||||||
expect(linkParams[1].id).toEqual(hero.id, 'should nav to fake hero\'s id');
|
expect(linkParams[1].id).toEqual(hero.id, 'should nav to fake hero\'s id');
|
||||||
|
|
||||||
});
|
});
|
||||||
}));
|
})));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {
|
||||||
beforeEach, beforeEachProviders, withProviders,
|
beforeEach, beforeEachProviders, withProviders,
|
||||||
describe, ddescribe, xdescribe,
|
describe, ddescribe, xdescribe,
|
||||||
expect, it, iit, xit,
|
expect, it, iit, xit,
|
||||||
inject, injectAsync, fakeAsync, TestComponentBuilder, tick
|
async, inject, TestComponentBuilder
|
||||||
} from 'angular2/testing';
|
} from 'angular2/testing';
|
||||||
|
|
||||||
import { provide } from 'angular2/core';
|
import { provide } from 'angular2/core';
|
||||||
|
@ -81,45 +81,45 @@ describe('Http-HeroService (mockBackend)', () => {
|
||||||
response = new Response(options);
|
response = new Response(options);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should have expected fake heroes (then)', injectAsync([], () => {
|
it('should have expected fake heroes (then)', async(inject([], () => {
|
||||||
backend.connections.subscribe((c: MockConnection) => c.mockRespond(response));
|
backend.connections.subscribe((c: MockConnection) => c.mockRespond(response));
|
||||||
|
|
||||||
return service.getHeroes().toPromise()
|
service.getHeroes().toPromise()
|
||||||
// .then(() => Promise.reject('deliberate'))
|
// .then(() => Promise.reject('deliberate'))
|
||||||
.then(heroes => {
|
.then(heroes => {
|
||||||
expect(heroes.length).toEqual(fakeHeroes.length,
|
expect(heroes.length).toEqual(fakeHeroes.length,
|
||||||
'should have expected no. of heroes');
|
'should have expected no. of heroes');
|
||||||
});
|
});
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('should have expected fake heroes (Observable.do)', injectAsync([], () => {
|
it('should have expected fake heroes (Observable.do)', async(inject([], () => {
|
||||||
backend.connections.subscribe((c: MockConnection) => c.mockRespond(response));
|
backend.connections.subscribe((c: MockConnection) => c.mockRespond(response));
|
||||||
|
|
||||||
return service.getHeroes()
|
service.getHeroes()
|
||||||
.do(heroes => {
|
.do(heroes => {
|
||||||
expect(heroes.length).toEqual(fakeHeroes.length,
|
expect(heroes.length).toEqual(fakeHeroes.length,
|
||||||
'should have expected no. of heroes');
|
'should have expected no. of heroes');
|
||||||
})
|
})
|
||||||
.toPromise();
|
.toPromise();
|
||||||
}));
|
})));
|
||||||
|
|
||||||
|
|
||||||
it('should be OK returning no heroes', injectAsync([], () => {
|
it('should be OK returning no heroes', async(inject([], () => {
|
||||||
let resp = new Response(new ResponseOptions({status: 200, body: {data: []}}));
|
let resp = new Response(new ResponseOptions({status: 200, body: {data: []}}));
|
||||||
backend.connections.subscribe((c: MockConnection) => c.mockRespond(resp));
|
backend.connections.subscribe((c: MockConnection) => c.mockRespond(resp));
|
||||||
|
|
||||||
return service.getHeroes()
|
service.getHeroes()
|
||||||
.do(heroes => {
|
.do(heroes => {
|
||||||
expect(heroes.length).toEqual(0, 'should have no heroes');
|
expect(heroes.length).toEqual(0, 'should have no heroes');
|
||||||
})
|
})
|
||||||
.toPromise();
|
.toPromise();
|
||||||
}));
|
})));
|
||||||
|
|
||||||
it('should treat 404 as an Observable error', injectAsync([], () => {
|
it('should treat 404 as an Observable error', async(inject([], () => {
|
||||||
let resp = new Response(new ResponseOptions({status: 404}));
|
let resp = new Response(new ResponseOptions({status: 404}));
|
||||||
backend.connections.subscribe((c: MockConnection) => c.mockRespond(resp));
|
backend.connections.subscribe((c: MockConnection) => c.mockRespond(resp));
|
||||||
|
|
||||||
return service.getHeroes()
|
service.getHeroes()
|
||||||
.do(heroes => {
|
.do(heroes => {
|
||||||
fail('should not respond with heroes');
|
fail('should not respond with heroes');
|
||||||
})
|
})
|
||||||
|
@ -128,6 +128,6 @@ describe('Http-HeroService (mockBackend)', () => {
|
||||||
return Observable.of(null); // failure is the expected test result
|
return Observable.of(null); // failure is the expected test result
|
||||||
})
|
})
|
||||||
.toPromise();
|
.toPromise();
|
||||||
}));
|
})));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,13 +5,22 @@ module.exports = function () {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
files: [
|
files: [
|
||||||
{pattern: 'node_modules/es6-shim/es6-shim.js', instrument: false},
|
// System.js for module loading
|
||||||
{pattern: 'node_modules/systemjs/dist/system-polyfills.js', instrument: false},
|
{pattern: 'node_modules/systemjs/dist/system-polyfills.js', instrument: false},
|
||||||
{pattern: 'node_modules/systemjs/dist/system.js', instrument: false},
|
{pattern: 'node_modules/systemjs/dist/system.js', instrument: false},
|
||||||
{pattern: 'node_modules/reflect-metadata/Reflect.js', instrument: false},
|
|
||||||
{pattern: 'node_modules/zone.js/dist/zone.js', instrument: false},
|
// Polyfills
|
||||||
{pattern: 'node_modules/zone.js/dist/long-stack-trace-zone.js', instrument: false},
|
{pattern: 'node_modules/es6-shim/es6-shim.js', instrument: false},
|
||||||
|
{pattern: 'node_modules/angular2/bundles/angular2-polyfills.js', instrument: false},
|
||||||
|
|
||||||
|
// Zone.js dependencies
|
||||||
|
// Note - do not include zone.js itself or long-stack-trace-zone.js` here as
|
||||||
|
// they are included already in angular2-polyfills
|
||||||
{pattern: 'node_modules/zone.js/dist/jasmine-patch.js', instrument: false},
|
{pattern: 'node_modules/zone.js/dist/jasmine-patch.js', instrument: false},
|
||||||
|
{pattern: 'node_modules/zone.js/dist/async-test.js', instrument: false},
|
||||||
|
{pattern: 'node_modules/zone.js/dist/fake-async-test.js', instrument: false},
|
||||||
|
|
||||||
|
// Rx.js, Angular 2 itself, and the testing library not here because loaded by systemjs
|
||||||
|
|
||||||
{pattern: 'app/**/*+(ts|html|css)', load: false},
|
{pattern: 'app/**/*+(ts|html|css)', load: false},
|
||||||
{pattern: 'app/**/*.spec.ts', ignore: true}
|
{pattern: 'app/**/*.spec.ts', ignore: true}
|
||||||
|
|
Loading…
Reference in New Issue