import { beforeEach, expect, test, vi } from 'vitest'; import { createCarousel } from '../src/index.ts'; // Minimal IO shim — records instances so tests can fire entries manually. class IOShim { static last: IOShim | null = null; cb: IntersectionObserverCallback; elements: Element[] = []; constructor(cb: IntersectionObserverCallback) { this.cb = cb; IOShim.last = this; } observe(el: Element) { this.elements.push(el); } unobserve() {} disconnect() {} // helper: emit "slide i is the one intersecting" (ratio 1), others 0 emit(i: number) { this.cb( this.elements.map((target, idx) => ({ target, isIntersecting: idx === i, intersectionRatio: idx === i ? 1 : 0, })) as unknown as IntersectionObserverEntry[], this as unknown as IntersectionObserver, ); } } vi.stubGlobal('IntersectionObserver', IOShim); function makeTrack(n: number): HTMLElement { const track = document.createElement('div'); for (let i = 0; i < n; i++) { const slide = document.createElement('div'); slide.className = 'slide'; track.append(slide); } track.scrollTo = vi.fn(); return track; } let track: HTMLElement; beforeEach(() => { track = makeTrack(3); }); test('count reflects slide children', () => { const c = createCarousel(track); expect(c.count).toBe(3); }); test('next/prev clamp to range and scroll to target offset', () => { const c = createCarousel(track); c.next(); expect(track.scrollTo).toHaveBeenCalled(); }); test('change fires with new index when a slide intersects', () => { const c = createCarousel(track); const seen: number[] = []; c.on('change', (i) => seen.push(i)); (IOShim.last as IOShim).emit(2); // user swiped to slide 2 expect(seen).toEqual([2]); expect(c.index).toBe(2); }); test('change does not re-fire for the same index', () => { const c = createCarousel(track); const seen: number[] = []; c.on('change', (i) => seen.push(i)); (IOShim.last as IOShim).emit(1); (IOShim.last as IOShim).emit(1); expect(seen).toEqual([1]); }); test('unsubscribe stops delivery; destroy disconnects observer', () => { const c = createCarousel(track); const seen: number[] = []; const off = c.on('change', (i) => seen.push(i)); off(); (IOShim.last as IOShim).emit(2); expect(seen).toEqual([]); const spy = vi.spyOn(IOShim.last as IOShim, 'disconnect'); c.destroy(); expect(spy).toHaveBeenCalled(); });