How to write a Jasmine test to test the observable using the debounce statement? I followed this blog post and understood the principles of testing it, but it just doesn't work.
Below is the factory that I use to create the observable:
import Rx from "rx/dist/rx.all"; import DOMFactory from "../utils/dom-factory"; import usernameService from "./username.service"; function createUsernameComponent(config) { const element = DOMFactory(config); const username = Rx.Observable .fromEvent(element.find('input'), 'input') .pluck('target', 'value') .startWith(config.value); const isAvailable = username .debounce(500) .tap(() => console.info('I am never called!')) .flatMapLatest(usernameService.isAvailable) .startWith(false); const usernameStream = Rx.Observable.combineLatest(username, isAvailable) .map((results) => { const [username, isAvailable] = results; return isAvailable ? username : '' }) .distinctUntilChanged(); return Object.freeze({ stream: usernameStream, view: element }); } export default createUsernameComponent;
Note that the tap statement is never called by the test. However, it will execute correctly if I run this code in a browser.
Below is my test attempt:
import Rx from "rx/dist/rx.all"; import Username from "./username.component"; import DataItemBuilder from "../../../test/js/utils/c+j-builders"; import usernameService from "./username.service" describe('Username Component', () => { let input, username; beforeEach(() => { const usernameConfig = DataItemBuilder.withName('foo') .withPrompt('label').withType('text').build(); const usernameComponent = Username(usernameConfig); usernameComponent.stream.subscribe(value => username = value); input = usernameComponent.view.find('input'); }); it('should set to a valid username after debounce', () => { const scheduler = injectTestSchedulerIntoDebounce(); scheduler.scheduleRelative(null, 1000, () => { doKeyUpTest('abcddd', 'abcdd'); scheduler.stop(); }); scheduler.start(); scheduler.advanceTo(1000); }); function injectTestSchedulerIntoDebounce() { const originalOperator = Rx.Observable.prototype.debounce; const scheduler = new Rx.TestScheduler(); spyOn(Rx.Observable.prototype, 'debounce').and.callFake((dueTime) => { console.info('The mocked debounce is never called!'); if (typeof dueTime === 'number') { return originalOperator.call(this, dueTime, scheduler); } return originalOperator.call(this, dueTime); }); return scheduler; } function doKeyUpTest(inputValue, expectation) { input.val(inputValue); input.trigger('input'); expect(username).toBe(expectation); } });
When I run the test, the debounce fake will never be called. I plan to mock the username service when I can get past debounce .
source share