133 lines
4.3 KiB
Dart
133 lines
4.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:miaoji_zhang/shared/services/recognition_import_service.dart';
|
|
import 'package:miaoji_zhang/shared/services/recognition_diagnostic_formatter.dart';
|
|
import 'package:miaoji_zhang/shared/services/screenshot_channel.dart';
|
|
import 'package:miaoji_zhang/shared/services/shanghai_time.dart';
|
|
import 'package:miaoji_zhang/shared/theme/theme_store.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
test('上海时区周期边界不受设备时区影响', () {
|
|
final civil = ShanghaiTime.toCivil(DateTime.utc(2026, 6, 30, 16, 30));
|
|
expect(civil, DateTime(2026, 7, 1, 0, 30));
|
|
|
|
final month = ShanghaiTime.monthRangeUtc(2026, 7);
|
|
expect(month.start, DateTime.utc(2026, 6, 30, 16));
|
|
expect(month.end, DateTime.utc(2026, 7, 31, 16));
|
|
|
|
final week = ShanghaiTime.weekRangeUtc(DateTime(2026, 7, 19));
|
|
expect(week.start, DateTime.utc(2026, 7, 12, 16));
|
|
expect(week.end, DateTime.utc(2026, 7, 19, 16));
|
|
});
|
|
|
|
test('无障碍运行时长不会被当作 Unix 时间戳', () {
|
|
final now = DateTime.utc(2026, 7, 22, 8, 30);
|
|
expect(RecognitionImportService.validOccurredAtUtc(1234, now: now), now);
|
|
expect(
|
|
RecognitionImportService.validOccurredAtUtc(
|
|
DateTime.utc(2026, 7, 22, 8).millisecondsSinceEpoch,
|
|
now: now,
|
|
),
|
|
DateTime.utc(2026, 7, 22, 8),
|
|
);
|
|
});
|
|
|
|
test('三态主题从本地恢复并持久化', () async {
|
|
SharedPreferences.setMockInitialValues({'theme_preference': 'dark'});
|
|
await ThemeStore.instance.initialize();
|
|
expect(ThemeStore.instance.preference, JzThemePreference.dark);
|
|
expect(ThemeStore.instance.themeMode, ThemeMode.dark);
|
|
|
|
await ThemeStore.instance.setPreference(JzThemePreference.light);
|
|
final preferences = await SharedPreferences.getInstance();
|
|
expect(preferences.getString('theme_preference'), 'light');
|
|
expect(ThemeStore.instance.themeMode, ThemeMode.light);
|
|
});
|
|
|
|
test('旧版无时区接口时间按 UTC 解释后显示上海时间', () {
|
|
expect(
|
|
ShanghaiTime.parseUtcInstant('2026-07-22T14:35:00'),
|
|
DateTime.utc(2026, 7, 22, 14, 35),
|
|
);
|
|
expect(
|
|
ShanghaiTime.parseCivil('2026-07-22T14:35:00'),
|
|
DateTime(2026, 7, 22, 22, 35),
|
|
);
|
|
expect(
|
|
ShanghaiTime.parseCivil('2026-07-22T14:35:00Z'),
|
|
DateTime(2026, 7, 22, 22, 35),
|
|
);
|
|
});
|
|
|
|
test('原生识别候选保留红包分类与金额来源', () {
|
|
final candidate = RecognitionCandidate.fromJson({
|
|
'id': 'candidate-1',
|
|
'clientRequestId': 'recognition-candidate-1',
|
|
'state': 'auto_ready',
|
|
'confidence': 'auto',
|
|
'type': 'income',
|
|
'source': 'local_ocr',
|
|
'appName': '微信',
|
|
'amount': 8.88,
|
|
'occurredAtEpochMs': DateTime.utc(
|
|
2026,
|
|
7,
|
|
22,
|
|
14,
|
|
35,
|
|
).millisecondsSinceEpoch,
|
|
'recognitionKind': 'red_packet_receive',
|
|
'categoryHint': '红包',
|
|
'amountSource': 'result',
|
|
'resultFingerprint': 'abc123',
|
|
});
|
|
|
|
expect(candidate.recognitionKind, 'red_packet_receive');
|
|
expect(candidate.categoryHint, '红包');
|
|
expect(candidate.amountSource, 'result');
|
|
expect(candidate.resultFingerprint, 'abc123');
|
|
});
|
|
|
|
test('智能识别诊断摘要能区分关键失败类型', () {
|
|
RecognitionDiagnostic diagnostic(String result, String reason) {
|
|
return RecognitionDiagnostic(
|
|
at: DateTime.utc(2026, 7, 22, 14, 35),
|
|
appName: '微信',
|
|
stage: 'ocr',
|
|
result: result,
|
|
reason: reason,
|
|
nodeCount: 12,
|
|
amountCandidates: 1,
|
|
);
|
|
}
|
|
|
|
expect(
|
|
RecognitionDiagnosticDisplay.from(
|
|
diagnostic('failed', 'capture_timeout'),
|
|
).summaryLabel,
|
|
'截图失败',
|
|
);
|
|
expect(
|
|
RecognitionDiagnosticDisplay.from(
|
|
diagnostic('failed', 'no_text'),
|
|
).summaryLabel,
|
|
'OCR 无结果',
|
|
);
|
|
expect(
|
|
RecognitionDiagnosticDisplay.from(
|
|
diagnostic('rejected', 'payment_input_page'),
|
|
).summaryLabel,
|
|
'规则拒绝',
|
|
);
|
|
expect(
|
|
RecognitionDiagnosticDisplay.from(
|
|
diagnostic('ignored', 'duplicate_result_surface'),
|
|
).summaryLabel,
|
|
'已合并',
|
|
);
|
|
});
|
|
}
|