feat(test): comments, auth, feed

This commit is contained in:
mso7nueh
2025-11-28 14:13:05 +03:00
parent 7df32dabd2
commit 2a25be5aa4
12 changed files with 1774 additions and 1 deletions

View File

@@ -0,0 +1,190 @@
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/oauth_cubit/oauth_cubit.dart';
import 'package:eatvio_app/features/auth/presentation/bloc/oauth_cubit/oauth_state.dart';
import 'package:eatvio_app/features/auth/repositories/auth_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 '../../../../../fixtures/doubles/auth_doubles.dart';
import '../../../../../fixtures/fixture_reader.dart';
import 'oauth_cubit_test.mocks.dart';
@GenerateNiceMocks([MockSpec<AuthRepository>(), MockSpec<Prefs>()])
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
group('OAuthCubit', () {
OAuthCubit? oauthCubit;
late MockAuthRepository mockAuthRepository;
late MockPrefs mockPrefs;
late TokenModel tokenFixture;
late Map<String, dynamic> signInRequestFixture;
late Map<String, dynamic> signUpRequestFixture;
setUp(() async {
tokenFixture = TokenModel.fromJson(FixtureReader.readAsMap('auth/token_response.json'));
signInRequestFixture = FixtureReader.readAsMap('auth/oauth_signin_request.json');
signUpRequestFixture = FixtureReader.readAsMap('auth/oauth_signup_request.json');
mockAuthRepository = MockAuthRepository();
mockPrefs = MockPrefs();
SharedPreferences.setMockInitialValues({});
// Mock Fluttertoast plugin
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(const MethodChannel('PonnamKarthik/fluttertoast'), (
MethodCall methodCall,
) async {
return null;
});
});
tearDown(() async {
if (oauthCubit != null && !oauthCubit!.isClosed) {
await Future.delayed(const Duration(milliseconds: 100));
oauthCubit!.close();
oauthCubit = null;
}
// Clear mock handlers
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(const MethodChannel('PonnamKarthik/fluttertoast'), null);
});
test('начальное состояние - OAuthState', () {
oauthCubit = OAuthCubit(authRepository: mockAuthRepository, prefs: mockPrefs);
expect(oauthCubit!.state, const OAuthState());
});
test('signInViaSocialMedia - успешный вход через соцсеть', () async {
oauthCubit = OAuthCubit(authRepository: mockAuthRepository, prefs: mockPrefs);
when(
mockAuthRepository.signInViaSocialMedia(
provider: signInRequestFixture['provider'] as String,
accessToken: signInRequestFixture['accessToken'] as String,
refreshToken: signInRequestFixture['refreshToken'] as String,
clientId: signInRequestFixture['clientId'] as String,
),
).thenAnswer((_) async => tokenFixture);
await oauthCubit!.signInViaSocialMedia(
provider: signInRequestFixture['provider'] as String,
accessToken: signInRequestFixture['accessToken'] as String,
refreshToken: signInRequestFixture['refreshToken'] as String,
clientId: signInRequestFixture['clientId'] as String,
);
await Future.delayed(const Duration(milliseconds: 100));
expect(oauthCubit!.state, isA<OAuthStateLoaded>());
final loadedState = oauthCubit!.state as OAuthStateLoaded;
expect(loadedState.token, tokenFixture.token);
// Проверяем, что токен сохранён
final savedToken = await TokenStorage.getTokenFromStorage();
expect(savedToken, tokenFixture.token);
});
test('signInViaSocialMedia - переход в состояние loading', () async {
oauthCubit = OAuthCubit(authRepository: mockAuthRepository, prefs: mockPrefs);
when(
mockAuthRepository.signInViaSocialMedia(
provider: anyNamed('provider'),
accessToken: anyNamed('accessToken'),
refreshToken: anyNamed('refreshToken'),
clientId: anyNamed('clientId'),
),
).thenAnswer((_) async {
await Future.delayed(const Duration(milliseconds: 50));
return tokenFixture;
});
final future = oauthCubit!.signInViaSocialMedia(
provider: signInRequestFixture['provider'] as String,
accessToken: signInRequestFixture['accessToken'] as String,
refreshToken: signInRequestFixture['refreshToken'] as String,
clientId: signInRequestFixture['clientId'] as String,
);
await Future.delayed(const Duration(milliseconds: 10));
expect(oauthCubit!.state, isA<OAuthStateLoading>());
await future;
});
test('signInViaSocialMedia - обработка ошибки', () async {
oauthCubit = OAuthCubit(authRepository: mockAuthRepository, prefs: mockPrefs);
when(
mockAuthRepository.signInViaSocialMedia(
provider: anyNamed('provider'),
accessToken: anyNamed('accessToken'),
refreshToken: anyNamed('refreshToken'),
clientId: anyNamed('clientId'),
),
).thenThrow(Exception('Ошибка авторизации'));
await oauthCubit!.signInViaSocialMedia(
provider: signInRequestFixture['provider'] as String,
accessToken: signInRequestFixture['accessToken'] as String,
refreshToken: signInRequestFixture['refreshToken'] as String,
clientId: signInRequestFixture['clientId'] as String,
);
await Future.delayed(const Duration(milliseconds: 100));
expect(oauthCubit!.state, isA<OAuthStateError>());
final errorState = oauthCubit!.state as OAuthStateError;
expect(errorState.errorMessage, contains('Exception'));
});
test('signUpViaSocialMedia - успешная регистрация через соцсеть', () async {
oauthCubit = OAuthCubit(authRepository: mockAuthRepository, prefs: mockPrefs);
when(
mockAuthRepository.signUpViaSocialMedia(
provider: anyNamed('provider'),
accessToken: anyNamed('accessToken'),
id: anyNamed('id'),
refreshToken: anyNamed('refreshToken'),
firstName: anyNamed('firstName'),
lastName: anyNamed('lastName'),
email: anyNamed('email'),
phone: anyNamed('phone'),
dateOfBirth: anyNamed('dateOfBirth'),
gender: anyNamed('gender'),
weight: anyNamed('weight'),
height: anyNamed('height'),
clientId: anyNamed('clientId'),
),
).thenAnswer((_) async => tokenFixture.token);
when(mockPrefs.setString(any, any)).thenAnswer((_) async => Future.value());
final result = await oauthCubit!.signUpViaSocialMedia(
provider: signUpRequestFixture['provider'] as String,
accessToken: signUpRequestFixture['accessToken'] as String,
id: signUpRequestFixture['id'] as String,
refreshToken: signUpRequestFixture['refreshToken'] as String,
firstName: signUpRequestFixture['firstName'] as String,
lastName: signUpRequestFixture['lastName'] as String,
email: signUpRequestFixture['email'] as String,
phone: signUpRequestFixture['phone'] as String,
dateOfBirth: signUpRequestFixture['dateOfBirth'] as String,
gender: signUpRequestFixture['gender'] as String,
weight: signUpRequestFixture['weight'] as int,
height: signUpRequestFixture['height'] as int,
clientId: signUpRequestFixture['clientId'] as String,
);
await Future.delayed(const Duration(milliseconds: 100));
expect(result, isNull); // Нет ошибок валидации
expect(oauthCubit!.state, isA<OAuthStateLoaded>());
final loadedState = oauthCubit!.state as OAuthStateLoaded;
expect(loadedState.token, tokenFixture.token);
});
});
}

View File

@@ -0,0 +1,216 @@
import 'package:eatvio_app/features/auth/presentation/bloc/reset_password_cubit/reset_password_cubit.dart';
import 'package:eatvio_app/features/auth/presentation/bloc/reset_password_cubit/reset_password_state.dart';
import 'package:eatvio_app/features/auth/repositories/reset_password_repository.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import '../../../../../fixtures/fixture_reader.dart';
import 'reset_password_cubit_test.mocks.dart';
@GenerateNiceMocks([MockSpec<ResetPasswordRepository>()])
void main() {
group('ResetPasswordCubit', () {
ResetPasswordCubit? resetPasswordCubit;
late MockResetPasswordRepository mockResetPasswordRepository;
late Map<String, dynamic> resetPasswordFixture;
setUp(() {
resetPasswordFixture = FixtureReader.readAsMap('auth/reset_password_request.json');
mockResetPasswordRepository = MockResetPasswordRepository();
});
tearDown(() async {
if (resetPasswordCubit != null && !resetPasswordCubit!.isClosed) {
await Future.delayed(const Duration(milliseconds: 100));
resetPasswordCubit!.close();
resetPasswordCubit = null;
}
});
test('начальное состояние - ResetPasswordState.empty', () {
resetPasswordCubit = ResetPasswordCubit(
resetPasswordRepository: mockResetPasswordRepository,
);
expect(resetPasswordCubit!.state, const ResetPasswordState.empty());
});
test('trySendEmailCode - успешная отправка кода', () async {
resetPasswordCubit = ResetPasswordCubit(
resetPasswordRepository: mockResetPasswordRepository,
);
when(mockResetPasswordRepository.sendEmailCodeForPasswordChange(
resetPasswordFixture['email'] as String,
)).thenAnswer((_) async => true);
await resetPasswordCubit!.trySendEmailCode(
resetPasswordFixture['email'] as String,
);
await Future.delayed(const Duration(milliseconds: 100));
expect(resetPasswordCubit!.state, const ResetPasswordState.codeSendSuccess());
verify(mockResetPasswordRepository.sendEmailCodeForPasswordChange(
resetPasswordFixture['email'] as String,
)).called(1);
});
test('trySendEmailCode - переход в состояние loading', () async {
resetPasswordCubit = ResetPasswordCubit(
resetPasswordRepository: mockResetPasswordRepository,
);
when(mockResetPasswordRepository.sendEmailCodeForPasswordChange(
any,
)).thenAnswer((_) async {
await Future.delayed(const Duration(milliseconds: 50));
return true;
});
final future = resetPasswordCubit!.trySendEmailCode(
resetPasswordFixture['email'] as String,
);
await Future.delayed(const Duration(milliseconds: 10));
expect(resetPasswordCubit!.state, const ResetPasswordState.loadingSendEmailCode());
await future;
});
test('trySendEmailCode - ошибка отправки кода', () async {
resetPasswordCubit = ResetPasswordCubit(
resetPasswordRepository: mockResetPasswordRepository,
);
when(mockResetPasswordRepository.sendEmailCodeForPasswordChange(
resetPasswordFixture['email'] as String,
)).thenAnswer((_) async => false);
await resetPasswordCubit!.trySendEmailCode(
resetPasswordFixture['email'] as String,
);
await Future.delayed(const Duration(milliseconds: 100));
expect(resetPasswordCubit!.state, const ResetPasswordState.codeSendError());
});
test('trySendEmailCode - обработка исключения', () async {
resetPasswordCubit = ResetPasswordCubit(
resetPasswordRepository: mockResetPasswordRepository,
);
when(mockResetPasswordRepository.sendEmailCodeForPasswordChange(
resetPasswordFixture['email'] as String,
)).thenThrow(Exception('Ошибка сети'));
await resetPasswordCubit!.trySendEmailCode(
resetPasswordFixture['email'] as String,
);
await Future.delayed(const Duration(milliseconds: 100));
expect(resetPasswordCubit!.state, const ResetPasswordState.codeSendError());
});
test('tryResetPassword - успешный сброс пароля', () async {
resetPasswordCubit = ResetPasswordCubit(
resetPasswordRepository: mockResetPasswordRepository,
);
when(mockResetPasswordRepository.confirmPasswordChange(
resetPasswordFixture['code'] as String,
resetPasswordFixture['password'] as String,
resetPasswordFixture['passwordConfirmation'] as String,
resetPasswordFixture['email'] as String,
)).thenAnswer((_) async => true);
await resetPasswordCubit!.tryResetPassword(
resetPasswordFixture['email'] as String,
resetPasswordFixture['code'] as String,
resetPasswordFixture['password'] as String,
resetPasswordFixture['passwordConfirmation'] as String,
);
await Future.delayed(const Duration(milliseconds: 100));
expect(resetPasswordCubit!.state, const ResetPasswordState.resetPasswordSuccess());
verify(mockResetPasswordRepository.confirmPasswordChange(
resetPasswordFixture['code'] as String,
resetPasswordFixture['password'] as String,
resetPasswordFixture['passwordConfirmation'] as String,
resetPasswordFixture['email'] as String,
)).called(1);
});
test('tryResetPassword - переход в состояние loading', () async {
resetPasswordCubit = ResetPasswordCubit(
resetPasswordRepository: mockResetPasswordRepository,
);
when(mockResetPasswordRepository.confirmPasswordChange(
any,
any,
any,
any,
)).thenAnswer((_) async {
await Future.delayed(const Duration(milliseconds: 50));
return true;
});
final future = resetPasswordCubit!.tryResetPassword(
resetPasswordFixture['email'] as String,
resetPasswordFixture['code'] as String,
resetPasswordFixture['password'] as String,
resetPasswordFixture['passwordConfirmation'] as String,
);
await Future.delayed(const Duration(milliseconds: 10));
expect(resetPasswordCubit!.state, const ResetPasswordState.loadingResetPassword());
await future;
});
test('tryResetPassword - ошибка сброса пароля', () async {
resetPasswordCubit = ResetPasswordCubit(
resetPasswordRepository: mockResetPasswordRepository,
);
when(mockResetPasswordRepository.confirmPasswordChange(
resetPasswordFixture['code'] as String,
resetPasswordFixture['password'] as String,
resetPasswordFixture['passwordConfirmation'] as String,
resetPasswordFixture['email'] as String,
)).thenAnswer((_) async => false);
await resetPasswordCubit!.tryResetPassword(
resetPasswordFixture['email'] as String,
resetPasswordFixture['code'] as String,
resetPasswordFixture['password'] as String,
resetPasswordFixture['passwordConfirmation'] as String,
);
await Future.delayed(const Duration(milliseconds: 100));
expect(resetPasswordCubit!.state, const ResetPasswordState.resetPasswordError());
});
test('tryResetPassword - обработка исключения', () async {
resetPasswordCubit = ResetPasswordCubit(
resetPasswordRepository: mockResetPasswordRepository,
);
when(mockResetPasswordRepository.confirmPasswordChange(
any,
any,
any,
any,
)).thenThrow(Exception('Неверный код'));
await resetPasswordCubit!.tryResetPassword(
resetPasswordFixture['email'] as String,
resetPasswordFixture['code'] as String,
resetPasswordFixture['password'] as String,
resetPasswordFixture['passwordConfirmation'] as String,
);
await Future.delayed(const Duration(milliseconds: 100));
expect(resetPasswordCubit!.state, const ResetPasswordState.resetPasswordError());
});
});
}