bak
This commit is contained in:
1 parent
cc6b11e61d
commit
b977ee35a8
11 files changed
+1641
-310
No files matched your search
@@ -986,6 +986,149 @@ export function registerAllTests(): void {
|
||||
})
|
||||
})
|
||||
|
||||
suite('clips — library & scope', () => {
|
||||
test('addClip creates empty clip in library', () => {
|
||||
const s = makeFreshStore()
|
||||
const c = s.addClip('Intro')
|
||||
expect(s.scene.clips?.length).toBe(1)
|
||||
expect(c.name).toBe('Intro')
|
||||
expect(c.layers).toHaveLength(0)
|
||||
expect(c.duration).toBeGreaterThan(0)
|
||||
})
|
||||
|
||||
test('enterClip switches activeLayers + activeDuration to clip scope', async () => {
|
||||
const s = makeFreshStore()
|
||||
const a = s.addAsset({ kind: 'rect', name: 'SceneL', width: 20, height: 20, fill: '#aaa' })
|
||||
s.addLayer(a.id)
|
||||
const c = s.addClip('C1')
|
||||
c.duration = 3.5
|
||||
expect(s.activeLayers).toHaveLength(1)
|
||||
expect(s.activeDuration).toBe(s.scene.duration)
|
||||
s.enterClip(c.id)
|
||||
await tick()
|
||||
expect(s.activeLayers).toHaveLength(0)
|
||||
expect(s.activeDuration).toBe(3.5)
|
||||
expect(s.playhead).toBe(0)
|
||||
s.exitClip()
|
||||
expect(s.activeLayers).toHaveLength(1)
|
||||
expect(s.activeDuration).toBe(s.scene.duration)
|
||||
})
|
||||
|
||||
test('addLayer while in clip scope targets clip layers, not scene layers', async () => {
|
||||
const s = makeFreshStore()
|
||||
const c = s.addClip('C2')
|
||||
const a = s.addAsset({ kind: 'rect', name: 'X', width: 20, height: 20, fill: '#888' })
|
||||
s.enterClip(c.id)
|
||||
await tick()
|
||||
s.addLayer(a.id)
|
||||
expect(c.layers).toHaveLength(1)
|
||||
expect(s.scene.layers).toHaveLength(0)
|
||||
})
|
||||
|
||||
test('addClip auto-creates a first clip track if none exist', () => {
|
||||
const s = makeFreshStore()
|
||||
expect(s.scene.clipTracks ?? []).toHaveLength(0)
|
||||
s.addClip('Auto')
|
||||
expect((s.scene.clipTracks ?? []).length).toBeGreaterThan(0)
|
||||
expect((s.scene.trackOrder ?? []).length).toBeGreaterThan(0)
|
||||
})
|
||||
|
||||
test('addClipInstance anchors to a specific clipTrackId', () => {
|
||||
const s = makeFreshStore()
|
||||
const c = s.addClip('C3')
|
||||
const t = s.scene.clipTracks![0]
|
||||
const ci = s.addClipInstance(c.id, 2.5, t.id)
|
||||
expect(ci).toBeTruthy()
|
||||
expect(s.scene.clipInstances).toHaveLength(1)
|
||||
expect(ci!.startTime).toBe(2.5)
|
||||
expect(ci!.clipTrackId).toBe(t.id)
|
||||
})
|
||||
|
||||
test('moveClipInstance updates position + can switch track', () => {
|
||||
const s = makeFreshStore()
|
||||
const c = s.addClip('C4')
|
||||
const t1 = s.scene.clipTracks![0]
|
||||
const t2 = s.addClipTrack()
|
||||
const ci = s.addClipInstance(c.id, 0, t1.id)!
|
||||
s.moveClipInstance(ci.id, 4, t2.id)
|
||||
expect(ci.startTime).toBe(4)
|
||||
expect(ci.clipTrackId).toBe(t2.id)
|
||||
})
|
||||
|
||||
test('removeClip removes all instances and exits if active', () => {
|
||||
const s = makeFreshStore()
|
||||
const c = s.addClip('C5')
|
||||
const t = s.scene.clipTracks![0]
|
||||
s.addClipInstance(c.id, 0, t.id)
|
||||
s.addClipInstance(c.id, 1, t.id)
|
||||
s.enterClip(c.id)
|
||||
s.removeClip(c.id)
|
||||
expect(s.scene.clips).toHaveLength(0)
|
||||
expect(s.scene.clipInstances).toHaveLength(0)
|
||||
expect(s.activeClipId).toBeNull()
|
||||
})
|
||||
|
||||
test('negative startTime is clamped to 0', () => {
|
||||
const s = makeFreshStore()
|
||||
const c = s.addClip('C6')
|
||||
const t = s.scene.clipTracks![0]
|
||||
const ci = s.addClipInstance(c.id, -5, t.id)!
|
||||
expect(ci.startTime).toBe(0)
|
||||
})
|
||||
|
||||
test('trimClipInstance clamps trimStart/trimEnd and preserves min visible duration', () => {
|
||||
const s = makeFreshStore()
|
||||
const c = s.addClip('Trim')
|
||||
c.duration = 4
|
||||
const t = s.scene.clipTracks![0]
|
||||
const ci = s.addClipInstance(c.id, 0, t.id)!
|
||||
s.trimClipInstance(ci.id, { trimStart: 1 })
|
||||
expect(ci.trimStart).toBe(1)
|
||||
s.trimClipInstance(ci.id, { trimEnd: 1 })
|
||||
expect(ci.trimEnd).toBe(1)
|
||||
// try to over-trim: start + end > duration - MIN_VISIBLE
|
||||
s.trimClipInstance(ci.id, { trimStart: 10 })
|
||||
const total = (ci.trimStart ?? 0) + (ci.trimEnd ?? 0)
|
||||
expect(total).toBeLessThan(c.duration)
|
||||
})
|
||||
|
||||
test('trimClipInstance accepts startTime shift (left-handle drag)', () => {
|
||||
const s = makeFreshStore()
|
||||
const c = s.addClip('TrimLeft')
|
||||
c.duration = 4
|
||||
const t = s.scene.clipTracks![0]
|
||||
const ci = s.addClipInstance(c.id, 2, t.id)!
|
||||
s.trimClipInstance(ci.id, { startTime: 2.5, trimStart: 0.5 })
|
||||
expect(ci.startTime).toBe(2.5)
|
||||
expect(ci.trimStart).toBe(0.5)
|
||||
})
|
||||
|
||||
test('negative trim values are clamped to zero', () => {
|
||||
const s = makeFreshStore()
|
||||
const c = s.addClip('Neg')
|
||||
c.duration = 3
|
||||
const t = s.scene.clipTracks![0]
|
||||
const ci = s.addClipInstance(c.id, 0, t.id)!
|
||||
s.trimClipInstance(ci.id, { trimStart: -1, trimEnd: -2 })
|
||||
expect(ci.trimStart).toBe(0)
|
||||
expect(ci.trimEnd).toBe(0)
|
||||
})
|
||||
|
||||
test('moveTrack reorders the unified stack (layer above clip track)', () => {
|
||||
const s = makeFreshStore()
|
||||
const a = s.addAsset({ kind: 'rect', name: 'M', width: 10, height: 10, fill: '#000' })
|
||||
const l = s.addLayer(a.id)
|
||||
s.addClip('X')
|
||||
const track = s.scene.clipTracks![0]
|
||||
// order is [layer, clipTrack]
|
||||
expect(s.scene.trackOrder![0]).toBe(l.id)
|
||||
expect(s.scene.trackOrder![1]).toBe(track.id)
|
||||
s.moveTrack(0, 2)
|
||||
expect(s.scene.trackOrder![0]).toBe(track.id)
|
||||
expect(s.scene.trackOrder![1]).toBe(l.id)
|
||||
})
|
||||
})
|
||||
|
||||
suite('app smoke — live DOM', () => {
|
||||
test('app root, topbar, timeline, stage are mounted', () => {
|
||||
expect(document.querySelector('.app')).toBeTruthy()
|
||||
|
||||
Reference in new issue
Block a user