fix: isolate attachment submission state
This commit is contained in:
@@ -3,7 +3,7 @@ import { once } from 'node:events';
|
||||
import { mkdtemp, rm } from 'node:fs/promises';
|
||||
import { tmpdir } from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { afterEach, describe, expect, it } from 'vitest';
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
import { handleCodingAttachmentRoutes } from '../../electron/api/routes/coding-attachments';
|
||||
import { getHostApiToken, startHostApiServer } from '../../electron/api/server';
|
||||
import { CodingAttachmentStore } from '../../electron/coding-projects/attachment-store';
|
||||
@@ -44,6 +44,37 @@ async function startAttachmentServer(maxBytes = 16 * 1024 * 1024) {
|
||||
};
|
||||
}
|
||||
|
||||
async function startAttachmentFailureServer() {
|
||||
const attachments = {
|
||||
put: vi.fn(async () => {
|
||||
throw new Error('write failed');
|
||||
}),
|
||||
read: vi.fn(async () => {
|
||||
throw new Error('read failed');
|
||||
}),
|
||||
};
|
||||
const context = { codingProducts: { attachments } } as unknown as HostApiContext;
|
||||
const server = createServer((request, response) => {
|
||||
const url = new URL(request.url ?? '/', 'http://127.0.0.1');
|
||||
void handleCodingAttachmentRoutes(request, response, url, context).then((handled) => {
|
||||
if (!handled) {
|
||||
response.statusCode = 404;
|
||||
response.end();
|
||||
}
|
||||
});
|
||||
});
|
||||
await new Promise<void>((resolve) => server.listen(0, '127.0.0.1', resolve));
|
||||
const address = server.address();
|
||||
if (!address || typeof address === 'string') throw new Error('Attachment test server failed');
|
||||
return {
|
||||
baseUrl: `http://127.0.0.1:${address.port}`,
|
||||
close: async () => await new Promise<void>((resolve, reject) => {
|
||||
server.closeAllConnections();
|
||||
server.close((error) => error ? reject(error) : resolve());
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
async function startAuthenticatedHostServer() {
|
||||
const root = await mkdtemp(path.join(tmpdir(), 'makelore-coding-host-attachments-'));
|
||||
roots.push(root);
|
||||
@@ -222,7 +253,33 @@ describe('coding attachment routes', () => {
|
||||
);
|
||||
expect(response.status).toBe(413);
|
||||
expect(response.body).toMatchObject({
|
||||
code: 'CODING_ATTACHMENT_TOO_LARGE',
|
||||
code: 'CODING_ATTACHMENT_INVALID',
|
||||
});
|
||||
} finally {
|
||||
await server.close();
|
||||
}
|
||||
});
|
||||
|
||||
it('uses registered errors for unreadable content and upload storage failures', async () => {
|
||||
const server = await startAttachmentFailureServer();
|
||||
try {
|
||||
const content = await fetch(
|
||||
`${server.baseUrl}/api/coding/attachments/attachment-1/content`,
|
||||
);
|
||||
expect(content.status).toBe(404);
|
||||
await expect(content.json()).resolves.toMatchObject({
|
||||
code: 'CODING_ATTACHMENT_NOT_FOUND',
|
||||
});
|
||||
|
||||
const upload = await fetch(`${server.baseUrl}/api/coding/attachments`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'image/png' },
|
||||
body: new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]),
|
||||
});
|
||||
expect(upload.status).toBe(500);
|
||||
await expect(upload.json()).resolves.toMatchObject({
|
||||
code: 'CODING_STORAGE_WRITE_FAILED',
|
||||
error: '本地数据写入失败,请检查存储后重试。',
|
||||
});
|
||||
} finally {
|
||||
await server.close();
|
||||
|
||||
Reference in New Issue
Block a user