Files
av-tools/tests/unit/components/job-panel.test.tsx

197 lines
5.2 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { cleanup, render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { JobPanel } from '../../../src/components/JobPanel';
import type { ExportResult } from '../../../src/export';
afterEach(() => {
cleanup();
vi.restoreAllMocks();
});
describe('JobPanel result selection', () => {
it('downloads only the selected generated results as ZIP', async () => {
const user = userEvent.setup();
const onSaveZip = vi.fn();
const first = result('one', 'one.png');
const second = result('two', 'two.png');
render(
<JobPanel
engineState={{
status: 'ready',
mode: 'single-thread',
capabilities: {
versionText: 'test',
buildConfiguration: [],
demuxers: new Set(),
muxers: new Set(),
decoders: new Set(),
encoders: new Set(),
filters: new Set(),
},
}}
jobs={[]}
results={[first, second]}
verifications={{}}
logs={[]}
onCancel={vi.fn()}
onCancelJob={vi.fn()}
onRetryJob={vi.fn()}
onClearJobHistory={vi.fn()}
onSave={vi.fn()}
onSaveZip={onSaveZip}
onSaveReport={vi.fn()}
onPreview={vi.fn()}
onRemove={vi.fn()}
onClearResults={vi.fn()}
/>
);
await waitFor(() =>
expect(
screen.getByRole('button', {
name: 'Download selected as ZIP (2)',
})
).toBeEnabled()
);
await user.click(
screen.getByRole('checkbox', { name: 'Select two.png for ZIP' })
);
await user.click(
screen.getByRole('button', { name: 'Download selected as ZIP (1)' })
);
expect(onSaveZip).toHaveBeenCalledWith([first]);
});
it('marks browser-rejected media as download-only and does not offer Preview', () => {
vi.spyOn(HTMLMediaElement.prototype, 'canPlayType').mockReturnValue('');
const output = mediaResult('audio', 'archive.flac', 'audio/flac');
render(
<JobPanel
engineState={{
status: 'ready',
mode: 'single-thread',
capabilities: {
versionText: 'test',
buildConfiguration: [],
demuxers: new Set(),
muxers: new Set(),
decoders: new Set(),
encoders: new Set(),
filters: new Set(),
},
}}
jobs={[]}
results={[output]}
verifications={{}}
logs={[]}
onCancel={vi.fn()}
onCancelJob={vi.fn()}
onRetryJob={vi.fn()}
onClearJobHistory={vi.fn()}
onSave={vi.fn()}
onSaveZip={vi.fn()}
onSaveReport={vi.fn()}
onPreview={vi.fn()}
onRemove={vi.fn()}
onClearResults={vi.fn()}
/>
);
expect(screen.queryByRole('button', { name: 'Preview' })).toBeNull();
expect(
screen.getByText(/Download only: The browser reports no native/iu)
).toBeVisible();
expect(screen.getByRole('button', { name: 'Save result' })).toBeEnabled();
});
it('shows the exact split interval and per-result verification state', () => {
const output = {
...mediaResult('segment', 'clip-001.mp4', 'video/mp4'),
timeRange: { startSeconds: 1.25, endSeconds: 3.5 },
};
render(
<JobPanel
engineState={{
status: 'ready',
mode: 'single-thread',
capabilities: {
versionText: 'test',
buildConfiguration: [],
demuxers: new Set(),
muxers: new Set(),
decoders: new Set(),
encoders: new Set(),
filters: new Set(),
},
}}
jobs={[]}
results={[output]}
verifications={{
segment: {
warning: 'Output was created, but its verification probe failed.',
},
}}
logs={[]}
onCancel={vi.fn()}
onCancelJob={vi.fn()}
onRetryJob={vi.fn()}
onClearJobHistory={vi.fn()}
onSave={vi.fn()}
onSaveZip={vi.fn()}
onSaveReport={vi.fn()}
onPreview={vi.fn()}
onRemove={vi.fn()}
onClearResults={vi.fn()}
/>
);
expect(
screen.getByText(
'Segment range 00:00:01.25000:00:03.500 · 00:00:02.250 duration'
)
).toBeVisible();
expect(screen.getByText(/created · verification warning/iu)).toBeVisible();
expect(
screen.getByText('Output was created, but its verification probe failed.')
).toBeVisible();
});
});
function result(id: string, fileName: string): ExportResult {
const blob = new Blob([id], { type: 'image/png' });
return {
id,
planId: `plan-${id}`,
outputId: `output-${id}`,
fileName,
blob,
mimeType: blob.type,
role: 'thumbnail',
size: blob.size,
createdAt: '2026-01-01T00:00:00.000Z',
};
}
function mediaResult(
id: string,
fileName: string,
mimeType: string
): ExportResult {
const blob = new Blob([id], { type: mimeType });
return {
id,
planId: `plan-${id}`,
outputId: `output-${id}`,
fileName,
blob,
mimeType,
role: 'media',
size: blob.size,
createdAt: '2026-01-01T00:00:00.000Z',
};
}