111 lines
3.5 KiB
TypeScript
111 lines
3.5 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { AppError } from '@/lib/error-model';
|
|
import { hostApiFetch } from '@/lib/host-api';
|
|
import {
|
|
createImageWorkspaceProject,
|
|
fetchImageWorkspace,
|
|
ImageWorkspaceApiError,
|
|
sendImageWorkspaceMessage,
|
|
uploadImageWorkspaceReference,
|
|
} from '@/lib/image-workspace';
|
|
|
|
vi.mock('@/lib/host-api', () => ({ hostApiFetch: vi.fn() }));
|
|
|
|
const hostApiFetchMock = vi.mocked(hostApiFetch);
|
|
|
|
const workspace = {
|
|
capabilities: {
|
|
modes: [],
|
|
models: [],
|
|
aspectRatios: [],
|
|
resolutions: [],
|
|
outputCounts: [],
|
|
maxReferenceImages: 0,
|
|
referenceUpload: { enabled: false, acceptedMimeTypes: [] },
|
|
},
|
|
projects: [],
|
|
};
|
|
|
|
describe('image workspace renderer API boundary', () => {
|
|
beforeEach(() => {
|
|
hostApiFetchMock.mockReset();
|
|
hostApiFetchMock.mockResolvedValue({ success: true, workspace });
|
|
});
|
|
|
|
it('uses a dedicated Main-owned route and forwards the cloud access token', async () => {
|
|
await fetchImageWorkspace('cloud-token');
|
|
|
|
expect(hostApiFetchMock).toHaveBeenCalledWith('/api/works/image-workspace', {
|
|
headers: { 'X-NianCode-Access-Token': 'cloud-token' },
|
|
});
|
|
});
|
|
|
|
it('allows an adapter-backed initial load without an access token', async () => {
|
|
await fetchImageWorkspace(null);
|
|
|
|
expect(hostApiFetchMock).toHaveBeenCalledWith('/api/works/image-workspace', {});
|
|
});
|
|
|
|
it('creates a cloud project with only its trimmed name', async () => {
|
|
await createImageWorkspaceProject('cloud-token', ' 角色设计 ');
|
|
|
|
expect(hostApiFetchMock).toHaveBeenCalledWith('/api/works/image-workspace/projects', {
|
|
method: 'POST',
|
|
headers: { 'X-NianCode-Access-Token': 'cloud-token' },
|
|
body: JSON.stringify({ name: '角色设计' }),
|
|
});
|
|
});
|
|
|
|
it('sends explicit references and server option ids without local task semantics', async () => {
|
|
await sendImageWorkspaceMessage('cloud-token', {
|
|
projectId: 'project/one',
|
|
agentId: 'agent-one',
|
|
prompt: '继续编辑',
|
|
referenceImageIds: ['image-one'],
|
|
settings: { modelId: 'server-model' },
|
|
});
|
|
|
|
expect(hostApiFetchMock).toHaveBeenCalledWith('/api/works/image-workspace/projects/project%2Fone/messages', {
|
|
method: 'POST',
|
|
headers: { 'X-NianCode-Access-Token': 'cloud-token' },
|
|
body: JSON.stringify({
|
|
projectId: 'project/one',
|
|
agentId: 'agent-one',
|
|
prompt: '继续编辑',
|
|
referenceImageIds: ['image-one'],
|
|
settings: { modelId: 'server-model' },
|
|
}),
|
|
});
|
|
});
|
|
|
|
it('requires the upload response to return a cloud reference id', async () => {
|
|
hostApiFetchMock.mockResolvedValueOnce({
|
|
success: true,
|
|
workspace,
|
|
reference: { id: 'reference-one', url: 'https://example.com/reference.png' },
|
|
});
|
|
|
|
await expect(uploadImageWorkspaceReference('cloud-token', {
|
|
projectId: 'project-one',
|
|
fileName: 'reference.png',
|
|
mimeType: 'image/png',
|
|
contentBase64: 'aW1hZ2U=',
|
|
})).resolves.toMatchObject({ reference: { id: 'reference-one' } });
|
|
});
|
|
|
|
it('maps the unimplemented Main route to a stable unavailable error', async () => {
|
|
hostApiFetchMock.mockRejectedValueOnce(new AppError(
|
|
'UNKNOWN',
|
|
'创作空间暂不可用',
|
|
undefined,
|
|
{ status: 501 },
|
|
));
|
|
|
|
await expect(fetchImageWorkspace('cloud-token')).rejects.toMatchObject<ImageWorkspaceApiError>({
|
|
status: 501,
|
|
code: 'IMAGE_WORKSPACE_UNAVAILABLE',
|
|
message: '创作空间暂不可用',
|
|
});
|
|
});
|
|
});
|