Files
Genarrative/src/components/game-distribution/gameZipPackage.test.ts
T
kdletters 328ac31844 恢复游戏分发完整实现(特性分支)
- 主站:游戏广场、详情、在线游玩、网页发布与作者中心,以及共享契约与客户端服务
- 后端:module-game-distribution 领域层、SpacetimeDB 表/迁移/绑定、spacetime-client facade、api-server 路由与发行网关
- 后台:游戏审核页(待审列表、通过/拒绝、安全下架)
- AGC:发布面板、本地导出包读取命令与发布服务,含默认跳过的真实链路测试
- 运维:发行来源 nginx 模板与门禁、game-distribution:publish 灰度发布开关、OSS PutObject 受控重试
- 文档:主规范、里程碑与实施计划、决策日志与踩坑记录
2026-09-20 20:49:42 +08:00

56 lines
1.7 KiB
TypeScript

/* @vitest-environment jsdom */
import JSZip from 'jszip';
import { describe, expect, it } from 'vitest';
import { prepareGamePackage } from './gameZipPackage';
async function buildZip(files: Record<string, string>) {
const zip = new JSZip();
for (const [name, content] of Object.entries(files)) {
zip.file(name, content);
}
const bytes = await zip.generateAsync({ type: 'uint8array' });
return new File([bytes as unknown as BlobPart], 'game.zip', {
type: 'application/zip',
});
}
describe('prepareGamePackage', () => {
it('读取根 index.html、统计文件数并给出稳定摘要', async () => {
const file = await buildZip({
'index.html': '<html></html>',
'assets/app.js': 'console.log(1)',
});
const prepared = await prepareGamePackage(file);
expect(prepared.fileCount).toBe(2);
expect(prepared.totalBytes).toBe(file.size);
expect(prepared.sha256).toMatch(/^[0-9a-f]{64}$/u);
const again = await prepareGamePackage(file);
expect(again.sha256).toBe(prepared.sha256);
});
it('缺少根 index.html 时失败关闭', async () => {
const file = await buildZip({ 'game/index.html': '<html></html>' });
await expect(prepareGamePackage(file)).rejects.toThrow(
'发行包根目录必须包含 index.html',
);
});
it('拒绝空文件与非 ZIP 内容', async () => {
await expect(
prepareGamePackage(
new File([], 'empty.zip', { type: 'application/zip' }),
),
).rejects.toThrow('请选择非空的发行包 ZIP');
await expect(
prepareGamePackage(
new File(['not a zip' as unknown as BlobPart], 'bad.zip', {
type: 'application/zip',
}),
),
).rejects.toThrow('发行包不是有效的 ZIP');
});
});