| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- import {
- fmtBalance,
- fmtPercent,
- fmtSize,
- fmtTokens,
- isMatrixReady,
- normProgress,
- usageOf,
- } from './format';
- import { Agent } from './api/models';
- /**
- * 纯函数单测 —— 格式化与派生口径
- *
- * 依据 SPEC NFR-06(可测)与《数据访问层设计.md》§五(格式化唯一实现)。
- * 这些口径曾在存量项目里出现 4 份重复实现,故必须有回归保护。
- */
- describe('format 纯函数', () => {
- describe('fmtSize', () => {
- it('按 1024 进制换算并保留 1 位小数', () => {
- expect(fmtSize(0)).toBe('0 B');
- expect(fmtSize(512)).toBe('512 B');
- expect(fmtSize(1024)).toBe('1.0 KB');
- expect(fmtSize(1536)).toBe('1.5 KB');
- expect(fmtSize(1024 * 1024)).toBe('1.0 MB');
- });
- it('空值返回占位符', () => {
- expect(fmtSize(undefined)).toBe('—');
- });
- });
- describe('fmtTokens', () => {
- it('按 1000 进制分档(k / M)', () => {
- expect(fmtTokens(0)).toBe('0');
- expect(fmtTokens(999)).toBe('999');
- expect(fmtTokens(1500)).toBe('1.5k');
- expect(fmtTokens(1_500_000)).toBe('1.5M');
- });
- it('空值返回占位符', () => {
- expect(fmtTokens(undefined)).toBe('—');
- });
- });
- describe('fmtBalance(FR-07 AC-07.4:余额转人民币)', () => {
- it('有记账时显示 ¥ xx.xx(两位小数)', () => {
- expect(fmtBalance({ remainCny: 17842.31 })).toBe('¥ 17842.31');
- expect(fmtBalance({ remainCny: 0 })).toBe('¥ 0.00');
- expect(fmtBalance({ remainCny: 86.4 })).toBe('¥ 86.40');
- });
- it('无记账时显示占位符,不伪造 ¥0', () => {
- expect(fmtBalance(undefined)).toBe('—');
- expect(fmtBalance({})).toBe('—');
- });
- it('负值如实显示为 -¥(不截断为 0,2026-11-11 余额口径事件)', () => {
- expect(fmtBalance({ remainCny: -76.12 })).toBe('-¥ 76.12');
- expect(fmtBalance({ remainCny: -0.5 })).toBe('-¥ 0.50');
- });
- });
- describe('normProgress(契约 §六-5:百分比 or 比例语义推断)', () => {
- it('0<x<=1 视为小数比例,乘 100', () => {
- expect(normProgress(0.5)).toBe(50);
- expect(normProgress(0.25)).toBe(25);
- expect(normProgress(1)).toBe(100);
- });
- it('>1 视为整数百分比,原样返回', () => {
- expect(normProgress(50)).toBe(50);
- expect(normProgress(100)).toBe(100);
- });
- it('越界被夹到 [0,100](防脏数据撑破进度条)', () => {
- expect(normProgress(150)).toBe(100);
- expect(normProgress(-5)).toBe(0);
- });
- it('0 与空值:0 返回 0,空值返回 undefined', () => {
- expect(normProgress(0)).toBe(0);
- expect(normProgress(undefined)).toBeUndefined();
- expect(normProgress(NaN)).toBeUndefined();
- });
- });
- describe('fmtPercent', () => {
- it('归一后带百分号', () => {
- expect(fmtPercent(0.5)).toBe('50%');
- expect(fmtPercent(72)).toBe('72%');
- });
- it('空值返回占位符', () => {
- expect(fmtPercent(undefined)).toBe('—');
- });
- });
- describe('usageOf / isMatrixReady(映射口径)', () => {
- it('usageOf 容忍缺失的 usage 字段', () => {
- expect(usageOf({ id: 'a', name: 'a', status: 'idle', matrixReady: false, unread: 0 })).toEqual(
- {},
- );
- });
- it('isMatrixReady 采用**账号级**口径(matrixConfig.userId),不只看 homeserver 可达', () => {
- const base = { id: 'a', name: 'a', status: 'idle', unread: 0 } as unknown as Agent;
- // 未接入
- expect(isMatrixReady({ ...base, matrixReady: false })).toBe(false);
- // 仅 channels.matrix=true 不算就绪(homeserver 可达 ≠ 该 Agent 有账号)
- expect(isMatrixReady({ ...base, channels: { matrix: true } })).toBe(false);
- // 账号级就绪:matrixConfig.userId 存在
- expect(
- isMatrixReady({ ...base, channels: { matrixConfig: { userId: '@x:fmode.cn' } } }),
- ).toBe(true);
- // 映射层已判定就绪时直接放行
- expect(isMatrixReady({ ...base, matrixReady: true })).toBe(true);
- });
- });
- });
|