forked from eatvio/eatvio_app
404 lines
14 KiB
Dart
404 lines
14 KiB
Dart
// ignore_for_file: deprecated_member_use
|
|
|
|
import 'package:eatvio_app/app_keys.dart';
|
|
import 'package:eatvio_app/core/firebase_api.dart';
|
|
import 'package:eatvio_app/core/prefs.dart';
|
|
import 'package:eatvio_app/core/theme/theme_helper.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/profile/repositories/profile_repository.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:mockito/annotations.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import '../../../../fixtures/doubles/auth_doubles.dart';
|
|
import '../../../../fixtures/doubles/profile_doubles.dart';
|
|
import '../../../../fixtures/fixture_reader.dart';
|
|
import 'basic_widget_test.mocks.dart';
|
|
|
|
@GenerateNiceMocks([MockSpec<Prefs>(), MockSpec<FirebaseApi>(), MockSpec<ProfileRepository>()])
|
|
void main() {
|
|
group('Auth Basic Widget Tests', () {
|
|
late FixtureAuthRepository authRepository;
|
|
late FixtureProfileRepository profileRepository;
|
|
late MockPrefs mockPrefs;
|
|
late MockFirebaseApi mockFirebaseApi;
|
|
late AuthCubit authCubit;
|
|
late Map<String, dynamic> credentialsFixture;
|
|
|
|
setUp(() async {
|
|
credentialsFixture = FixtureReader.readAsMap('auth/login_credentials.json');
|
|
authRepository = FixtureAuthRepository(tokenFixture: TokenModel.fromJson(FixtureReader.readAsMap('auth/token_response.json')));
|
|
profileRepository = FixtureProfileRepository();
|
|
mockPrefs = MockPrefs();
|
|
mockFirebaseApi = MockFirebaseApi();
|
|
SharedPreferences.setMockInitialValues({});
|
|
|
|
authCubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi);
|
|
});
|
|
|
|
tearDown(() {
|
|
authCubit.close();
|
|
});
|
|
|
|
Widget createTestWidget(Widget child) {
|
|
return MaterialApp(
|
|
theme: ThemeHelper().themeData(),
|
|
home: BlocProvider<AuthCubit>(
|
|
create: (context) => authCubit,
|
|
child: Scaffold(body: SingleChildScrollView(child: child)),
|
|
),
|
|
);
|
|
}
|
|
|
|
testWidgets('should create AuthCubit successfully', (WidgetTester tester) async {
|
|
// Arrange & Act
|
|
final cubit = AuthCubit(authRepository: authRepository, prefs: mockPrefs, profileRepository: profileRepository, firebaseApi: mockFirebaseApi);
|
|
|
|
// Assert
|
|
expect(cubit, isA<AuthCubit>());
|
|
|
|
cubit.close();
|
|
});
|
|
|
|
testWidgets('should display email text field', (WidgetTester tester) async {
|
|
// Arrange
|
|
Widget emailWidget = TextFormField(
|
|
key: AppKeys.emailTextFieldAuthScreen,
|
|
decoration: const InputDecoration(labelText: 'Email', hintText: 'Введите email'),
|
|
keyboardType: TextInputType.emailAddress,
|
|
);
|
|
|
|
// Act
|
|
await tester.pumpWidget(createTestWidget(emailWidget));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Assert
|
|
expect(find.byKey(AppKeys.emailTextFieldAuthScreen), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('should display password text field', (WidgetTester tester) async {
|
|
// Arrange
|
|
Widget passwordWidget = TextFormField(
|
|
key: AppKeys.passwordTextFieldAuthScreen,
|
|
decoration: const InputDecoration(labelText: 'Пароль', hintText: 'Введите пароль'),
|
|
obscureText: true,
|
|
);
|
|
|
|
// Act
|
|
await tester.pumpWidget(createTestWidget(passwordWidget));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Assert
|
|
expect(find.byKey(AppKeys.passwordTextFieldAuthScreen), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('should display sign in button', (WidgetTester tester) async {
|
|
// Arrange
|
|
Widget buttonWidget = FloatingActionButton.extended(key: AppKeys.signInButtonAuthScreen, onPressed: () {}, label: const Text('Войти'));
|
|
|
|
// Act
|
|
await tester.pumpWidget(createTestWidget(buttonWidget));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Assert
|
|
expect(find.byKey(AppKeys.signInButtonAuthScreen), findsOneWidget);
|
|
expect(find.text('Войти'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('should update email when user types in email field', (WidgetTester tester) async {
|
|
// Arrange
|
|
Widget emailWidget = TextFormField(
|
|
key: AppKeys.emailTextFieldAuthScreen,
|
|
decoration: const InputDecoration(labelText: 'Email', hintText: 'Введите email'),
|
|
keyboardType: TextInputType.emailAddress,
|
|
);
|
|
|
|
await tester.pumpWidget(createTestWidget(emailWidget));
|
|
await tester.pumpAndSettle();
|
|
|
|
final testEmail = credentialsFixture['email'] as String;
|
|
|
|
// Act
|
|
await tester.enterText(find.byKey(AppKeys.emailTextFieldAuthScreen), testEmail);
|
|
await tester.pump();
|
|
|
|
// Assert
|
|
expect(find.text(testEmail), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('should update password when user types in password field', (WidgetTester tester) async {
|
|
// Arrange
|
|
Widget passwordWidget = TextFormField(
|
|
key: AppKeys.passwordTextFieldAuthScreen,
|
|
decoration: const InputDecoration(labelText: 'Пароль', hintText: 'Введите пароль'),
|
|
obscureText: true,
|
|
);
|
|
|
|
await tester.pumpWidget(createTestWidget(passwordWidget));
|
|
await tester.pumpAndSettle();
|
|
|
|
final testPassword = credentialsFixture['password'] as String;
|
|
|
|
// Act
|
|
await tester.enterText(find.byKey(AppKeys.passwordTextFieldAuthScreen), testPassword);
|
|
await tester.pump();
|
|
|
|
// Assert
|
|
expect(find.text(testPassword), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('should display complete auth form', (WidgetTester tester) async {
|
|
// Arrange
|
|
Widget completeForm = Column(
|
|
children: [
|
|
TextFormField(
|
|
key: AppKeys.emailTextFieldAuthScreen,
|
|
decoration: const InputDecoration(labelText: 'Email', hintText: 'Введите email'),
|
|
keyboardType: TextInputType.emailAddress,
|
|
),
|
|
const SizedBox(height: 16),
|
|
TextFormField(
|
|
key: AppKeys.passwordTextFieldAuthScreen,
|
|
decoration: const InputDecoration(labelText: 'Пароль', hintText: 'Введите пароль'),
|
|
obscureText: true,
|
|
),
|
|
const SizedBox(height: 16),
|
|
FloatingActionButton.extended(key: AppKeys.signInButtonAuthScreen, onPressed: () {}, label: const Text('Войти')),
|
|
],
|
|
);
|
|
|
|
// Act
|
|
await tester.pumpWidget(createTestWidget(completeForm));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Assert
|
|
expect(find.byKey(AppKeys.emailTextFieldAuthScreen), findsOneWidget);
|
|
expect(find.byKey(AppKeys.passwordTextFieldAuthScreen), findsOneWidget);
|
|
expect(find.byKey(AppKeys.signInButtonAuthScreen), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('should display loading state', (WidgetTester tester) async {
|
|
// Arrange
|
|
Widget loadingWidget = const Center(child: CircularProgressIndicator());
|
|
|
|
// Act
|
|
await tester.pumpWidget(createTestWidget(loadingWidget));
|
|
await tester.pump();
|
|
|
|
// Assert
|
|
expect(find.byType(CircularProgressIndicator), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('should display error message', (WidgetTester tester) async {
|
|
// Arrange
|
|
Widget errorWidget = const Center(child: Text('Неверный адрес электронной почты или пароль'));
|
|
|
|
// Act
|
|
await tester.pumpWidget(createTestWidget(errorWidget));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Assert
|
|
expect(find.text('Неверный адрес электронной почты или пароль'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('should handle sign in button tap', (WidgetTester tester) async {
|
|
// Arrange
|
|
bool buttonPressed = false;
|
|
Widget buttonWidget = FloatingActionButton.extended(
|
|
key: AppKeys.signInButtonAuthScreen,
|
|
onPressed: () {
|
|
buttonPressed = true;
|
|
},
|
|
label: const Text('Войти'),
|
|
);
|
|
|
|
await tester.pumpWidget(createTestWidget(buttonWidget));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Act
|
|
await tester.tap(find.byKey(AppKeys.signInButtonAuthScreen));
|
|
await tester.pump();
|
|
|
|
// Assert
|
|
expect(buttonPressed, isTrue);
|
|
});
|
|
|
|
testWidgets('should display password visibility toggle', (WidgetTester tester) async {
|
|
// Arrange
|
|
Widget passwordWidget = TextFormField(
|
|
key: AppKeys.passwordTextFieldAuthScreen,
|
|
decoration: const InputDecoration(
|
|
labelText: 'Пароль',
|
|
hintText: 'Введите пароль',
|
|
suffix: IconButton(onPressed: null, icon: Icon(Icons.visibility_outlined)),
|
|
),
|
|
obscureText: true,
|
|
);
|
|
|
|
await tester.pumpWidget(createTestWidget(passwordWidget));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Assert
|
|
expect(find.byIcon(Icons.visibility_outlined), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('should display "Забыли пароль?" link', (WidgetTester tester) async {
|
|
// Arrange
|
|
Widget forgotPasswordWidget = GestureDetector(
|
|
onTap: () {},
|
|
child: const Text('Забыли пароль?', style: TextStyle(decoration: TextDecoration.underline)),
|
|
);
|
|
|
|
// Act
|
|
await tester.pumpWidget(createTestWidget(forgotPasswordWidget));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Assert
|
|
expect(find.text('Забыли пароль?'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('should display registration link', (WidgetTester tester) async {
|
|
// Arrange
|
|
Widget registrationLinkWidget = Row(
|
|
children: [
|
|
const Text('Нет аккаунта? '),
|
|
GestureDetector(
|
|
onTap: () {},
|
|
child: const Text('Зарегистрироваться', style: TextStyle(decoration: TextDecoration.underline)),
|
|
),
|
|
],
|
|
);
|
|
|
|
// Act
|
|
await tester.pumpWidget(createTestWidget(registrationLinkWidget));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Assert
|
|
expect(find.text('Нет аккаунта? '), findsOneWidget);
|
|
expect(find.text('Зарегистрироваться'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('should display social auth buttons', (WidgetTester tester) async {
|
|
// Arrange
|
|
Widget socialButtonsWidget = Column(
|
|
children: [
|
|
const Text('Авторизация через'),
|
|
const SizedBox(height: 12),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
InkWell(
|
|
onTap: () {},
|
|
child: Container(
|
|
height: 48,
|
|
width: 80,
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(20),
|
|
border: Border.all(color: const Color(0xFFDBDBDB), width: 1),
|
|
),
|
|
child: const Center(child: Text('VK')),
|
|
),
|
|
),
|
|
InkWell(
|
|
onTap: () {},
|
|
child: Container(
|
|
height: 48,
|
|
width: 80,
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(20),
|
|
border: Border.all(color: const Color(0xFFDBDBDB), width: 1),
|
|
),
|
|
child: const Center(child: Text('OK')),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
);
|
|
|
|
// Act
|
|
await tester.pumpWidget(createTestWidget(socialButtonsWidget));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Assert
|
|
expect(find.text('Авторизация через'), findsOneWidget);
|
|
expect(find.text('VK'), findsOneWidget);
|
|
expect(find.text('OK'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('should validate email format', (WidgetTester tester) async {
|
|
// Arrange
|
|
Widget emailWidget = TextFormField(
|
|
key: AppKeys.emailTextFieldAuthScreen,
|
|
decoration: const InputDecoration(labelText: 'Email', hintText: 'Введите email', errorText: 'Введите корректный email'),
|
|
keyboardType: TextInputType.emailAddress,
|
|
);
|
|
|
|
// Act
|
|
await tester.pumpWidget(createTestWidget(emailWidget));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Assert
|
|
expect(find.text('Введите корректный email'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('should disable sign in button when loading', (WidgetTester tester) async {
|
|
// Arrange
|
|
Widget buttonWidget = const FloatingActionButton.extended(
|
|
key: AppKeys.signInButtonAuthScreen,
|
|
onPressed: null, // Disabled
|
|
label: Text('Войти'),
|
|
);
|
|
|
|
// Act
|
|
await tester.pumpWidget(createTestWidget(buttonWidget));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Assert
|
|
final button = tester.widget(find.byKey(AppKeys.signInButtonAuthScreen));
|
|
expect(button, isA<FloatingActionButton>());
|
|
});
|
|
|
|
testWidgets('should display form labels correctly', (WidgetTester tester) async {
|
|
// Arrange
|
|
Widget formWidget = const Column(children: [Text('Email'), Text('Пароль')]);
|
|
|
|
// Act
|
|
await tester.pumpWidget(createTestWidget(formWidget));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Assert
|
|
expect(find.text('Email'), findsOneWidget);
|
|
expect(find.text('Пароль'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('should display placeholder text in fields', (WidgetTester tester) async {
|
|
// Arrange
|
|
Widget formWidget = Column(
|
|
children: [
|
|
TextFormField(
|
|
key: AppKeys.emailTextFieldAuthScreen,
|
|
decoration: const InputDecoration(labelText: 'Email', hintText: 'Введите email'),
|
|
),
|
|
const SizedBox(height: 16),
|
|
TextFormField(
|
|
key: AppKeys.passwordTextFieldAuthScreen,
|
|
decoration: const InputDecoration(labelText: 'Пароль', hintText: 'Введите пароль'),
|
|
),
|
|
],
|
|
);
|
|
|
|
// Act
|
|
await tester.pumpWidget(createTestWidget(formWidget));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Assert
|
|
expect(find.text('Введите email'), findsOneWidget);
|
|
expect(find.text('Введите пароль'), findsOneWidget);
|
|
});
|
|
});
|
|
}
|