template/packages-user/data-base/src/flag/system.test.ts
unanmed 2cb9bba3ce test(06-08): cover FlagSystem, FaceManager handlers and RoleFaceBinder (stage 2)
- add system.test.ts covering the full FlagSystem public surface and warn code 111
- add faceManager.test.ts covering FaceManager registry plus Dir4/Dir8 handlers
- add face.test.ts covering RoleFaceBinder malloc/bind/query and error codes 43/44
2026-09-14 16:56:17 +08:00

172 lines
5.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 测试 data-base 全局 Flag 系统的公开接口行为(存读档归 06-09此处不测
import { beforeAll, describe, expect, it, vi } from 'vitest';
vi.hoisted(() => {
vi.stubGlobal('main', { replayChecking: true });
vi.stubGlobal('location', { origin: 'http://localhost' });
Map.prototype.getOrInsertComputed ??= function <K, V>(
this: Map<K, V>,
key: K,
callback: (key: K) => V
): V {
const existing = this.get(key);
if (existing !== undefined) return existing;
const value = callback(key);
this.set(key, value);
return value;
};
Map.prototype.getOrInsert ??= function <K, V>(
this: Map<K, V>,
key: K,
defaultValue: V
): V {
const existing = this.get(key);
if (existing !== undefined) return existing;
this.set(key, defaultValue);
return defaultValue;
};
});
interface TestModules {
FlagSystem: typeof import('./system').FlagSystem;
logger: typeof import('@motajs/common').logger;
}
let modules: TestModules;
beforeAll(async () => {
vi.stubGlobal('main', { replayChecking: true });
vi.stubGlobal('location', { origin: 'http://localhost' });
const systemModule = await import('./system');
const commonModule = await import('@motajs/common');
modules = {
FlagSystem: systemModule.FlagSystem,
logger: commonModule.logger
};
});
/** 创建一个 Flag 系统及其中一个已插入字段,便于直接操作字段对象 */
function createField<T>(key: PropertyKey, value: T) {
const system = new modules.FlagSystem();
return { system, field: system.insertField(key, value) };
}
describe('FlagSystem field container', () => {
// 验证新系统的字段初始未占用,插入字段后被占用
it('tracks field occupancy', () => {
const system = new modules.FlagSystem();
expect(system.occupied('score')).toBe(false);
system.insertField('score', 1);
expect(system.occupied('score')).toBe(true);
});
// 验证 insertField 返回的字段对象支持取值、赋值与结构化克隆
it('returns a field exposing get, set and toStructured', () => {
const { field } = createField('nested', { list: [1, 2] });
expect(field.get()).toEqual({ list: [1, 2] });
field.set({ list: [3] });
expect(field.get()).toEqual({ list: [3] });
const structured = field.toStructured();
expect(structured).toEqual({ list: [3] });
expect(structured).not.toBe(field.get());
});
// 验证 getField 对未知字段返回 nullgetOrInsert 插入默认值且二次调用返回同一实例
it('gets by key and reuses the same field instance', () => {
const system = new modules.FlagSystem();
expect(system.getField('missing')).toBeNull();
const first = system.getOrInsert('count', 5);
const second = system.getOrInsert('count', 99);
expect(first).toBe(second);
expect(first.get()).toBe(5);
expect(system.getField('count')).toBe(first);
});
// 验证 getOrInsertComputed 把 key 传给默认值函数且仅在字段缺失时执行一次
it('computes the default only when the field is missing', () => {
const system = new modules.FlagSystem();
let calls = 0;
const compute = (key: string) => {
calls++;
return `value:${key}`;
};
const field = system.getOrInsertComputed('name', compute);
expect(field.get()).toBe('value:name');
expect(system.getOrInsertComputed('name', compute)).toBe(field);
expect(calls).toBe(1);
});
// 验证 deleteField 移除字段并恢复未占用状态
it('deletes a field', () => {
const system = new modules.FlagSystem();
system.insertField('temp', 1);
system.deleteField('temp');
expect(system.occupied('temp')).toBe(false);
expect(system.getField('temp')).toBeNull();
expect(system.getFieldValue('temp')).toBeUndefined();
});
});
describe('FlagSystem value accessors', () => {
// 验证 setFieldValue 覆盖已有值并创建缺失字段
it('sets values creating or overriding fields', () => {
const system = new modules.FlagSystem();
system.setFieldValue('score', 1);
system.setFieldValue('score', 9);
expect(system.getFieldValue<number>('score')).toBe(9);
expect(system.occupied('score')).toBe(true);
});
// 验证 addFieldValue 对数值字段累加
it('accumulates numeric field values', () => {
const system = new modules.FlagSystem();
system.addFieldValue('score', 4);
system.addFieldValue('score', 6);
expect(system.getFieldValue<number>('score')).toBe(10);
});
// 验证对非数值字段调用 addFieldValue 时经 logger 观测告警码 111
it('warns code 111 when adding to a non-numeric field', () => {
const system = new modules.FlagSystem();
system.setFieldValue('name', 'hero');
const result = modules.logger.catch(() =>
system.addFieldValue('name', 1)
);
expect(result.info.map(info => info.code)).toContain(111);
expect(system.getFieldValue<string>('name')).toBe('hero');
});
// 验证 getFieldValue 对未知字段返回 undefined
it('returns undefined for an unknown value', () => {
const system = new modules.FlagSystem();
expect(system.getFieldValue('missing')).toBeUndefined();
});
// 验证 getFieldValueDefaults 返回默认值并以该值插入字段
it('returns and inserts the default value', () => {
const system = new modules.FlagSystem();
const value = system.getFieldValueDefaults('lives', 3);
expect(value).toBe(3);
expect(system.occupied('lives')).toBe(true);
expect(system.getFieldValue<number>('lives')).toBe(3);
});
});