feat: add clip management with I/O marking, timeline markers, and clip list

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-21 11:05:45 -04:00
parent 36701feb9e
commit c13755e5d1
6 changed files with 513 additions and 6 deletions

View File

@@ -0,0 +1,77 @@
import { describe, it, expect, beforeEach } from 'vitest';
import {
addClip,
removeClip,
updateClip,
markInPoint,
markOutPoint,
getClips,
getSelectedClipId,
getPendingInPoint,
clearAll,
selectClip,
} from '$lib/stores/clips.svelte';
describe('clip store', () => {
beforeEach(() => {
clearAll();
});
it('starts with no clips', () => {
expect(getClips()).toHaveLength(0);
});
it('adds a clip', () => {
addClip(10, 20);
const clips = getClips();
expect(clips).toHaveLength(1);
expect(clips[0].startTime).toBe(10);
expect(clips[0].endTime).toBe(20);
expect(clips[0].label).toBe('Clip 1');
});
it('removes a clip', () => {
addClip(10, 20);
const id = getClips()[0].id;
removeClip(id);
expect(getClips()).toHaveLength(0);
});
it('updates clip times', () => {
addClip(10, 20);
const id = getClips()[0].id;
updateClip(id, { startTime: 5 });
expect(getClips()[0].startTime).toBe(5);
expect(getClips()[0].endTime).toBe(20);
});
it('marks in-point and out-point to create a clip', () => {
markInPoint(15);
expect(getPendingInPoint()).toBe(15);
expect(getClips()).toHaveLength(0);
markOutPoint(25);
expect(getPendingInPoint()).toBeNull();
expect(getClips()).toHaveLength(1);
expect(getClips()[0].startTime).toBe(15);
expect(getClips()[0].endTime).toBe(25);
});
it('updates selected clip start when I is pressed', () => {
addClip(10, 20);
const id = getClips()[0].id;
selectClip(id);
markInPoint(5);
expect(getClips()[0].startTime).toBe(5);
expect(getPendingInPoint()).toBeNull();
});
it('swaps start/end if in-point is after out-point', () => {
markInPoint(30);
markOutPoint(10);
const clip = getClips()[0];
expect(clip.startTime).toBe(10);
expect(clip.endTime).toBe(30);
});
});