Files
eryao/apps/test/features/auth/auth_repository_test.dart

117 lines
3.3 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
import 'package:meeyao_qianwen/core/auth/session_store.dart';
import 'package:meeyao_qianwen/data/network/api_client.dart';
import 'package:meeyao_qianwen/data/storage/local_kv_store.dart';
import 'package:meeyao_qianwen/features/auth/data/apis/auth_api.dart';
import 'package:meeyao_qianwen/features/auth/data/repositories/auth_repository.dart';
class _FakeSessionStore extends SessionStore {
_FakeSessionStore({this.refreshToken, this.throwOnGetRefreshToken = false})
: super(LocalKvStore());
String? refreshToken;
bool throwOnGetRefreshToken;
bool clearTokenCalled = false;
bool clearRefreshTokenCalled = false;
bool clearEmailCalled = false;
@override
Future<String?> getRefreshToken() async {
if (throwOnGetRefreshToken) {
throw Exception('read refresh token failed');
}
return refreshToken;
}
@override
Future<void> clearToken() async {
clearTokenCalled = true;
}
@override
Future<void> clearRefreshToken() async {
clearRefreshTokenCalled = true;
}
@override
Future<void> clearEmail() async {
clearEmailCalled = true;
}
}
class _FakeAuthApi extends AuthApi {
_FakeAuthApi()
: super(apiClient: ApiClient(baseUrl: 'http://127.0.0.1:5775'));
bool deleteSessionCalled = false;
bool throwOnDeleteSession = false;
@override
Future<void> deleteSession({required String refreshToken}) async {
deleteSessionCalled = true;
if (throwOnDeleteSession) {
throw Exception('delete session failed');
}
}
}
void main() {
test(
'logout should clear local session when getRefreshToken throws',
() async {
final authApi = _FakeAuthApi();
final sessionStore = _FakeSessionStore(throwOnGetRefreshToken: true);
final repository = AuthRepositoryImpl(
authApi: authApi,
sessionStore: sessionStore,
);
await expectLater(repository.logout(), throwsA(isA<Exception>()));
expect(authApi.deleteSessionCalled, isFalse);
expect(sessionStore.clearTokenCalled, isTrue);
expect(sessionStore.clearRefreshTokenCalled, isTrue);
expect(sessionStore.clearEmailCalled, isTrue);
},
);
test(
'logout should skip deleteSession when refresh token is empty',
() async {
final authApi = _FakeAuthApi();
final sessionStore = _FakeSessionStore(refreshToken: '');
final repository = AuthRepositoryImpl(
authApi: authApi,
sessionStore: sessionStore,
);
await repository.logout();
expect(authApi.deleteSessionCalled, isFalse);
expect(sessionStore.clearTokenCalled, isTrue);
expect(sessionStore.clearRefreshTokenCalled, isTrue);
expect(sessionStore.clearEmailCalled, isTrue);
},
);
test(
'logout should still clear local session when deleteSession throws',
() async {
final authApi = _FakeAuthApi()..throwOnDeleteSession = true;
final sessionStore = _FakeSessionStore(refreshToken: 'r1');
final repository = AuthRepositoryImpl(
authApi: authApi,
sessionStore: sessionStore,
);
await expectLater(repository.logout(), throwsA(isA<Exception>()));
expect(authApi.deleteSessionCalled, isTrue);
expect(sessionStore.clearTokenCalled, isTrue);
expect(sessionStore.clearRefreshTokenCalled, isTrue);
expect(sessionStore.clearEmailCalled, isTrue);
},
);
}