88 lines
2.4 KiB
Dart
88 lines
2.4 KiB
Dart
|
|
import 'package:flutter_test/flutter_test.dart';
|
||
|
|
import 'package:meeyao_qianwen/features/auth/data/models/auth_user.dart';
|
||
|
|
import 'package:meeyao_qianwen/features/auth/data/repositories/auth_repository.dart';
|
||
|
|
import 'package:meeyao_qianwen/features/auth/presentation/bloc/auth_bloc.dart';
|
||
|
|
import 'package:meeyao_qianwen/features/auth/presentation/bloc/auth_state.dart';
|
||
|
|
|
||
|
|
class _FakeAuthRepository implements AuthRepository {
|
||
|
|
_FakeAuthRepository({this.recoveredUser, this.throwOnLogout = false});
|
||
|
|
|
||
|
|
AuthUser? recoveredUser;
|
||
|
|
bool clearCalled = false;
|
||
|
|
bool logoutCalled = false;
|
||
|
|
bool throwOnLogout;
|
||
|
|
|
||
|
|
@override
|
||
|
|
Future<void> clearLocalSession() async {
|
||
|
|
clearCalled = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
Future<AuthUser> loginWithEmailOtp({
|
||
|
|
required String email,
|
||
|
|
required String otp,
|
||
|
|
}) async {
|
||
|
|
return AuthUser(id: 'u1', email: email);
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
Future<void> logout() async {
|
||
|
|
logoutCalled = true;
|
||
|
|
if (throwOnLogout) {
|
||
|
|
throw Exception('logout failed');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
Future<AuthUser?> recoverSession() async {
|
||
|
|
return recoveredUser;
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
Future<void> sendOtp(String email) async {}
|
||
|
|
}
|
||
|
|
|
||
|
|
void main() {
|
||
|
|
test('start should become authenticated when recover success', () async {
|
||
|
|
final repo = _FakeAuthRepository(
|
||
|
|
recoveredUser: const AuthUser(id: 'u1', email: 'a@b.com'),
|
||
|
|
);
|
||
|
|
final bloc = AuthBloc(repository: repo);
|
||
|
|
|
||
|
|
await bloc.start();
|
||
|
|
|
||
|
|
expect(bloc.state.status, AuthStatus.authenticated);
|
||
|
|
expect(bloc.state.user?.email, 'a@b.com');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('handleUnauthorized401 should clear local session and unauth', () async {
|
||
|
|
final repo = _FakeAuthRepository(
|
||
|
|
recoveredUser: const AuthUser(id: 'u1', email: 'a@b.com'),
|
||
|
|
);
|
||
|
|
final bloc = AuthBloc(repository: repo);
|
||
|
|
|
||
|
|
await bloc.start();
|
||
|
|
await bloc.handleUnauthorized401();
|
||
|
|
|
||
|
|
expect(repo.clearCalled, isTrue);
|
||
|
|
expect(bloc.state.status, AuthStatus.unauthenticated);
|
||
|
|
});
|
||
|
|
|
||
|
|
test(
|
||
|
|
'logout should set unauthenticated even when repository throws',
|
||
|
|
() async {
|
||
|
|
final repo = _FakeAuthRepository(
|
||
|
|
recoveredUser: const AuthUser(id: 'u1', email: 'a@b.com'),
|
||
|
|
throwOnLogout: true,
|
||
|
|
);
|
||
|
|
final bloc = AuthBloc(repository: repo);
|
||
|
|
|
||
|
|
await bloc.start();
|
||
|
|
|
||
|
|
await expectLater(bloc.logout(), throwsA(isA<Exception>()));
|
||
|
|
expect(repo.logoutCalled, isTrue);
|
||
|
|
expect(bloc.state.status, AuthStatus.unauthenticated);
|
||
|
|
},
|
||
|
|
);
|
||
|
|
}
|