60 lines
2.9 KiB
TypeScript
60 lines
2.9 KiB
TypeScript
import { readFileSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
import { describe, expect, it } from 'vitest';
|
|
import { decideDownloadStart, normalizeDownloadPolicy } from './download-policy';
|
|
|
|
describe('download policy integration contract', () => {
|
|
it('keeps a normalized persisted policy after a config-shaped restart payload', () => {
|
|
const persisted = JSON.parse(JSON.stringify({
|
|
download_policy: {
|
|
throttle: { maxBytesPerSecond: 1_572_864 },
|
|
windows: [{ start: '22:00', end: '06:00' }, { start: '22:00', end: '06:00' }, { start: 'bad', end: '12:00' }]
|
|
}
|
|
}));
|
|
|
|
expect(normalizeDownloadPolicy(persisted.download_policy)).toEqual({
|
|
throttle: { maxBytesPerSecond: 1_572_864 },
|
|
windows: [{ start: '22:00', end: '06:00' }]
|
|
});
|
|
|
|
const mainSource = readFileSync(join(process.cwd(), 'src', 'main.ts'), 'utf8');
|
|
expect(mainSource).toContain('download_policy: { throttle: null, windows: [] }');
|
|
expect(mainSource).toContain('download_policy: normalizeDownloadPolicy(input.download_policy)');
|
|
});
|
|
|
|
it('blocks automatic queue starts outside the local window but allows a manual override', () => {
|
|
const policy = normalizeDownloadPolicy({
|
|
throttle: { maxBytesPerSecond: 1_048_576 },
|
|
windows: [{ start: '22:00', end: '06:00' }]
|
|
});
|
|
const now = new Date(2026, 0, 13, 13, 0);
|
|
|
|
expect(decideDownloadStart(policy, now)).toMatchObject({
|
|
allowed: false,
|
|
reason: 'outside-window',
|
|
nextStart: new Date(2026, 0, 13, 22, 0)
|
|
});
|
|
expect(decideDownloadStart(policy, now, true)).toMatchObject({
|
|
allowed: true,
|
|
reason: 'manual-override',
|
|
maxBytesPerSecond: 1_048_576
|
|
});
|
|
|
|
const mainSource = readFileSync(join(process.cwd(), 'src', 'main.ts'), 'utf8');
|
|
expect(mainSource).toContain('function scheduleQueueProcessing(manualOverride = false)');
|
|
expect(mainSource).toContain('scheduleQueueProcessing(manualOverride === true)');
|
|
expect(mainSource).toContain('scheduleDownloadPolicyWake(decision.nextStart)');
|
|
});
|
|
|
|
it('uses the app-side stdout transform and retains the existing Streamlink argument pipeline', () => {
|
|
const source = readFileSync(join(process.cwd(), 'src', 'main.ts'), 'utf8');
|
|
const start = source.indexOf('function downloadVODPart(');
|
|
const end = source.indexOf('const outputFinished = output.finished', start);
|
|
const section = source.slice(start, end);
|
|
|
|
expect(section).toContain('createTokenBucketTransform');
|
|
expect(section).toContain("const args = [...streamlinkCmd.prefixArgs, url, getStreamlinkStreamArg(), '--stdout'];");
|
|
expect(section).not.toMatch(/args\.push\([^\n]*(?:bandwidth|rate-limit|max-rate|throttle)/i);
|
|
});
|
|
});
|