This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* Unit tests for the resolutionW/resolutionH promotion (METADATA_KEYS §3).
|
||||
*
|
||||
* Pure function over an already-built stream/* map - no FFprobe, no fixtures,
|
||||
* so these run everywhere (unlike integration.test.ts).
|
||||
*/
|
||||
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { promoteResolution, applyDisplayRotation, isQuarterTurn } from '../src/plugin.js';
|
||||
|
||||
const stream = (o: Record<string, unknown>) => JSON.stringify(o);
|
||||
|
||||
// Values as fluent-ffmpeg hands them over: positive degrees parse to a Number,
|
||||
// negative ones stay strings.
|
||||
describe('isQuarterTurn', () => {
|
||||
it.each([90, '-90', 270, '-270', '90.0'])('%s is a quarter turn', (r) => {
|
||||
expect(isQuarterTurn(r)).toBe(true);
|
||||
});
|
||||
it.each([0, '-180', 180, undefined, '', 'N/A'])('%s is not', (r) => {
|
||||
expect(isQuarterTurn(r)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('applyDisplayRotation', () => {
|
||||
it('swaps coded dimensions to display dimensions on a quarter turn', () => {
|
||||
const s: Record<string, unknown> = { type: 'video', width: 1920, height: 1080 };
|
||||
applyDisplayRotation(s, '-90');
|
||||
expect(s).toEqual({ type: 'video', width: 1080, height: 1920 });
|
||||
});
|
||||
|
||||
it('leaves a half turn unswapped and drops the rotation field', () => {
|
||||
const s: Record<string, unknown> = { width: 1920, height: 1080, rotation: -180 };
|
||||
applyDisplayRotation(s);
|
||||
expect(s).toEqual({ width: 1920, height: 1080 });
|
||||
});
|
||||
|
||||
it('moves a lone axis to the other side', () => {
|
||||
const s: Record<string, unknown> = { height: 1080, rotation: 90 };
|
||||
applyDisplayRotation(s);
|
||||
expect(s).toEqual({ width: 1080 });
|
||||
});
|
||||
});
|
||||
|
||||
describe('promoteResolution', () => {
|
||||
it('promotes the primary video stream dimensions', () => {
|
||||
expect(
|
||||
promoteResolution({
|
||||
'stream/0': stream({ type: 'video', codec: 'h264', width: 1920, height: 1080 }),
|
||||
'stream/1': stream({ type: 'audio', codec: 'eac3' }),
|
||||
})
|
||||
).toEqual({ resolutionW: '1920', resolutionH: '1080' });
|
||||
});
|
||||
|
||||
it('uses the FIRST video stream, not a later one', () => {
|
||||
expect(
|
||||
promoteResolution({
|
||||
'stream/0': stream({ type: 'audio', codec: 'aac' }),
|
||||
'stream/1': stream({ type: 'video', width: 1280, height: 720 }),
|
||||
'stream/2': stream({ type: 'video', width: 640, height: 480 }),
|
||||
})
|
||||
).toEqual({ resolutionW: '1280', resolutionH: '720' });
|
||||
});
|
||||
|
||||
it('emits string values, never numbers (int-string format)', () => {
|
||||
const out = promoteResolution({
|
||||
'stream/0': stream({ type: 'video', width: 1920, height: 1080 }),
|
||||
});
|
||||
expect(typeof out.resolutionW).toBe('string');
|
||||
expect(typeof out.resolutionH).toBe('string');
|
||||
});
|
||||
|
||||
it('writes each axis independently when one is missing', () => {
|
||||
expect(
|
||||
promoteResolution({ 'stream/0': stream({ type: 'video', height: 1080 }) })
|
||||
).toEqual({ resolutionH: '1080' });
|
||||
});
|
||||
|
||||
it('returns nothing when there is no video stream', () => {
|
||||
expect(
|
||||
promoteResolution({
|
||||
'stream/0': stream({ type: 'audio', codec: 'flac' }),
|
||||
'stream/1': stream({ type: 'subtitle', codec: 'subrip' }),
|
||||
})
|
||||
).toEqual({});
|
||||
});
|
||||
|
||||
it('returns nothing when the video stream has no usable dimensions', () => {
|
||||
expect(
|
||||
promoteResolution({ 'stream/0': stream({ type: 'video', width: 0, height: 0 }) })
|
||||
).toEqual({});
|
||||
});
|
||||
|
||||
it('never overwrites values already on the record', () => {
|
||||
expect(
|
||||
promoteResolution(
|
||||
{ 'stream/0': stream({ type: 'video', width: 1920, height: 1080 }) },
|
||||
{ resolutionW: '1440', resolutionH: '1080' }
|
||||
)
|
||||
).toEqual({});
|
||||
});
|
||||
|
||||
it('backfills only the axis that is missing', () => {
|
||||
expect(
|
||||
promoteResolution(
|
||||
{ 'stream/0': stream({ type: 'video', width: 1920, height: 1080 }) },
|
||||
{ resolutionH: '1080' }
|
||||
)
|
||||
).toEqual({ resolutionW: '1920' });
|
||||
});
|
||||
|
||||
it('survives a malformed stream entry', () => {
|
||||
expect(
|
||||
promoteResolution({
|
||||
'stream/0': 'not json',
|
||||
'stream/1': stream({ type: 'video', width: 3840, height: 2160 }),
|
||||
})
|
||||
).toEqual({ resolutionW: '3840', resolutionH: '2160' });
|
||||
});
|
||||
|
||||
it('promotes display dimensions from a legacy stream that still carries rotation', () => {
|
||||
expect(
|
||||
promoteResolution({
|
||||
'stream/0': stream({ type: 'video', width: 1920, height: 1080, rotation: '90' }),
|
||||
})
|
||||
).toEqual({ resolutionW: '1080', resolutionH: '1920' });
|
||||
});
|
||||
|
||||
it('stops at the first gap in the stream index', () => {
|
||||
expect(
|
||||
promoteResolution({
|
||||
'stream/0': stream({ type: 'audio' }),
|
||||
'stream/2': stream({ type: 'video', width: 1920, height: 1080 }),
|
||||
})
|
||||
).toEqual({});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user