feat: 将发布预检移入内置浏览器

This commit is contained in:
2026-08-12 16:33:50 +08:00
parent be9bc84474
commit 926056a59b
16 changed files with 840 additions and 9 deletions

View File

@@ -18,6 +18,7 @@ vi.mock('@electron/services/works-square-session', () => ({
getValidWorksSquareAccessToken: (...args: unknown[]) => getValidWorksSquareAccessTokenMock(...args),
}));
function createResponse() {
const chunks: string[] = [];
const res = {
@@ -1082,6 +1083,7 @@ describe('works square host api routes', () => {
vi.stubGlobal('fetch', fetchMock);
const response = createResponse();
const recordSubmitted = vi.fn(async () => undefined);
const preflightCurrentProject = vi.fn(async () => ({ ok: true as const }));
const handled = await handleWorksRoutes(
createRendererRequest('POST', { projectId: project.id, project: projectMetadata }),
@@ -1089,6 +1091,7 @@ describe('works square host api routes', () => {
new URL('http://127.0.0.1/api/works/projects/publish-source'),
{
opencodeProjectStore: { listProjects: vi.fn(async () => [project]) },
agentBrowser: { preflightCurrentProject },
worksSubmissionBinding: { recordSubmitted },
} as never,
);
@@ -1153,6 +1156,50 @@ describe('works square host api routes', () => {
reviewStatus: 'building',
zipSha256: expect.stringMatching(/^[a-f0-9]{64}$/),
});
expect(preflightCurrentProject).toHaveBeenCalledWith(tempDir);
});
it('stops before creating or uploading when the local browser preflight fails', async () => {
tempDir = await mkdtemp(join(tmpdir(), 'makelore-source-preflight-failure-'));
await writePublishableProject(tempDir);
const preflightCurrentProject = vi.fn(async () => {
throw Object.assign(new Error(`${tempDir} token=secret`), {
code: 'PUBLISH_PREFLIGHT_BLANK',
});
});
const fetchMock = vi.fn();
vi.stubGlobal('fetch', fetchMock);
const response = createResponse();
await handleWorksRoutes(
createRendererRequest('POST', {
projectId: 'project-1',
project: {
app_id: 'space-cleaner',
title: '太空清洁队',
summary: '收集漂浮垃圾的小游戏。',
},
}),
response.res,
new URL('http://127.0.0.1/api/works/projects/publish-source'),
{
opencodeProjectStore: {
listProjects: vi.fn(async () => [{ id: 'project-1', path: tempDir, name: 'space-cleaner' }]),
},
agentBrowser: { preflightCurrentProject },
} as never,
);
expect(response.statusCode).toBe(200);
expect(response.json()).toEqual({
success: false,
status: 400,
code: 'PUBLISH_PREFLIGHT_BLANK',
error: '作品打开后没有可见内容。',
});
expect(fetchMock).not.toHaveBeenCalled();
expect(JSON.stringify(response.json())).not.toContain(tempDir);
expect(JSON.stringify(response.json())).not.toContain('token=secret');
});
it('keeps a confirmed submission successful when the local preview mapping cannot be saved', async () => {
@@ -1181,6 +1228,7 @@ describe('works square host api routes', () => {
new URL('http://127.0.0.1/api/works/projects/publish-source'),
{
opencodeProjectStore: { listProjects: vi.fn(async () => [project]) },
agentBrowser: { preflightCurrentProject: vi.fn(async () => ({ ok: true })) },
worksSubmissionBinding: {
recordSubmitted: vi.fn(async () => { throw new Error('disk unavailable'); }),
},
@@ -1225,7 +1273,10 @@ describe('works square host api routes', () => {
}),
response.res,
new URL('http://127.0.0.1/api/works/projects/publish-source'),
{ opencodeProjectStore: { listProjects: vi.fn(async () => [project]) } } as never,
{
opencodeProjectStore: { listProjects: vi.fn(async () => [project]) },
agentBrowser: { preflightCurrentProject: vi.fn(async () => ({ ok: true })) },
} as never,
);
expect(response.json().success).toBe(true);
@@ -1253,7 +1304,10 @@ describe('works square host api routes', () => {
.mockRejectedValueOnce(new Error('socket reset with secret upstream detail'))
.mockResolvedValueOnce(new Response(uploadPayload, { status: 201 }));
vi.stubGlobal('fetch', fetchMock);
const ctx = { opencodeProjectStore: { listProjects: vi.fn(async () => [project]) } } as never;
const ctx = {
opencodeProjectStore: { listProjects: vi.fn(async () => [project]) },
agentBrowser: { preflightCurrentProject: vi.fn(async () => ({ ok: true })) },
} as never;
for (let index = 0; index < 2; index += 1) {
const response = createResponse();
@@ -1307,7 +1361,10 @@ describe('works square host api routes', () => {
}),
response.res,
new URL('http://127.0.0.1/api/works/projects/publish-source'),
{ opencodeProjectStore: { listProjects: vi.fn(async () => [project]) } } as never,
{
opencodeProjectStore: { listProjects: vi.fn(async () => [project]) },
agentBrowser: { preflightCurrentProject: vi.fn(async () => ({ ok: true })) },
} as never,
);
expect(response.statusCode).toBe(200);
@@ -1343,7 +1400,10 @@ describe('works square host api routes', () => {
}),
response.res,
new URL('http://127.0.0.1/api/works/projects/publish-source'),
{ opencodeProjectStore: { listProjects: vi.fn(async () => [project]) } } as never,
{
opencodeProjectStore: { listProjects: vi.fn(async () => [project]) },
agentBrowser: { preflightCurrentProject: vi.fn(async () => ({ ok: true })) },
} as never,
);
expect(response.statusCode).toBe(200);