打通一键发布与真机预览集成
需求:将登录续期、一键提交审核和精确 Release 真机预览合为可推进主分支的完整客户端链路。 实现:提交成功后保存安全版本映射,映射失败不误报上传失败;同步新会话测试契约和集成态项目文档。
This commit is contained in:
@@ -2159,9 +2159,11 @@ describe('OpencodeChatPanel', () => {
|
||||
loading: false,
|
||||
error: null,
|
||||
accessToken: 'stale-token',
|
||||
refreshToken: 'refresh-token',
|
||||
tokenType: 'Bearer',
|
||||
expiresAt: Date.now() + 60_000,
|
||||
lastActiveAt: Date.now(),
|
||||
canRefresh: true,
|
||||
legacyRefreshToken: null,
|
||||
user: {
|
||||
username: 'student',
|
||||
userId: '42',
|
||||
@@ -2200,18 +2202,16 @@ describe('OpencodeChatPanel', () => {
|
||||
},
|
||||
};
|
||||
}
|
||||
if (path === '/api/auth/refresh' && init?.method === 'POST') {
|
||||
expect(init.body).toBe(JSON.stringify({ refreshToken: 'refresh-token' }));
|
||||
if (path === '/api/auth/session/refresh' && init?.method === 'POST') {
|
||||
expect(init.body).toBe(JSON.stringify({ forceRefresh: true }));
|
||||
return {
|
||||
success: true,
|
||||
token: {
|
||||
access_token: 'fresh-token',
|
||||
refresh_token: 'refresh-token',
|
||||
token_type: 'Bearer',
|
||||
expires_in: 3600,
|
||||
username: 'student',
|
||||
user_id: '42',
|
||||
authorities: [],
|
||||
session: {
|
||||
accessToken: 'fresh-token',
|
||||
tokenType: 'Bearer',
|
||||
expiresAt: Date.now() + 3_600_000,
|
||||
lastActiveAt: Date.now(),
|
||||
canRefresh: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1039,12 +1039,16 @@ describe('works square host api routes', () => {
|
||||
}), { status: 201 }));
|
||||
vi.stubGlobal('fetch', fetchMock);
|
||||
const response = createResponse();
|
||||
const recordSubmitted = vi.fn(async () => undefined);
|
||||
|
||||
const handled = await handleWorksRoutes(
|
||||
createRequest('POST', { projectId: project.id, project: projectMetadata }),
|
||||
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]) },
|
||||
worksCloudDeployment: { recordSubmitted },
|
||||
} as never,
|
||||
);
|
||||
|
||||
expect(handled).toBe(true);
|
||||
@@ -1100,6 +1104,53 @@ describe('works square host api routes', () => {
|
||||
expect(archive).toBeInstanceOf(File);
|
||||
expect((archive as File).name).toBe('project.zip');
|
||||
expect((archive as File).size).toBeGreaterThan(0);
|
||||
expect(recordSubmitted).toHaveBeenCalledWith(project.id, {
|
||||
appId: 'space-cleaner',
|
||||
versionId: 'version-1',
|
||||
versionName: 'v2.3.4',
|
||||
reviewStatus: 'building',
|
||||
zipSha256: expect.stringMatching(/^[a-f0-9]{64}$/),
|
||||
});
|
||||
});
|
||||
|
||||
it('keeps a confirmed submission successful when the local preview mapping cannot be saved', async () => {
|
||||
tempDir = await mkdtemp(join(tmpdir(), 'makelore-source-mapping-failure-'));
|
||||
await writePublishableProject(tempDir);
|
||||
const project = { id: 'project-1', path: tempDir, name: 'space-cleaner' };
|
||||
const fetchMock = vi.fn()
|
||||
.mockResolvedValueOnce(new Response('{}', { status: 201 }))
|
||||
.mockResolvedValueOnce(new Response(JSON.stringify({
|
||||
version_id: 'version-1',
|
||||
review_status: 'building',
|
||||
}), { status: 201 }));
|
||||
vi.stubGlobal('fetch', fetchMock);
|
||||
const response = createResponse();
|
||||
|
||||
await handleWorksRoutes(
|
||||
createRequest('POST', {
|
||||
projectId: project.id,
|
||||
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 () => [project]) },
|
||||
worksCloudDeployment: {
|
||||
recordSubmitted: vi.fn(async () => { throw new Error('disk unavailable'); }),
|
||||
},
|
||||
} as never,
|
||||
);
|
||||
|
||||
expect(response.statusCode).toBe(201);
|
||||
expect(response.json()).toMatchObject({
|
||||
success: true,
|
||||
upload: { version_id: 'version-1', review_status: 'building' },
|
||||
});
|
||||
expect(fetchMock).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('uses a bounded timestamp version when VERSION.md is oversized', async () => {
|
||||
|
||||
Reference in New Issue
Block a user