- 切换到 expo-router 文件路由,删除 App.tsx - 新增 5 个 Expo 原生插件:ppocr (OCR), accessibility (账单抓取), notification-listener, screenshot-monitor, sms-receiver - 实现核心领域逻辑:billPipeline (账单流水), dedup (去重), transferRecognizer (转账识别), ruleEngine + categories (双轨制分类), budgets, creditCards, recurring, sync, ocrProcessor - 增强 ledger.ts:支持 balance assertion, option, pad/note 指令, posting 级 metadata, cost/price 解析 - 新增完整 UI:tabs (首页/报表/设置), 交易详情, 预算, 日历热力图, 分类管理, 信用卡, 定期交易, 规则管理 - 实现 Zustand 状态管理:ledgerStore, importStore, settingsStore, metadataStore, automationStore + 持久化 - 新增 AI 功能:chatAssistant, monthlySummary, voiceInput - 实现多端同步:gitSync, webdavSync, icloudSync - 新增主题系统 (tokens/presets) 和 i18n (zh/en) - 添加 30+ 单元测试覆盖核心逻辑
71 lines
2.9 KiB
TypeScript
71 lines
2.9 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { lightTheme, darkTheme, presetThemes } from '../src/theme/presets';
|
|
import { createTheme } from '../src/theme/createTheme';
|
|
import type { ThemeTokens } from '../src/theme/tokens';
|
|
|
|
describe('预置主题', () => {
|
|
it('lightTheme 与 darkTheme 关键色彩不同', () => {
|
|
expect(lightTheme.colors.bgPrimary).not.toBe(darkTheme.colors.bgPrimary);
|
|
expect(lightTheme.colors.fgPrimary).not.toBe(darkTheme.colors.fgPrimary);
|
|
});
|
|
|
|
it('lightTheme 背景为亮色、darkTheme 背景为深色', () => {
|
|
// 亮色背景接近白,深色背景接近黑
|
|
expect(lightTheme.colors.bgPrimary).toBe('#FFFFFF');
|
|
expect(darkTheme.colors.bgPrimary).not.toBe('#FFFFFF');
|
|
});
|
|
|
|
it('presetThemes 注册表含 light 与 dark', () => {
|
|
expect(presetThemes.light).toBe(lightTheme);
|
|
expect(presetThemes.dark).toBe(darkTheme);
|
|
});
|
|
|
|
it('财务语义色三态齐全', () => {
|
|
for (const theme of [lightTheme, darkTheme]) {
|
|
expect(theme.colors.financial.income).toBeTruthy();
|
|
expect(theme.colors.financial.expense).toBeTruthy();
|
|
expect(theme.colors.financial.transfer).toBeTruthy();
|
|
}
|
|
});
|
|
|
|
it('spacing/radii/typography/shadows 结构完整', () => {
|
|
for (const theme of [lightTheme, darkTheme] as ThemeTokens[]) {
|
|
expect(theme.spacing).toHaveProperty('xs');
|
|
expect(theme.spacing).toHaveProperty('xl');
|
|
expect(theme.radii).toHaveProperty('sm');
|
|
expect(theme.radii).toHaveProperty('full');
|
|
expect(theme.typography).toHaveProperty('h1');
|
|
expect(theme.typography).toHaveProperty('caption');
|
|
expect(theme.shadows).toHaveProperty('sm');
|
|
expect(theme.shadows).toHaveProperty('lg');
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('createTheme 自定义主题工厂', () => {
|
|
it('未覆盖时等价于 lightTheme', () => {
|
|
const custom = createTheme({});
|
|
expect(custom.colors.bgPrimary).toBe(lightTheme.colors.bgPrimary);
|
|
expect(custom.spacing).toEqual(lightTheme.spacing);
|
|
});
|
|
|
|
it('覆盖 accent 颜色时其他颜色保留', () => {
|
|
const custom = createTheme({ colors: { ...lightTheme.colors, accent: '#FF5722' } });
|
|
expect(custom.colors.accent).toBe('#FF5722');
|
|
expect(custom.colors.bgPrimary).toBe(lightTheme.colors.bgPrimary); // 保留
|
|
expect(custom.colors.success).toBe(lightTheme.colors.success); // 保留
|
|
});
|
|
|
|
it('覆盖 financial 子对象时深度合并', () => {
|
|
const custom = createTheme({ colors: { ...lightTheme.colors, financial: { ...lightTheme.colors.financial, income: '#000' } } });
|
|
expect(custom.colors.financial.income).toBe('#000'); // 覆盖
|
|
expect(custom.colors.financial.expense).toBe(lightTheme.colors.financial.expense); // 保留
|
|
});
|
|
|
|
it('覆盖 spacing 部分键时其他键保留', () => {
|
|
const custom = createTheme({ spacing: { ...lightTheme.spacing, lg: 32 } });
|
|
expect(custom.spacing.lg).toBe(32);
|
|
expect(custom.spacing.md).toBe(lightTheme.spacing.md); // 保留
|
|
});
|
|
});
|