• [Unit testing RxJS] Test complex logic with time progression syntax


    For example we have a search input:

    const input$ = fromEvent(document.getElementById("#input"), "input");
    
    input$
      .pipe(
        debounceTime(200),
        pluck("target", "value"),
        distinctUntilChanged(),
        switchMap((searchTerm) => {
          ajax
            .getJSON(`${BASE_URL}?by_name=${searchTerm}`)
            .pipe(catchError(() => EMPTY));
        })
      )
      .subscribe();

    We want to test the logic about the input box.

    First thing we need to do is making it easy to mock ajaxrequest.

    const typeahead =
      (ajaxHelper = ajax) =>
      (sourceObservable) => {
        return sourceObservable.pipe(
          debounceTime(200),
          pluck("target", "value"),
          distinctUntilChanged(),
          switchMap((searchTerm) => {
            ajaxHelper
              .getJSON(`${BASE_URL}?by_name=${searchTerm}`)
              .pipe(catchError(() => EMPTY));
          })
        );
      };
    
    input$.pipe(typeahead()).subscribe();
    const { of, throwError } = require("rxjs");
    const { delay } = require("rxjs/operators");
    const { TestScheduler } = require("rxjs/testing");
    const { typeahead } = require("..");
    
    describe("THe typehead", () => {
      beforeEach(() => {
        testScheduler = new TestScheduler((actual, expected) => {
          expect(actual).toEqual(expected);
        });
      });
    
      it("should debounce input by 200ms", () => {
        testScheduler.run((helpers) => {
          const { cold, expectObservable } = helpers;
          const searchTerm = "testing";
          const source$ = cold("a", { a: { target: { value: searchTerm } } });
          const final$ = source$.pipe(
            typeahead({
              getJSON: () => of(searchTerm).pipe(delay(300)),
            })
          );
          const expected = "500ms a";
          expectObservable(final$).toBe(expected, { a: searchTerm });
        });
      });
    
      it("should cancel active requests if another value is emitted", () => {
        testScheduler.run((helpers) => {
          const { cold, expectObservable } = helpers;
          const searchTerm = "testing";
          const source$ = cold("a 250ms b", {
            a: { target: { value: "first" } },
            b: { target: { value: "second" } },
          });
          const final$ = source$.pipe(
            typeahead({
              getJSON: () => of(searchTerm).pipe(delay(300)),
            })
          );
          const expected = "751ms b"; // 200 (debounce) + 250 (wait time) + 300 (network) + 1 (b)
          expectObservable(final$).toBe(expected, { b: searchTerm });
        });
      });
    
      it("should not emit duplciate values in a row", () => {
        testScheduler.run((helpers) => {
          const { cold, expectObservable } = helpers;
          const searchTerm = "testing";
          const source$ = cold("a 250ms b", {
            a: { target: { value: "same" } },
            b: { target: { value: "same" } },
          });
          const final$ = source$.pipe(
            typeahead({
              getJSON: () => of(searchTerm).pipe(delay(300)),
            })
          );
          const expected = "500ms b"; // 200 (debounce) + 300 (network)
          expectObservable(final$).toBe(expected, { b: searchTerm });
        });
      });
    
      it("should ingore ajax errors", () => {
        testScheduler.run((helpers) => {
          const { cold, expectObservable } = helpers;
          const searchTerm = "testing";
          const source$ = cold("a 250ms b", {
            a: { target: { value: "same" } },
            b: { target: { value: "same" } },
          });
          const final$ = source$.pipe(
            typeahead({
              getJSON: () => throwError("error"),
            })
          );
          const expected = ""; // in case of error, emit empty
          expectObservable(final$).toBe(expected);
        });
      });
    });
  • 相关阅读:
    软件开发术语定义
    软件开发流程纲要及各个阶段产生的文档
    Java封装自己的Api
    Java中如何使封装自己的类,建立并使用自己的类库?
    Struts2中ActionContext和ServletActionContext
    TP-Link 无线路由器设置图文教程----怎么设置TP-Link无线路由器图解
    数据库(第一范式,第二范式,第三范式)
    ORACLE配置tnsnames.ora文件实例
    Windows下64位Apache服务器的安装
    公司内部Oracle RAC测试环境的简单使用说明.
  • 原文地址:https://www.cnblogs.com/Answer1215/p/16793013.html
Copyright © 2020-2023  润新知