TF-2528 Add integration test for search email with sort by sender nam…e ascending
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:patrol/patrol.dart';
|
||||
|
||||
abstract class BaseScenario {
|
||||
@@ -6,4 +7,9 @@ abstract class BaseScenario {
|
||||
const BaseScenario(this.$);
|
||||
|
||||
Future<void> execute();
|
||||
|
||||
Future<void> expectViewVisible(PatrolFinder patrolFinder) async {
|
||||
await $.waitUntilVisible(patrolFinder);
|
||||
expect(patrolFinder, findsWidgets);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:patrol/patrol.dart';
|
||||
|
||||
abstract class CoreRobot {
|
||||
@@ -6,10 +5,5 @@ abstract class CoreRobot {
|
||||
|
||||
CoreRobot(this.$);
|
||||
|
||||
Future<void> ensureViewVisible(PatrolFinder patrolFinder) async {
|
||||
await $.waitUntilVisible(patrolFinder);
|
||||
expect(patrolFinder, findsWidgets);
|
||||
}
|
||||
|
||||
dynamic ignoreException() => $.tester.takeException();
|
||||
}
|
||||
@@ -50,10 +50,6 @@ class ComposerRobot extends CoreRobot {
|
||||
.tap();
|
||||
}
|
||||
|
||||
Future<void> expectSendEmailSuccessToast() async {
|
||||
expect($('Message has been sent successfully'), findsOneWidget);
|
||||
}
|
||||
|
||||
Future<void> grantContactPermission() async {
|
||||
if (await $.native.isPermissionDialogVisible(timeout: const Duration(seconds: 5))) {
|
||||
await $.native.grantPermissionWhenInUse();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import 'package:core/presentation/views/text/type_ahead_form_field_builder.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:patrol/patrol.dart';
|
||||
import 'package:tmail_ui_user/features/login/domain/model/recent_login_username.dart';
|
||||
import 'package:tmail_ui_user/features/login/presentation/login_view.dart';
|
||||
import 'package:tmail_ui_user/features/login/presentation/widgets/login_text_input_builder.dart';
|
||||
import 'package:tmail_ui_user/features/starting_page/presentation/twake_welcome/twake_welcome_view.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
import '../base/core_robot.dart';
|
||||
@@ -11,15 +11,17 @@ import '../base/core_robot.dart';
|
||||
class LoginRobot extends CoreRobot {
|
||||
LoginRobot(super.$);
|
||||
|
||||
Future<void> expectWelcomeViewVisible() => ensureViewVisible($(TwakeWelcomeView));
|
||||
Future<void> grantNotificationPermission(NativeAutomator nativeAutomator) async {
|
||||
if (await nativeAutomator.isPermissionDialogVisible(timeout: const Duration(seconds: 5))) {
|
||||
await nativeAutomator.grantPermissionWhenInUse();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> tapOnUseCompanyServer() async {
|
||||
await $.pumpAndSettle();
|
||||
await $(AppLocalizations().useCompanyServer).tap();
|
||||
}
|
||||
|
||||
Future<void> expectLoginViewVisible() => ensureViewVisible($(LoginView));
|
||||
|
||||
Future<void> enterEmail(String email) async {
|
||||
final finder = $(LoginView).$(TextField);
|
||||
await finder.enterText(email);
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../base/core_robot.dart';
|
||||
|
||||
class SearchRobot extends CoreRobot {
|
||||
SearchRobot(super.$);
|
||||
|
||||
Future<void> enterQueryString(String queryString) async {
|
||||
await $(#search_email_text_field).enterText(queryString);
|
||||
}
|
||||
|
||||
Future<void> scrollToEndListSearchFilter() async {
|
||||
await $.scrollUntilVisible(
|
||||
finder: $(#mobile_sortBy_search_filter_button),
|
||||
view: $(#search_filter_list_view),
|
||||
scrollDirection: AxisDirection.right,
|
||||
delta: 300,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> openSortOrderBottomDialog() async {
|
||||
await $(#mobile_sortBy_search_filter_button).tap();
|
||||
}
|
||||
|
||||
Future<void> selectSortOrder(String sortOrderName) async {
|
||||
await $(find.text(sortOrderName)).tap();
|
||||
await $.pump(const Duration(seconds: 2));
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,17 @@
|
||||
import 'package:core/presentation/views/search/search_bar_view.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tmail_ui_user/features/base/widget/compose_floating_button.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/composer_view.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/thread_view.dart';
|
||||
|
||||
import '../base/core_robot.dart';
|
||||
|
||||
class ThreadRobot extends CoreRobot {
|
||||
ThreadRobot(super.$);
|
||||
|
||||
Future<void> expectThreadViewVisible() => ensureViewVisible($(ThreadView));
|
||||
|
||||
Future<void> openComposer() async {
|
||||
await $(ComposeFloatingButton).$(InkWell).tap();
|
||||
}
|
||||
|
||||
Future<void> expectComposerViewVisible() => ensureViewVisible($(ComposerView));
|
||||
Future<void> openSearchView() async {
|
||||
await $(SearchBarView).$(InkWell).tap();
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
import 'package:tmail_ui_user/features/login/presentation/login_view.dart';
|
||||
import 'package:tmail_ui_user/features/starting_page/presentation/twake_welcome/twake_welcome_view.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/thread_view.dart';
|
||||
|
||||
import '../base/base_scenario.dart';
|
||||
import '../robots/login_robot.dart';
|
||||
import '../robots/thread_robot.dart';
|
||||
import '../utils/scenario_utils_mixin.dart';
|
||||
|
||||
class LoginWithBasicAuthScenario extends BaseScenario with ScenarioUtilsMixin {
|
||||
class LoginWithBasicAuthScenario extends BaseScenario {
|
||||
const LoginWithBasicAuthScenario(
|
||||
super.$,
|
||||
{
|
||||
@@ -22,12 +24,12 @@ class LoginWithBasicAuthScenario extends BaseScenario with ScenarioUtilsMixin {
|
||||
@override
|
||||
Future<void> execute() async {
|
||||
final loginRobot = LoginRobot($);
|
||||
final threadRobot = ThreadRobot($);
|
||||
|
||||
await loginRobot.expectWelcomeViewVisible();
|
||||
await _expectWelcomeViewVisible();
|
||||
|
||||
await loginRobot.tapOnUseCompanyServer();
|
||||
await _expectLoginViewVisible();
|
||||
|
||||
await loginRobot.expectLoginViewVisible();
|
||||
await loginRobot.enterEmail(username);
|
||||
await loginRobot.enterHostUrl(hostUrl);
|
||||
|
||||
@@ -35,8 +37,14 @@ class LoginWithBasicAuthScenario extends BaseScenario with ScenarioUtilsMixin {
|
||||
await loginRobot.enterBasicAuthPassword(password);
|
||||
await loginRobot.loginBasicAuth();
|
||||
|
||||
await grantNotificationPermission($.native);
|
||||
await loginRobot.grantNotificationPermission($.native);
|
||||
|
||||
await threadRobot.expectThreadViewVisible();
|
||||
await _expectThreadViewVisible();
|
||||
}
|
||||
|
||||
Future<void> _expectWelcomeViewVisible() => expectViewVisible($(TwakeWelcomeView));
|
||||
|
||||
Future<void> _expectLoginViewVisible() => expectViewVisible($(LoginView));
|
||||
|
||||
Future<void> _expectThreadViewVisible() => expectViewVisible($(ThreadView));
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:core/domain/extensions/list_datetime_extension.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/search/email_sort_order_type.dart';
|
||||
import 'package:tmail_ui_user/features/search/email/presentation/search_email_view.dart';
|
||||
import 'package:tmail_ui_user/features/thread/presentation/widgets/email_tile_builder.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
import '../base/base_scenario.dart';
|
||||
import '../robots/search_robot.dart';
|
||||
import '../robots/thread_robot.dart';
|
||||
import 'login_with_basic_auth_scenario.dart';
|
||||
|
||||
class SearchEmailWithSortOrderScenario extends BaseScenario {
|
||||
const SearchEmailWithSortOrderScenario(
|
||||
super.$,
|
||||
{
|
||||
required this.loginWithBasicAuthScenario,
|
||||
required this.queryString,
|
||||
required this.listUsername,
|
||||
}
|
||||
);
|
||||
|
||||
final LoginWithBasicAuthScenario loginWithBasicAuthScenario;
|
||||
final String queryString;
|
||||
final List<String> listUsername;
|
||||
|
||||
@override
|
||||
Future<void> execute() async {
|
||||
await loginWithBasicAuthScenario.execute();
|
||||
|
||||
final threadRobot = ThreadRobot($);
|
||||
await threadRobot.openSearchView();
|
||||
await _expectSearchViewVisible();
|
||||
|
||||
final searchRobot = SearchRobot($);
|
||||
await searchRobot.enterQueryString(queryString);
|
||||
await _expectSuggestionSearchListViewVisible();
|
||||
|
||||
await searchRobot.scrollToEndListSearchFilter();
|
||||
await _expectSortBySearchFilterButtonVisible();
|
||||
|
||||
final appLocalizations = AppLocalizations();
|
||||
|
||||
for (var sortOrderType in EmailSortOrderType.values) {
|
||||
await _performSelectSortOrderAndValidateSearchResult(
|
||||
searchRobot: searchRobot,
|
||||
sortOrderType: sortOrderType,
|
||||
appLocalizations: appLocalizations,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _performSelectSortOrderAndValidateSearchResult({
|
||||
required SearchRobot searchRobot,
|
||||
required EmailSortOrderType sortOrderType,
|
||||
required AppLocalizations appLocalizations,
|
||||
}) async {
|
||||
await Future.delayed(const Duration(seconds: 2));
|
||||
|
||||
await searchRobot.openSortOrderBottomDialog();
|
||||
await _expectSortFilterContextMenuVisible();
|
||||
|
||||
await searchRobot.selectSortOrder(sortOrderType.getTitleByAppLocalizations(appLocalizations));
|
||||
await _expectSearchResultEmailListVisible();
|
||||
await _expectEmailListDisplayedCorrectly(listUsername: listUsername);
|
||||
|
||||
switch (sortOrderType) {
|
||||
case EmailSortOrderType.mostRecent:
|
||||
await _expectEmailListSortedCorrectByMostRecent();
|
||||
break;
|
||||
case EmailSortOrderType.oldest:
|
||||
await _expectEmailListSortedCorrectByOldest();
|
||||
break;
|
||||
case EmailSortOrderType.senderAscending:
|
||||
await _expectEmailListSortedCorrectBySenderAscending(listUsername: listUsername);
|
||||
break;
|
||||
case EmailSortOrderType.senderDescending:
|
||||
await _expectEmailListSortedCorrectBySenderDescending(listUsername: listUsername);
|
||||
break;
|
||||
case EmailSortOrderType.subjectAscending:
|
||||
await _expectEmailListSortedCorrectBySubjectAscending(listUsername: listUsername);
|
||||
break;
|
||||
case EmailSortOrderType.subjectDescending:
|
||||
await _expectEmailListSortedCorrectBySubjectDescending(listUsername: listUsername);
|
||||
break;
|
||||
case EmailSortOrderType.relevance:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _expectSearchViewVisible() async {
|
||||
await expectViewVisible($(SearchEmailView));
|
||||
}
|
||||
|
||||
Future<void> _expectSuggestionSearchListViewVisible() async {
|
||||
await expectViewVisible($(#suggestion_search_list_view));
|
||||
}
|
||||
|
||||
Future<void> _expectSortBySearchFilterButtonVisible() async {
|
||||
await expectViewVisible($(#mobile_sortBy_search_filter_button));
|
||||
}
|
||||
|
||||
Future<void> _expectSortFilterContextMenuVisible() async {
|
||||
await expectViewVisible($(#sort_filter_context_menu));
|
||||
}
|
||||
|
||||
Future<void> _expectSearchResultEmailListVisible() async {
|
||||
await expectViewVisible($(#search_email_list_notification_listener));
|
||||
}
|
||||
|
||||
Future<void> _expectEmailListDisplayedCorrectly({
|
||||
required List<String> listUsername,
|
||||
}) async {
|
||||
expect(find.byType(EmailTileBuilder), findsNWidgets(listUsername.length));
|
||||
}
|
||||
|
||||
Future<void> _expectEmailListSortedCorrectBySenderAscending({
|
||||
required List<String> listUsername,
|
||||
}) async {
|
||||
final listEmailTile = $.tester
|
||||
.widgetList<EmailTileBuilder>(find.byType(EmailTileBuilder));
|
||||
|
||||
for (int i = 0; i < listUsername.length; i++) {
|
||||
EmailTileBuilder emailTile = listEmailTile.elementAt(i);
|
||||
final senderName = emailTile.presentationEmail.firstEmailAddressInFrom;
|
||||
expect(senderName, equals('${listUsername[i].toLowerCase()}@example.com'));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _expectEmailListSortedCorrectBySenderDescending({
|
||||
required List<String> listUsername,
|
||||
}) async {
|
||||
final listEmailTile = $.tester
|
||||
.widgetList<EmailTileBuilder>(find.byType(EmailTileBuilder));
|
||||
|
||||
final reversedListUsername = listUsername.reversed.toList();
|
||||
|
||||
for (int i = 0; i < reversedListUsername.length; i++) {
|
||||
EmailTileBuilder emailTile = listEmailTile.elementAt(i);
|
||||
final senderName = emailTile.presentationEmail.firstEmailAddressInFrom;
|
||||
expect(senderName, equals('${reversedListUsername[i].toLowerCase()}@example.com'));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _expectEmailListSortedCorrectBySubjectAscending({
|
||||
required List<String> listUsername,
|
||||
}) async {
|
||||
final listEmailTile = $.tester
|
||||
.widgetList<EmailTileBuilder>(find.byType(EmailTileBuilder));
|
||||
|
||||
for (int i = 0; i < listUsername.length; i++) {
|
||||
EmailTileBuilder emailTile = listEmailTile.elementAt(i);
|
||||
final subject = emailTile.presentationEmail.subject;
|
||||
expect(subject, equals('${listUsername[i]} send Bob'));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _expectEmailListSortedCorrectBySubjectDescending({
|
||||
required List<String> listUsername,
|
||||
}) async {
|
||||
final listEmailTile = $.tester
|
||||
.widgetList<EmailTileBuilder>(find.byType(EmailTileBuilder));
|
||||
|
||||
final reversedListUsername = listUsername.reversed.toList();
|
||||
|
||||
for (int i = 0; i < reversedListUsername.length; i++) {
|
||||
EmailTileBuilder emailTile = listEmailTile.elementAt(i);
|
||||
final subject = emailTile.presentationEmail.subject;
|
||||
expect(subject, equals('${reversedListUsername[i]} send Bob'));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _expectEmailListSortedCorrectByMostRecent() async {
|
||||
final listEmailTile = $.tester
|
||||
.widgetList<EmailTileBuilder>(find.byType(EmailTileBuilder));
|
||||
|
||||
final listReceiveAtTime = listEmailTile
|
||||
.map((emailTile) => emailTile.presentationEmail.receivedAt?.value)
|
||||
.whereNotNull()
|
||||
.toList();
|
||||
|
||||
expect(listReceiveAtTime.isSortedByMostRecent(), isTrue);
|
||||
}
|
||||
|
||||
Future<void> _expectEmailListSortedCorrectByOldest() async {
|
||||
final listEmailTile = $.tester
|
||||
.widgetList<EmailTileBuilder>(find.byType(EmailTileBuilder));
|
||||
|
||||
final listReceiveAtTime = listEmailTile
|
||||
.map((emailTile) => emailTile.presentationEmail.receivedAt?.value)
|
||||
.whereNotNull()
|
||||
.toList();
|
||||
|
||||
expect(listReceiveAtTime.isSortedByOldestFirst(), isTrue);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/composer_view.dart';
|
||||
|
||||
import '../base/base_scenario.dart';
|
||||
import '../robots/composer_robot.dart';
|
||||
import '../robots/thread_robot.dart';
|
||||
@@ -27,7 +30,7 @@ class SendEmailScenario extends BaseScenario {
|
||||
await loginWithBasicAuthScenario.execute();
|
||||
|
||||
await threadRobot.openComposer();
|
||||
await threadRobot.expectComposerViewVisible();
|
||||
await _expectComposerViewVisible();
|
||||
|
||||
await composerRobot.grantContactPermission();
|
||||
|
||||
@@ -36,6 +39,13 @@ class SendEmailScenario extends BaseScenario {
|
||||
await composerRobot.addSubject(subject);
|
||||
await composerRobot.addContent(content);
|
||||
await composerRobot.sendEmail();
|
||||
await composerRobot.expectSendEmailSuccessToast();
|
||||
|
||||
await _expectSendEmailSuccessToast();
|
||||
}
|
||||
|
||||
Future<void> _expectComposerViewVisible() => expectViewVisible($(ComposerView));
|
||||
|
||||
Future<void> _expectSendEmailSuccessToast() async {
|
||||
expect($('Message has been sent successfully'), findsOneWidget);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import '../../base/test_base.dart';
|
||||
import '../../scenarios/login_with_basic_auth_scenario.dart';
|
||||
import '../../scenarios/search_email_with_sort_order_scenario.dart';
|
||||
|
||||
void main() {
|
||||
TestBase().runPatrolTest(
|
||||
description: 'Should see list email displayed by sort order selected when search email successfully',
|
||||
test: ($) async {
|
||||
const username = String.fromEnvironment('USERNAME');
|
||||
const password = String.fromEnvironment('PASSWORD');
|
||||
const hostUrl = String.fromEnvironment('BASIC_AUTH_URL');
|
||||
const email = String.fromEnvironment('BASIC_AUTH_EMAIL');
|
||||
|
||||
final loginWithBasicAuthScenario = LoginWithBasicAuthScenario(
|
||||
$,
|
||||
username: username,
|
||||
password: password,
|
||||
hostUrl: hostUrl,
|
||||
email: email,
|
||||
);
|
||||
|
||||
const queryString = 'hello';
|
||||
const listUsername = ['Alice', 'Brian', 'Charlotte', 'David', 'Emma'];
|
||||
|
||||
final searchEmailWithSortOrderScenario = SearchEmailWithSortOrderScenario(
|
||||
$,
|
||||
loginWithBasicAuthScenario: loginWithBasicAuthScenario,
|
||||
queryString: queryString,
|
||||
listUsername: listUsername
|
||||
);
|
||||
|
||||
await searchEmailWithSortOrderScenario.execute();
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import 'package:patrol/patrol.dart';
|
||||
|
||||
mixin ScenarioUtilsMixin {
|
||||
Future<void> grantNotificationPermission(NativeAutomator nativeAutomator) async {
|
||||
if (await nativeAutomator.isPermissionDialogVisible(timeout: const Duration(seconds: 5))) {
|
||||
await nativeAutomator.grantPermissionWhenInUse();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user