forked from eatvio/eatvio_app
chore(version): update app version to 1.3.5+85 and improve test coverage reporting in CI
This commit is contained in:
@@ -0,0 +1,258 @@
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/features/chat/models/chat_message_model.dart';
|
||||
import 'package:eatvio_app/features/chat/models/chat_room_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/widgets/chat_entry_widget.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:network_image_mock/network_image_mock.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('ChatEntryWidget', () {
|
||||
Widget createTestWidget(ChatRoom chatRoom) {
|
||||
return MaterialApp.router(
|
||||
theme: ThemeHelper().themeData(),
|
||||
localizationsDelegates: [
|
||||
S.delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
],
|
||||
supportedLocales: const [Locale('ru'), Locale('en')],
|
||||
locale: const Locale('ru'),
|
||||
routerConfig: GoRouter(
|
||||
initialLocation: '/',
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: '/',
|
||||
builder: (context, state) => Scaffold(
|
||||
body: ChatEntryWidget(chatRoom: chatRoom),
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/chatScreen',
|
||||
name: 'chatScreen',
|
||||
builder: (context, state) => Scaffold(
|
||||
appBar: AppBar(title: const Text('Chat')),
|
||||
body: Center(child: Text('Chat: ${state.extra}')),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
testWidgets('displays chat room with user name', (tester) async {
|
||||
final chatRoom = ChatRoom(
|
||||
id: 'test-id',
|
||||
users: Users(
|
||||
fromChatUser: ChatUser(
|
||||
id: 1,
|
||||
name: 'From User',
|
||||
profilePhotoPath: null,
|
||||
profilePhotoUrl: 'http://localhost/photo.jpg',
|
||||
),
|
||||
toChatUser: ChatUser(
|
||||
id: 2,
|
||||
name: 'Test User',
|
||||
profilePhotoPath: null,
|
||||
profilePhotoUrl: 'http://localhost/photo.jpg',
|
||||
),
|
||||
),
|
||||
unreadMessagesCount: 0,
|
||||
lastMessage: null,
|
||||
chosenPlan: null,
|
||||
);
|
||||
|
||||
mockNetworkImagesFor(() async {
|
||||
await tester.pumpWidget(createTestWidget(chatRoom));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Test User'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('displays chat room with last message', (tester) async {
|
||||
final chatRoom = ChatRoom(
|
||||
id: 'test-id',
|
||||
users: Users(
|
||||
fromChatUser: ChatUser(
|
||||
id: 1,
|
||||
name: 'From User',
|
||||
profilePhotoPath: null,
|
||||
profilePhotoUrl: 'http://localhost/photo.jpg',
|
||||
),
|
||||
toChatUser: ChatUser(
|
||||
id: 2,
|
||||
name: 'Test User',
|
||||
profilePhotoPath: null,
|
||||
profilePhotoUrl: 'http://localhost/photo.jpg',
|
||||
),
|
||||
),
|
||||
unreadMessagesCount: 0,
|
||||
lastMessage: ChatMessageModel(
|
||||
id: 1,
|
||||
data: 'Test message',
|
||||
updatedAt: DateTime.now(),
|
||||
isCurrentUserAuthor: false,
|
||||
mediaData: null,
|
||||
authorId: 1,
|
||||
isRead: false,
|
||||
roomId: 'test-id',
|
||||
),
|
||||
chosenPlan: null,
|
||||
);
|
||||
|
||||
mockNetworkImagesFor(() async {
|
||||
await tester.pumpWidget(createTestWidget(chatRoom));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Test message'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('displays chat room with unread messages count', (tester) async {
|
||||
final chatRoom = ChatRoom(
|
||||
id: 'test-id',
|
||||
users: Users(
|
||||
fromChatUser: ChatUser(
|
||||
id: 1,
|
||||
name: 'From User',
|
||||
profilePhotoPath: null,
|
||||
profilePhotoUrl: 'http://localhost/photo.jpg',
|
||||
),
|
||||
toChatUser: ChatUser(
|
||||
id: 2,
|
||||
name: 'Test User',
|
||||
profilePhotoPath: null,
|
||||
profilePhotoUrl: 'http://localhost/photo.jpg',
|
||||
),
|
||||
),
|
||||
unreadMessagesCount: 5,
|
||||
lastMessage: null,
|
||||
chosenPlan: null,
|
||||
);
|
||||
|
||||
mockNetworkImagesFor(() async {
|
||||
await tester.pumpWidget(createTestWidget(chatRoom));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('5'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('displays message from current user', (tester) async {
|
||||
final chatRoom = ChatRoom(
|
||||
id: 'test-id',
|
||||
users: Users(
|
||||
fromChatUser: ChatUser(
|
||||
id: 1,
|
||||
name: 'From User',
|
||||
profilePhotoPath: null,
|
||||
profilePhotoUrl: 'http://localhost/photo.jpg',
|
||||
),
|
||||
toChatUser: ChatUser(
|
||||
id: 2,
|
||||
name: 'Test User',
|
||||
profilePhotoPath: null,
|
||||
profilePhotoUrl: 'http://localhost/photo.jpg',
|
||||
),
|
||||
),
|
||||
unreadMessagesCount: 0,
|
||||
lastMessage: ChatMessageModel(
|
||||
id: 1,
|
||||
data: 'Test message',
|
||||
updatedAt: DateTime.now(),
|
||||
isCurrentUserAuthor: true,
|
||||
mediaData: null,
|
||||
authorId: 1,
|
||||
isRead: false,
|
||||
roomId: 'test-id',
|
||||
),
|
||||
chosenPlan: null,
|
||||
);
|
||||
|
||||
mockNetworkImagesFor(() async {
|
||||
await tester.pumpWidget(createTestWidget(chatRoom));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.textContaining('Вы:'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('displays media attachment message', (tester) async {
|
||||
final chatRoom = ChatRoom(
|
||||
id: 'test-id',
|
||||
users: Users(
|
||||
fromChatUser: ChatUser(
|
||||
id: 1,
|
||||
name: 'From User',
|
||||
profilePhotoPath: null,
|
||||
profilePhotoUrl: 'http://localhost/photo.jpg',
|
||||
),
|
||||
toChatUser: ChatUser(
|
||||
id: 2,
|
||||
name: 'Test User',
|
||||
profilePhotoPath: null,
|
||||
profilePhotoUrl: 'http://localhost/photo.jpg',
|
||||
),
|
||||
),
|
||||
unreadMessagesCount: 0,
|
||||
lastMessage: ChatMessageModel(
|
||||
id: 1,
|
||||
data: 'Test message',
|
||||
updatedAt: DateTime.now(),
|
||||
isCurrentUserAuthor: false,
|
||||
mediaData: [{'type': 'image', 'url': 'https://example.com/image.jpg'}],
|
||||
authorId: 1,
|
||||
isRead: false,
|
||||
roomId: 'test-id',
|
||||
),
|
||||
chosenPlan: null,
|
||||
);
|
||||
|
||||
mockNetworkImagesFor(() async {
|
||||
await tester.pumpWidget(createTestWidget(chatRoom));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.textContaining('📎 Вложение'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('truncates long user names', (tester) async {
|
||||
final longName = 'A' * 30;
|
||||
final chatRoom = ChatRoom(
|
||||
id: 'test-id',
|
||||
users: Users(
|
||||
fromChatUser: ChatUser(
|
||||
id: 1,
|
||||
name: 'From User',
|
||||
profilePhotoPath: null,
|
||||
profilePhotoUrl: 'http://localhost/photo.jpg',
|
||||
),
|
||||
toChatUser: ChatUser(
|
||||
id: 2,
|
||||
name: longName,
|
||||
profilePhotoPath: null,
|
||||
profilePhotoUrl: 'http://localhost/photo.jpg',
|
||||
),
|
||||
),
|
||||
unreadMessagesCount: 0,
|
||||
lastMessage: null,
|
||||
chosenPlan: null,
|
||||
);
|
||||
|
||||
mockNetworkImagesFor(() async {
|
||||
await tester.pumpWidget(createTestWidget(chatRoom));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.textContaining('...'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,117 +1,108 @@
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/widgets/chat_search_bar_widget.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('ChatSearchBarWidget Tests', () {
|
||||
Widget createTestWidget(Widget child) {
|
||||
return MaterialApp(
|
||||
theme: ThemeHelper().themeData(),
|
||||
localizationsDelegates: const [
|
||||
S.delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
],
|
||||
supportedLocales: const [Locale('ru')],
|
||||
home: Scaffold(body: child),
|
||||
group('ChatSearchBarWidget', () {
|
||||
testWidgets('displays search bar with default icon', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeHelper().themeData(),
|
||||
home: Scaffold(
|
||||
body: ChatSearchBarWidget(
|
||||
onSuffixIconTap: () {},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
testWidgets('ChatSearchBarWidget - отображается с дефолтными значениями', (WidgetTester tester) async {
|
||||
final widget = ChatSearchBarWidget(onSuffixIconTap: () {});
|
||||
|
||||
await tester.pumpWidget(createTestWidget(widget));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byType(TextFormField), findsOneWidget);
|
||||
expect(find.byType(ChatSearchBarWidget), findsOneWidget);
|
||||
expect(find.byIcon(Icons.search), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('ChatSearchBarWidget - вызывает onSuffixIconTap при нажатии на иконку очистки', (WidgetTester tester) async {
|
||||
testWidgets('displays custom hint text', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeHelper().themeData(),
|
||||
home: Scaffold(
|
||||
body: ChatSearchBarWidget(
|
||||
hintText: 'Search messages',
|
||||
onSuffixIconTap: () {},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.byType(ChatSearchBarWidget), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('calls onSuffixIconTap when clear button is tapped', (tester) async {
|
||||
bool suffixTapped = false;
|
||||
final controller = TextEditingController(text: 'test');
|
||||
final widget = ChatSearchBarWidget(
|
||||
controller: controller,
|
||||
onSuffixIconTap: () {
|
||||
suffixTapped = true;
|
||||
},
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeHelper().themeData(),
|
||||
home: Scaffold(
|
||||
body: ChatSearchBarWidget(
|
||||
controller: controller,
|
||||
onSuffixIconTap: () {
|
||||
suffixTapped = true;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(createTestWidget(widget));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Находим иконку очистки и нажимаем на неё
|
||||
final clearIcon = find.byIcon(Icons.clear);
|
||||
expect(clearIcon, findsOneWidget);
|
||||
await tester.tap(clearIcon);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byIcon(Icons.clear));
|
||||
await tester.pump();
|
||||
|
||||
expect(suffixTapped, isTrue);
|
||||
expect(controller.text, isEmpty);
|
||||
});
|
||||
|
||||
testWidgets('ChatSearchBarWidget - вызывает onChanged при вводе текста', (WidgetTester tester) async {
|
||||
testWidgets('clears controller when clear button is tapped', (tester) async {
|
||||
final controller = TextEditingController(text: 'test');
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeHelper().themeData(),
|
||||
home: Scaffold(
|
||||
body: ChatSearchBarWidget(
|
||||
controller: controller,
|
||||
onSuffixIconTap: () {},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(controller.text, 'test');
|
||||
await tester.tap(find.byIcon(Icons.clear));
|
||||
await tester.pump();
|
||||
|
||||
expect(controller.text, '');
|
||||
});
|
||||
|
||||
testWidgets('calls onChanged when text is entered', (tester) async {
|
||||
String? changedValue;
|
||||
final controller = TextEditingController();
|
||||
final widget = ChatSearchBarWidget(
|
||||
controller: controller,
|
||||
onChanged: (value) {
|
||||
changedValue = value;
|
||||
},
|
||||
onSuffixIconTap: () {},
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeHelper().themeData(),
|
||||
home: Scaffold(
|
||||
body: ChatSearchBarWidget(
|
||||
controller: controller,
|
||||
onChanged: (value) {
|
||||
changedValue = value;
|
||||
},
|
||||
onSuffixIconTap: () {},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(createTestWidget(widget));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.enterText(find.byType(TextFormField), 'test');
|
||||
await tester.pump();
|
||||
|
||||
await tester.enterText(find.byType(TextFormField), 'test query');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(changedValue, equals('test query'));
|
||||
});
|
||||
|
||||
testWidgets('ChatSearchBarWidget - отображает кастомный hintText', (WidgetTester tester) async {
|
||||
const hintText = 'Search chats...';
|
||||
final widget = ChatSearchBarWidget(hintText: hintText, onSuffixIconTap: () {});
|
||||
|
||||
await tester.pumpWidget(createTestWidget(widget));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text(hintText), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('ChatSearchBarWidget - использует кастомный prefix', (WidgetTester tester) async {
|
||||
const customPrefix = Icon(Icons.filter_list);
|
||||
final widget = ChatSearchBarWidget(prefix: customPrefix, onSuffixIconTap: () {});
|
||||
|
||||
await tester.pumpWidget(createTestWidget(widget));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byIcon(Icons.filter_list), findsOneWidget);
|
||||
expect(find.byIcon(Icons.search), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('ChatSearchBarWidget - использует кастомный suffix', (WidgetTester tester) async {
|
||||
bool suffixTapped = false;
|
||||
final customSuffix = IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: () {
|
||||
suffixTapped = true;
|
||||
},
|
||||
);
|
||||
final widget = ChatSearchBarWidget(suffix: customSuffix, onSuffixIconTap: () {});
|
||||
|
||||
await tester.pumpWidget(createTestWidget(widget));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.byIcon(Icons.close));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(suffixTapped, isTrue);
|
||||
expect(changedValue, 'test');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user