Files
ytplayer/frontend/video-edit.test.js
Claude Worker 8c0776f97d feat: Add support for editing video
Add an Edit
2026-07-18 16:43:15 +00:00

90 lines
3.3 KiB
JavaScript

'use strict';
const { test } = require('node:test');
const assert = require('node:assert');
const VE = require('./video-edit');
test('parseTime: bare seconds, clock forms, fractions', () => {
assert.strictEqual(VE.parseTime('90'), 90);
assert.strictEqual(VE.parseTime('1:30'), 90);
assert.strictEqual(VE.parseTime('1:00:00'), 3600);
assert.strictEqual(VE.parseTime('0:05.5'), 5.5);
assert.strictEqual(VE.parseTime(42), 42);
});
test('parseTime: rejects garbage and negatives', () => {
assert.strictEqual(VE.parseTime(''), null);
assert.strictEqual(VE.parseTime('abc'), null);
assert.strictEqual(VE.parseTime('1:99'), null); // seconds field out of range
assert.strictEqual(VE.parseTime('-3'), null);
assert.strictEqual(VE.parseTime('1:2:3:4'), null);
});
test('normalizeCuts: clamps, drops zero-length, merges overlaps', () => {
const cuts = [
{ start: -5, end: 10 }, // clamps to 0-10
{ start: 8, end: 15 }, // overlaps → merge to 0-15
{ start: 40, end: 40 }, // zero-length → dropped
{ start: 200, end: 300 }, // clamps end to duration 120 → 120-120 dropped? start>dur
{ start: 50, end: 60 },
];
const out = VE.normalizeCuts(cuts, 120);
assert.deepStrictEqual(out, [
{ start: 0, end: 15 },
{ start: 50, end: 60 },
]);
});
test('normalizeCuts: reversed range tolerated', () => {
assert.deepStrictEqual(VE.normalizeCuts([{ start: 30, end: 10 }], 60), [{ start: 10, end: 30 }]);
});
test('invertCuts: complement over [0,duration]', () => {
const keep = VE.invertCuts([{ start: 10, end: 20 }], 60);
assert.deepStrictEqual(keep, [{ start: 0, end: 10 }, { start: 20, end: 60 }]);
});
test('invertCuts: cut at the very start and end', () => {
const keep = VE.invertCuts([{ start: 0, end: 5 }, { start: 55, end: 60 }], 60);
assert.deepStrictEqual(keep, [{ start: 5, end: 55 }]);
});
test('invertCuts: no cuts keeps whole video', () => {
assert.deepStrictEqual(VE.invertCuts([], 60), [{ start: 0, end: 60 }]);
});
test('invertCuts: cutting the entire video yields no keep segments', () => {
assert.deepStrictEqual(VE.invertCuts([{ start: 0, end: 60 }], 60), []);
});
test('invertCuts: needs a finite positive duration', () => {
assert.deepStrictEqual(VE.invertCuts([{ start: 1, end: 2 }], 0), []);
assert.deepStrictEqual(VE.invertCuts([{ start: 1, end: 2 }], Infinity), []);
});
test('keepDuration sums surviving spans', () => {
const keep = VE.invertCuts([{ start: 10, end: 20 }], 60);
assert.strictEqual(VE.keepDuration(keep), 50);
});
test('keepToParam / parseKeepParam round-trip', () => {
const keep = [{ start: 12.5, end: 40 }, { start: 95, end: 130.2 }];
const param = VE.keepToParam(keep);
assert.strictEqual(param, '12.5-40,95-130.2');
assert.deepStrictEqual(VE.parseKeepParam(param), keep);
});
test('parseKeepParam skips malformed / non-increasing tokens', () => {
assert.deepStrictEqual(VE.parseKeepParam('0-10,bad,20-15,30-40'), [
{ start: 0, end: 10 },
{ start: 30, end: 40 },
]);
assert.deepStrictEqual(VE.parseKeepParam(''), []);
assert.deepStrictEqual(VE.parseKeepParam(null), []);
});
test('hasEdits reflects whether a real cut exists', () => {
assert.strictEqual(VE.hasEdits([], 60), false);
assert.strictEqual(VE.hasEdits([{ start: 0, end: 0 }], 60), false);
assert.strictEqual(VE.hasEdits([{ start: 5, end: 10 }], 60), true);
});