DriftLedger/tests/adapters-migrations.test.ts
fengmengqi f6437b83fe feat: 初始化完整应用框架
- 切换到 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+ 单元测试覆盖核心逻辑
2026-07-15 10:01:31 +08:00

69 lines
2.7 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.

import { describe, expect, it } from 'vitest';
import { parseCmbCsv, parseIcbcCsv, parseGenericBankCsv } from '../src/domain/adapters';
import { migrateDb, MemoryMigrationDb, SCHEMA_VERSION } from '../src/storage/migrations';
describe('CSV adapters', () => {
it('parseCmbCsv 招商银行', () => {
const csv = '交易日期,交易类型,交易金额,交易对方,摘要\n2026-07-10,消费,100.50,超市,买日用品\n2026-07-11,收入,5000.00,公司,工资';
const events = parseCmbCsv(csv);
expect(events).toHaveLength(2);
expect(events[0].channel).toBe('Bank:CMB');
expect(events[0].direction).toBe('expense');
expect(events[0].amount).toBe('-100.50');
expect(events[1].direction).toBe('income');
expect(events[1].amount).toBe('5000.00');
});
it('parseIcbcCsv 工商银行', () => {
const csv = '交易时间,交易类型,交易金额,对方户名,摘要\n2026-07-10,消费,200,商户,购物';
const events = parseIcbcCsv(csv);
expect(events).toHaveLength(1);
expect(events[0].channel).toBe('Bank:ICBC');
expect(events[0].counterparty).toBe('商户');
});
it('parseGenericBankCsv 通用', () => {
const csv = '日期,金额,交易对方\n2026-07-10,50,便利店';
const events = parseGenericBankCsv(csv, 'Bank:Custom');
expect(events).toHaveLength(1);
expect(events[0].channel).toBe('Bank:Custom');
});
it('退款项识别为 refund', () => {
const csv = '日期,交易类型,金额,交易对方\n2026-07-10,退款,30,商家';
const events = parseGenericBankCsv(csv);
expect(events[0].direction).toBe('refund');
});
});
describe('migrations', () => {
it('从 0 迁移到当前版本', async () => {
const db = new MemoryMigrationDb();
await migrateDb(db);
expect(db.executed.length).toBeGreaterThan(0);
// 应包含建表语句
expect(db.executed.some(s => s.includes('CREATE TABLE'))).toBe(true);
// 应包含 user_version 设置
expect(db.executed.some(s => s.includes('PRAGMA user_version'))).toBe(true);
});
it('已迁移过的不再重复执行', async () => {
const db = new MemoryMigrationDb();
await migrateDb(db);
const firstCount = db.executed.length;
await migrateDb(db); // 第二次
expect(db.executed.length).toBe(firstCount); // 无新增
});
it('SCHEMA_VERSION 至少为 2含双轨制表', () => {
expect(SCHEMA_VERSION).toBeGreaterThanOrEqual(2);
});
it('v2 包含 categories 表', async () => {
const db = new MemoryMigrationDb();
await migrateDb(db);
expect(db.executed.some(s => s.includes('categories'))).toBe(true);
expect(db.executed.some(s => s.includes('credit_cards'))).toBe(true);
});
});