// 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 {} class TestAuthenticationCubit extends AuthenticationCubit { TestAuthenticationCubit({required super.authenticationRepository}); @override FutureOrResult onDelete() async => const Ok(null); @override FutureOrResult onReauthenticate( Result result, ) async => const Ok(null); @override FutureOrResult onRefresh(Result result) async => const Ok(null); @override FutureOrResult onSignInFromCache(SessionWrapper wrapper) async => const Ok(null); @override FutureOrResult onSignOut() async => const Ok(null); } void main() { group('AuthenticationCubit', () { final MockAccount account = MockAccount(); final SessionWrapper wrapper = SessionWrapper( event: const UnknownAuthenticationEvent(), session: Session(account: account, data: 10), ); late AuthenticationRepository authenticationRepository; setUp(() { authenticationRepository = MockAuthenticationRepository(); when(() => authenticationRepository.sessionStream()).thenAnswer( (_) => const Stream.empty(), ); }); test('initial auth state is `unknown`', () { expect( TestAuthenticationCubit( authenticationRepository: authenticationRepository, ).state, const AuthenticationState.unknown(), ); }); group('ListenForAuthenticationChanges', () { blocTest, AuthenticationState>( 'emits authenticated when stream contains session', setUp: () { when(() => authenticationRepository.sessionStream()).thenAnswer( (_) => Stream.fromIterable([wrapper]), ); }, build: () => TestAuthenticationCubit( authenticationRepository: authenticationRepository, ), seed: () => const AuthenticationState.unknown(), expect: () => [AuthenticationState.authenticated(wrapper)], ); blocTest, AuthenticationState>( 'emits unauthenticated when account stream is empty', setUp: () { when(() => authenticationRepository.sessionStream()).thenAnswer( (_) => Stream.fromIterable( [const SessionWrapper(event: SignedOutEvent())],), ); }, build: () => TestAuthenticationCubit( 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: () => TestAuthenticationCubit( authenticationRepository: authenticationRepository, ), act: (cubit) => cubit.signOut(), verify: (_) { verify(() => authenticationRepository.signOut()).called(1); }, ); }); }); }