fix:参考金值,研听,研值工程通用通用工程公共能力,重点对比网络请求、登录认证、状态管理、本地存储、WebView、推送、版本更新、一键登录、主题/UI 等模块,确定后续统一整改方案
This commit is contained in:
1 parent
6997a65c96
commit
d364c6d908
46 files changed
+2060
-395
No files matched your search
@@ -1,9 +1,14 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:jinzhi_flutter_app/common/storage/secure_identity_storage.dart';
|
||||
import 'package:jinzhi_flutter_app/common/storage/storage_keys.dart';
|
||||
import 'package:jinzhi_flutter_app/common/storage/preferences_storage.dart';
|
||||
import 'package:jinzhi_flutter_app/features/auth/application/auth_controller.dart';
|
||||
import 'package:jinzhi_flutter_app/features/auth/application/auth_session_coordinator.dart';
|
||||
import 'package:jinzhi_flutter_app/features/auth/data/auth_models.dart';
|
||||
import 'package:jinzhi_flutter_app/features/assets/data/mock_asset_repository.dart';
|
||||
import 'package:jinzhi_flutter_app/models/pb/jinzhi/v1/account.pb.dart' as pb;
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
@@ -61,7 +66,7 @@ void main() {
|
||||
|
||||
await fixture.controller.retryBootstrap();
|
||||
|
||||
expect(fixture.controller.state.value, isA<GuestAuthState>());
|
||||
expect(fixture.controller.state.value, isA<SessionExpiredAuthState>());
|
||||
expect(await fixture.identity.readJwt(), isNull);
|
||||
});
|
||||
|
||||
@@ -81,6 +86,59 @@ void main() {
|
||||
expect(fixture.preferences.containsKey('jinzhi_mock_logged_in'), isFalse);
|
||||
});
|
||||
|
||||
test('restores cached profile before the background profile reply', () async {
|
||||
final fixture = await _Fixture.create();
|
||||
await fixture.identity.saveJwt('token');
|
||||
await fixture.preferences.setString(storageUserId, 'cached-user');
|
||||
await fixture.preferences.setString(storageUserPhone, '13900139000');
|
||||
fixture.profileCompleter = Completer<void>();
|
||||
|
||||
final bootstrap = fixture.controller.retryBootstrap();
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
|
||||
final stale = fixture.controller.state.value! as LoggedInAuthState;
|
||||
expect(stale.user.id, 'cached-user');
|
||||
expect(stale.isVerified, isFalse);
|
||||
|
||||
fixture.profileCompleter!.complete();
|
||||
await bootstrap;
|
||||
expect(
|
||||
(fixture.controller.state.value! as LoggedInAuthState).isVerified,
|
||||
isTrue,
|
||||
);
|
||||
});
|
||||
|
||||
test('keeps cached login on 403, 429, 5xx, and decode failures', () async {
|
||||
for (final failure in [403, 429, 503, -1]) {
|
||||
final fixture = await _Fixture.create();
|
||||
await fixture.identity.saveJwt('token');
|
||||
await fixture.preferences.setString(storageUserId, 'cached-user');
|
||||
fixture.profileFailureStatus = failure;
|
||||
|
||||
await fixture.controller.retryBootstrap();
|
||||
|
||||
expect(fixture.controller.state.value, isA<LoggedInAuthState>());
|
||||
expect(await fixture.identity.readJwt(), 'token');
|
||||
}
|
||||
});
|
||||
|
||||
test('logout preserves assets while account deletion removes them', () async {
|
||||
final logoutFixture = await _Fixture.create();
|
||||
await logoutFixture.identity.saveJwt('token');
|
||||
await logoutFixture.preferences.setString(storageJinzhiHoldings, 'assets');
|
||||
await logoutFixture.controller.logout();
|
||||
expect(
|
||||
logoutFixture.preferences.getString(storageJinzhiHoldings),
|
||||
'assets',
|
||||
);
|
||||
|
||||
final deleteFixture = await _Fixture.create();
|
||||
await deleteFixture.identity.saveJwt('token');
|
||||
await deleteFixture.preferences.setString(storageJinzhiHoldings, 'assets');
|
||||
await deleteFixture.controller.deleteAccount('123456');
|
||||
expect(deleteFixture.preferences.getString(storageJinzhiHoldings), isNull);
|
||||
});
|
||||
|
||||
test('keeps the verified one-key login state shape', () async {
|
||||
final fixture = await _Fixture.create();
|
||||
|
||||
@@ -106,20 +164,47 @@ class _Fixture {
|
||||
bool failDeletion = false;
|
||||
bool failProfile = false;
|
||||
bool profileUnauthorized = false;
|
||||
int? profileFailureStatus;
|
||||
Completer<void>? profileCompleter;
|
||||
String? deletedWithCode;
|
||||
|
||||
static Future<_Fixture> create() async {
|
||||
final preferences = await SharedPreferences.getInstance();
|
||||
final identity = SecureIdentityStorage(
|
||||
preferences,
|
||||
PreferencesStorage(preferences),
|
||||
secureStorage: _MemorySecureStorage(),
|
||||
);
|
||||
late _Fixture fixture;
|
||||
final dio = Dio()
|
||||
..interceptors.add(
|
||||
InterceptorsWrapper(
|
||||
onRequest: (options, handler) {
|
||||
onRequest: (options, handler) async {
|
||||
if (options.path == '/api/v1/me' && options.method == 'GET') {
|
||||
if (fixture.profileCompleter case final completer?) {
|
||||
await completer.future;
|
||||
}
|
||||
if (fixture.profileFailureStatus case final status?) {
|
||||
if (status == -1) {
|
||||
handler.resolve(
|
||||
Response<List<int>>(
|
||||
requestOptions: options,
|
||||
statusCode: 200,
|
||||
data: const [255],
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
handler.reject(
|
||||
DioException(
|
||||
requestOptions: options,
|
||||
response: Response<void>(
|
||||
requestOptions: options,
|
||||
statusCode: status,
|
||||
),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (fixture.failProfile) {
|
||||
handler.reject(DioException(requestOptions: options));
|
||||
return;
|
||||
@@ -185,10 +270,17 @@ class _Fixture {
|
||||
},
|
||||
),
|
||||
);
|
||||
final preferencesStorage = PreferencesStorage(preferences);
|
||||
final sessionStorage = AuthSessionStorage(identity);
|
||||
final coordinator = AuthSessionCoordinator(
|
||||
sessionStorage,
|
||||
preferencesStorage,
|
||||
MockAssetRepository(preferencesStorage),
|
||||
);
|
||||
final controller = AuthController(
|
||||
dio,
|
||||
identityStorage: identity,
|
||||
preferences: preferences,
|
||||
preferences: preferencesStorage,
|
||||
coordinator: coordinator,
|
||||
autoBootstrap: false,
|
||||
);
|
||||
fixture = _Fixture(
|
||||
|
||||
Reference in new issue
Block a user