<!DOCTYPE html>
<html>
<head>
<title>Angular2 Testing Playground - Jasmine</title>
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/jasmine.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/jasmine.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/jasmine-html.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/boot.js"></script>
<script src="https://code.angularjs.org/tools/system.js"></script>
<script src="https://code.angularjs.org/tools/typescript.js"></script>
<script src="config.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.0/angular2-polyfills.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.0/Rx.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.0/angular2.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.0/http.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.0/testing.dev.js"></script>
</head>
<body>
<script>
Promise.all([
System.import('app/testsetup'),
System.import('app/app.spec'),
System.import('app/myservice.spec'),
])
.then(window.onload)
.catch(console.error.bind(console));
</script>
</body>
</html>
/* Styles go here */
THIS IS A FAILING CONDITION IN TESTING
However, it looks like it passes.
But look at myservice.spec.ts and see the reason is MockBackend is being provided
to the injector.
Issue on Angular2 https://github.com/angular/angular/issues/6375
System.config({
//use typescript for compilation
transpiler: 'typescript',
//typescript compiler options
typescriptOptions: {
emitDecoratorMetadata: true
},
//map tells the System loader where to look for things
map: {
app: "./src"
},
//packages defines our app package
packages: {
app: {
defaultExtension: 'ts'
}
}
});
//main entry point
import {bootstrap} from 'angular2/platform/browser';
import {App} from './app';
import {HTTP_PROVDIERS} from 'angular2/http';
import {MyService} from './myservice';
bootstrap(App, [HTTP_PROVIDERS])
.catch(err => console.error(err));
//our root app component
import {Component} from 'angular2/core';
import {MyService} from './myservice';
@Component({
selector: 'my-app',
//providers: [MyService],
template: `
<div>
<h2>Hello {{name}}</h2>
<button (click)="finish()">Finish</button>
</div>
`,
directives: []
})
export class App {
constructor(public service: MyService) {
this.name = 'Angular2'
}
finish() {
this.service.getSomeData();
this.name = 'Joe';
}
}
import {
describe,
expect,
it,
injectAsync,
TestComponentBuilder,
beforeEachProviders
} from 'angular2/testing';
import {Component, provide} from 'angular2/core';
import {HTTP_PROVIDERS} from 'angular2/http';
import {App} from './app';
import {MyService} from './myservice';
@Component({
template: '',
directives: [App]
})
class TestComponent {
}
class MyServiceMock {
doSomething() {
}
getSomeData() {
}
};
describe('App Component', () => {
beforeEachProviders(() => [
provide(MyService, {useClass: MyServiceMock})
]);
it('should be defined', () => {
expect(App).toBeDefined();
});
it('should say Hello Angular2', injectAsync([TestComponentBuilder], (tcb) => {
return tcb.overrideTemplate(TestComponent, '<my-app></my-app>')
.createAsync(TestComponent).then((fixture) => {
fixture.detectChanges();
var compiled = fixture.debugElement.nativeElement;
expect(compiled).toContainText('Hello Angular2');
});
});
it('should finish when you click the button', injectAsync([TestComponentBuilder], (tcb) => {
return tcb.overrideTemplate(TestComponent, '<my-app></my-app>')
.createAsync(TestComponent).then((fixture) => {
fixture.detectChanges();
let element = fixture.debugElement;
let compiled = element.nativeElement;
let button = compiled.querySelector('button');
button.click();
fixture.detectChanges();
expect(compiled).toContainText('Hello Joe');
});
});
});
import 'angular2/testing';
import 'rxjs/Rx';
import {BrowserDomAdapter} from 'angular2/platform/browser';
BrowserDomAdapter.makeCurrent();
beforeEach(() => {
jasmine.addMatchers({
toContainText: function() {
return {
compare: function(actual, expectedText) {
var actualText = actual.textContent;
return {
pass: actualText.indexOf(expectedText) > -1,
get message() { return 'Expected ' + actualText + ' to contain ' + expectedText; }
};
}
};
}
});
});
import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';
@Injectable()
export class MyService {
constructor(public http: Http) {
}
doSomething() {
return 'done';
}
getSomeData() {
return this.http.get('./users.json')
.map((res) => res.json());
}
}
import {
describe,
expect,
it,
inject,
beforeEachProviders
} from 'angular2/testing';
import {provide, Injector} from 'angular2/core';
import {MyService} from './myservice';
import {Http, HTTP_PROVIDERS, XHRBackend, Response, ResponseOptions} from 'angular2/http';
import {MockBackend} from 'angular2/http/testing';
describe('MyService', () => {
let injector,
backend,
mockBackend,
httpService,
service;
beforeEach(() => {
injector = Injector.resolveAndCreate([
HTTP_PROVIDERS,
// this next value should NOT be provided, but when it is,
// we lose the ability to correlate the backend calls
// to the test Is there a way to detect this has been
// done and reject it out-of-hand?
MockBackend, // this is clearly wrong...
provide(XHRBackend, {useClass: MockBackend}),
MyService
]);
mockBackend = injector.get(MockBackend);
backend = injector.get(XHRBackend);
httpService = injector.get(Http);
service = injector.get(MyService);
]);
it('should be defined', () => {
expect(service).toBeDefined();
});
// if not, somehow I'd like the test to fail with an error
// stating that another backend is in use - could we somehow
// ask the test injector NOT to provide two Mock backends?
// or log a warning when it does?
// bottom line: beginners can get very confused if they
// accidentally provide the MockBackend class as a simple
// class definition in addition to using the provide function
// to replace XHRBackend with MockBackend
it('should be the same instance of the mockBackend or provide warning/error...', () => {
expect(httpService._backend).toBe(mockBackend);
})
it('should do something', () => {
expect(service.doSomething()).toBe('done');
});
it('should get some data', () => {
backend.connections.subscribe(connection => {
connection.mockRespond(new Response(new ResponseOptions({body: { username: 'test2', password: 'test2'}})));
});
service.getSomeData().subscribe((data) => {
expect(data.username).toBe('test2');
expect(data.password).toBe('test2');
});
});
});
{
username: "test",
password: "test"
}