Shuffle/app/test/features/auth/data/auth_status_tracker_test.dart
cschlaefke 54337ffc59 feat(auth): add auth domain, repository, validators and router redirects
Refs #1

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-03 00:09:47 +01:00

105 lines
3.4 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
import 'package:shuffle/features/auth/data/auth_status_tracker.dart';
import 'package:shuffle/features/auth/domain/auth_status.dart';
import 'package:shuffle/features/auth/domain/auth_user.dart';
import 'package:supabase_flutter/supabase_flutter.dart' hide AuthUser;
import 'auth_test_support.dart';
void main() {
group('KTO-01 Kriterium 5: AuthStatusTracker event mapping', () {
test('no session -> signedOut', () {
final tracker = AuthStatusTracker();
expect(tracker.statusFor(null), const AuthStatus.signedOut());
expect(
tracker.handle(AuthChangeEvent.initialSession, null),
const AuthStatus.signedOut(),
);
});
test(
'signedIn, tokenRefreshed, userUpdated, initialSession -> signedIn',
() {
final tracker = AuthStatusTracker();
const user = AuthUser(
id: 'user-1',
email: 'anna@example.com',
emailConfirmed: true,
);
for (final event in [
AuthChangeEvent.initialSession,
AuthChangeEvent.signedIn,
AuthChangeEvent.tokenRefreshed,
AuthChangeEvent.userUpdated,
]) {
expect(
tracker.handle(event, testSession()),
const AuthStatus.signedIn(user),
reason: event.name,
);
}
},
);
test('unconfirmed email is reflected in the user', () {
final status = AuthStatusTracker().handle(
AuthChangeEvent.signedIn,
testSession(user: testUser(confirmed: false)),
);
expect((status as SignedIn).user.emailConfirmed, isFalse);
});
test('signedOut -> signedOut', () {
final tracker = AuthStatusTracker()
..handle(AuthChangeEvent.signedIn, testSession());
expect(
tracker.handle(AuthChangeEvent.signedOut, null),
const AuthStatus.signedOut(),
);
});
});
group('KTO-01 Kriterium 8: recovery guard (process only)', () {
test('passwordRecovery -> passwordRecovery', () {
final tracker = AuthStatusTracker();
expect(
tracker.handle(AuthChangeEvent.passwordRecovery, testSession()),
isA<PasswordRecovery>(),
);
});
test('guard survives tokenRefreshed and signedIn during recovery', () {
final tracker = AuthStatusTracker()
..handle(AuthChangeEvent.passwordRecovery, testSession());
expect(
tracker.handle(AuthChangeEvent.tokenRefreshed, testSession()),
isA<PasswordRecovery>(),
);
expect(
tracker.handle(AuthChangeEvent.signedIn, testSession()),
isA<PasswordRecovery>(),
);
expect(tracker.statusFor(testSession()), isA<PasswordRecovery>());
});
test('userUpdated (password changed) ends the recovery', () {
final tracker = AuthStatusTracker()
..handle(AuthChangeEvent.passwordRecovery, testSession());
expect(
tracker.handle(AuthChangeEvent.userUpdated, testSession()),
isA<SignedIn>(),
);
});
test('signedOut (abort) ends the recovery', () {
final tracker = AuthStatusTracker()
..handle(AuthChangeEvent.passwordRecovery, testSession());
tracker.handle(AuthChangeEvent.signedOut, null);
expect(tracker.statusFor(testSession()), isA<SignedIn>());
});
test('a fresh tracker never derives recovery from a session (reload)', () {
expect(AuthStatusTracker().statusFor(testSession()), isA<SignedIn>());
});
});
}