I have an Angular 2 application that works OK so far. My GlobalsService.getGlobals() fetches "USA States" through my OptionService.getOptions(). Where my code falls down is in Karma / Jasmine testing.
When I call getGlobals() in my current test setup I get the "this._subscribe is not a function" error. I'm finding it hard to debug this because Google Chrome isn't cooperating.
My getGlobals() code with debugging added. I split the code between getOptions() and .subscribe() to see what is going on.
public getGlobals(): void {
let asdf = this.optionService.getOptions();
console.log("asdf is " + (typeof asdf) + ", asdf.subscribe is: " + asdf.subscribe);
try {
asdf.subscribe(
(options: Option[]) => this.fillOptions(options),
(error: string) => this.error = error
);
} catch(error) {
console.log("caught error involving asdf, it is: " + error);
throw error;
}
}
When I run this code I get:
LOG: 'asdf is object, asdf.subscribe is: function (observerOrNext, error, complete) {
[1] var operator = this.operator;
[1] var sink = toSubscriber_1.toSubscriber(observerOrNext, error, complete);
[1] if (operator) {
[1] operator.call(sink, this.source);
[1] }
[1] else {
[1] sink.add(this._subscribe(sink));
[1] }
[1] if (sink.syncErrorThrowable) {
[1] sink.syncErrorThrowable = false;
[1] if (sink.syncErrorThrown) {
[1] throw sink.syncErrorValue;
[1] }
[1] }
[1] return sink;
[1] }'
The code of asdf.subscribe is what you see from node_modules/rxjs/Observable.js. So the return from getOptions() is a Observable. Among its many properties it has these features:
_subscribe: Array[4] (each item is an Object of my Option data type)
_proto_: Object
_subscribe: (subscriber)
subscribe: (observer or next, error, complete)
But if I let the code continue I get the error. In the place with the asdf variable "this" is GlobalsService.
My mocked OptionService code is:
@Injectable()
export class MockOptionService {
constructor() { }
getOptions(): Observable<Option[]> {
let options: Option[] = [
{ id: 'IN', name: 'Indiana', topic: Option.TOPIC_STATE },
{ id: 'NJ', name: 'New Jersey', topic: Option.TOPIC_STATE },
{ id: 'CONCERT', name: "Concert", topic: Option.TOPIC_EVENT_TYPE },
{ id: 'NY', name: 'New York', topic: Option.TOPIC_STATE }
];
return Observable.create(options);
}
}
This is injected through:
describe('Globals Service', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
{ provide: OptionService, useClass: MockOptionService },
{ provide: GlobalsService, useClass: GlobalsService }
]
});
[SNIP]
});
As I said, I'm having trouble with Chrome when debugging this. If I show the Observable.js source in the debugger and try to set a breakpoint the browser displays a blank page for the non-existent Observable.ts file. The breakpoint doesn't show in either place. The code is stopping on the non-existent Observable.ts:92.
My questions are, then:
1. Can I convince Chrome to give me a Javascript breakpoint in a Typescript world?
2. What is the proper function for creating an object array and then attaching it to an Observable? I suspect that Observable.create() is wrong.
Thanks, Jerome.