fix: improve transfer recognition and local data safety

This commit is contained in:
2026-07-26 21:36:46 +08:00
parent 7df25edd96
commit 882293343e
21 changed files with 505 additions and 128 deletions
+24
View File
@@ -1,12 +1,36 @@
import 'dart:convert';
import 'package:flutter_test/flutter_test.dart';
import 'package:miaoji_zhang/shared/api/backend_identity.dart';
import 'package:miaoji_zhang/shared/api/business_api.dart';
import 'package:miaoji_zhang/shared/api/sse_frame_accumulator.dart';
import 'package:miaoji_zhang/shared/services/current_ledger_store.dart';
import 'package:miaoji_zhang/shared/widgets/app_icons.dart';
void main() {
test('本地账号命名空间同时隔离后端和用户', () {
final first = BackendIdentity.accountNamespaceFor(
'https://api-a.example.com/',
1,
);
final normalized = BackendIdentity.accountNamespaceFor(
'https://API-A.example.com',
1,
);
final otherBackend = BackendIdentity.accountNamespaceFor(
'https://api-b.example.com',
1,
);
final otherUser = BackendIdentity.accountNamespaceFor(
'https://api-a.example.com',
2,
);
expect(first, normalized);
expect(first, isNot(otherBackend));
expect(first, isNot(otherUser));
});
test(
'SSE framing preserves split UTF-8 characters and trailing events',
() async {
@@ -82,4 +82,29 @@ void main() {
throwsStateError,
);
});
test('云端回写失败时保留待同步的本地账单', () {
final database = LocalDatabase.inMemoryForTesting();
addTearDown(database.close);
final local = database.createTransaction({
'ledgerId': 1,
'categoryId': 1,
'type': 'expense',
'amount': 28,
'occurredAt': '2026-07-25T03:00:00.000Z',
'source': 'manual',
});
final localId = local['id'] as int;
expect(
() => database.replaceLocalTransaction(localId, {
...local,
'id': 42,
'occurredAt': 'invalid-time',
}),
throwsFormatException,
);
expect(database.transaction(localId), isNotNull);
expect(database.transaction(42), isNull);
});
}
+15
View File
@@ -3,6 +3,21 @@ import 'dart:io';
import 'package:flutter_test/flutter_test.dart';
void main() {
test('登录强制刷新远端资料并按后端隔离本地账号数据', () {
final auth = File('lib/shared/api/auth_api.dart').readAsStringSync();
final session = File(
'lib/shared/services/session_store.dart',
).readAsStringSync();
expect(auth, contains('me(forceRemote: true)'));
expect(auth, contains('if (!forceRemote &&'));
expect(session, contains('BackendIdentity.accountNamespace(userId)'));
expect(session, contains('pending_account_archive_namespace'));
expect(session, contains('last_account_namespace'));
final client = File('lib/shared/api/api_client.dart').readAsStringSync();
expect(client, contains("'auth_token_\${BackendIdentity.scope}'"));
});
test('启动页只读取本地缓存,不等待远程接口', () {
final source = File(
'lib/features/auth/pages/splash_page.dart',