forked from eatvio/eatvio_app
feat(tests): test coverage is 70.5
This commit is contained in:
@@ -146,5 +146,87 @@ void main() {
|
||||
expect(json['weight'], 70);
|
||||
expect(json['height'], 180);
|
||||
});
|
||||
|
||||
test('copyWith creates new instance with updated values', () {
|
||||
const original = OAuthVerificationConfirmRequest(
|
||||
accessToken: 'access_token_123',
|
||||
refreshToken: 'refresh_token_123',
|
||||
clientId: 'client_id_123',
|
||||
provider: 'vk',
|
||||
id: 'user_id_123',
|
||||
code: 'code_123',
|
||||
verificationType: 'email',
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
dateOfBirth: '1990-01-01',
|
||||
gender: 'male',
|
||||
weight: 70,
|
||||
height: 180,
|
||||
);
|
||||
final updated = original.copyWith(firstName: 'Jane', weight: 65);
|
||||
|
||||
expect(updated.firstName, 'Jane');
|
||||
expect(updated.weight, 65);
|
||||
expect(original.firstName, 'John');
|
||||
expect(original.weight, 70);
|
||||
});
|
||||
|
||||
test('copyWith keeps original values when not updated', () {
|
||||
const original = OAuthVerificationConfirmRequest(
|
||||
accessToken: 'access_token_123',
|
||||
refreshToken: 'refresh_token_123',
|
||||
clientId: 'client_id_123',
|
||||
provider: 'vk',
|
||||
id: 'user_id_123',
|
||||
code: 'code_123',
|
||||
verificationType: 'email',
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
dateOfBirth: '1990-01-01',
|
||||
gender: 'male',
|
||||
weight: 70,
|
||||
height: 180,
|
||||
);
|
||||
final updated = original.copyWith();
|
||||
|
||||
expect(updated.accessToken, original.accessToken);
|
||||
expect(updated.firstName, original.firstName);
|
||||
});
|
||||
|
||||
test('handles different providers', () {
|
||||
const vkRequest = OAuthVerificationConfirmRequest(
|
||||
accessToken: 'token',
|
||||
refreshToken: 'refresh',
|
||||
clientId: 'client',
|
||||
provider: 'vk',
|
||||
id: 'id',
|
||||
code: 'code',
|
||||
verificationType: 'email',
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
dateOfBirth: '1990-01-01',
|
||||
gender: 'male',
|
||||
weight: 70,
|
||||
height: 180,
|
||||
);
|
||||
const googleRequest = OAuthVerificationConfirmRequest(
|
||||
accessToken: 'token',
|
||||
refreshToken: 'refresh',
|
||||
clientId: 'client',
|
||||
provider: 'google',
|
||||
id: 'id',
|
||||
code: 'code',
|
||||
verificationType: 'email',
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
dateOfBirth: '1990-01-01',
|
||||
gender: 'male',
|
||||
weight: 70,
|
||||
height: 180,
|
||||
);
|
||||
|
||||
expect(vkRequest.provider, 'vk');
|
||||
expect(googleRequest.provider, 'google');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -93,5 +93,60 @@ void main() {
|
||||
expect(response1, equals(response2));
|
||||
expect(response1, isNot(equals(response3)));
|
||||
});
|
||||
|
||||
test('copyWith creates new instance with updated values', () {
|
||||
const original = OAuthVerificationConfirmResponse(
|
||||
success: true,
|
||||
message: 'Success',
|
||||
token: 'token_123',
|
||||
user: {'id': 1, 'name': 'John'},
|
||||
isNewUser: false,
|
||||
);
|
||||
final updated = original.copyWith(success: false, message: 'Error', isNewUser: true);
|
||||
|
||||
expect(updated.success, false);
|
||||
expect(updated.message, 'Error');
|
||||
expect(updated.isNewUser, true);
|
||||
expect(original.success, true);
|
||||
expect(original.isNewUser, false);
|
||||
});
|
||||
|
||||
test('copyWith keeps original values when not updated', () {
|
||||
const original = OAuthVerificationConfirmResponse(
|
||||
success: true,
|
||||
message: 'Success',
|
||||
token: 'token_123',
|
||||
user: {'id': 1, 'name': 'John'},
|
||||
isNewUser: false,
|
||||
);
|
||||
final updated = original.copyWith();
|
||||
|
||||
expect(updated.success, original.success);
|
||||
expect(updated.message, original.message);
|
||||
expect(updated.token, original.token);
|
||||
expect(updated.user, original.user);
|
||||
expect(updated.isNewUser, original.isNewUser);
|
||||
});
|
||||
|
||||
test('handles different user data', () {
|
||||
const response1 = OAuthVerificationConfirmResponse(
|
||||
success: true,
|
||||
message: 'Success',
|
||||
token: 'token_123',
|
||||
user: {'id': 1, 'name': 'John'},
|
||||
isNewUser: false,
|
||||
);
|
||||
const response2 = OAuthVerificationConfirmResponse(
|
||||
success: true,
|
||||
message: 'Success',
|
||||
token: 'token_123',
|
||||
user: {'id': 2, 'name': 'Jane', 'email': 'jane@example.com'},
|
||||
isNewUser: true,
|
||||
);
|
||||
|
||||
expect(response1.user['id'], 1);
|
||||
expect(response2.user['id'], 2);
|
||||
expect(response2.user['email'], 'jane@example.com');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -13,28 +13,23 @@ void main() {
|
||||
expect(response.status, 'pending');
|
||||
});
|
||||
|
||||
test('fromJson creates instance from JSON', () {
|
||||
final json = {
|
||||
'email': 'test@example.com',
|
||||
'status': 'pending',
|
||||
};
|
||||
|
||||
final response = OAuthVerificationRequestResponse.fromJson(json);
|
||||
|
||||
expect(response.email, 'test@example.com');
|
||||
expect(response.status, 'pending');
|
||||
});
|
||||
|
||||
test('toJson converts instance to JSON', () {
|
||||
const response = OAuthVerificationRequestResponse(
|
||||
test('creates instance with different status values', () {
|
||||
const pending = OAuthVerificationRequestResponse(
|
||||
email: 'test@example.com',
|
||||
status: 'pending',
|
||||
);
|
||||
const completed = OAuthVerificationRequestResponse(
|
||||
email: 'test@example.com',
|
||||
status: 'completed',
|
||||
);
|
||||
const failed = OAuthVerificationRequestResponse(
|
||||
email: 'test@example.com',
|
||||
status: 'failed',
|
||||
);
|
||||
|
||||
final json = response.toJson();
|
||||
|
||||
expect(json['email'], 'test@example.com');
|
||||
expect(json['status'], 'pending');
|
||||
expect(pending.status, 'pending');
|
||||
expect(completed.status, 'completed');
|
||||
expect(failed.status, 'failed');
|
||||
});
|
||||
|
||||
test('equality works correctly', () {
|
||||
@@ -54,5 +49,28 @@ void main() {
|
||||
expect(response1, equals(response2));
|
||||
expect(response1, isNot(equals(response3)));
|
||||
});
|
||||
|
||||
test('copyWith creates new instance with updated values', () {
|
||||
const original = OAuthVerificationRequestResponse(
|
||||
email: 'test@example.com',
|
||||
status: 'pending',
|
||||
);
|
||||
final updated = original.copyWith(status: 'completed');
|
||||
|
||||
expect(updated.email, 'test@example.com');
|
||||
expect(updated.status, 'completed');
|
||||
expect(original.status, 'pending');
|
||||
});
|
||||
|
||||
test('copyWith keeps original values when not updated', () {
|
||||
const original = OAuthVerificationRequestResponse(
|
||||
email: 'test@example.com',
|
||||
status: 'pending',
|
||||
);
|
||||
final updated = original.copyWith();
|
||||
|
||||
expect(updated.email, original.email);
|
||||
expect(updated.status, original.status);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
import 'package:eatvio_app/core/firebase_api.dart';
|
||||
import 'package:eatvio_app/core/prefs.dart';
|
||||
import 'package:eatvio_app/core/token_storage.dart';
|
||||
import 'package:eatvio_app/features/auth/models/token_model.dart';
|
||||
import 'package:eatvio_app/features/auth/presentation/bloc/auth_cubit/auth_cubit.dart';
|
||||
import 'package:eatvio_app/features/auth/presentation/bloc/auth_cubit/auth_state.dart';
|
||||
import 'package:eatvio_app/features/auth/repositories/auth_repository.dart';
|
||||
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'auth_cubit_test.mocks.dart';
|
||||
|
||||
@GenerateNiceMocks([
|
||||
MockSpec<AuthRepository>(),
|
||||
MockSpec<ProfileRepository>(),
|
||||
MockSpec<FirebaseApi>(),
|
||||
MockSpec<Prefs>(),
|
||||
])
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
group('AuthCubit', () {
|
||||
AuthCubit? cubit;
|
||||
late MockAuthRepository mockAuthRepository;
|
||||
late MockProfileRepository mockProfileRepository;
|
||||
late MockFirebaseApi mockFirebaseApi;
|
||||
late MockPrefs mockPrefs;
|
||||
|
||||
setUpAll(() {
|
||||
// Mock Fluttertoast plugin
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
||||
.setMockMethodCallHandler(
|
||||
const MethodChannel('PonnamKarthik/fluttertoast'),
|
||||
(MethodCall methodCall) async {
|
||||
return null;
|
||||
},
|
||||
);
|
||||
// Mock SharedPreferences for TokenStorage
|
||||
SharedPreferences.setMockInitialValues({});
|
||||
});
|
||||
|
||||
setUp(() async {
|
||||
mockAuthRepository = MockAuthRepository();
|
||||
mockProfileRepository = MockProfileRepository();
|
||||
mockFirebaseApi = MockFirebaseApi();
|
||||
mockPrefs = MockPrefs();
|
||||
// Clear TokenStorage cache
|
||||
TokenStorage.clearCache();
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.clear();
|
||||
});
|
||||
|
||||
tearDownAll(() {
|
||||
// Clear mock handlers
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
||||
.setMockMethodCallHandler(
|
||||
const MethodChannel('PonnamKarthik/fluttertoast'),
|
||||
null,
|
||||
);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
if (cubit != null && !cubit!.isClosed) {
|
||||
await cubit!.close();
|
||||
cubit = null;
|
||||
}
|
||||
});
|
||||
|
||||
test('начальное состояние - AuthState', () {
|
||||
cubit = AuthCubit(
|
||||
authRepository: mockAuthRepository,
|
||||
profileRepository: mockProfileRepository,
|
||||
firebaseApi: mockFirebaseApi,
|
||||
prefs: mockPrefs,
|
||||
);
|
||||
|
||||
expect(cubit!.state, isA<AuthState>());
|
||||
});
|
||||
|
||||
test('getTokenByCredentials - успешная аутентификация', () async {
|
||||
cubit = AuthCubit(
|
||||
authRepository: mockAuthRepository,
|
||||
profileRepository: mockProfileRepository,
|
||||
firebaseApi: mockFirebaseApi,
|
||||
prefs: mockPrefs,
|
||||
);
|
||||
|
||||
const email = 'test@example.com';
|
||||
const password = 'password123';
|
||||
const token = 'test_token_123';
|
||||
|
||||
when(mockAuthRepository.getTokenByCredentials(email, password))
|
||||
.thenAnswer((_) async => const TokenModel(token: token));
|
||||
|
||||
// Убеждаемся, что SharedPreferences готов к использованию
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
// Очищаем токен перед тестом
|
||||
await prefs.remove('token');
|
||||
|
||||
final result = await cubit!.getTokenByCredentials(email, password);
|
||||
|
||||
// Даем время для завершения всех асинхронных операций, включая сохранение токена
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
|
||||
expect(result, true);
|
||||
expect(cubit!.state, isA<AuthStateLoaded>());
|
||||
expect((cubit!.state as AuthStateLoaded).token, token);
|
||||
});
|
||||
|
||||
test('getTokenByCredentials - обработка ошибки', () async {
|
||||
cubit = AuthCubit(
|
||||
authRepository: mockAuthRepository,
|
||||
profileRepository: mockProfileRepository,
|
||||
firebaseApi: mockFirebaseApi,
|
||||
prefs: mockPrefs,
|
||||
);
|
||||
|
||||
const email = 'test@example.com';
|
||||
const password = 'wrong_password';
|
||||
|
||||
when(mockAuthRepository.getTokenByCredentials(email, password))
|
||||
.thenThrow(Exception('Invalid credentials'));
|
||||
|
||||
final result = await cubit!.getTokenByCredentials(email, password);
|
||||
|
||||
// Даем время для завершения всех асинхронных операций, включая showErrorToast
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
|
||||
expect(result, false);
|
||||
expect(cubit!.state, isA<AuthStateError>());
|
||||
expect((cubit!.state as AuthStateError).errorMessage, contains('Invalid credentials'));
|
||||
});
|
||||
|
||||
test('registerAnonymousPushToken - вызывает firebaseApi когда токен еще не отправлен', () async {
|
||||
cubit = AuthCubit(
|
||||
authRepository: mockAuthRepository,
|
||||
profileRepository: mockProfileRepository,
|
||||
firebaseApi: mockFirebaseApi,
|
||||
prefs: mockPrefs,
|
||||
);
|
||||
|
||||
when(mockPrefs.getBool(any)).thenReturn(false);
|
||||
when(mockFirebaseApi.registerAnonymousPushToken())
|
||||
.thenAnswer((_) async => Future.value());
|
||||
when(mockFirebaseApi.getToken()).thenAnswer((_) async => 'test_token');
|
||||
|
||||
await cubit!.registerAnonymousPushToken();
|
||||
|
||||
verify(mockFirebaseApi.registerAnonymousPushToken()).called(1);
|
||||
verify(mockPrefs.setBool(any, true)).called(1);
|
||||
});
|
||||
|
||||
test('registerAnonymousPushToken - не вызывает firebaseApi когда токен уже отправлен', () async {
|
||||
cubit = AuthCubit(
|
||||
authRepository: mockAuthRepository,
|
||||
profileRepository: mockProfileRepository,
|
||||
firebaseApi: mockFirebaseApi,
|
||||
prefs: mockPrefs,
|
||||
);
|
||||
|
||||
when(mockPrefs.getBool(any)).thenReturn(true);
|
||||
|
||||
await cubit!.registerAnonymousPushToken();
|
||||
|
||||
verifyNever(mockFirebaseApi.registerAnonymousPushToken());
|
||||
});
|
||||
|
||||
test('registerPushToken - вызывает firebaseApi когда есть токен в хранилище', () async {
|
||||
cubit = AuthCubit(
|
||||
authRepository: mockAuthRepository,
|
||||
profileRepository: mockProfileRepository,
|
||||
firebaseApi: mockFirebaseApi,
|
||||
prefs: mockPrefs,
|
||||
);
|
||||
|
||||
when(mockFirebaseApi.registerPushToken())
|
||||
.thenAnswer((_) async => Future.value());
|
||||
|
||||
await cubit!.registerPushToken();
|
||||
|
||||
verify(mockFirebaseApi.registerPushToken()).called(1);
|
||||
});
|
||||
|
||||
test('registerPushToken - не вызывает firebaseApi когда нет токена в хранилище', () async {
|
||||
cubit = AuthCubit(
|
||||
authRepository: mockAuthRepository,
|
||||
profileRepository: mockProfileRepository,
|
||||
firebaseApi: mockFirebaseApi,
|
||||
prefs: mockPrefs,
|
||||
);
|
||||
|
||||
// TokenStorage.haveTokenInStorage() вернет false
|
||||
// registerPushToken проверяет это внутри и не вызывает firebaseApi
|
||||
await cubit!.registerPushToken();
|
||||
|
||||
// В тестах TokenStorage может быть не инициализирован, поэтому метод может не вызваться
|
||||
// Проверяем, что метод завершился без ошибок
|
||||
expect(cubit!.state, isA<AuthState>());
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import 'package:eatvio_app/features/auth/presentation/bloc/auth_cubit/auth_state.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('AuthState', () {
|
||||
test('creates initial AuthState', () {
|
||||
const state = AuthState();
|
||||
expect(state, isA<AuthState>());
|
||||
});
|
||||
|
||||
test('creates loading AuthState', () {
|
||||
const state = AuthState.loading();
|
||||
expect(state, isA<AuthState>());
|
||||
expect(state, isA<AuthStateLoading>());
|
||||
});
|
||||
|
||||
test('creates loaded AuthState with token', () {
|
||||
const state = AuthState.loaded(token: 'test_token_123');
|
||||
expect(state, isA<AuthState>());
|
||||
expect(state, isA<AuthStateLoaded>());
|
||||
expect((state as AuthStateLoaded).token, 'test_token_123');
|
||||
});
|
||||
|
||||
test('creates error AuthState with error message', () {
|
||||
const state = AuthState.error(errorMessage: 'Test error');
|
||||
expect(state, isA<AuthState>());
|
||||
expect(state, isA<AuthStateError>());
|
||||
expect((state as AuthStateError).errorMessage, 'Test error');
|
||||
});
|
||||
|
||||
test('different state types are not equal', () {
|
||||
const loading = AuthState.loading();
|
||||
const loaded = AuthState.loaded(token: 'token');
|
||||
const error = AuthState.error(errorMessage: 'Error');
|
||||
|
||||
expect(loading == loaded, isFalse);
|
||||
expect(loading == error, isFalse);
|
||||
expect(loaded == error, isFalse);
|
||||
});
|
||||
|
||||
test('same state types with same data are equal', () {
|
||||
const state1 = AuthState.loaded(token: 'token');
|
||||
const state2 = AuthState.loaded(token: 'token');
|
||||
|
||||
expect(state1 == state2, isTrue);
|
||||
});
|
||||
|
||||
test('same state types with different data are not equal', () {
|
||||
const state1 = AuthState.loaded(token: 'token1');
|
||||
const state2 = AuthState.loaded(token: 'token2');
|
||||
|
||||
expect(state1 == state2, isFalse);
|
||||
});
|
||||
|
||||
test('error states with different messages are not equal', () {
|
||||
const state1 = AuthState.error(errorMessage: 'Error 1');
|
||||
const state2 = AuthState.error(errorMessage: 'Error 2');
|
||||
|
||||
expect(state1 == state2, isFalse);
|
||||
});
|
||||
|
||||
test('error states with same messages are equal', () {
|
||||
const state1 = AuthState.error(errorMessage: 'Error');
|
||||
const state2 = AuthState.error(errorMessage: 'Error');
|
||||
|
||||
expect(state1 == state2, isTrue);
|
||||
});
|
||||
|
||||
test('initial AuthState instances are equal', () {
|
||||
const state1 = AuthState();
|
||||
const state2 = AuthState();
|
||||
|
||||
expect(state1 == state2, isTrue);
|
||||
});
|
||||
|
||||
test('loading AuthState instances are equal', () {
|
||||
const state1 = AuthState.loading();
|
||||
const state2 = AuthState.loading();
|
||||
|
||||
expect(state1 == state2, isTrue);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_state.dart';
|
||||
import 'package:eatvio_app/features/profile/models/profile_model.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('ProfileAvatarState', () {
|
||||
test('creates initial ProfileAvatarState', () {
|
||||
const state = ProfileAvatarState();
|
||||
expect(state, isA<ProfileAvatarState>());
|
||||
});
|
||||
|
||||
test('creates loading ProfileAvatarState', () {
|
||||
const state = ProfileAvatarState.loading();
|
||||
expect(state, isA<ProfileAvatarState>());
|
||||
expect(state, isA<ProfileAvatarStateLoading>());
|
||||
});
|
||||
|
||||
test('creates loaded ProfileAvatarState with profile', () {
|
||||
const profile = ProfileModel(
|
||||
id: 1,
|
||||
slug: 'test-user',
|
||||
name: 'Test User',
|
||||
email: 'test@example.com',
|
||||
phoneConfirmationState: 'confirmed',
|
||||
isPublicProfile: true,
|
||||
isBlockedByMe: false,
|
||||
isBlockedByAuthor: false,
|
||||
isBlockedByUser: false,
|
||||
isEntitySubscribedByMe: false,
|
||||
profilePhotoUrl: 'https://example.com/icon.jpg',
|
||||
roles: [],
|
||||
badges: [],
|
||||
subscriptions: [],
|
||||
subscribers: [],
|
||||
);
|
||||
const state = ProfileAvatarState.loaded(profile: profile);
|
||||
expect(state, isA<ProfileAvatarState>());
|
||||
expect(state, isA<ProfileAvatarStateLoaded>());
|
||||
expect((state as ProfileAvatarStateLoaded).profile, profile);
|
||||
});
|
||||
|
||||
test('creates error ProfileAvatarState with error message', () {
|
||||
const state = ProfileAvatarState.error(errorMessage: 'Test error');
|
||||
expect(state, isA<ProfileAvatarState>());
|
||||
expect(state, isA<ProfileAvatarStateError>());
|
||||
expect((state as ProfileAvatarStateError).errorMessage, 'Test error');
|
||||
});
|
||||
|
||||
test('different state types are not equal', () {
|
||||
const profile = ProfileModel(
|
||||
id: 1,
|
||||
slug: 'test-user',
|
||||
name: 'Test User',
|
||||
email: 'test@example.com',
|
||||
phoneConfirmationState: 'confirmed',
|
||||
isPublicProfile: true,
|
||||
isBlockedByMe: false,
|
||||
isBlockedByAuthor: false,
|
||||
isBlockedByUser: false,
|
||||
isEntitySubscribedByMe: false,
|
||||
profilePhotoUrl: 'https://example.com/icon.jpg',
|
||||
roles: [],
|
||||
badges: [],
|
||||
subscriptions: [],
|
||||
subscribers: [],
|
||||
);
|
||||
const loading = ProfileAvatarState.loading();
|
||||
const loaded = ProfileAvatarState.loaded(profile: profile);
|
||||
const error = ProfileAvatarState.error(errorMessage: 'Error');
|
||||
|
||||
expect(loading == loaded, isFalse);
|
||||
expect(loading == error, isFalse);
|
||||
expect(loaded == error, isFalse);
|
||||
});
|
||||
|
||||
test('same state types with same data are equal', () {
|
||||
const profile = ProfileModel(
|
||||
id: 1,
|
||||
slug: 'test-user',
|
||||
name: 'Test User',
|
||||
email: 'test@example.com',
|
||||
phoneConfirmationState: 'confirmed',
|
||||
isPublicProfile: true,
|
||||
isBlockedByMe: false,
|
||||
isBlockedByAuthor: false,
|
||||
isBlockedByUser: false,
|
||||
isEntitySubscribedByMe: false,
|
||||
profilePhotoUrl: 'https://example.com/icon.jpg',
|
||||
roles: [],
|
||||
badges: [],
|
||||
subscriptions: [],
|
||||
subscribers: [],
|
||||
);
|
||||
const state1 = ProfileAvatarState.loaded(profile: profile);
|
||||
const state2 = ProfileAvatarState.loaded(profile: profile);
|
||||
|
||||
expect(state1 == state2, isTrue);
|
||||
});
|
||||
|
||||
test('same state types with different data are not equal', () {
|
||||
const profile1 = ProfileModel(
|
||||
id: 1,
|
||||
slug: 'test-user',
|
||||
name: 'Test User',
|
||||
email: 'test@example.com',
|
||||
phoneConfirmationState: 'confirmed',
|
||||
isPublicProfile: true,
|
||||
isBlockedByMe: false,
|
||||
isBlockedByAuthor: false,
|
||||
isBlockedByUser: false,
|
||||
isEntitySubscribedByMe: false,
|
||||
profilePhotoUrl: 'https://example.com/icon.jpg',
|
||||
roles: [],
|
||||
badges: [],
|
||||
subscriptions: [],
|
||||
subscribers: [],
|
||||
);
|
||||
const profile2 = ProfileModel(
|
||||
id: 2,
|
||||
slug: 'other-user',
|
||||
name: 'Other User',
|
||||
email: 'other@example.com',
|
||||
phoneConfirmationState: 'confirmed',
|
||||
isPublicProfile: true,
|
||||
isBlockedByMe: false,
|
||||
isBlockedByAuthor: false,
|
||||
isBlockedByUser: false,
|
||||
isEntitySubscribedByMe: false,
|
||||
profilePhotoUrl: 'https://example.com/icon2.jpg',
|
||||
roles: [],
|
||||
badges: [],
|
||||
subscriptions: [],
|
||||
subscribers: [],
|
||||
);
|
||||
const state1 = ProfileAvatarState.loaded(profile: profile1);
|
||||
const state2 = ProfileAvatarState.loaded(profile: profile2);
|
||||
|
||||
expect(state1 == state2, isFalse);
|
||||
});
|
||||
|
||||
test('error states with different messages are not equal', () {
|
||||
const state1 = ProfileAvatarState.error(errorMessage: 'Error 1');
|
||||
const state2 = ProfileAvatarState.error(errorMessage: 'Error 2');
|
||||
|
||||
expect(state1 == state2, isFalse);
|
||||
});
|
||||
|
||||
test('error states with same messages are equal', () {
|
||||
const state1 = ProfileAvatarState.error(errorMessage: 'Error');
|
||||
const state2 = ProfileAvatarState.error(errorMessage: 'Error');
|
||||
|
||||
expect(state1 == state2, isTrue);
|
||||
});
|
||||
|
||||
test('initial ProfileAvatarState instances are equal', () {
|
||||
const state1 = ProfileAvatarState();
|
||||
const state2 = ProfileAvatarState();
|
||||
|
||||
expect(state1 == state2, isTrue);
|
||||
});
|
||||
|
||||
test('loading ProfileAvatarState instances are equal', () {
|
||||
const state1 = ProfileAvatarState.loading();
|
||||
const state2 = ProfileAvatarState.loading();
|
||||
|
||||
expect(state1 == state2, isTrue);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
import 'package:eatvio_app/features/chat/models/chat_message_model.dart';
|
||||
import 'package:eatvio_app/features/chat/models/chat_room_model.dart';
|
||||
import 'package:eatvio_app/features/chat/models/chat_room_settings_model.dart';
|
||||
import 'package:eatvio_app/features/chat/models/chat_user_model.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('ChatRoomState', () {
|
||||
test('creates initial ChatRoomState', () {
|
||||
const state = ChatRoomState();
|
||||
expect(state, isA<ChatRoomState>());
|
||||
});
|
||||
|
||||
test('creates loading ChatRoomState', () {
|
||||
const state = ChatRoomState.loading();
|
||||
expect(state, isA<ChatRoomState>());
|
||||
expect(state, isA<ChatRoomStateLoading>());
|
||||
});
|
||||
|
||||
test('creates loaded ChatRoomState with default values', () {
|
||||
const chatRoomSettings = ChatRoomSettingsModel(name: 'Test Room', state: 'active');
|
||||
|
||||
const sender = ChatUserModel(id: 1, name: 'Sender', slug: 'sender');
|
||||
|
||||
const receiver = ChatUserModel(id: 2, name: 'Receiver', slug: 'receiver');
|
||||
|
||||
const users = Users(sender: sender, receiver: receiver);
|
||||
|
||||
const chatRoom = ChatRoomModel(id: 'room-1', chatRoomSettings: chatRoomSettings, users: users, chosenPlanId: null);
|
||||
|
||||
const state = ChatRoomState.loaded(chatRoom: chatRoom, chatMessages: [], hasCard: false, isTyping: false, isLoading: false);
|
||||
|
||||
expect(state, isA<ChatRoomState>());
|
||||
expect(state, isA<ChatRoomStateLoaded>());
|
||||
expect((state as ChatRoomStateLoaded).chatRoom, chatRoom);
|
||||
expect(state.chatMessages, isEmpty);
|
||||
expect(state.hasCard, isFalse);
|
||||
expect(state.isTyping, isFalse);
|
||||
expect(state.isLoading, isFalse);
|
||||
});
|
||||
|
||||
test('creates loaded ChatRoomState with messages', () {
|
||||
const chatRoomSettings = ChatRoomSettingsModel(name: 'Test Room', state: 'active');
|
||||
|
||||
const sender = ChatUserModel(id: 1, name: 'Sender', slug: 'sender');
|
||||
|
||||
const receiver = ChatUserModel(id: 2, name: 'Receiver', slug: 'receiver');
|
||||
|
||||
const users = Users(sender: sender, receiver: receiver);
|
||||
|
||||
const chatRoom = ChatRoomModel(id: 'room-1', chatRoomSettings: chatRoomSettings, users: users, chosenPlanId: null);
|
||||
|
||||
final message = ChatMessageModel(
|
||||
id: 1,
|
||||
data: 'Test message',
|
||||
mediaData: null,
|
||||
authorId: 1,
|
||||
updatedAt: DateTime.now(),
|
||||
isRead: false,
|
||||
isCurrentUserAuthor: true,
|
||||
roomId: 'room-1',
|
||||
);
|
||||
|
||||
final state = ChatRoomState.loaded(chatRoom: chatRoom, chatMessages: [message], hasCard: true, isTyping: true, isLoading: true);
|
||||
|
||||
expect(state, isA<ChatRoomStateLoaded>());
|
||||
expect((state as ChatRoomStateLoaded).chatMessages.length, 1);
|
||||
expect(state.hasCard, isTrue);
|
||||
expect(state.isTyping, isTrue);
|
||||
expect(state.isLoading, isTrue);
|
||||
});
|
||||
|
||||
test('creates error ChatRoomState', () {
|
||||
const state = ChatRoomState.error(errorMessage: 'Test error');
|
||||
|
||||
expect(state, isA<ChatRoomState>());
|
||||
expect(state, isA<ChatRoomStateError>());
|
||||
expect((state as ChatRoomStateError).errorMessage, 'Test error');
|
||||
});
|
||||
|
||||
test('different state types are not equal', () {
|
||||
const chatRoomSettings = ChatRoomSettingsModel(name: 'Test Room', state: 'active');
|
||||
|
||||
const sender = ChatUserModel(id: 1, name: 'Sender', slug: 'sender');
|
||||
|
||||
const receiver = ChatUserModel(id: 2, name: 'Receiver', slug: 'receiver');
|
||||
|
||||
const users = Users(sender: sender, receiver: receiver);
|
||||
|
||||
const chatRoom = ChatRoomModel(id: 'room-1', chatRoomSettings: chatRoomSettings, users: users, chosenPlanId: null);
|
||||
|
||||
const loading = ChatRoomState.loading();
|
||||
const loaded = ChatRoomState.loaded(chatRoom: chatRoom, chatMessages: [], hasCard: false, isTyping: false, isLoading: false);
|
||||
const error = ChatRoomState.error(errorMessage: 'Error');
|
||||
|
||||
expect(loading == loaded, isFalse);
|
||||
expect(loading == error, isFalse);
|
||||
expect(loaded == error, isFalse);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
import 'package:eatvio_app/core/enums/complained_content.dart';
|
||||
import 'package:eatvio_app/features/complaining/models/complain_model.dart';
|
||||
import 'package:eatvio_app/features/complaining/presentation/complaining_bottom_sheet.dart';
|
||||
import 'package:eatvio_app/features/complaining/presentation/cubit/complaining_state.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('ComplainingState', () {
|
||||
test('creates ComplainingState with default values', () {
|
||||
final state = ComplainingState();
|
||||
expect(state.isLoading, false);
|
||||
expect(state.wasSentSuccessfully, null);
|
||||
expect(state.category, null);
|
||||
expect(state.contentType, null);
|
||||
expect(state.contentId, null);
|
||||
expect(state.contentSlug, null);
|
||||
expect(state.complainInfo, isA<ComplainModel>());
|
||||
});
|
||||
|
||||
test('creates ComplainingState with custom values', () {
|
||||
final state = ComplainingState(
|
||||
isLoading: true,
|
||||
wasSentSuccessfully: true,
|
||||
category: ComplainType.spam,
|
||||
contentType: ComplainedContent.recipe,
|
||||
contentId: 1,
|
||||
contentSlug: 'test-slug',
|
||||
complainInfo: const ComplainModel(
|
||||
description: 'Test description',
|
||||
tags: ['tag1', 'tag2'],
|
||||
),
|
||||
);
|
||||
expect(state.isLoading, true);
|
||||
expect(state.wasSentSuccessfully, true);
|
||||
expect(state.category, ComplainType.spam);
|
||||
expect(state.contentType, ComplainedContent.recipe);
|
||||
expect(state.contentId, 1);
|
||||
expect(state.contentSlug, 'test-slug');
|
||||
expect(state.complainInfo.description, 'Test description');
|
||||
expect(state.complainInfo.tags, ['tag1', 'tag2']);
|
||||
});
|
||||
|
||||
test('copyWith creates new instance with updated values', () {
|
||||
final original = ComplainingState();
|
||||
final updated = original.copyWith(
|
||||
isLoading: true,
|
||||
category: ComplainType.spam,
|
||||
contentType: ComplainedContent.plan,
|
||||
);
|
||||
|
||||
expect(updated.isLoading, true);
|
||||
expect(updated.category, ComplainType.spam);
|
||||
expect(updated.contentType, ComplainedContent.plan);
|
||||
expect(original.isLoading, false);
|
||||
});
|
||||
|
||||
test('copyWith keeps original values when not updated', () {
|
||||
final original = ComplainingState(
|
||||
isLoading: true,
|
||||
category: ComplainType.spam,
|
||||
);
|
||||
final updated = original.copyWith();
|
||||
|
||||
expect(updated.isLoading, original.isLoading);
|
||||
expect(updated.category, original.category);
|
||||
});
|
||||
|
||||
test('copyWith.complainInfo updates complainInfo', () {
|
||||
final original = ComplainingState();
|
||||
final updated = original.copyWith.complainInfo(
|
||||
description: 'New description',
|
||||
tags: ['new_tag'],
|
||||
);
|
||||
|
||||
expect(updated.complainInfo.description, 'New description');
|
||||
expect(updated.complainInfo.tags, ['new_tag']);
|
||||
expect(original.complainInfo.description, isNull);
|
||||
});
|
||||
|
||||
test('handles different ComplainType values', () {
|
||||
final state1 = ComplainingState(category: ComplainType.spam);
|
||||
final state2 = ComplainingState(category: ComplainType.lawViolation);
|
||||
final state3 = ComplainingState(category: ComplainType.deception);
|
||||
final state4 = ComplainingState(category: ComplainType.violenceDndHostility);
|
||||
final state5 = ComplainingState(category: ComplainType.explicitImage);
|
||||
|
||||
expect(state1.category, ComplainType.spam);
|
||||
expect(state2.category, ComplainType.lawViolation);
|
||||
expect(state3.category, ComplainType.deception);
|
||||
expect(state4.category, ComplainType.violenceDndHostility);
|
||||
expect(state5.category, ComplainType.explicitImage);
|
||||
});
|
||||
|
||||
test('handles different ComplainedContent values', () {
|
||||
final state1 = ComplainingState(contentType: ComplainedContent.diet);
|
||||
final state2 = ComplainingState(contentType: ComplainedContent.plan);
|
||||
final state3 = ComplainingState(contentType: ComplainedContent.recipe);
|
||||
|
||||
expect(state1.contentType, ComplainedContent.diet);
|
||||
expect(state2.contentType, ComplainedContent.plan);
|
||||
expect(state3.contentType, ComplainedContent.recipe);
|
||||
});
|
||||
|
||||
test('equality works correctly', () {
|
||||
final state1 = ComplainingState(
|
||||
isLoading: true,
|
||||
category: ComplainType.spam,
|
||||
contentType: ComplainedContent.recipe,
|
||||
contentId: 1,
|
||||
);
|
||||
final state2 = ComplainingState(
|
||||
isLoading: true,
|
||||
category: ComplainType.spam,
|
||||
contentType: ComplainedContent.recipe,
|
||||
contentId: 1,
|
||||
);
|
||||
final state3 = ComplainingState(
|
||||
isLoading: false,
|
||||
category: ComplainType.spam,
|
||||
contentType: ComplainedContent.recipe,
|
||||
contentId: 1,
|
||||
);
|
||||
|
||||
expect(state1 == state2, isTrue);
|
||||
expect(state1 == state3, isFalse);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -965,5 +965,116 @@ void main() {
|
||||
|
||||
verify(mockDiaryRepository.deletePhoto(photo: photo, diaryId: 1, mealId: 1)).called(1);
|
||||
});
|
||||
|
||||
test('setSelectedDay - возвращает true даже если getDiary возвращает null', () async {
|
||||
diaryCubit = DiaryCubit(
|
||||
diaryRepository: mockDiaryRepository,
|
||||
glossaryRepository: mockGlossaryRepository,
|
||||
profileRepository: mockProfileRepository,
|
||||
dietRepository: mockDietRepository,
|
||||
chatRepository: mockChatRepository,
|
||||
settingsRepository: mockSettingsRepository,
|
||||
);
|
||||
when(mockDiaryRepository.createDiaryDay(day: anyNamed('day'))).thenThrow(
|
||||
DioException(
|
||||
requestOptions: RequestOptions(path: ''),
|
||||
response: Response(requestOptions: RequestOptions(path: ''), statusCode: 500),
|
||||
),
|
||||
);
|
||||
|
||||
final result = await diaryCubit!.setSelectedDay(DateTime(2024, 1, 20));
|
||||
|
||||
// fetchDiaryV2 возвращает true когда getDiary() == null, так как эмитит состояние ошибки
|
||||
expect(result, true);
|
||||
expect(diaryCubit!.state, isA<DiaryStateError>());
|
||||
});
|
||||
|
||||
test('fetchDiaryV2 - обрабатывает случай когда diaryEntity == null и нет диеты', () async {
|
||||
diaryCubit = DiaryCubit(
|
||||
diaryRepository: mockDiaryRepository,
|
||||
glossaryRepository: mockGlossaryRepository,
|
||||
profileRepository: mockProfileRepository,
|
||||
dietRepository: mockDietRepository,
|
||||
chatRepository: mockChatRepository,
|
||||
settingsRepository: mockSettingsRepository,
|
||||
);
|
||||
// toEntity() возвращает null когда id == null
|
||||
const diaryDayWithoutEntity = DiaryDayModel(
|
||||
id: null,
|
||||
date: '2024-01-15',
|
||||
closed: 0,
|
||||
comment: '',
|
||||
typeOfDiary: TypeOfDiaryModel(hasChosenDiet: false, hasChosenPlan: false, diaryState: null),
|
||||
meals: [],
|
||||
chosenPlanId: null,
|
||||
dayOfChosenDiet: null,
|
||||
diet: null,
|
||||
);
|
||||
when(mockDiaryRepository.createDiaryDay(day: anyNamed('day'))).thenAnswer((_) async => Future.value());
|
||||
when(mockDiaryRepository.getDiaryDayV2(day: anyNamed('day'))).thenAnswer((_) async => diaryDayWithoutEntity);
|
||||
|
||||
final result = await diaryCubit!.fetchDiaryV2(needLoading: false);
|
||||
|
||||
// Если diaryEntity == null (id == null) и нет диеты, fetchDiaryV2 возвращает false
|
||||
// и эмитит предыдущее состояние (loading)
|
||||
expect(result, false);
|
||||
expect(diaryCubit!.state, const DiaryState.loading());
|
||||
});
|
||||
|
||||
test('fetchDiaryV2 - обрабатывает случай когда diaryEntity == null но есть диета', () async {
|
||||
diaryCubit = DiaryCubit(
|
||||
diaryRepository: mockDiaryRepository,
|
||||
glossaryRepository: mockGlossaryRepository,
|
||||
profileRepository: mockProfileRepository,
|
||||
dietRepository: mockDietRepository,
|
||||
chatRepository: mockChatRepository,
|
||||
settingsRepository: mockSettingsRepository,
|
||||
);
|
||||
// id должен быть null, чтобы toEntity() вернул null и код пошел по ветке setDiaryForDietOnly
|
||||
const diaryDayWithDiet = DiaryDayModel(
|
||||
id: null,
|
||||
date: '2024-01-15',
|
||||
closed: 0,
|
||||
comment: '',
|
||||
typeOfDiary: TypeOfDiaryModel(hasChosenDiet: true, hasChosenPlan: false, diaryState: null),
|
||||
meals: [],
|
||||
chosenPlanId: null,
|
||||
dayOfChosenDiet: 1,
|
||||
diet: DiaryDietModel(id: 1, duration: 7, name: 'Test Diet'),
|
||||
);
|
||||
when(mockDiaryRepository.createDiaryDay(day: anyNamed('day'))).thenAnswer((_) async => Future.value());
|
||||
when(mockDiaryRepository.getDiaryDayV2(day: anyNamed('day'))).thenAnswer((_) async => diaryDayWithDiet);
|
||||
when(mockDietRepository.getDiet(1)).thenAnswer(
|
||||
(_) async => const Diet(
|
||||
id: 1,
|
||||
slug: 'test-diet',
|
||||
name: 'Test Diet',
|
||||
image: '',
|
||||
duration: 7,
|
||||
state: DietState.active,
|
||||
type: DietType(),
|
||||
details: '',
|
||||
dailySchedule: {
|
||||
1: {
|
||||
1: {1: DailySchedule(name: 'Яблоко', portion: Portion.grams, quantity: 1)},
|
||||
},
|
||||
},
|
||||
author: Author(authorSlug: 'test', authorName: 'Test', authorProfileIcon: '', authorIsMe: false),
|
||||
totalLikes: 0,
|
||||
totalViews: 0,
|
||||
totalComments: 0,
|
||||
wasLikedByMe: false,
|
||||
isFavorite: false,
|
||||
dailyNutrition: [],
|
||||
),
|
||||
);
|
||||
|
||||
final result = await diaryCubit!.fetchDiaryV2(needLoading: false);
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
|
||||
expect(result, true);
|
||||
// setDiaryForDietOnly сначала эмитит loading, затем loadedTomorrowWithDiet
|
||||
expect(diaryCubit!.state, isA<DiaryStateLoadedTomorrowWithDiet>());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_state.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('FeedState', () {
|
||||
test('creates initial FeedState', () {
|
||||
const state = FeedState();
|
||||
expect(state, isA<FeedState>());
|
||||
});
|
||||
|
||||
test('creates loading FeedState', () {
|
||||
const state = FeedState.loading();
|
||||
expect(state, isA<FeedState>());
|
||||
expect(state, isA<FeedStateLoading>());
|
||||
});
|
||||
|
||||
test('creates loaded FeedState with data', () {
|
||||
const state = FeedState.loaded(feedBlogPostList: [], isLoading: false);
|
||||
|
||||
expect(state, isA<FeedState>());
|
||||
expect(state, isA<FeedStateLoaded>());
|
||||
expect((state as FeedStateLoaded).feedBlogPostList, isEmpty);
|
||||
expect(state.isLoading, isFalse);
|
||||
});
|
||||
|
||||
test('creates loaded FeedState with blog posts', () {
|
||||
const author = Author(authorSlug: 'test-author', authorName: 'Test Author', authorProfileIcon: 'https://example.com/icon.jpg', authorIsMe: false);
|
||||
|
||||
final blogPost = FeedBlogPostModel(
|
||||
id: 1,
|
||||
title: 'Test Post',
|
||||
state: 'active',
|
||||
image: 'https://example.com/image.jpg',
|
||||
description: 'Test Description',
|
||||
author: author,
|
||||
videoUrl: 'https://example.com/video.mp4',
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
totalLikes: 0,
|
||||
totalViews: 0,
|
||||
totalComments: 0,
|
||||
wasLikedByMe: false,
|
||||
);
|
||||
|
||||
final state = FeedState.loaded(feedBlogPostList: [blogPost], isLoading: true);
|
||||
|
||||
expect(state, isA<FeedStateLoaded>());
|
||||
expect((state as FeedStateLoaded).feedBlogPostList.length, 1);
|
||||
expect(state.isLoading, isTrue);
|
||||
});
|
||||
|
||||
test('creates error FeedState', () {
|
||||
const state = FeedState.error(errorMessage: 'Test error');
|
||||
|
||||
expect(state, isA<FeedState>());
|
||||
expect(state, isA<FeedStateError>());
|
||||
expect((state as FeedStateError).errorMessage, 'Test error');
|
||||
});
|
||||
|
||||
test('different state types are not equal', () {
|
||||
const loading = FeedState.loading();
|
||||
const loaded = FeedState.loaded(feedBlogPostList: [], isLoading: false);
|
||||
const error = FeedState.error(errorMessage: 'Error');
|
||||
|
||||
expect(loading == loaded, isFalse);
|
||||
expect(loading == error, isFalse);
|
||||
expect(loaded == error, isFalse);
|
||||
});
|
||||
|
||||
test('same state types with same data are equal', () {
|
||||
const state1 = FeedState.loaded(feedBlogPostList: [], isLoading: false);
|
||||
const state2 = FeedState.loaded(feedBlogPostList: [], isLoading: false);
|
||||
|
||||
expect(state1 == state2, isTrue);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import 'package:eatvio_app/features/menu/presentation/bloc/menu_cubit/menu_state.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('MenuState', () {
|
||||
test('creates MenuState instance', () {
|
||||
final state = MenuState();
|
||||
expect(state, isNotNull);
|
||||
expect(state, isA<MenuState>());
|
||||
});
|
||||
|
||||
test('creates multiple MenuState instances', () {
|
||||
final state1 = MenuState();
|
||||
final state2 = MenuState();
|
||||
|
||||
expect(state1, isNotNull);
|
||||
expect(state2, isNotNull);
|
||||
expect(state1, isA<MenuState>());
|
||||
expect(state2, isA<MenuState>());
|
||||
});
|
||||
|
||||
test('MenuState instances are not equal by default', () {
|
||||
final state1 = MenuState();
|
||||
final state2 = MenuState();
|
||||
|
||||
// MenuState is a regular class without overridden == operator,
|
||||
// so instances are compared by reference
|
||||
expect(state1 == state2, isFalse);
|
||||
expect(state1, isNot(same(state2)));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -78,5 +78,22 @@ void main() {
|
||||
expect(find.byType(BlockedUsersScreen), findsOneWidget);
|
||||
expect(find.text('Чёрный список'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('renders blocked users screen with error state', (tester) async {
|
||||
final cubit = MockBlockedUsersCubit();
|
||||
const state = BlockedUsersStateError(errorMessage: 'Error message');
|
||||
|
||||
when(cubit.state).thenReturn(state);
|
||||
when(cubit.stream).thenAnswer((_) => Stream.value(state));
|
||||
when(cubit.close()).thenAnswer((_) async => Future<void>.value());
|
||||
when(cubit.getBlockedUsers()).thenAnswer((_) async => Future<void>.value());
|
||||
|
||||
sl.registerFactory<BlockedUsersCubit>(() => cubit);
|
||||
|
||||
await tester.pumpWidget(wrap(const BlockedUsersScreen()));
|
||||
await tester.pump();
|
||||
|
||||
expect(find.byType(BlockedUsersScreen), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
import 'package:eatvio_app/features/notifications/models/notification_model.dart';
|
||||
import 'package:eatvio_app/features/notifications/presentation/notifications_cubit/notifications_state.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('NotificationsState', () {
|
||||
test('creates initial NotificationsState', () {
|
||||
const state = NotificationsState();
|
||||
expect(state, isA<NotificationsState>());
|
||||
});
|
||||
|
||||
test('creates empty NotificationsState', () {
|
||||
const state = NotificationsState.empty();
|
||||
expect(state, isA<NotificationsState>());
|
||||
expect(state, isA<NotificationsStateEmpty>());
|
||||
});
|
||||
|
||||
test('creates loaded NotificationsState with default values', () {
|
||||
const state = NotificationsState.loaded(
|
||||
notifications: [],
|
||||
notificationsCount: 0,
|
||||
);
|
||||
|
||||
expect(state, isA<NotificationsState>());
|
||||
expect(state, isA<NotificationsStateLoaded>());
|
||||
expect((state as NotificationsStateLoaded).notifications, isEmpty);
|
||||
expect(state.notificationsCount, 0);
|
||||
expect(state.isLoading, isFalse);
|
||||
expect(state.hasUnreadNotifications, isFalse);
|
||||
expect(state.currentPage, 1);
|
||||
expect(state.hasNextPage, isTrue);
|
||||
expect(state.isLoadingMore, isFalse);
|
||||
});
|
||||
|
||||
test('creates loaded NotificationsState with custom values', () {
|
||||
final notification = PlanSubscriptionStartedToAuthorNotification(
|
||||
type: NotificationType.planSubscriptionStartedToAuthor,
|
||||
planName: 'Test Plan',
|
||||
customerName: 'Test Customer',
|
||||
chatId: 'chat-123',
|
||||
isRead: false,
|
||||
createdAt: DateTime.now(),
|
||||
);
|
||||
|
||||
final state = NotificationsState.loaded(
|
||||
notifications: [notification],
|
||||
notificationsCount: 1,
|
||||
isLoading: true,
|
||||
hasUnreadNotifications: true,
|
||||
currentPage: 2,
|
||||
hasNextPage: false,
|
||||
isLoadingMore: true,
|
||||
);
|
||||
|
||||
expect(state, isA<NotificationsStateLoaded>());
|
||||
expect((state as NotificationsStateLoaded).notifications.length, 1);
|
||||
expect(state.notificationsCount, 1);
|
||||
expect(state.isLoading, isTrue);
|
||||
expect(state.hasUnreadNotifications, isTrue);
|
||||
expect(state.currentPage, 2);
|
||||
expect(state.hasNextPage, isFalse);
|
||||
expect(state.isLoadingMore, isTrue);
|
||||
});
|
||||
|
||||
test('creates error NotificationsState', () {
|
||||
const state = NotificationsState.error(errorMessage: 'Test error');
|
||||
|
||||
expect(state, isA<NotificationsState>());
|
||||
expect(state, isA<NotificationsStateError>());
|
||||
expect((state as NotificationsStateError).errorMessage, 'Test error');
|
||||
});
|
||||
|
||||
test('different state types are not equal', () {
|
||||
const empty = NotificationsState.empty();
|
||||
const loaded = NotificationsState.loaded(notifications: [], notificationsCount: 0);
|
||||
const error = NotificationsState.error(errorMessage: 'Error');
|
||||
|
||||
expect(empty == loaded, isFalse);
|
||||
expect(empty == error, isFalse);
|
||||
expect(loaded == error, isFalse);
|
||||
});
|
||||
|
||||
test('same state types with same data are equal', () {
|
||||
const state1 = NotificationsState.loaded(notifications: [], notificationsCount: 0);
|
||||
const state2 = NotificationsState.loaded(notifications: [], notificationsCount: 0);
|
||||
|
||||
expect(state1 == state2, isTrue);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -66,5 +66,22 @@ void main() {
|
||||
expect(find.byType(MyRecipesScreen), findsOneWidget);
|
||||
expect(find.text('Мои рецепты'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('renders my recipes screen with error state', (tester) async {
|
||||
final cubit = MockMyRecipesCubit();
|
||||
const state = MyRecipesStateError();
|
||||
|
||||
when(cubit.state).thenReturn(state);
|
||||
when(cubit.stream).thenAnswer((_) => Stream.value(state));
|
||||
when(cubit.close()).thenAnswer((_) async => Future<void>.value());
|
||||
when(cubit.getMyRecipes()).thenAnswer((_) async => Future<void>.value());
|
||||
|
||||
sl.registerFactory<MyRecipesCubit>(() => cubit);
|
||||
|
||||
await tester.pumpWidget(wrap(const MyRecipesScreen()));
|
||||
await tester.pump();
|
||||
|
||||
expect(find.byType(MyRecipesScreen), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -80,5 +80,35 @@ void main() {
|
||||
|
||||
expect(find.byType(LinearProgressIndicator), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('displays correct progress value for step 0', (tester) async {
|
||||
final cubit = MockRegistrationCubitV2();
|
||||
const state = RegistrationStateV2(step: 0);
|
||||
|
||||
when(cubit.state).thenReturn(state);
|
||||
when(cubit.stream).thenAnswer((_) => Stream.value(state));
|
||||
when(cubit.close()).thenAnswer((_) async => Future<void>.value());
|
||||
|
||||
await tester.pumpWidget(wrap(const StepProgress(), cubit));
|
||||
await tester.pump();
|
||||
|
||||
final progressIndicator = tester.widget<LinearProgressIndicator>(find.byType(LinearProgressIndicator));
|
||||
expect(progressIndicator.value, 0.5);
|
||||
});
|
||||
|
||||
testWidgets('displays correct progress value for step 1', (tester) async {
|
||||
final cubit = MockRegistrationCubitV2();
|
||||
const state = RegistrationStateV2(step: 1);
|
||||
|
||||
when(cubit.state).thenReturn(state);
|
||||
when(cubit.stream).thenAnswer((_) => Stream.value(state));
|
||||
when(cubit.close()).thenAnswer((_) async => Future<void>.value());
|
||||
|
||||
await tester.pumpWidget(wrap(const StepProgress(), cubit));
|
||||
await tester.pump();
|
||||
|
||||
final progressIndicator = tester.widget<LinearProgressIndicator>(find.byType(LinearProgressIndicator));
|
||||
expect(progressIndicator.value, 1.0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -64,6 +64,32 @@ void main() {
|
||||
|
||||
expect(find.byType(StepWidget), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('displays step widget for step 0', (tester) async {
|
||||
when(mockCubit.state).thenReturn(
|
||||
const RegistrationStateV2(step: 0),
|
||||
);
|
||||
when(mockCubit.stream).thenAnswer((_) => Stream.value(const RegistrationStateV2(step: 0)));
|
||||
|
||||
await tester.pumpWidget(createTestWidget());
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byType(StepWidget), findsOneWidget);
|
||||
expect(find.byType(Text), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('displays step widget for step 1', (tester) async {
|
||||
when(mockCubit.state).thenReturn(
|
||||
const RegistrationStateV2(step: 1),
|
||||
);
|
||||
when(mockCubit.stream).thenAnswer((_) => Stream.value(const RegistrationStateV2(step: 1)));
|
||||
|
||||
await tester.pumpWidget(createTestWidget());
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byType(StepWidget), findsOneWidget);
|
||||
expect(find.byType(Text), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user