a2b70d92b8
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m21s
Project CI / Backend tests (pull_request) Failing after 16s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m18s
Project CI / Frontend tests (pull_request) Successful in 2m8s
Project CI / Repository checks (pull_request) Failing after 16s
Project CI / AI game creator shell web tests (pull_request) Successful in 1m56s
Project CI / Native shell tests (pull_request) Successful in 5m47s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
补齐 Phaser4 客户端发布前校验、阶段进度与原生幂等账本 增加 Web 作者私有作品管理、资料编辑、版本历史与软删除 增加后台作品筛选、游标分页与删除治理 同步 SpacetimeDB schema、bindings、DTO、文档与定向测试
137 lines
4.1 KiB
TypeScript
137 lines
4.1 KiB
TypeScript
// @vitest-environment jsdom
|
|
/**
|
|
* 发布进度事件的前端收敛层:Rust 的 `game-package-upload-progress` 载荷在这里被
|
|
* 规范化(未知阶段丢弃)、换算百分比,并通过统一的事件订阅入口投递给 UI。
|
|
*/
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
import {
|
|
computeGamePackageUploadPercent,
|
|
GAME_PACKAGE_UPLOAD_PROGRESS_EVENT,
|
|
readGamePackageUploadProgressEvent,
|
|
subscribeGamePackageUploadProgress,
|
|
} from '../src/services/gamePackageUploadProgress';
|
|
import { createTauriEventFake, type TauriEventFake } from './tauriEventFake';
|
|
|
|
let fake: TauriEventFake | null = null;
|
|
|
|
beforeEach(() => {
|
|
fake = createTauriEventFake();
|
|
fake.install();
|
|
});
|
|
|
|
afterEach(() => {
|
|
fake?.restore();
|
|
fake = null;
|
|
});
|
|
|
|
describe('发布进度事件收敛', () => {
|
|
it('规范化原生载荷:阶段、文案与字节计数都对上', () => {
|
|
expect(
|
|
readGamePackageUploadProgressEvent({
|
|
versionId: ' gamever_1 ',
|
|
publishId: ' agc-publish-1 ',
|
|
phase: 'upload',
|
|
message: ' 正在上传发行包… ',
|
|
receivedBytes: 5_242_880.9,
|
|
totalBytes: 10_000_000,
|
|
}),
|
|
).toEqual({
|
|
versionId: 'gamever_1',
|
|
publishId: 'agc-publish-1',
|
|
phase: 'upload',
|
|
message: '正在上传发行包…',
|
|
receivedBytes: 5_242_880,
|
|
totalBytes: 10_000_000,
|
|
});
|
|
});
|
|
|
|
it('不认识的阶段与非法载荷一律丢弃,不让 UI 退回错误阶段', () => {
|
|
expect(readGamePackageUploadProgressEvent(null)).toBeNull();
|
|
expect(readGamePackageUploadProgressEvent('upload')).toBeNull();
|
|
expect(
|
|
readGamePackageUploadProgressEvent({
|
|
phase: 'staging',
|
|
receivedBytes: 1,
|
|
totalBytes: 2,
|
|
}),
|
|
).toBeNull();
|
|
expect(
|
|
readGamePackageUploadProgressEvent({
|
|
phase: 'verify',
|
|
receivedBytes: -3,
|
|
totalBytes: Number.NaN,
|
|
}),
|
|
).toEqual({
|
|
versionId: '',
|
|
publishId: '',
|
|
phase: 'verify',
|
|
message: '',
|
|
receivedBytes: 0,
|
|
totalBytes: 0,
|
|
});
|
|
});
|
|
|
|
it('只有拿到总字节才换算百分比,其余阶段返回 null', () => {
|
|
expect(computeGamePackageUploadPercent(0, 0)).toBeNull();
|
|
expect(computeGamePackageUploadPercent(5, 0)).toBeNull();
|
|
expect(computeGamePackageUploadPercent(0, 10)).toBe(0);
|
|
expect(computeGamePackageUploadPercent(5, 10)).toBe(50);
|
|
expect(computeGamePackageUploadPercent(1, 3)).toBe(33);
|
|
expect(computeGamePackageUploadPercent(12, 10)).toBe(100);
|
|
});
|
|
|
|
it('订阅只投递规范化后的事件,注销后不再投递', async () => {
|
|
const handler = vi.fn();
|
|
const unsubscribe = await subscribeGamePackageUploadProgress(handler);
|
|
fake?.flushRegistrationEvals();
|
|
|
|
fake?.emit(GAME_PACKAGE_UPLOAD_PROGRESS_EVENT, {
|
|
versionId: 'gamever_1',
|
|
publishId: 'agc-publish-1',
|
|
phase: 'upload',
|
|
message: '正在上传发行包…',
|
|
receivedBytes: 10,
|
|
totalBytes: 40,
|
|
});
|
|
expect(handler).toHaveBeenCalledTimes(1);
|
|
expect(handler).toHaveBeenCalledWith({
|
|
versionId: 'gamever_1',
|
|
publishId: 'agc-publish-1',
|
|
phase: 'upload',
|
|
message: '正在上传发行包…',
|
|
receivedBytes: 10,
|
|
totalBytes: 40,
|
|
});
|
|
|
|
// 未知阶段不投递:UI 不会因为一条不认识的事件退回错误步骤。
|
|
fake?.emit(GAME_PACKAGE_UPLOAD_PROGRESS_EVENT, {
|
|
phase: 'unknown',
|
|
message: '不该出现',
|
|
receivedBytes: 0,
|
|
totalBytes: 0,
|
|
});
|
|
expect(handler).toHaveBeenCalledTimes(1);
|
|
|
|
unsubscribe();
|
|
fake?.emit(GAME_PACKAGE_UPLOAD_PROGRESS_EVENT, {
|
|
phase: 'submit',
|
|
message: '正在提交审核…',
|
|
receivedBytes: 0,
|
|
totalBytes: 0,
|
|
});
|
|
expect(handler).toHaveBeenCalledTimes(1);
|
|
expect(fake?.jsCallbackCount()).toBe(0);
|
|
});
|
|
|
|
it('没有原生宿主时订阅是空操作而不是报错', async () => {
|
|
fake?.restore();
|
|
fake = null;
|
|
const handler = vi.fn();
|
|
const unsubscribe = await subscribeGamePackageUploadProgress(handler);
|
|
expect(typeof unsubscribe).toBe('function');
|
|
unsubscribe();
|
|
expect(handler).not.toHaveBeenCalled();
|
|
});
|
|
});
|