如何开玩笑地为我的 raf util 编写单元测试?

How to write a unit test for my raf util with jest?

我想开玩笑地为我的代码编写一个单元测试,但我不知道如何处理。

这是我的代码:

type anyFunction = (...args: any[]) => any

let i = 0
const idMap = new Map<number, ReturnType<typeof requestAnimationFrame>>()

/**
 * Clean `id`.
 *
 * @param id `id` in idMap.
 */
function cleanup(id: number) {
  idMap.delete(id)
}

/**
 * Use RAF to do somthing. When there's no left frames,
 * exec callback function.
 *
 * @param callback Callback when animation is over.
 * @param delayFrames Frames before fn executing.
 * @returns Return id of this RAF.
 */
export function createRAF(callback: anyFunction, delayFrames = 1): number {
  const id = i++

  /**
   * Call raf when there's no left frame.
   *
   * @param leftFrames Left frames before executing.
   */
  function callRaf(leftFrames: number) {
    if (leftFrames === 0) {
      cleanup(id)
      callback()
      return
    }

    // Call raf and bind real raf id with `idMap`.
    const realId = requestAnimationFrame(() => callRaf(leftFrames - 1))
    idMap.set(id, realId)
  }

  callRaf(delayFrames)

  return id
}

/**
 * Cancel raf by id.
 *
 * @param id Raf id created by `raf`.
 */
export function cancelRAF(id: number): void {
  const realId = idMap.get(id)
  if (realId) {
    cleanup(id)
    cancelAnimationFrame(realId)
  }
}

也许我需要检查 cacllback 在每一帧中制作的效果?但是我不知道怎么办。

我期待并欢迎任何建议和想法。

您可以使用 jest.spyOn(object, methodName) 模拟 window.requestAnimationFrame() 方法及其实现。

index.ts:

type anyFunction = (...args: any[]) => any;

let i = 0;
const idMap = new Map<number, ReturnType<typeof requestAnimationFrame>>();

function cleanup(id: number) {
  idMap.delete(id);
}

export function createRAF(callback: anyFunction, delayFrames = 1): number {
  const id = i++;
  function callRaf(leftFrames: number) {
    if (leftFrames === 0) {
      cleanup(id);
      callback();
      return;
    }

    // Call raf and bind real raf id with `idMap`.
    const realId = requestAnimationFrame(() => callRaf(leftFrames - 1));
    idMap.set(id, realId);
  }
  callRaf(delayFrames);
  return id;
}

index.test.ts:

import { createRAF } from './';

describe('69582282', () => {
  test('should pass', () => {
    const requestAnimationFrameSpy = jest.spyOn(window, 'requestAnimationFrame').mockImplementation((cb) => {
      cb(Date.now());
      return Math.random();
    });
    const callback = jest.fn();
    createRAF(callback);
    expect(callback).toBeCalledTimes(1);
    expect(requestAnimationFrameSpy).toBeCalledTimes(1);
    requestAnimationFrameSpy.mockRestore();
  });
});

测试结果:

 PASS  examples/69582282/index.test.ts (11.298 s)
  69582282
    ✓ should pass (6 ms)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |     100 |      100 |     100 |     100 |                   
 index.ts |     100 |      100 |     100 |     100 |                   
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        12.733 s

包版本:"jest": "^26.6.3"