import { describe, it, expect, beforeEach } from 'vitest'; import { addChunk, trimAged, getBuffer, resetBuffer } from '../../src/offscreen/recorder'; describe('ring buffer', () => { beforeEach(() => resetBuffer()); it('first chunk is header', () => { addChunk({ size: 1024 } as unknown as Blob, 1_000); const buf = getBuffer(); expect(buf.length).toBe(1); expect(buf[0].isFirst).toBe(true); }); it('second chunk is NOT header', () => { addChunk({ size: 1024 } as unknown as Blob, 1_000); addChunk({ size: 512 } as unknown as Blob, 2_000); const buf = getBuffer(); expect(buf.length).toBe(2); expect(buf[0].isFirst).toBe(true); expect(buf[1].isFirst).toBeFalsy(); }); it('trim 30s — keeps header, evicts aged tail', () => { addChunk({ size: 1024 } as unknown as Blob, 0); // header at t=0 addChunk({ size: 512 } as unknown as Blob, 10_000); // t=10s addChunk({ size: 512 } as unknown as Blob, 35_000); // t=35s trimAged(40_000); // now=40s const buf = getBuffer(); expect(buf[0].isFirst).toBe(true); // header survives unconditionally expect(buf.length).toBeGreaterThanOrEqual(2); // header + at least the t=35s chunk // The header chunk's age (40s) does NOT cause it to be trimmed. const headerStillThere = buf.some((c) => c.isFirst); expect(headerStillThere).toBe(true); }); it('trim with empty buffer does not throw', () => { expect(() => trimAged(0)).not.toThrow(); expect(getBuffer()).toEqual([]); }); });