fix(design): connect video preparation and playable history
This commit is contained in:
1 parent
4321c77613
commit
1acca836fe
21 files changed
+900
-115
No files matched your search
@@ -0,0 +1,89 @@
|
||||
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 的画面');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user