我如何测试在玩笑中使用`requestAnimationFrame`的代码?

问题描述 投票:0回答:1

我想为使用requestAnimationFramecancelAnimationFrame的模块编写一个有趣的单元测试。

我尝试使用自己的模拟方法覆盖window.requestAnimationFrame(如this answer中的建议,但是该模块继续使用jsdom提供的实现。

[我目前的方法是使用jsdom中的(某种程度上)内置的requestAnimationFrame实现,似乎似乎在后台使用了setTimeout,应该可以通过使用jest.useFakeTimers()对其进行模拟。

jest.useFakeTimers();

describe("fakeTimers", () => {
    test.only("setTimeout and trigger", () => {
        const order: number[] = [];

        expect(order).toEqual([]);
        setTimeout(t => order.push(1));
        expect(order).toEqual([]);
        jest.runAllTimers();
        expect(order).toEqual([1]);
    });

    test.only("requestAnimationFrame and runAllTimers", () => {
        const order: number[] = [];

        expect(order).toEqual([]);
        requestAnimationFrame(t => order.push(1));
        expect(order).toEqual([]);
        jest.runAllTimers();
        expect(order).toEqual([1]);
    });
});

第一次测试成功,而第二次失败,因为order为空。

依靠requestAnimationFrame()来测试代码的正确方法是什么?特别是如果我需要测试取消帧的条件吗?

jestjs settimeout requestanimationframe jsdom
1个回答
0
投票

我不确定此解决方案是否完美,但这是否适合我的情况。

这里有两个主要原则。

1)创建一个基于requestAnimationFrame的延迟:

const waitRAF = () => new Promise(resolve => requestAnimationFrame(resolve));

2)使我正在测试的动画运行得非常快:

就我而言,我正在等待的动画具有可配置的持续时间,在我的道具数据中将其设置为1。

您可能还需要模拟requestAnimationFrame,但这取决于您的设置,测试框架和实现

我的示例测试文件(带有Jest的Vue应用程序:] >>

import { mount } from '@vue/test-utils';
import AnimatedCount from '@/components/AnimatedCount.vue';

const waitRAF = () => new Promise(resolve => requestAnimationFrame(resolve));

let wrapper;
describe('AnimatedCount.vue', () => {
  beforeEach(() => {
    wrapper = mount(AnimatedCount, {
      propsData: {
        value: 9,
        duration: 1,
        formatDisplayFn: (val) => "£" + val
      }
    });
  });

  it('renders a vue instance', () => {
    expect(wrapper.isVueInstance()).toBe(true);
  });

  describe('When a value is passed in', () => {
    it('should render the correct amount', async () => {
      const valueOutputElement = wrapper.get("span");
      wrapper.setProps({ value: 10 });

      await wrapper.vm.$nextTick();
      await waitRAF();

      expect(valueOutputElement.text()).toBe("£10");
    })
  })
});
© www.soinside.com 2019 - 2024. All rights reserved.