Angular testing - ngBootstraps typeahead
I don't think you actually want to call any ngBootstrap code during your test - after all you want to unit test your code, not theirs. :)
Therefore I would suggest mocking the user actually typing by setting up a timed Observable of your own, and calling your function with it. Perhaps mock sending a character every 100ms. Something like this:
it('should call spy on city search', fakeAsync(() => {
component.user = <User>{uid: 'test', username: 'mleko', location: null, description: null};
// Change next line depending on implementation of cityStub ...
const spy = spyOn(cityStub, 'getLocation').and.returnValue(of('München Bayern'));
fixture.detectChanges();
let inputTextArray = ['M', 'Mü', 'Mün', 'Münc', 'Münch', 'Münche', 'München'];
let textMock$ : Observable<string> = interval(100).pipe(take(7),map(index => inputTextArray[index]));
component.search(textMock$);
tick(1000);
expect(spy).toHaveBeenCalled();
}));
Update:
I put together a stackblitz here to test this out: https://stackblitz.com/edit/stackoverflow-question-52914753 (open app folder along the left side and click on my.component.spec.ts to see the test file)
Once I got it in there, it was obvious what was wrong - the observable was not being subscribed to because the subscription seems to be done by ngBootstrap, so for testing we need to subscribe explicitly. Here is my new suggested spec (taken from the stackblitz):
it('should call spy on city search', fakeAsync(() => {
const cityStub = TestBed.get(CityService);
const spy = spyOn(cityStub, 'getLocation').and.returnValue(of('München Bayern'));
fixture.detectChanges();
let inputTextArray = ['M', 'Mü', 'Mün', 'Münc', 'Münch', 'Münche', 'München'];
let textMock$ : Observable<string> = interval(100).pipe(take(7),map(index => inputTextArray[index]));
component.search(textMock$).subscribe(result => {
expect(result).toEqual('München Bayern');
});
tick(1000);
expect(spy).toHaveBeenCalled();
}));