1import { describe, expect, it } from 'vitest'; 2import { decideThrough } from './jevCore.mjs'; 3import { Cyclist } from '../../../packages/core/cyclist.mjs'; 4 5// a jev() as decideThrough sees it: `decide(segment)` resolves to its 6// decision, or null past where the song ends; `last` once the ending is known 7const view = (endsAt, log) => { 8 const v = { last: null }; 9 v.decide = async (s) => { 10 log.push(s); 11 if (endsAt !== null && s > endsAt) return null; 12 if (s === endsAt) v.last = s; 13 return { segment: s }; 14 }; 15 return v; 16}; 17 18describe('decideThrough', () => { 19 it('asks each section in order, every jev() of one before any of the next', async () => { 20 const log = []; 21 const reached = await decideThrough([view(null, log), view(null, log)], 3); 22 expect(reached).toBe(3); 23 expect(log).toEqual([0, 0, 1, 1, 2, 2, 3, 3]); 24 }); 25 it('stops on the section the song ends on, and asks nothing past it', async () => { 26 const log = []; 27 expect(await decideThrough([view(2, log)], 6)).toBe(2); 28 expect(log).toEqual([0, 1, 2]); 29 }); 30}); 31 32describe('Cyclist.seek', () => { 33 it('begins the next tick at the cycle sought, back or forward', () => { 34 const queried = []; 35 let now = 0; 36 const c = new Cyclist({ getTime: () => now, setInterval: () => 0, clearInterval: () => {} }); 37 c.pattern = { queryArc: (b, e) => (queried.push([b, e]), []) }; 38 c.setCps(1); 39 c.clock.start(); 40 const first = queried.length; 41 c.seek(40); 42 now = 0.1; 43 c.clock.start(); 44 expect(queried[first][0]).toBe(40); 45 expect(queried[first][1]).toBeGreaterThan(40); 46 c.seek(8); 47 now = 0.2; 48 c.clock.start(); 49 expect(queried.at(-1)[0]).toBeGreaterThanOrEqual(8); 50 expect(queried.at(-1)[1]).toBeLessThan(9); 51 }); 52});