feat: 完善图像工作区与创作工具体验
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
confirmImageWorkspaceGeneration,
|
||||
createImageWorkspaceConversation,
|
||||
createImageWorkspaceProject,
|
||||
deleteImageWorkspaceProject,
|
||||
fetchImageWorkspace,
|
||||
fetchImageWorkspaceConversation,
|
||||
ImageWorkspaceApiError,
|
||||
@@ -17,6 +18,7 @@ import {
|
||||
resolveImageWorkspaceAssetUrl,
|
||||
saveImageWorkspaceAsset,
|
||||
sendImageWorkspaceMessage,
|
||||
updateImageWorkspaceGenerationQuote,
|
||||
uploadImageWorkspaceAsset,
|
||||
} from '@/lib/image-workspace';
|
||||
|
||||
@@ -83,6 +85,18 @@ describe('AI design renderer API boundary', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('deletes a Workspace through its encoded Main-owned route', async () => {
|
||||
const result = { workspaceId: 'workspace/one', deleted: true as const };
|
||||
hostApiFetchMock.mockResolvedValueOnce({ success: true, status: 200, data: result });
|
||||
|
||||
await expect(deleteImageWorkspaceProject('workspace/one')).resolves.toEqual(result);
|
||||
|
||||
expect(hostApiFetchMock).toHaveBeenCalledWith(
|
||||
'/api/works/image-workspace/workspaces/workspace%2Fone',
|
||||
{ method: 'DELETE' },
|
||||
);
|
||||
});
|
||||
|
||||
it('creates and reads Conversations through encoded Main-owned routes', async () => {
|
||||
await createImageWorkspaceConversation(
|
||||
'workspace/one',
|
||||
@@ -190,6 +204,49 @@ describe('AI design renderer API boundary', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('re-quotes a Quote through the Main-owned PATCH route without adding defaults', async () => {
|
||||
const quote = {
|
||||
quoteId: 'quote-one',
|
||||
status: 'active',
|
||||
medium: 'video',
|
||||
briefVersion: 3,
|
||||
briefSummary: '校园海报转为动态视觉',
|
||||
finalPrompt: '用户最新编辑后的完整提示词',
|
||||
promptMode: 'guided',
|
||||
generationParameters: {
|
||||
model: 'wan2.7-i2v-2026-04-25',
|
||||
resolution: '720P',
|
||||
aspectRatio: '16:9',
|
||||
durationSeconds: 6,
|
||||
},
|
||||
generationOptions: { models: [], resolutions: [], durations: [], aspectRatios: [] },
|
||||
pricing: { schema: 'design-pricing-v2', amount: 9, rounding: 'ceil' },
|
||||
quotedDesignPoints: 9,
|
||||
expiresAt: '2026-08-15T10:30:00Z',
|
||||
} as const;
|
||||
hostApiFetchMock.mockResolvedValueOnce({ success: true, status: 200, data: quote });
|
||||
|
||||
await expect(updateImageWorkspaceGenerationQuote(
|
||||
'workspace-one',
|
||||
'quote-one',
|
||||
quote.finalPrompt,
|
||||
quote.generationParameters,
|
||||
)).resolves.toEqual(quote);
|
||||
|
||||
const [path, init] = hostApiFetchMock.mock.calls[0];
|
||||
expect(path).toBe(
|
||||
'/api/works/image-workspace/workspaces/workspace-one/generation-quotes/quote-one',
|
||||
);
|
||||
expect(init).toMatchObject({ method: 'PATCH' });
|
||||
expect(JSON.parse(String(init?.body))).toEqual({
|
||||
finalPrompt: quote.finalPrompt,
|
||||
model: quote.generationParameters.model,
|
||||
resolution: quote.generationParameters.resolution,
|
||||
aspectRatio: quote.generationParameters.aspectRatio,
|
||||
durationSeconds: quote.generationParameters.durationSeconds,
|
||||
});
|
||||
});
|
||||
|
||||
it('preserves structured Main error codes for revision recovery', async () => {
|
||||
hostApiFetchMock.mockRejectedValueOnce(new AppError(
|
||||
'UNKNOWN',
|
||||
@@ -241,4 +298,34 @@ describe('AI design renderer API boundary', () => {
|
||||
);
|
||||
expect(JSON.stringify(hostApiFetchMock.mock.calls[0])).not.toContain('private/content');
|
||||
});
|
||||
|
||||
it('uses a video extension when Main saves a generated video asset', async () => {
|
||||
hostApiFetchMock.mockResolvedValueOnce({
|
||||
success: true,
|
||||
status: 200,
|
||||
data: { status: 'saved' },
|
||||
});
|
||||
|
||||
await saveImageWorkspaceAsset({
|
||||
assetId: 'video/one',
|
||||
workspaceId: 'workspace/one',
|
||||
mediaType: 'video',
|
||||
mimeType: 'video/mp4',
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
durationMilliseconds: 4_000,
|
||||
createdAt: '2026-08-05T12:00:00Z',
|
||||
contentPath: '/api/works/image-workspace/private/video',
|
||||
});
|
||||
|
||||
expect(hostApiFetchMock).toHaveBeenCalledWith(
|
||||
'/api/works/image-workspace/workspaces/workspace%2Fone/assets/video%2Fone/download',
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
defaultFileName: 'Makelore-AI-Design-video-one.mp4',
|
||||
}),
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user