feat(fix-a3): retire ring-buffer first-chunk pin tests, add segment-rotation contract
Per debug session webm-playback-freeze "Activation Plan" step 4: the
D-09..D-11 ring-buffer semantics (first-chunk header pin + 30 s age trim)
are being replaced by D-13 restart-segments. The pinned-header assertions
were architecture-specific and become meaningless once each segment is
a self-contained WebM with its own EBML header and seed keyframe.
Changes:
- tests/offscreen/ring-buffer.test.ts: collapsed to a single breadcrumb
test pointing at the successor file. Kept the path so git history /
failure bisects land on the retirement commit cleanly.
- tests/offscreen/segment-rotation.test.ts (new): 8 tests pinning the
D-13 invariants against the production recorder module:
* MAX_SEGMENTS = 3, SEGMENT_DURATION_MS = 10_000 (= legacy 30 s window)
* empty-by-default, ordered, oldest-evicted-at-cap
* resetBuffer clears
* getSegments returns a defensive snapshot (no internal aliasing)
Uses a `pushSegmentForTest` seam so vitest can drive rotation
deterministically without instantiating a real MediaRecorder.
RED today by design (TDD discipline) — the segment-rotation suite
imports `getSegments`, `pushSegmentForTest`, `MAX_SEGMENTS`,
`SEGMENT_DURATION_MS` from src/offscreen/recorder.ts. Those exports
land in the next commit. tsconfig.include is "src" only so tsc stays
clean during the RED window.
This commit is contained in:
@@ -1,40 +1,29 @@
|
||||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import { addChunk, trimAged, getBuffer, resetBuffer } from '../../src/offscreen/recorder';
|
||||
// tests/offscreen/ring-buffer.test.ts — vestigial entry point.
|
||||
//
|
||||
// Under D-09..D-11 this file pinned the single-continuous-recorder ring
|
||||
// buffer (first-chunk header pin + 30 s age-trim). Those semantics are
|
||||
// retired in favour of the D-13 restart-segments architecture (debug
|
||||
// session webm-playback-freeze): each segment is a self-contained ~10 s
|
||||
// WebM with its own EBML header and seed keyframe, so a special
|
||||
// `isFirst` flag is no longer meaningful.
|
||||
//
|
||||
// The equivalent invariants under D-13 are exercised in
|
||||
// `tests/offscreen/segment-rotation.test.ts`. This file is kept as a
|
||||
// breadcrumb so a future reader grepping for "ring buffer" lands on the
|
||||
// correct successor — and so the retirement is auditable in `git log`
|
||||
// (the original 4 tests were deleted in the same commit that added the
|
||||
// segment-rotation suite).
|
||||
//
|
||||
// See: .planning/debug/webm-playback-freeze.md "Activation Plan"
|
||||
// step 4 — the D-09..D-11 invariants are replaced, not weakened.
|
||||
|
||||
describe('ring buffer', () => {
|
||||
beforeEach(() => resetBuffer());
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
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([]);
|
||||
describe('ring buffer (retired — see segment-rotation.test.ts)', () => {
|
||||
it('D-09..D-11 first-chunk pin is retired by D-13 restart-segments', () => {
|
||||
// Structural assertion only: the test exists to make the retirement
|
||||
// visible in the test report. Behavioural assertions live in
|
||||
// segment-rotation.test.ts.
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user