Ctrl K
ComunidadGuías…

frontend/test/auto-scroll.test.ts

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { afterEach, expect, it, vi } from 'vitest';
import { stopAutoScroll, wireAutoScroll } from '../src/ui-kit/scroll';

let row:HTMLElement;
afterEach(()=>{stopAutoScroll(row);document.body.removeAttribute('data-detail-open');document.body.innerHTML='';vi.unstubAllGlobals()});

it('详情打开时背景自动滚动停止,关闭后从当前位置继续',async()=>{
  const frames=new Map<number,FrameRequestCallback>();let id=0;
  vi.stubGlobal('requestAnimationFrame',(callback:FrameRequestCallback)=>{frames.set(++id,callback);return id});
  vi.stubGlobal('cancelAnimationFrame',(key:number)=>frames.delete(key));
  vi.stubGlobal('matchMedia',()=>({matches:false}));
  vi.stubGlobal('innerHeight',800);
  row=document.createElement('div');document.body.append(row);
  Object.defineProperties(row,{scrollWidth:{value:2000},clientWidth:{value:200}});
  const measure=vi.spyOn(row,'getBoundingClientRect').mockReturnValue({width:200,top:10,bottom:100} as DOMRect);
  const tick=(now:number)=>{const callbacks=[...frames.values()];frames.clear();callbacks.forEach(callback=>callback(now))};
  wireAutoScroll(row);tick(100);tick(2200);
  expect(row.scrollLeft).toBeGreaterThan(0);const held=row.scrollLeft;
  document.body.setAttribute('data-detail-open','');measure.mockClear();tick(2250);
  expect(frames.size).toBe(0);expect(measure).not.toHaveBeenCalled();expect(row.scrollLeft).toBe(held);
  document.body.removeAttribute('data-detail-open');
  await vi.waitFor(()=>expect(frames.size).toBe(1));
  tick(2300);tick(2350);expect(row.scrollLeft).toBeGreaterThan(held);
});

it('滚出视口或被播放墙盖住时停下,循环里不量几何;回到视口接着走',async()=>{
  const frames=new Map<number,FrameRequestCallback>();let id=0;
  vi.stubGlobal('requestAnimationFrame',(callback:FrameRequestCallback)=>{frames.set(++id,callback);return id});
  vi.stubGlobal('cancelAnimationFrame',(key:number)=>frames.delete(key));
  vi.stubGlobal('matchMedia',()=>({matches:false}));
  let sight:(entries:Partial<IntersectionObserverEntry>[])=>void=()=>{};
  vi.stubGlobal('IntersectionObserver',class{constructor(callback:typeof sight){sight=callback}observe(){}unobserve(){}disconnect(){}});
  row=document.createElement('div');document.body.append(row);
  Object.defineProperties(row,{scrollWidth:{value:2000},clientWidth:{value:200}});
  const measure=vi.spyOn(row,'getBoundingClientRect');
  const tick=(now:number)=>{const callbacks=[...frames.values()];frames.clear();callbacks.forEach(callback=>callback(now))};
  wireAutoScroll(row);tick(100);tick(2200);
  expect(row.scrollLeft).toBeGreaterThan(0);
  sight([{target:row,isIntersecting:false}]);tick(2250);
  expect(frames.size).toBe(0);const held=row.scrollLeft;
  sight([{target:row,isIntersecting:true}]);expect(frames.size).toBe(1);
  tick(2300);tick(2350);expect(row.scrollLeft).toBeGreaterThan(held);
  document.body.setAttribute('data-wall-open','');tick(2400);
  expect(frames.size).toBe(0);
  document.body.removeAttribute('data-wall-open');
  await vi.waitFor(()=>expect(frames.size).toBe(1));
  expect(measure).not.toHaveBeenCalled();
});