feat(post_creation): added multiple image posts creation and validation

This commit is contained in:
misha
2026-08-04 17:47:43 +03:00
parent 3210f38d4a
commit 04de956769
21 changed files with 2791 additions and 982 deletions

View File

@@ -14,7 +14,9 @@ void main() {
setUp(() {
blogPostRepository = FixtureBlogPostRepository();
blogPostCreateCubit = BlogPostCreateCubit(blogPostRepository: blogPostRepository);
blogPostCreateCubit = BlogPostCreateCubit(
blogPostRepository: blogPostRepository,
);
});
tearDown(() {
@@ -31,7 +33,9 @@ void main() {
);
}
testWidgets('should create BlogPostCreateCubit successfully', (WidgetTester tester) async {
testWidgets('should create BlogPostCreateCubit successfully', (
WidgetTester tester,
) async {
// Arrange & Act
final cubit = BlogPostCreateCubit(blogPostRepository: blogPostRepository);
@@ -41,13 +45,18 @@ void main() {
cubit.close();
});
testWidgets('should display basic blog post form fields', (WidgetTester tester) async {
testWidgets('should display basic blog post form fields', (
WidgetTester tester,
) async {
// Arrange
Widget formWidget = Column(
children: [
TextFormField(
key: AppKeys.blogPostCreateScreenTitleTextField,
decoration: const InputDecoration(labelText: 'Заголовок', hintText: 'Введите заголовок поста'),
decoration: const InputDecoration(
labelText: 'Заголовок',
hintText: 'Введите заголовок поста',
),
),
const SizedBox(height: 16),
TextFormField(
@@ -62,7 +71,11 @@ void main() {
decoration: const InputDecoration(labelText: 'Ссылка на видео'),
),
const SizedBox(height: 16),
ElevatedButton(key: AppKeys.blogPostCreateScreenCreateButton, onPressed: () {}, child: const Text('Опубликовать')),
ElevatedButton(
key: AppKeys.blogPostCreateScreenCreateButton,
onPressed: () {},
child: const Text('Опубликовать'),
),
],
);
@@ -71,17 +84,34 @@ void main() {
await tester.pumpAndSettle();
// Assert
expect(find.byKey(AppKeys.blogPostCreateScreenTitleTextField), findsOneWidget);
expect(find.byKey(AppKeys.blogPostCreateScreenContentTextField), findsOneWidget);
expect(find.byKey(AppKeys.blogPostCreateScreenVideoLinkTextField), findsOneWidget);
expect(find.byKey(AppKeys.blogPostCreateScreenCreateButton), findsOneWidget);
expect(
find.byKey(AppKeys.blogPostCreateScreenTitleTextField),
findsOneWidget,
);
expect(
find.byKey(AppKeys.blogPostCreateScreenContentTextField),
findsOneWidget,
);
expect(
find.byKey(AppKeys.blogPostCreateScreenVideoLinkTextField),
findsOneWidget,
);
expect(
find.byKey(AppKeys.blogPostCreateScreenCreateButton),
findsOneWidget,
);
});
testWidgets('should update title when user types in title field', (WidgetTester tester) async {
testWidgets('should update title when user types in title field', (
WidgetTester tester,
) async {
// Arrange
Widget formWidget = TextFormField(
key: AppKeys.blogPostCreateScreenTitleTextField,
decoration: const InputDecoration(labelText: 'Заголовок', hintText: 'Введите заголовок поста'),
decoration: const InputDecoration(
labelText: 'Заголовок',
hintText: 'Введите заголовок поста',
),
);
await tester.pumpWidget(createTestWidget(formWidget));
@@ -90,36 +120,47 @@ void main() {
const testTitle = 'Тестовый заголовок поста';
// Act
await tester.enterText(find.byKey(AppKeys.blogPostCreateScreenTitleTextField), testTitle);
await tester.enterText(
find.byKey(AppKeys.blogPostCreateScreenTitleTextField),
testTitle,
);
await tester.pump();
// Assert
expect(find.text(testTitle), findsOneWidget);
});
testWidgets('should update description when user types in description field', (WidgetTester tester) async {
// Arrange
Widget formWidget = TextFormField(
key: AppKeys.blogPostCreateScreenContentTextField,
decoration: const InputDecoration(labelText: 'Описание'),
maxLines: 6,
minLines: 4,
);
testWidgets(
'should update description when user types in description field',
(WidgetTester tester) async {
// Arrange
Widget formWidget = TextFormField(
key: AppKeys.blogPostCreateScreenContentTextField,
decoration: const InputDecoration(labelText: 'Описание'),
maxLines: 6,
minLines: 4,
);
await tester.pumpWidget(createTestWidget(formWidget));
await tester.pumpAndSettle();
await tester.pumpWidget(createTestWidget(formWidget));
await tester.pumpAndSettle();
const testDescription = 'Это тестовое описание блог поста';
const testDescription = 'Это тестовое описание блог поста';
// Act
await tester.enterText(find.byKey(AppKeys.blogPostCreateScreenContentTextField), testDescription);
await tester.pump();
// Act
await tester.enterText(
find.byKey(AppKeys.blogPostCreateScreenContentTextField),
testDescription,
);
await tester.pump();
// Assert
expect(find.text(testDescription), findsOneWidget);
});
// Assert
expect(find.text(testDescription), findsOneWidget);
},
);
testWidgets('should update video URL when user types in video field', (WidgetTester tester) async {
testWidgets('should update video URL when user types in video field', (
WidgetTester tester,
) async {
// Arrange
Widget formWidget = TextFormField(
key: AppKeys.blogPostCreateScreenVideoLinkTextField,
@@ -132,16 +173,27 @@ void main() {
const testVideoUrl = 'https://youtube.com/watch?v=example';
// Act
await tester.enterText(find.byKey(AppKeys.blogPostCreateScreenVideoLinkTextField), testVideoUrl);
await tester.enterText(
find.byKey(AppKeys.blogPostCreateScreenVideoLinkTextField),
testVideoUrl,
);
await tester.pump();
// Assert
expect(find.text(testVideoUrl), findsOneWidget);
});
testWidgets('should display form labels correctly', (WidgetTester tester) async {
testWidgets('should display form labels correctly', (
WidgetTester tester,
) async {
// Arrange
Widget formWidget = const Column(children: [Text('Заголовок'), Text('Описание'), Text('Ссылка на видео')]);
Widget formWidget = const Column(
children: [
Text('Заголовок'),
Text('Описание'),
Text('Ссылка на видео'),
],
);
// Act
await tester.pumpWidget(createTestWidget(formWidget));
@@ -153,11 +205,16 @@ void main() {
expect(find.text('Ссылка на видео'), findsOneWidget);
});
testWidgets('should display placeholder text in title field', (WidgetTester tester) async {
testWidgets('should display placeholder text in title field', (
WidgetTester tester,
) async {
// Arrange
Widget formWidget = TextFormField(
key: AppKeys.blogPostCreateScreenTitleTextField,
decoration: const InputDecoration(labelText: 'Заголовок', hintText: 'Введите заголовок поста'),
decoration: const InputDecoration(
labelText: 'Заголовок',
hintText: 'Введите заголовок поста',
),
);
// Act
@@ -170,14 +227,21 @@ void main() {
testWidgets('should display create button', (WidgetTester tester) async {
// Arrange
Widget formWidget = ElevatedButton(key: AppKeys.blogPostCreateScreenCreateButton, onPressed: () {}, child: const Text('Опубликовать'));
Widget formWidget = ElevatedButton(
key: AppKeys.blogPostCreateScreenCreateButton,
onPressed: () {},
child: const Text('Опубликовать'),
);
// Act
await tester.pumpWidget(createTestWidget(formWidget));
await tester.pumpAndSettle();
// Assert
expect(find.byKey(AppKeys.blogPostCreateScreenCreateButton), findsOneWidget);
expect(
find.byKey(AppKeys.blogPostCreateScreenCreateButton),
findsOneWidget,
);
expect(find.text('Опубликовать'), findsOneWidget);
});
@@ -217,19 +281,26 @@ void main() {
testWidgets('should display error message', (WidgetTester tester) async {
// Arrange
Widget errorWidget = const Center(child: Text('Произошла ошибка при создании блог поста'));
Widget errorWidget = const Center(
child: Text('Произошла ошибка при создании блог поста'),
);
// Act
await tester.pumpWidget(createTestWidget(errorWidget));
await tester.pumpAndSettle();
// Assert
expect(find.text('Произошла ошибка при создании блог поста'), findsOneWidget);
expect(
find.text('Произошла ошибка при создании блог поста'),
findsOneWidget,
);
});
testWidgets('should display success message', (WidgetTester tester) async {
// Arrange
Widget successWidget = const Center(child: Text('Блог пост успешно создан!'));
Widget successWidget = const Center(
child: Text('Блог пост успешно создан!'),
);
// Act
await tester.pumpWidget(createTestWidget(successWidget));
@@ -245,12 +316,18 @@ void main() {
children: [
TextFormField(
key: AppKeys.blogPostCreateScreenTitleTextField,
decoration: const InputDecoration(labelText: 'Заголовок', errorText: 'Заголовок обязателен'),
decoration: const InputDecoration(
labelText: 'Заголовок',
errorText: 'Заголовок обязателен',
),
),
const SizedBox(height: 16),
TextFormField(
key: AppKeys.blogPostCreateScreenContentTextField,
decoration: const InputDecoration(labelText: 'Описание', errorText: 'Описание обязательно'),
decoration: const InputDecoration(
labelText: 'Описание',
errorText: 'Описание обязательно',
),
),
],
);
@@ -264,13 +341,18 @@ void main() {
expect(find.text('Описание обязательно'), findsOneWidget);
});
testWidgets('should display form with all required fields', (WidgetTester tester) async {
testWidgets('should display form with all required fields', (
WidgetTester tester,
) async {
// Arrange
Widget completeForm = Column(
children: [
TextFormField(
key: AppKeys.blogPostCreateScreenTitleTextField,
decoration: const InputDecoration(labelText: 'Заголовок', hintText: 'Введите заголовок поста'),
decoration: const InputDecoration(
labelText: 'Заголовок',
hintText: 'Введите заголовок поста',
),
),
const SizedBox(height: 16),
TextFormField(
@@ -285,7 +367,11 @@ void main() {
decoration: const InputDecoration(labelText: 'Ссылка на видео'),
),
const SizedBox(height: 32),
ElevatedButton(key: AppKeys.blogPostCreateScreenCreateButton, onPressed: () {}, child: const Text('Опубликовать')),
ElevatedButton(
key: AppKeys.blogPostCreateScreenCreateButton,
onPressed: () {},
child: const Text('Опубликовать'),
),
],
);
@@ -294,13 +380,27 @@ void main() {
await tester.pumpAndSettle();
// Assert
expect(find.byKey(AppKeys.blogPostCreateScreenTitleTextField), findsOneWidget);
expect(find.byKey(AppKeys.blogPostCreateScreenContentTextField), findsOneWidget);
expect(find.byKey(AppKeys.blogPostCreateScreenVideoLinkTextField), findsOneWidget);
expect(find.byKey(AppKeys.blogPostCreateScreenCreateButton), findsOneWidget);
expect(
find.byKey(AppKeys.blogPostCreateScreenTitleTextField),
findsOneWidget,
);
expect(
find.byKey(AppKeys.blogPostCreateScreenContentTextField),
findsOneWidget,
);
expect(
find.byKey(AppKeys.blogPostCreateScreenVideoLinkTextField),
findsOneWidget,
);
expect(
find.byKey(AppKeys.blogPostCreateScreenCreateButton),
findsOneWidget,
);
});
testWidgets('should display image upload widget', (WidgetTester tester) async {
testWidgets('should display image upload widget', (
WidgetTester tester,
) async {
// Arrange
Widget imageWidget = GestureDetector(
key: AppKeys.imageWidget,
@@ -373,68 +473,101 @@ void main() {
expect(imageUploadTapped, isTrue);
});
testWidgets('should display blog post creation form with image and video options', (WidgetTester tester) async {
// Arrange
Widget completeForm = Column(
children: [
const Text('Заголовок'),
const SizedBox(height: 8),
TextFormField(
key: AppKeys.blogPostCreateScreenTitleTextField,
decoration: const InputDecoration(hintText: 'Введите заголовок поста'),
),
const SizedBox(height: 16),
const Text('Описание'),
const SizedBox(height: 8),
TextFormField(key: AppKeys.blogPostCreateScreenContentTextField, decoration: const InputDecoration(), maxLines: 6, minLines: 4),
const SizedBox(height: 16),
const Text('Изображение поста'),
const SizedBox(height: 8),
GestureDetector(
key: AppKeys.imageWidget,
onTap: () {},
child: Container(
height: 200,
width: double.infinity,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(8),
testWidgets(
'should display blog post creation form with image and video options',
(WidgetTester tester) async {
// Arrange
Widget completeForm = Column(
children: [
const Text('Заголовок'),
const SizedBox(height: 8),
TextFormField(
key: AppKeys.blogPostCreateScreenTitleTextField,
decoration: const InputDecoration(
hintText: 'Введите заголовок поста',
),
child: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.add_photo_alternate, size: 48, color: Colors.grey),
SizedBox(height: 8),
Text('Добавить изображение'),
],
),
const SizedBox(height: 16),
const Text('Описание'),
const SizedBox(height: 8),
TextFormField(
key: AppKeys.blogPostCreateScreenContentTextField,
decoration: const InputDecoration(),
maxLines: 6,
minLines: 4,
),
const SizedBox(height: 16),
const Text('Изображение поста'),
const SizedBox(height: 8),
GestureDetector(
key: AppKeys.imageWidget,
onTap: () {},
child: Container(
height: 200,
width: double.infinity,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(8),
),
child: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.add_photo_alternate,
size: 48,
color: Colors.grey,
),
SizedBox(height: 8),
Text('Добавить изображение'),
],
),
),
),
),
),
const SizedBox(height: 16),
const Text('Ссылка на видео'),
const SizedBox(height: 8),
TextFormField(key: AppKeys.blogPostCreateScreenVideoLinkTextField, decoration: const InputDecoration()),
const SizedBox(height: 32),
ElevatedButton(key: AppKeys.blogPostCreateScreenCreateButton, onPressed: () {}, child: const Text('Опубликовать')),
],
);
const SizedBox(height: 16),
const Text('Ссылка на видео'),
const SizedBox(height: 8),
TextFormField(
key: AppKeys.blogPostCreateScreenVideoLinkTextField,
decoration: const InputDecoration(),
),
const SizedBox(height: 32),
ElevatedButton(
key: AppKeys.blogPostCreateScreenCreateButton,
onPressed: () {},
child: const Text('Опубликовать'),
),
],
);
// Act
await tester.pumpWidget(createTestWidget(completeForm));
await tester.pumpAndSettle();
// Act
await tester.pumpWidget(createTestWidget(completeForm));
await tester.pumpAndSettle();
// Assert
expect(find.text('Заголовок'), findsOneWidget);
expect(find.text('Описание'), findsOneWidget);
expect(find.text('Изображение поста'), findsOneWidget);
expect(find.text('Ссылка на видео'), findsOneWidget);
expect(find.byKey(AppKeys.blogPostCreateScreenTitleTextField), findsOneWidget);
expect(find.byKey(AppKeys.blogPostCreateScreenContentTextField), findsOneWidget);
expect(find.byKey(AppKeys.imageWidget), findsOneWidget);
expect(find.byKey(AppKeys.blogPostCreateScreenVideoLinkTextField), findsOneWidget);
expect(find.byKey(AppKeys.blogPostCreateScreenCreateButton), findsOneWidget);
});
// Assert
expect(find.text('Заголовок'), findsOneWidget);
expect(find.text('Описание'), findsOneWidget);
expect(find.text('Изображение поста'), findsOneWidget);
expect(find.text('Ссылка на видео'), findsOneWidget);
expect(
find.byKey(AppKeys.blogPostCreateScreenTitleTextField),
findsOneWidget,
);
expect(
find.byKey(AppKeys.blogPostCreateScreenContentTextField),
findsOneWidget,
);
expect(find.byKey(AppKeys.imageWidget), findsOneWidget);
expect(
find.byKey(AppKeys.blogPostCreateScreenVideoLinkTextField),
findsOneWidget,
);
expect(
find.byKey(AppKeys.blogPostCreateScreenCreateButton),
findsOneWidget,
);
},
);
});
}