收敛客户端静态发布链路
This commit is contained in:
@@ -40,17 +40,17 @@ async function writeLegacyPromotionPlan(projectPath: string, content: string): P
|
||||
await writeFile(join(projectPath, 'PROMOTION_PLAN.md'), content, 'utf8');
|
||||
}
|
||||
|
||||
function createServerPublishFile(appId: string): string {
|
||||
function createServerBindingFile(projectId: string, appId: string): string {
|
||||
return `${JSON.stringify({
|
||||
schema_version: 2,
|
||||
project_id: projectId,
|
||||
status: 'submitted',
|
||||
requested_at: '2026-08-10T00:00:00.000Z',
|
||||
updated_at: '2026-08-10T00:00:00.000Z',
|
||||
app_id: appId,
|
||||
title: '测试游戏',
|
||||
summary: '合规同步测试',
|
||||
category: 'game',
|
||||
age_band: '10-16',
|
||||
difficulty: 'beginner',
|
||||
version_id: 'version-1',
|
||||
version_name: 'v0.1.0',
|
||||
change_log: 'test',
|
||||
zip_file_path: 'dist/test.zip',
|
||||
review_status: 'building',
|
||||
})}\n`;
|
||||
}
|
||||
|
||||
@@ -95,11 +95,14 @@ describe('project progress compliance synchronization', () => {
|
||||
const localPath = await createProjectDirectory('local');
|
||||
await writeGameDocuments(serverPath, '# server gdd', '# server tasks');
|
||||
await writeGameDocuments(localPath, '# local gdd', '# local tasks');
|
||||
await writeFile(join(serverPath, 'works-publish.json'), createServerPublishFile('server-game'), 'utf8');
|
||||
|
||||
const projectStore = createProjectStore(createMemoryProjectStorage());
|
||||
const serverProject = await projectStore.rememberProject(serverPath);
|
||||
const localProject = await projectStore.rememberProject(localPath);
|
||||
await writeFile(
|
||||
join(serverPath, 'works-cloud-deploy.json'),
|
||||
createServerBindingFile(serverProject.id, 'server-game'),
|
||||
'utf8',
|
||||
);
|
||||
const harness = createWatcherHarness();
|
||||
const fetchMock = vi.fn().mockResolvedValue(new Response('{}', { status: 200 }));
|
||||
const sync = createProjectProgressSync(projectStore, {
|
||||
@@ -129,7 +132,7 @@ describe('project progress compliance synchronization', () => {
|
||||
project_key: localProject.id,
|
||||
});
|
||||
|
||||
const serverChanged = harness.callbacks.get(serverPath);
|
||||
const serverChanged = harness.callbacks.get(serverProject.path);
|
||||
expect(serverChanged).toBeDefined();
|
||||
serverChanged?.('GDD.md');
|
||||
await vi.advanceTimersByTimeAsync(25);
|
||||
@@ -149,10 +152,13 @@ describe('project progress compliance synchronization', () => {
|
||||
const productOverview = '# 产品运营介绍\n\n一句话价值:让玩家在三分钟内完成一次太空清洁任务。';
|
||||
await writeGameDocuments(projectPath, '# gdd', '# tasks');
|
||||
await writeProductOverview(projectPath, productOverview);
|
||||
await writeFile(join(projectPath, 'works-publish.json'), createServerPublishFile('promotion-game'), 'utf8');
|
||||
|
||||
const projectStore = createProjectStore(createMemoryProjectStorage());
|
||||
const project = await projectStore.rememberProject(projectPath);
|
||||
await writeFile(
|
||||
join(projectPath, 'works-cloud-deploy.json'),
|
||||
createServerBindingFile(project.id, 'promotion-game'),
|
||||
'utf8',
|
||||
);
|
||||
const harness = createWatcherHarness();
|
||||
const fetchMock = vi.fn().mockResolvedValue(new Response('{}', { status: 200 }));
|
||||
const sync = createProjectProgressSync(projectStore, {
|
||||
@@ -180,10 +186,13 @@ describe('project progress compliance synchronization', () => {
|
||||
await writeGameDocuments(projectPath, '# gdd', '# tasks');
|
||||
await writeProductOverview(projectPath, productOverview);
|
||||
await writeLegacyPromotionPlan(projectPath, '# 旧运营宣传计划\n\n不应覆盖新文档');
|
||||
await writeFile(join(projectPath, 'works-publish.json'), createServerPublishFile('overview-preferred-game'), 'utf8');
|
||||
|
||||
const projectStore = createProjectStore(createMemoryProjectStorage());
|
||||
const project = await projectStore.rememberProject(projectPath);
|
||||
await writeFile(
|
||||
join(projectPath, 'works-cloud-deploy.json'),
|
||||
createServerBindingFile(project.id, 'overview-preferred-game'),
|
||||
'utf8',
|
||||
);
|
||||
const harness = createWatcherHarness();
|
||||
const fetchMock = vi.fn().mockResolvedValue(new Response('{}', { status: 200 }));
|
||||
const sync = createProjectProgressSync(projectStore, {
|
||||
@@ -206,10 +215,13 @@ describe('project progress compliance synchronization', () => {
|
||||
const legacyPromotionPlan = '# 旧运营宣传计划\n\n卖点:用简单操作理解环保行动。';
|
||||
await writeGameDocuments(projectPath, '# gdd', '# tasks');
|
||||
await writeLegacyPromotionPlan(projectPath, legacyPromotionPlan);
|
||||
await writeFile(join(projectPath, 'works-publish.json'), createServerPublishFile('legacy-promotion-game'), 'utf8');
|
||||
|
||||
const projectStore = createProjectStore(createMemoryProjectStorage());
|
||||
const project = await projectStore.rememberProject(projectPath);
|
||||
await writeFile(
|
||||
join(projectPath, 'works-cloud-deploy.json'),
|
||||
createServerBindingFile(project.id, 'legacy-promotion-game'),
|
||||
'utf8',
|
||||
);
|
||||
const harness = createWatcherHarness();
|
||||
const fetchMock = vi.fn().mockResolvedValue(new Response('{}', { status: 200 }));
|
||||
const sync = createProjectProgressSync(projectStore, {
|
||||
@@ -250,8 +262,12 @@ describe('project progress compliance synchronization', () => {
|
||||
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||
expect(fetchMock.mock.calls.some(([url]) => String(url).includes('/agent/prompt'))).toBe(false);
|
||||
|
||||
await writeFile(join(projectPath, 'works-publish.json'), createServerPublishFile('bound-promotion-game'), 'utf8');
|
||||
harness.callbacks.get(projectPath)?.('works-publish.json');
|
||||
await writeFile(
|
||||
join(projectPath, 'works-cloud-deploy.json'),
|
||||
createServerBindingFile(project.id, 'bound-promotion-game'),
|
||||
'utf8',
|
||||
);
|
||||
harness.callbacks.get(project.path)?.('works-cloud-deploy.json');
|
||||
await sync.flushProject(project.id);
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledTimes(3);
|
||||
@@ -268,10 +284,13 @@ describe('project progress compliance synchronization', () => {
|
||||
const secondOverview = '# 更新后的产品运营介绍\n\n新增真实试玩证据。';
|
||||
await writeGameDocuments(projectPath, '# gdd', '# tasks');
|
||||
await writeProductOverview(projectPath, firstOverview);
|
||||
await writeFile(join(projectPath, 'works-publish.json'), createServerPublishFile('retry-promotion-game'), 'utf8');
|
||||
|
||||
const projectStore = createProjectStore(createMemoryProjectStorage());
|
||||
const project = await projectStore.rememberProject(projectPath);
|
||||
await writeFile(
|
||||
join(projectPath, 'works-cloud-deploy.json'),
|
||||
createServerBindingFile(project.id, 'retry-promotion-game'),
|
||||
'utf8',
|
||||
);
|
||||
const harness = createWatcherHarness();
|
||||
const fetchMock = vi.fn()
|
||||
.mockResolvedValueOnce(new Response('{}', { status: 200 }))
|
||||
@@ -396,13 +415,13 @@ describe('project progress compliance synchronization', () => {
|
||||
synchronizers.push(sync);
|
||||
|
||||
await sync.start();
|
||||
expect(harness.closeMocks.get(projectPath)).toBeDefined();
|
||||
expect(harness.closeMocks.get(project.path)).toBeDefined();
|
||||
await projectStore.removeProject(project.id);
|
||||
expect(sync.getWatchedProjectIds()).toEqual([]);
|
||||
expect(harness.closeMocks.get(projectPath)).toHaveBeenCalledTimes(1);
|
||||
expect(harness.closeMocks.get(project.path)).toHaveBeenCalledTimes(1);
|
||||
|
||||
sync.stop();
|
||||
expect(harness.closeMocks.get(projectPath)).toHaveBeenCalledTimes(1);
|
||||
expect(harness.closeMocks.get(project.path)).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('does not expose document content in error logs or request URLs', async () => {
|
||||
|
||||
Reference in New Issue
Block a user