无法理解为什么这个 Jasmine 测试一直失败并出现队列中的计时器错误

Unable to understand why this Jasmine test keeps failing with a timer in queue error

我正在尝试测试以下使用 RxJS 向订阅者广播长按事件的函数

export function watchForLongPress(target: HTMLElement) {
  let timer: number;
  const notifier = new Subject<PointerEvent>();
  const pointerdown = (event: PointerEvent) => {
    timer = window.setTimeout(() => notifier.next(event), 500);
  };
  const pointerup = () => {
    window.clearTimeout(timer);
  };

  target.addEventListener('pointerdown', pointerdown, false);
  window.addEventListener('pointerup', pointerup, false);

  return notifier.asObservable().pipe(finalize(() => {
    target.removeEventListener('pointerdown', pointerdown, false);
    window.removeEventListener('pointerup', pointerup, false);
  }));
}

下面是确保如果用户长按少于 500 毫秒不会广播任何事件的测试,但 Jasmine 一直失败 Error: 1 timer(s) still in the queue. 但我不明白为什么。我使用 Karma 作为测试运行器,Jasmine 作为断言库

  describe('#watchForLongPress', () => {

    // This test passes
    it('1. should emit after pressing on target for 500ms or longer', fakeAsync(() => {
      const target = document.createElement('button');
      const longPressListenerSpy = jasmine.createSpy('longPressListenerSpy');
      watchForLongPress(target).subscribe({
        next: longPressListenerSpy
      });
      target.dispatchEvent(new Event('pointerdown'));
      tick(600);
      target.dispatchEvent(new Event('pointerup'));
      expect(longPressListenerSpy).toHaveBeenCalledTimes(1);
    }));

    // While this test keeps failing with `Error: 1 timer(s) still in the queue.`
    it('2. should not emit if pressing on target for less than 500ms', fakeAsync(() => {
      const target = document.createElement('button');
      const longPressListenerSpy = jasmine.createSpy('longPressListenerSpy');
      watchForLongPress(target).subscribe({
        next: longPressListenerSpy
      });
      target.dispatchEvent(new Event('pointerdown'));
      tick(300);
      target.dispatchEvent(new Event('pointerup'));
      expect(longPressListenerSpy).toHaveBeenCalledTimes(0);
    }));

  });

对于测试 #2,我只是将 target.dispatchEvent(new Event('pointerup')); 更改为 window.dispatchEvent(new Event('pointerup'));,因为在我的 watchForLongPress 函数中,我将 pointerup 附加到 window,而不是target,即使执行 target.dispatchEvent(new Event('pointerup', { bubbles: true })); 仍然不会在测试环境中使分派的事件冒泡到 window