Files
carousel/tests/autoplay.test.ts
T

74 lines
2.0 KiB
TypeScript

import { afterEach, beforeEach, expect, test, vi } from 'vitest';
import { autoplay } from '../src/autoplay.ts';
function fakeCarousel(count = 3) {
let index = 0;
return {
get index() {
return index;
},
count,
next: vi.fn(() => {
index = (index + 1) % count;
}),
prev: vi.fn(),
scrollToIndex: vi.fn(),
on: () => () => {},
destroy: vi.fn(),
};
}
// jsdom has no matchMedia — stub it. reduce = whether reduce-motion matches.
function stubMatchMedia(reduce: boolean) {
vi.stubGlobal('matchMedia', (q: string) => ({
matches: reduce && q.includes('reduce'),
media: q,
addEventListener() {},
removeEventListener() {},
}));
}
beforeEach(() => {
vi.useFakeTimers();
stubMatchMedia(false);
});
afterEach(() => {
vi.useRealTimers();
vi.unstubAllGlobals();
});
test('advances every interval', () => {
const c = fakeCarousel();
autoplay(c as never, { interval: 1000, root: document.createElement('div') });
vi.advanceTimersByTime(2000);
expect(c.next).toHaveBeenCalledTimes(2);
});
test('pause on pointerenter, resume on pointerleave', () => {
const c = fakeCarousel();
const root = document.createElement('div');
autoplay(c as never, { interval: 1000, root });
root.dispatchEvent(new Event('pointerenter'));
vi.advanceTimersByTime(3000);
expect(c.next).not.toHaveBeenCalled();
root.dispatchEvent(new Event('pointerleave'));
vi.advanceTimersByTime(1000);
expect(c.next).toHaveBeenCalledTimes(1);
});
test('does not start under prefers-reduced-motion', () => {
stubMatchMedia(true);
const c = fakeCarousel();
autoplay(c as never, { interval: 1000, root: document.createElement('div') });
vi.advanceTimersByTime(5000);
expect(c.next).not.toHaveBeenCalled();
});
test('stop() halts and removes listeners', () => {
const c = fakeCarousel();
const stop = autoplay(c as never, { interval: 1000, root: document.createElement('div') });
stop();
vi.advanceTimersByTime(5000);
expect(c.next).not.toHaveBeenCalled();
});