• [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);
        });
      });
    });
  • 相关阅读:
    洛谷—— P1187 3D模型
    商铺项目(Redis缓存)
    商铺项目(使用DES加密配置信息)
    Linux下tomcat启动项目原因排查
    商铺项目(商品详情页开发)
    商铺项目(店铺详情页开发)
    商铺项目(店铺列表开发)
    商铺项目(首页前端开发)
    商铺项目(首页后台开发)
    商铺项目(商品类别模块二)
  • 原文地址:https://www.cnblogs.com/Answer1215/p/16793013.html
Copyright © 2020-2023  润新知