test(auth): add tests for all features

This commit is contained in:
2022-11-11 16:54:08 -05:00
parent 03a51b97ad
commit 38480d84f4
10 changed files with 1463 additions and 321 deletions
@@ -17,100 +17,114 @@
import 'package:bloc_test/bloc_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:wyatt_architecture/wyatt_architecture.dart';
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
class MockAuthenticationRepository extends Mock
implements AuthenticationRepository {}
implements AuthenticationRepository<int> {}
class MockUser extends Mock implements User {}
class MockAccount extends Mock implements Account {}
void main() {
group('AuthenticationCubit<T>', () {
final MockUser user = MockUser();
late AuthenticationRepository authenticationRepository;
final MockAccount account = MockAccount();
final AccountWrapper<int> wrapper = AccountWrapperModel(account, 10);
late AuthenticationRepository<int> authenticationRepository;
setUp(() {
authenticationRepository = MockAuthenticationRepository();
when(() => authenticationRepository.user).thenAnswer(
when(() => authenticationRepository.streamAccount()).thenAnswer(
(_) => const Stream.empty(),
);
when(() => authenticationRepository.cubitStatus).thenAnswer(
(_) => Stream.fromIterable([AuthCubitStatus.stoped]),
);
when(
() => authenticationRepository.currentUser,
).thenReturn(user);
() => authenticationRepository.getAccount(),
).thenAnswer((_) async => Ok(account));
});
test('initial auth state is `unknown`', () {
expect(
AuthenticationCubit<void>(
AuthenticationCubit<int>(
authenticationRepository: authenticationRepository,
).state,
const AuthenticationState<Never>.unknown(),
);
});
test('initial cubit status is `stoped`', () async {
expect(
await AuthenticationCubit<void>(
authenticationRepository: authenticationRepository,
).status,
AuthCubitStatus.stoped,
);
});
group('UserChanged', () {
blocTest<AuthenticationCubit<void>, AuthenticationState<void>>(
'emits authenticated when user is not empty',
group('ListenForAuthenticationChanges', () {
blocTest<AuthenticationCubit<int>, AuthenticationState<int>>(
'emits authenticated when stream contains account',
setUp: () {
when(() => user.isNotEmpty).thenReturn(true);
when(() => authenticationRepository.user).thenAnswer(
(_) => Stream.value(user),
when(() => authenticationRepository.streamAccount()).thenAnswer(
(_) => Stream.fromIterable([
Future.value(
Ok(wrapper),
)
]),
);
when(() => authenticationRepository.cubitStatus).thenAnswer(
(_) => Stream.value(AuthCubitStatus.started),
);
},
build: () => AuthenticationCubit(
authenticationRepository: authenticationRepository,
)..init(),
seed: () => const AuthenticationState.unknown(),
expect: () => [AuthenticationState<void>.authenticated(user, null)],
);
blocTest<AuthenticationCubit<void>, AuthenticationState<void>>(
'emits unauthenticated when user is empty',
setUp: () {
when(() => user.isEmpty).thenReturn(true);
when(() => user.isNotEmpty).thenReturn(false);
when(() => authenticationRepository.user).thenAnswer(
(_) => Stream.value(user),
);
when(() => authenticationRepository.cubitStatus).thenAnswer(
(_) => Stream.value(AuthCubitStatus.started),
);
},
build: () => AuthenticationCubit(
authenticationRepository: authenticationRepository,
)..init(),
seed: () => const AuthenticationState.unknown(),
expect: () => [const AuthenticationState<Never>.unauthenticated()],
);
});
group('LogoutRequested', () {
blocTest<AuthenticationCubit<void>, AuthenticationState<void>>(
'invokes signOut',
setUp: () {
when(
() => authenticationRepository.signOut(),
).thenAnswer((_) async {});
},
build: () => AuthenticationCubit(
authenticationRepository: authenticationRepository,
),
act: (cubit) => cubit.logOut(),
seed: () => const AuthenticationState.unknown(),
expect: () => [AuthenticationState<int>.authenticated(wrapper)],
);
blocTest<AuthenticationCubit<int>, AuthenticationState<int>>(
'emits unauthenticated when account stream is empty',
setUp: () {
when(
() => authenticationRepository.destroyCache(),
).thenAnswer((_) async => const Ok(null));
when(() => authenticationRepository.streamAccount()).thenAnswer(
(_) => Stream.fromIterable([
Future.value(
Ok(AccountWrapperModel(null, 1)),
)
]),
);
},
build: () => AuthenticationCubit(
authenticationRepository: authenticationRepository,
),
seed: () => const AuthenticationState.unknown(),
expect: () => [const AuthenticationState<int>.unauthenticated()],
);
blocTest<AuthenticationCubit<int>, AuthenticationState<int>>(
'emits unauthenticated when there is an error in stream',
setUp: () {
when(
() => authenticationRepository.destroyCache(),
).thenAnswer((_) async => const Ok(null));
when(() => authenticationRepository.streamAccount()).thenAnswer(
(_) => Stream.fromIterable([
Future.value(
Err(ServerException()),
)
]),
);
},
build: () => AuthenticationCubit(
authenticationRepository: authenticationRepository,
),
seed: () => const AuthenticationState.unknown(),
expect: () => [const AuthenticationState<int>.unauthenticated()],
);
});
group('SignOut', () {
blocTest<AuthenticationCubit<int>, AuthenticationState<int>>(
'invokes signOut',
setUp: () {
when(
() => authenticationRepository.signOut(),
).thenAnswer((_) async => const Ok(null));
},
build: () => AuthenticationCubit(
authenticationRepository: authenticationRepository,
),
act: (cubit) => cubit.signOut(),
verify: (_) {
verify(() => authenticationRepository.signOut()).called(1);
},
@@ -18,7 +18,7 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
class MockUser extends Mock implements User {}
class MockAccount extends Mock implements Account {}
void main() {
group('AuthenticationState', () {
@@ -27,29 +27,33 @@ void main() {
const AuthenticationState<void> state =
AuthenticationState.unauthenticated();
expect(state.status, AuthenticationStatus.unauthenticated);
expect(state.user, null);
expect(state.accountWrapper, null);
});
});
group('authenticated', () {
test('has correct status', () {
final MockUser user = MockUser();
final MockAccount account = MockAccount();
final AuthenticationState<void> state =
AuthenticationState.authenticated(user, null);
AuthenticationState.authenticated(
AccountWrapperModel<void>(account, null),
);
expect(state.status, AuthenticationStatus.authenticated);
expect(state.user, user);
expect(state.accountWrapper?.account, account);
});
});
group('authenticated with extra data', () {
test('has correct status', () {
final MockUser user = MockUser();
final MockAccount account = MockAccount();
const String extra = 'AwesomeExtraData';
final AuthenticationState<String> state =
AuthenticationState.authenticated(user, extra);
AuthenticationState.authenticated(
AccountWrapperModel(account, extra),
);
expect(state.status, AuthenticationStatus.authenticated);
expect(state.user, user);
expect(state.extra, extra);
expect(state.accountWrapper?.account, account);
expect(state.accountWrapper?.data, extra);
});
});
});