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 getRefreshToken() async { if (throwOnGetRefreshToken) { throw Exception('read refresh token failed'); } return refreshToken; } @override Future clearToken() async { clearTokenCalled = true; } @override Future clearRefreshToken() async { clearRefreshTokenCalled = true; } @override Future 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 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())); 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())); expect(authApi.deleteSessionCalled, isTrue); expect(sessionStore.clearTokenCalled, isTrue); expect(sessionStore.clearRefreshTokenCalled, isTrue); expect(sessionStore.clearEmailCalled, isTrue); }, ); }