Files
makelore/tests/unit/video-first-frame.test.ts

90 lines
3.1 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { createVideoFirstFrameOperations } from '@/pages/ImageCanvas/video-first-frame';
import {
designFormFixture,
designValuesFixture,
designWorkspaceFixture,
} from '../fixtures/design-workspace-v2';
import type { DesignAsset } from '../../shared/image-workspace';
const imageAsset: DesignAsset = {
assetId: 'asset-first-frame',
workspaceId: 'workspace-1',
role: 'uploaded',
mediaType: 'image',
mimeType: 'image/png',
width: 720,
height: 1280,
durationMilliseconds: null,
generationTaskId: null,
createdAt: '2026-09-16T00:00:00Z',
contentPath: '/api/design/assets/asset-first-frame/content',
};
describe('video first-frame binding', () => {
it('adds an explicit first-frame reference without deleting the asset', () => {
const workspace = designWorkspaceFixture();
const result = createVideoFirstFrameOperations(workspace, imageAsset);
expect(result.nextPrompt).toContain('@图片1');
expect(result.operations).toEqual(expect.arrayContaining([
{ kind: 'set', path: 'video.first_frame_asset_id', value: imageAsset.assetId },
expect.objectContaining({ kind: 'set', path: 'references' }),
expect.objectContaining({ kind: 'set', path: 'content.concept' }),
]));
const referencesOperation = result.operations.find((operation) => operation.path === 'references');
expect(referencesOperation).toMatchObject({
value: [expect.objectContaining({ asset_id: imageAsset.assetId, role: 'first_frame' })],
});
});
it('promotes an existing reference and demotes the old first frame in place', () => {
const values = structuredClone(designValuesFixture);
values.intent.media = 'video';
values.references = [
{
id: 'reference-old',
asset_id: 'asset-old',
asset_revision: null,
role: 'first_frame',
preserve: [],
adapt: [],
do_not_copy: [],
reviewed_observations: [],
},
{
id: 'reference-next',
asset_id: imageAsset.assetId,
asset_revision: null,
role: 'inspiration',
preserve: [],
adapt: [],
do_not_copy: [],
reviewed_observations: [],
},
];
values.video.first_frame_asset_id = 'asset-old';
values.content.concept = '参考 @图片1 和 @图片2 的画面';
const workspace = designWorkspaceFixture({
form: designFormFixture({
specification: { schema_version: 1, values, field_decisions: {} },
}),
});
const result = createVideoFirstFrameOperations(workspace, imageAsset);
const referencesOperation = result.operations.find((operation) => operation.path === 'references');
expect(referencesOperation).toMatchObject({
value: [
expect.objectContaining({ asset_id: 'asset-old', role: 'inspiration' }),
expect.objectContaining({ asset_id: imageAsset.assetId, role: 'first_frame' }),
],
});
expect(result.operations).toContainEqual({
kind: 'set',
path: 'video.first_frame_asset_id',
value: imageAsset.assetId,
});
expect(result.nextPrompt).toBe('参考 @图片1 和 @图片2 的画面');
});
});