// Copyright (C) 2023 WYATT GROUP // Please see the AUTHORS file for details. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . 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 {} class MockAccount extends Mock implements Account {} void main() { group('AuthenticationCubit', () { final MockAccount account = MockAccount(); final AccountWrapper wrapper = AccountWrapperModel(account, 10); late AuthenticationRepository authenticationRepository; setUp(() { authenticationRepository = MockAuthenticationRepository(); when(() => authenticationRepository.streamAccount()).thenAnswer( (_) => const Stream.empty(), ); when( () => authenticationRepository.getAccount(), ).thenAnswer((_) async => Ok(account)); }); test('initial auth state is `unknown`', () { expect( AuthenticationCubit( authenticationRepository: authenticationRepository, ).state, const AuthenticationState.unknown(), ); }); group('ListenForAuthenticationChanges', () { blocTest, AuthenticationState>( 'emits authenticated when stream contains account', setUp: () { when(() => authenticationRepository.streamAccount()).thenAnswer( (_) => Stream.fromIterable([ Future.value( Ok(wrapper), ) ]), ); }, build: () => AuthenticationCubit( authenticationRepository: authenticationRepository, ), seed: () => const AuthenticationState.unknown(), expect: () => [AuthenticationState.authenticated(wrapper)], ); blocTest, AuthenticationState>( '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.unauthenticated()], ); blocTest, AuthenticationState>( '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.unauthenticated()], ); }); group('SignOut', () { blocTest, AuthenticationState>( '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); }, ); }); }); }