From 58cc6b102253c839e6347063aa7a1e185912a99a Mon Sep 17 00:00:00 2001 From: Jakes <71591438+JakesMD@users.noreply.github.com> Date: Thu, 2 Jul 2026 15:28:07 +0200 Subject: [PATCH] fix: restore auth session on app startup (#100) * fix: restore auth session on app startup * Add helpful comment --- app/lib/shared/logic/current_user_cubit.dart | 6 +- app/test/helpers/test_clients.dart | 1 + .../signin/auth_state_persistence_test.dart | 76 +++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 app/test/pages/signin/auth_state_persistence_test.dart diff --git a/app/lib/shared/logic/current_user_cubit.dart b/app/lib/shared/logic/current_user_cubit.dart index dda8ab72..3614175c 100644 --- a/app/lib/shared/logic/current_user_cubit.dart +++ b/app/lib/shared/logic/current_user_cubit.dart @@ -46,7 +46,11 @@ class CCurrentUserCubit > { /// {@macro CCurrentUserCubit} CCurrentUserCubit({required this.authRepository}) - : super(const CCurrentUserState(outcome: null)); + : super( + CCurrentUserState( + outcome: BobsSuccess(BobsMaybe.from(authRepository.currentUser)), + ), + ); /// The repository this cubit uses to stream the auth user. final CAuthRepository authRepository; diff --git a/app/test/helpers/test_clients.dart b/app/test/helpers/test_clients.dart index 9bd60864..12010a4d 100644 --- a/app/test/helpers/test_clients.dart +++ b/app/test/helpers/test_clients.dart @@ -19,6 +19,7 @@ class MockCStorageClient extends Mock implements CStorageClient {} class CTestClients { CTestClients() { + when(() => authClient.currentUser).thenReturn(null); when(authClient.currentUserStream).thenAnswer( (_) => BobsStream( stream: () => Stream.value(bobsSuccess(bobsAbsent())), diff --git a/app/test/pages/signin/auth_state_persistence_test.dart b/app/test/pages/signin/auth_state_persistence_test.dart new file mode 100644 index 00000000..f10443ef --- /dev/null +++ b/app/test/pages/signin/auth_state_persistence_test.dart @@ -0,0 +1,76 @@ +import 'package:bobs_jobs/bobs_jobs.dart'; +import 'package:cauth_client/cauth_client.dart'; +import 'package:cdatabase_client/cdatabase_client.dart'; +import 'package:chuckle_chest/pages/get_started/page.dart'; +import 'package:chuckle_chest/pages/signin/page.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:test_beautifier/test_beautifier.dart'; + +import '../../helpers/helpers.dart'; + +const _fakeRawUser = CRawAuthUser( + id: 'user-1', + username: 'testuser', + email: 'test@example.com', + chests: [], +); + +void _setupPersistedSession(CTestClients clients) { + when(() => clients.authClient.currentUser).thenReturn(_fakeRawUser); + when(clients.authClient.currentUserStream).thenAnswer( + (_) => BobsStream( + stream: () => Stream.value(bobsSuccess(bobsPresent(_fakeRawUser))), + ), + ); + when( + clients.authClient.refreshSession, + ).thenReturn(bobsFakeSuccessJob(bobsNothing)); +} + +void main() { + group('Auth State Persistence Tests', () { + late CTestClients clients; + + setUp(() { + clients = CTestClients(); + }); + + testWidgets( + requirement( + given: 'user has a persisted signed-in session', + whenever: 'app starts', + then: 'skips signin and shows authenticated page', + why: 'closing the app must not log the user out', + ), + (tester) async { + _setupPersistedSession(clients); + // CGetStartedPage calls fetchUserInvitations on init. + when( + () => clients.chestClient.fetchUserInvitations( + email: any(named: 'email'), + ), + ).thenReturn(bobsFakeSuccessJob([])); + + await tester.pumpChuckleChestApp(clients: clients); + + expect(find.byType(CSigninPage), findsNothing); + expect(find.byType(CGetStartedPage), findsOneWidget); + }, + ); + + testWidgets( + requirement( + given: 'user has no persisted session', + whenever: 'app starts', + then: 'shows signin page', + why: 'unauthenticated users must be directed to sign in', + ), + (tester) async { + await tester.pumpChuckleChestApp(clients: clients); + + expect(find.byType(CSigninPage), findsOneWidget); + }, + ); + }); +}