Initial project import
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:archive/archive.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:miaoji_zhang/shared/services/local_export_service.dart';
|
||||
|
||||
void main() {
|
||||
test('local export creates readable CSV and privacy-safe JSON', () {
|
||||
final bytes = LocalExportService.buildZipFromSnapshot(
|
||||
{
|
||||
'schemaVersion': 1,
|
||||
'exportedAt': '2026-07-21T00:00:00.000Z',
|
||||
'ledgers': [
|
||||
{
|
||||
'id': 1,
|
||||
'name': '日常账本',
|
||||
'iconKey': 'wallet',
|
||||
'isDefault': true,
|
||||
'updatedAt': '2026-07-21T00:00:00.000Z',
|
||||
},
|
||||
],
|
||||
'categories': [
|
||||
{
|
||||
'id': 2,
|
||||
'name': '餐饮',
|
||||
'iconKey': 'food',
|
||||
'colorKey': 'coral',
|
||||
'type': 'expense',
|
||||
'sortOrder': 10,
|
||||
'isCustom': false,
|
||||
'isDeleted': false,
|
||||
'updatedAt': '2026-07-21T00:00:00.000Z',
|
||||
},
|
||||
],
|
||||
'transactions': [
|
||||
{
|
||||
'id': 3,
|
||||
'ledgerId': 1,
|
||||
'categoryId': 2,
|
||||
'categoryName': '餐饮',
|
||||
'categoryIcon': 'food',
|
||||
'categoryColor': 'coral',
|
||||
'type': 'expense',
|
||||
'amount': 12.5,
|
||||
'note': '午饭,"套餐"\n已报销',
|
||||
'paymentMethod': '微信',
|
||||
'source': 'manual',
|
||||
'sourceText': null,
|
||||
'occurredAt': '2026-07-21T04:00:00.000Z',
|
||||
'isDeleted': false,
|
||||
'updatedAt': '2026-07-21T04:00:00.000Z',
|
||||
},
|
||||
],
|
||||
'budgets': [
|
||||
{
|
||||
'ledgerId': 1,
|
||||
'period': 202607,
|
||||
'categoryId': 2,
|
||||
'amount': 800.0,
|
||||
'recurring': true,
|
||||
'updatedAt': '2026-07-21T00:00:00.000Z',
|
||||
},
|
||||
],
|
||||
},
|
||||
profile: const {'mode': 'guest', 'nickname': '游客'},
|
||||
);
|
||||
|
||||
final archive = ZipDecoder().decodeBytes(bytes);
|
||||
expect(
|
||||
archive.map((file) => file.name),
|
||||
containsAll(['transactions.csv', 'budgets.csv', 'jizhi-backup.json']),
|
||||
);
|
||||
|
||||
final transactionCsv = utf8.decode(
|
||||
archive.findFile('transactions.csv')!.readBytes()!,
|
||||
);
|
||||
expect(transactionCsv, contains('12.50'));
|
||||
expect(transactionCsv, contains('"午饭,""套餐""\n已报销"'));
|
||||
|
||||
final json = utf8.decode(
|
||||
archive.findFile('jizhi-backup.json')!.readBytes()!,
|
||||
);
|
||||
final document = jsonDecode(json) as Map<String, dynamic>;
|
||||
expect(document['transactions'], hasLength(1));
|
||||
expect((document['profile'] as Map)['mode'], 'guest');
|
||||
expect(json, isNot(contains('passwordHash')));
|
||||
expect(json, isNot(contains('local_db_key')));
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user