import 'package:flutter_test/flutter_test.dart'; import 'package:tatlock_ui/core/auth/auth_state.dart'; import 'package:tatlock_ui/core/auth/permissions.dart'; import 'package:tatlock_ui/core/auth/user_preferences.dart'; void main() { group('AuthState', () { group('default constructor', () { test('creates unauthenticated state by default', () { const state = AuthState(); expect(state.isAuthenticated, isFalse); expect(state.accessToken, isNull); expect(state.refreshToken, isNull); expect(state.expiresAt, isNull); expect(state.userId, isNull); expect(state.userName, isNull); expect(state.userEmail, isNull); expect(state.roles, isEmpty); expect(state.preferences, isNull); }); }); group('authenticated state', () { test('stores all user data', () { final expiresAt = DateTime.now().add(const Duration(hours: 1)); const preferences = UserPreferences( theme: 'dark', defaultRoom: 'kitchen', ); final state = AuthState( isAuthenticated: true, accessToken: 'access_token', refreshToken: 'refresh_token', expiresAt: expiresAt, userId: 'user-123', authentikId: 'authentik-456', userName: 'Test User', userEmail: 'test@example.com', avatarUrl: 'https://example.com/avatar.jpg', roles: const [ Role( id: '1', name: 'admin.general:admin', domain: Domain.admin, category: 'general', action: Action.admin, ), ], preferences: preferences, ); expect(state.isAuthenticated, isTrue); expect(state.accessToken, equals('access_token')); expect(state.refreshToken, equals('refresh_token')); expect(state.expiresAt, equals(expiresAt)); expect(state.userId, equals('user-123')); expect(state.authentikId, equals('authentik-456')); expect(state.userName, equals('Test User')); expect(state.userEmail, equals('test@example.com')); expect(state.avatarUrl, equals('https://example.com/avatar.jpg')); expect(state.roles.length, equals(1)); expect(state.preferences?.theme, equals('dark')); }); }); group('isTokenExpired', () { test('returns true when expiresAt is null', () { const state = AuthState(isAuthenticated: true); expect(state.isTokenExpired, isTrue); }); test('returns true when token is expired', () { final expiredTime = DateTime.now().subtract(const Duration(hours: 1)); final state = AuthState( isAuthenticated: true, expiresAt: expiredTime, ); expect(state.isTokenExpired, isTrue); }); test('returns true when token expires within 1 minute', () { final soonExpires = DateTime.now().add(const Duration(seconds: 30)); final state = AuthState( isAuthenticated: true, expiresAt: soonExpires, ); expect(state.isTokenExpired, isTrue); }); test('returns false when token is valid', () { final futureExpires = DateTime.now().add(const Duration(hours: 1)); final state = AuthState( isAuthenticated: true, expiresAt: futureExpires, ); expect(state.isTokenExpired, isFalse); }); }); group('hasPermission', () { test('returns true when role grants permission', () { const state = AuthState( isAuthenticated: true, roles: [ Role( id: '1', name: 'control-room.general:admin', domain: Domain.controlRoom, category: 'general', action: Action.admin, ), ], ); expect(state.hasPermission(Domain.controlRoom, Action.admin), isTrue); expect(state.hasPermission(Domain.controlRoom, Action.viewer), isTrue); }); test('returns false when no role grants permission', () { const state = AuthState( isAuthenticated: true, roles: [ Role( id: '1', name: 'media.general:viewer', domain: Domain.media, category: 'general', action: Action.viewer, ), ], ); expect(state.hasPermission(Domain.controlRoom, Action.viewer), isFalse); expect(state.hasPermission(Domain.media, Action.admin), isFalse); }); test('respects category parameter', () { const state = AuthState( isAuthenticated: true, roles: [ Role( id: '1', name: 'control-room.servers:admin', domain: Domain.controlRoom, category: 'servers', action: Action.admin, ), ], ); expect( state.hasPermission( Domain.controlRoom, Action.admin, category: 'servers', ), isTrue, ); expect( state.hasPermission( Domain.controlRoom, Action.admin, category: 'general', ), isFalse, ); }); test('returns false for empty roles list', () { const state = AuthState(isAuthenticated: true, roles: []); expect(state.hasPermission(Domain.controlRoom, Action.viewer), isFalse); }); }); group('isGlobalAdmin', () { test('returns true when user has admin.general:admin role', () { const state = AuthState( isAuthenticated: true, roles: [ Role( id: '1', name: 'admin.general:admin', domain: Domain.admin, category: 'general', action: Action.admin, ), ], ); expect(state.isGlobalAdmin, isTrue); }); test('returns false when user lacks admin role', () { const state = AuthState( isAuthenticated: true, roles: [ Role( id: '1', name: 'control-room.general:admin', domain: Domain.controlRoom, category: 'general', action: Action.admin, ), ], ); expect(state.isGlobalAdmin, isFalse); }); test('returns false for empty roles list', () { const state = AuthState(isAuthenticated: true, roles: []); expect(state.isGlobalAdmin, isFalse); }); }); group('copyWith', () { test('creates a copy with modified values', () { const original = AuthState( isAuthenticated: true, accessToken: 'old_token', userName: 'Original User', ); final updated = original.copyWith( accessToken: 'new_token', userName: 'Updated User', ); // Original unchanged expect(original.accessToken, equals('old_token')); expect(original.userName, equals('Original User')); // Updated has new values expect(updated.accessToken, equals('new_token')); expect(updated.userName, equals('Updated User')); // Preserved unchanged values expect(updated.isAuthenticated, equals(original.isAuthenticated)); }); }); group('equality', () { test('two identical states are equal', () { const state1 = AuthState( isAuthenticated: true, userId: 'user-123', userName: 'Test User', ); const state2 = AuthState( isAuthenticated: true, userId: 'user-123', userName: 'Test User', ); expect(state1, equals(state2)); }); test('different states are not equal', () { const state1 = AuthState( isAuthenticated: true, userId: 'user-123', ); const state2 = AuthState( isAuthenticated: true, userId: 'user-456', ); expect(state1, isNot(equals(state2))); }); }); }); }