From abdcb614ce436afc084ad97cec0a360dff6558bc Mon Sep 17 00:00:00 2001 From: dab246 Date: Fri, 21 Feb 2025 01:51:19 +0700 Subject: [PATCH] TF-3493 Refactor integration test code for performance and maintainability Signed-off-by: dab246 --- integration_test/base/base_test_scenario.dart | 18 +++++++++ integration_test/base/test_base.dart | 33 +++++++++++------ .../mixin/requires_login_mixin.dart | 15 ++++++++ .../scenario_utils_mixin.dart | 0 .../scenarios/app_grid_scenario.dart | 18 ++------- .../download_all_attachments_scenario.dart | 23 ++++-------- .../scenarios/forward_email_scenario.dart | 17 ++------- .../no_disposition_inline_scenario.dart | 16 ++------ ...ime_and_sort_order_relevance_scenario.dart | 35 ++++++++---------- ...search_email_with_sort_order_scenario.dart | 23 +++--------- .../search_result_highlights_scenario.dart | 30 ++++++--------- ...search_suggestion_highlights_scenario.dart | 32 +++++++--------- .../scenarios/send_email_scenario.dart | 31 +++++----------- .../web_socket_update_ui_scenario.dart | 26 +++++-------- .../tests/app_grid/app_grid_test.dart | 17 +-------- .../download_all_attachments_test.dart | 17 +-------- .../no_disposition_inline_test.dart | 16 +------- .../tests/compose/forward_email_test.dart | 16 +------- .../tests/compose/send_email_test.dart | 17 +-------- .../login/login_with_basic_auth_test.dart | 17 ++++----- ...te_time_and_sort_order_relevance_test.dart | 37 +------------------ .../search_email_with_sort_order_test.dart | 28 +------------- .../search/search_result_highlights_test.dart | 29 +-------------- .../search_suggestion_highlights_test.dart | 29 +-------------- .../tests/web_socket/web_socket_test.dart | 18 +-------- 25 files changed, 157 insertions(+), 401 deletions(-) create mode 100644 integration_test/base/base_test_scenario.dart create mode 100644 integration_test/mixin/requires_login_mixin.dart rename integration_test/{utils => mixin}/scenario_utils_mixin.dart (100%) diff --git a/integration_test/base/base_test_scenario.dart b/integration_test/base/base_test_scenario.dart new file mode 100644 index 000000000..30ed32f58 --- /dev/null +++ b/integration_test/base/base_test_scenario.dart @@ -0,0 +1,18 @@ + +import '../mixin/requires_login_mixin.dart'; +import '../mixin/scenario_utils_mixin.dart'; +import 'base_scenario.dart'; + +abstract class BaseTestScenario extends BaseScenario + with RequiresLoginMixin, ScenarioUtilsMixin { + + const BaseTestScenario(super.$); + + @override + Future execute() async { + await executeLoginScenario(); + await runTestLogic(); + } + + Future runTestLogic(); +} diff --git a/integration_test/base/test_base.dart b/integration_test/base/test_base.dart index bc62afb9f..50cddf73a 100644 --- a/integration_test/base/test_base.dart +++ b/integration_test/base/test_base.dart @@ -3,10 +3,17 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:patrol/patrol.dart'; import 'package:tmail_ui_user/main.dart' as app; +import 'base_scenario.dart'; + class TestBase { + static final TestBase _instance = TestBase._internal(); + factory TestBase() => _instance; + + TestBase._internal(); + void runPatrolTest({ required String description, - required Function(PatrolIntegrationTester $) test, + required BaseScenario Function(PatrolIntegrationTester $) scenarioBuilder, }) { patrolTest( description, @@ -19,15 +26,19 @@ class TestBase { findTimeout: Duration(seconds: 10), ), framePolicy: LiveTestWidgetsFlutterBindingFramePolicy.benchmarkLive, - ($) async { - await app.runTmail(); - // https://github.com/leancodepl/patrol/issues/1602#issuecomment-1665317814 - final originalOnError = FlutterError.onError!; - FlutterError.onError = (FlutterErrorDetails details) { - originalOnError(details); - }; - - await test($); - }); + ($) async { + await setupTest(); + await scenarioBuilder($).execute(); + }, + ); + } + + Future setupTest() async { + await app.runTmail(); + + final originalOnError = FlutterError.onError!; + FlutterError.onError = (FlutterErrorDetails details) { + originalOnError(details); + }; } } \ No newline at end of file diff --git a/integration_test/mixin/requires_login_mixin.dart b/integration_test/mixin/requires_login_mixin.dart new file mode 100644 index 000000000..286282aa4 --- /dev/null +++ b/integration_test/mixin/requires_login_mixin.dart @@ -0,0 +1,15 @@ +import '../base/base_scenario.dart'; +import '../scenarios/login_with_basic_auth_scenario.dart'; + +mixin RequiresLoginMixin on BaseScenario { + Future executeLoginScenario() async { + final loginScenario = LoginWithBasicAuthScenario( + $, + username: const String.fromEnvironment('USERNAME'), + hostUrl: const String.fromEnvironment('BASIC_AUTH_URL'), + email: const String.fromEnvironment('BASIC_AUTH_EMAIL'), + password: const String.fromEnvironment('PASSWORD'), + ); + await loginScenario.execute(); + } +} \ No newline at end of file diff --git a/integration_test/utils/scenario_utils_mixin.dart b/integration_test/mixin/scenario_utils_mixin.dart similarity index 100% rename from integration_test/utils/scenario_utils_mixin.dart rename to integration_test/mixin/scenario_utils_mixin.dart diff --git a/integration_test/scenarios/app_grid_scenario.dart b/integration_test/scenarios/app_grid_scenario.dart index bdb5b9e53..35ea60673 100644 --- a/integration_test/scenarios/app_grid_scenario.dart +++ b/integration_test/scenarios/app_grid_scenario.dart @@ -5,31 +5,21 @@ import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_view.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/widgets/app_grid_view.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/widgets/app_dashboard/app_list_dashboard_item.dart'; -import '../base/base_scenario.dart'; +import '../base/base_test_scenario.dart'; import '../robots/app_grid_robot.dart'; import '../robots/mailbox_menu_robot.dart'; import '../robots/thread_robot.dart'; -import 'login_with_basic_auth_scenario.dart'; -class AppGridScenario extends BaseScenario { +class AppGridScenario extends BaseTestScenario { - final LoginWithBasicAuthScenario loginWithBasicAuthScenario; - - AppGridScenario( - super.$, - { - required this.loginWithBasicAuthScenario - } - ); + const AppGridScenario(super.$); @override - Future execute() async { + Future runTestLogic() async { final threadRobot = ThreadRobot($); final mailboxMenuRobot = MailboxMenuRobot($); final appGridRobot = AppGridRobot($); - await loginWithBasicAuthScenario.execute(); - await threadRobot.openMailbox(); await _expectMailboxViewVisible(); await _expectAppGridViewVisible(); diff --git a/integration_test/scenarios/download_all_attachments_scenario.dart b/integration_test/scenarios/download_all_attachments_scenario.dart index c1d197e97..4bb6a1d70 100644 --- a/integration_test/scenarios/download_all_attachments_scenario.dart +++ b/integration_test/scenarios/download_all_attachments_scenario.dart @@ -1,31 +1,24 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:patrol/patrol.dart'; -import '../base/base_scenario.dart'; +import '../base/base_test_scenario.dart'; import '../models/provisioning_email.dart'; import '../robots/email_robot.dart'; import '../robots/thread_robot.dart'; -import '../utils/scenario_utils_mixin.dart'; -import 'login_with_basic_auth_scenario.dart'; -class DownloadAllAttachmentsScenario extends BaseScenario with ScenarioUtilsMixin { - DownloadAllAttachmentsScenario( - super.$, { - required this.loginWithBasicAuthScenario, - required this.attachmentContents, - }); +class DownloadAllAttachmentsScenario extends BaseTestScenario { - final LoginWithBasicAuthScenario loginWithBasicAuthScenario; - final List attachmentContents; + const DownloadAllAttachmentsScenario(super.$); @override - Future execute() async { + Future runTestLogic() async { const subject = 'download all attachments subject'; + final List attachmentContents = ['file1', 'file2', 'file3']; + const email = String.fromEnvironment('BASIC_AUTH_EMAIL'); + final threadRobot = ThreadRobot($); final emailRobot = EmailRobot($); - await loginWithBasicAuthScenario.execute(); - // Prepare attachment files final attachmentFiles = await Future.wait( attachmentContents.map( @@ -36,7 +29,7 @@ class DownloadAllAttachmentsScenario extends BaseScenario with ScenarioUtilsMixi // Provisioning email await provisionEmail( [ProvisioningEmail( - toEmail: loginWithBasicAuthScenario.email, + toEmail: email, subject: subject, content: 'download all attachments content', attachmentPaths: attachmentFiles.map((file) => file.path).toList(), diff --git a/integration_test/scenarios/forward_email_scenario.dart b/integration_test/scenarios/forward_email_scenario.dart index ef3043e02..8e862dd85 100644 --- a/integration_test/scenarios/forward_email_scenario.dart +++ b/integration_test/scenarios/forward_email_scenario.dart @@ -7,27 +7,18 @@ import 'package:tmail_ui_user/features/composer/presentation/view/mobile/mobile_ import 'package:tmail_ui_user/features/email/presentation/email_view.dart'; import 'package:tmail_ui_user/features/search/email/presentation/search_email_view.dart'; -import '../base/base_scenario.dart'; +import '../base/base_test_scenario.dart'; import '../robots/composer_robot.dart'; import '../robots/email_robot.dart'; import '../robots/search_robot.dart'; import '../robots/thread_robot.dart'; -import 'login_with_basic_auth_scenario.dart'; -class ForwardEmailScenario extends BaseScenario { - const ForwardEmailScenario( - super.$, - { - required this.loginWithBasicAuthScenario, - } - ); +class ForwardEmailScenario extends BaseTestScenario { - final LoginWithBasicAuthScenario loginWithBasicAuthScenario; + const ForwardEmailScenario(super.$); @override - Future execute() async { - await loginWithBasicAuthScenario.execute(); - + Future runTestLogic() async { final threadRobot = ThreadRobot($); await threadRobot.openSearchView(); await _expectSearchViewVisible(); diff --git a/integration_test/scenarios/no_disposition_inline_scenario.dart b/integration_test/scenarios/no_disposition_inline_scenario.dart index 7774217d4..ac09397e8 100644 --- a/integration_test/scenarios/no_disposition_inline_scenario.dart +++ b/integration_test/scenarios/no_disposition_inline_scenario.dart @@ -3,29 +3,21 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:tmail_ui_user/features/email/presentation/email_view.dart'; import 'package:tmail_ui_user/features/search/email/presentation/search_email_view.dart'; -import '../base/base_scenario.dart'; +import '../base/base_test_scenario.dart'; import '../robots/search_robot.dart'; import '../robots/thread_robot.dart'; -import 'login_with_basic_auth_scenario.dart'; -class NoDispositionInlineScenario extends BaseScenario { +class NoDispositionInlineScenario extends BaseTestScenario { static const _base64DataString = '''data:image/jpeg;base64,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'''; static const emailSubject = 'Greeting Card'; - NoDispositionInlineScenario( - super.$, { - required this.loginWithBasicAuthScenario, - }); - - final LoginWithBasicAuthScenario loginWithBasicAuthScenario; + const NoDispositionInlineScenario(super.$); @override - Future execute() async { + Future runTestLogic() async { final threadRobot = ThreadRobot($); final searchRobot = SearchRobot($); - await loginWithBasicAuthScenario.execute(); - await threadRobot.openSearchView(); await _expectSearchViewVisible(); diff --git a/integration_test/scenarios/search_email_by_date_time_and_sort_order_relevance_scenario.dart b/integration_test/scenarios/search_email_by_date_time_and_sort_order_relevance_scenario.dart index cbaaa88d7..76ac5fe77 100644 --- a/integration_test/scenarios/search_email_by_date_time_and_sort_order_relevance_scenario.dart +++ b/integration_test/scenarios/search_email_by_date_time_and_sort_order_relevance_scenario.dart @@ -6,32 +6,27 @@ import 'package:tmail_ui_user/features/search/email/presentation/search_email_vi 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 '../base/base_test_scenario.dart'; import '../models/provisioning_email.dart'; import '../robots/search_robot.dart'; import '../robots/thread_robot.dart'; -import '../utils/scenario_utils_mixin.dart'; -import 'login_with_basic_auth_scenario.dart'; -class SearchEmailByDatetimeAndSortOrderRelevanceScenario extends BaseScenario - with ScenarioUtilsMixin { +class SearchEmailByDatetimeAndSortOrderRelevanceScenario extends BaseTestScenario { - const SearchEmailByDatetimeAndSortOrderRelevanceScenario( - super.$, - { - required this.loginWithBasicAuthScenario, - required this.queryString, - required this.listProvisioningEmail, - } - ); + const SearchEmailByDatetimeAndSortOrderRelevanceScenario(super.$); - final LoginWithBasicAuthScenario loginWithBasicAuthScenario; - final String queryString; - final List listProvisioningEmail; + static const queryString = 'relevance'; + static const listUsername = ['Alice', 'Brian', 'Charlotte', 'David', 'Emma']; @override - Future execute() async { - await loginWithBasicAuthScenario.execute(); + Future runTestLogic() async { + final listProvisioningEmail = listUsername + .map((username) => ProvisioningEmail( + toEmail: '${username.toLowerCase()}@example.com', + subject: queryString, + content: '$queryString to user $username', + )) + .toList(); await provisionEmail(listProvisioningEmail); await $.pumpAndSettle(); @@ -70,7 +65,7 @@ class SearchEmailByDatetimeAndSortOrderRelevanceScenario extends BaseScenario ); await _expectSearchResultEmailListVisible(); - await _expectEmailListDisplayedCorrectly(); + await _expectEmailListDisplayedCorrectly(listProvisioningEmail); } @@ -98,7 +93,7 @@ class SearchEmailByDatetimeAndSortOrderRelevanceScenario extends BaseScenario await expectViewVisible($(#sort_filter_context_menu)); } - Future _expectEmailListDisplayedCorrectly() async { + Future _expectEmailListDisplayedCorrectly(List listProvisioningEmail) async { expect(find.byType(EmailTileBuilder), findsNWidgets(listProvisioningEmail.length)); } diff --git a/integration_test/scenarios/search_email_with_sort_order_scenario.dart b/integration_test/scenarios/search_email_with_sort_order_scenario.dart index bac755a99..9b436133d 100644 --- a/integration_test/scenarios/search_email_with_sort_order_scenario.dart +++ b/integration_test/scenarios/search_email_with_sort_order_scenario.dart @@ -7,29 +7,18 @@ import 'package:tmail_ui_user/features/search/email/presentation/search_email_vi 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 '../base/base_test_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, - } - ); +class SearchEmailWithSortOrderScenario extends BaseTestScenario { + const SearchEmailWithSortOrderScenario(super.$); - final LoginWithBasicAuthScenario loginWithBasicAuthScenario; - final String queryString; - final List listUsername; + static const queryString = 'hello'; + static const listUsername = ['Alice', 'Brian', 'Charlotte', 'David', 'Emma']; @override - Future execute() async { - await loginWithBasicAuthScenario.execute(); - + Future runTestLogic() async { final threadRobot = ThreadRobot($); await threadRobot.openSearchView(); await _expectSearchViewVisible(); diff --git a/integration_test/scenarios/search_result_highlights_scenario.dart b/integration_test/scenarios/search_result_highlights_scenario.dart index 38dbf4c71..27fb10623 100644 --- a/integration_test/scenarios/search_result_highlights_scenario.dart +++ b/integration_test/scenarios/search_result_highlights_scenario.dart @@ -1,34 +1,28 @@ import 'package:core/core.dart'; import 'package:flutter_test/flutter_test.dart'; -import '../base/base_scenario.dart'; +import '../base/base_test_scenario.dart'; import '../models/provisioning_email.dart'; import '../robots/search_robot.dart'; import '../robots/thread_robot.dart'; -import '../utils/scenario_utils_mixin.dart'; -import 'login_with_basic_auth_scenario.dart'; -class SearchResultHighlightsScenario extends BaseScenario with ScenarioUtilsMixin { - SearchResultHighlightsScenario( - super.$, { - required this.loginWithBasicAuthScenario, - required this.keyword, - required this.longEmailContents, - }); +class SearchResultHighlightsScenario extends BaseTestScenario { + SearchResultHighlightsScenario(super.$); - final LoginWithBasicAuthScenario loginWithBasicAuthScenario; - final String keyword; - final List longEmailContents; + static const keyword = 'Search snippet results'; + static const List longEmailContents = [ + "$keyword Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s", + "Lorem Ipsum is simply dummy text of the printing and typesetting industry. $keyword Lorem Ipsum has been the industry's standard dummy text ever since the 1500s", + "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s $keyword", + ]; @override - Future execute() async { + Future runTestLogic() async { + const email = String.fromEnvironment('BASIC_AUTH_EMAIL'); // Robots final threadRobot = ThreadRobot($); final searchRobot = SearchRobot($); - // Login - await loginWithBasicAuthScenario.execute(); - // Prepare attachment file final file = await preparingTxtFile(keyword); @@ -36,7 +30,7 @@ class SearchResultHighlightsScenario extends BaseScenario with ScenarioUtilsMixi await provisionEmail(longEmailContents .map( (emailContent) => ProvisioningEmail( - toEmail: loginWithBasicAuthScenario.email, + toEmail: email, subject: keyword, content: emailContent, attachmentPaths: emailContent == longEmailContents.first diff --git a/integration_test/scenarios/search_suggestion_highlights_scenario.dart b/integration_test/scenarios/search_suggestion_highlights_scenario.dart index 13459b98f..685f0fbd4 100644 --- a/integration_test/scenarios/search_suggestion_highlights_scenario.dart +++ b/integration_test/scenarios/search_suggestion_highlights_scenario.dart @@ -1,34 +1,28 @@ -import 'package:core/core.dart'; +import 'package:core/presentation/views/text/rich_text_builder.dart'; import 'package:flutter_test/flutter_test.dart'; -import '../base/base_scenario.dart'; +import '../base/base_test_scenario.dart'; import '../models/provisioning_email.dart'; import '../robots/search_robot.dart'; import '../robots/thread_robot.dart'; -import '../utils/scenario_utils_mixin.dart'; -import 'login_with_basic_auth_scenario.dart'; -class SearchSuggestionHighlightsScenario extends BaseScenario with ScenarioUtilsMixin { - SearchSuggestionHighlightsScenario( - super.$, { - required this.loginWithBasicAuthScenario, - required this.keyword, - required this.longEmailContents, - }); +class SearchSuggestionHighlightsScenario extends BaseTestScenario { + SearchSuggestionHighlightsScenario(super.$); - final LoginWithBasicAuthScenario loginWithBasicAuthScenario; - final String keyword; - final List longEmailContents; + static const keyword = 'Search snippet suggestions'; + static const List longEmailContents = [ + "$keyword Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s", + "Lorem Ipsum is simply dummy text of the printing and typesetting industry. $keyword Lorem Ipsum has been the industry's standard dummy text ever since the 1500s", + "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s $keyword", + ]; @override - Future execute() async { + Future runTestLogic() async { + const email = String.fromEnvironment('BASIC_AUTH_EMAIL'); // Robots final threadRobot = ThreadRobot($); final searchRobot = SearchRobot($); - // Login - await loginWithBasicAuthScenario.execute(); - // Prepare attachment file final file = await preparingTxtFile(keyword); @@ -36,7 +30,7 @@ class SearchSuggestionHighlightsScenario extends BaseScenario with ScenarioUtils await provisionEmail(longEmailContents .map( (emailContent) => ProvisioningEmail( - toEmail: loginWithBasicAuthScenario.email, + toEmail: email, subject: keyword, content: emailContent, attachmentPaths: emailContent == longEmailContents.first diff --git a/integration_test/scenarios/send_email_scenario.dart b/integration_test/scenarios/send_email_scenario.dart index e0d5f6b8a..48dd311f6 100644 --- a/integration_test/scenarios/send_email_scenario.dart +++ b/integration_test/scenarios/send_email_scenario.dart @@ -1,40 +1,29 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:tmail_ui_user/features/composer/presentation/composer_view.dart'; -import '../base/base_scenario.dart'; +import '../base/base_test_scenario.dart'; import '../robots/composer_robot.dart'; import '../robots/thread_robot.dart'; -import 'login_with_basic_auth_scenario.dart'; -class SendEmailScenario extends BaseScenario { - const SendEmailScenario( - super.$, - { - required this.loginWithBasicAuthScenario, - required this.additionalRecipient, - required this.subject, - required this.content - } - ); - - final LoginWithBasicAuthScenario loginWithBasicAuthScenario; - final String additionalRecipient; - final String subject; - final String content; +class SendEmailScenario extends BaseTestScenario { + const SendEmailScenario(super.$); @override - Future execute() async { + Future runTestLogic() async { + const additionalRecipient = String.fromEnvironment('ADDITIONAL_MAIL_RECIPIENT'); + const email = String.fromEnvironment('BASIC_AUTH_EMAIL'); + const subject = 'Test subject'; + const content = 'Test content'; + final threadRobot = ThreadRobot($); final composerRobot = ComposerRobot($); - await loginWithBasicAuthScenario.execute(); - await threadRobot.openComposer(); await _expectComposerViewVisible(); await composerRobot.grantContactPermission(); - await composerRobot.addRecipient(loginWithBasicAuthScenario.email); + await composerRobot.addRecipient(email); await composerRobot.addRecipient(additionalRecipient); await composerRobot.addSubject(subject); await composerRobot.addContent(content); diff --git a/integration_test/scenarios/web_socket_update_ui_scenario.dart b/integration_test/scenarios/web_socket_update_ui_scenario.dart index e4783544f..3e9e79909 100644 --- a/integration_test/scenarios/web_socket_update_ui_scenario.dart +++ b/integration_test/scenarios/web_socket_update_ui_scenario.dart @@ -1,35 +1,27 @@ import 'package:tmail_ui_user/features/thread/presentation/widgets/email_tile_builder.dart'; -import '../base/base_scenario.dart'; +import '../base/base_test_scenario.dart'; import '../models/provisioning_email.dart'; -import '../utils/scenario_utils_mixin.dart'; -import 'login_with_basic_auth_scenario.dart'; -class WebSocketUpdateUiScenario extends BaseScenario with ScenarioUtilsMixin { - const WebSocketUpdateUiScenario(super.$, { - required this.loginWithBasicAuthScenario, - required this.subject, - required this.content, - }); - - final LoginWithBasicAuthScenario loginWithBasicAuthScenario; - final String subject; - final String content; +class WebSocketUpdateUiScenario extends BaseTestScenario { + const WebSocketUpdateUiScenario(super.$); @override - Future execute() async { - await loginWithBasicAuthScenario.execute(); + Future runTestLogic() async { + const email = String.fromEnvironment('BASIC_AUTH_EMAIL'); + const subject = 'web socket subject'; + const content = 'web socket content'; await provisionEmail( [ProvisioningEmail( - toEmail: loginWithBasicAuthScenario.email, + toEmail: email, subject: subject, content: content, )], refreshEmailView: false, ); await $.pumpAndSettle(); - await _expectEmailVisible(loginWithBasicAuthScenario.email); + await _expectEmailVisible(email); await _expectEmailUnreadWithSubject(subject); await _expectEmailUnstarredWithSubject(subject); diff --git a/integration_test/tests/app_grid/app_grid_test.dart b/integration_test/tests/app_grid/app_grid_test.dart index 3ea0b7a69..d6d318891 100644 --- a/integration_test/tests/app_grid/app_grid_test.dart +++ b/integration_test/tests/app_grid/app_grid_test.dart @@ -1,24 +1,9 @@ import '../../base/test_base.dart'; import '../../scenarios/app_grid_scenario.dart'; -import '../../scenarios/login_with_basic_auth_scenario.dart'; void main() { TestBase().runPatrolTest( description: 'Should display and navigate app grid correctly when clicked', - test: ($) async { - final loginWithBasicAuthScenario = LoginWithBasicAuthScenario($, - username: const String.fromEnvironment('USERNAME'), - hostUrl: const String.fromEnvironment('BASIC_AUTH_URL'), - email: const String.fromEnvironment('BASIC_AUTH_EMAIL'), - password: const String.fromEnvironment('PASSWORD'), - ); - - final appGridScenario = AppGridScenario( - $, - loginWithBasicAuthScenario: loginWithBasicAuthScenario, - ); - - await appGridScenario.execute(); - } + scenarioBuilder: ($) => AppGridScenario($), ); } \ No newline at end of file diff --git a/integration_test/tests/attachments/download_all_attachments_test.dart b/integration_test/tests/attachments/download_all_attachments_test.dart index 03ac21e06..455f3849f 100644 --- a/integration_test/tests/attachments/download_all_attachments_test.dart +++ b/integration_test/tests/attachments/download_all_attachments_test.dart @@ -1,24 +1,9 @@ import '../../base/test_base.dart'; import '../../scenarios/download_all_attachments_scenario.dart'; -import '../../scenarios/login_with_basic_auth_scenario.dart'; void main() { TestBase().runPatrolTest( description: 'Should see save dialog when download all attachments successfully', - test: ($) async { - final loginWithBasicAuthScenario = LoginWithBasicAuthScenario($, - username: const String.fromEnvironment('USERNAME'), - hostUrl: const String.fromEnvironment('BASIC_AUTH_URL'), - email: const String.fromEnvironment('BASIC_AUTH_EMAIL'), - password: const String.fromEnvironment('PASSWORD'), - ); - - final downloadAllAttachmentsScenario = DownloadAllAttachmentsScenario($, - loginWithBasicAuthScenario: loginWithBasicAuthScenario, - attachmentContents: ['file1', 'file2', 'file3'], - ); - - await downloadAllAttachmentsScenario.execute(); - } + scenarioBuilder: ($) => DownloadAllAttachmentsScenario($), ); } \ No newline at end of file diff --git a/integration_test/tests/attachments/no_disposition_inline_test.dart b/integration_test/tests/attachments/no_disposition_inline_test.dart index d11969089..7a0463ba1 100644 --- a/integration_test/tests/attachments/no_disposition_inline_test.dart +++ b/integration_test/tests/attachments/no_disposition_inline_test.dart @@ -1,23 +1,9 @@ import '../../base/test_base.dart'; -import '../../scenarios/login_with_basic_auth_scenario.dart'; import '../../scenarios/no_disposition_inline_scenario.dart'; void main() { TestBase().runPatrolTest( description: 'Should see base64 inline image when attachment has no disposition but has cid', - test: ($) async { - final loginWithBasicAuthScenario = LoginWithBasicAuthScenario($, - username: const String.fromEnvironment('USERNAME'), - hostUrl: const String.fromEnvironment('BASIC_AUTH_URL'), - email: const String.fromEnvironment('BASIC_AUTH_EMAIL'), - password: const String.fromEnvironment('PASSWORD'), - ); - - final noDispositionInlineScenario = NoDispositionInlineScenario($, - loginWithBasicAuthScenario: loginWithBasicAuthScenario, - ); - - await noDispositionInlineScenario.execute(); - } + scenarioBuilder: ($) => NoDispositionInlineScenario($), ); } \ No newline at end of file diff --git a/integration_test/tests/compose/forward_email_test.dart b/integration_test/tests/compose/forward_email_test.dart index c24a0549f..d40b05412 100644 --- a/integration_test/tests/compose/forward_email_test.dart +++ b/integration_test/tests/compose/forward_email_test.dart @@ -1,23 +1,9 @@ import '../../base/test_base.dart'; import '../../scenarios/forward_email_scenario.dart'; -import '../../scenarios/login_with_basic_auth_scenario.dart'; void main() { TestBase().runPatrolTest( description: 'Should see HTML content contain enough: Subject, From, To, Cc, Bcc, Reply to', - test: ($) async { - final loginWithBasicAuthScenario = LoginWithBasicAuthScenario($, - username: const String.fromEnvironment('USERNAME'), - hostUrl: const String.fromEnvironment('BASIC_AUTH_URL'), - email: const String.fromEnvironment('BASIC_AUTH_EMAIL'), - password: const String.fromEnvironment('PASSWORD'), - ); - final forwardEmailScenario = ForwardEmailScenario( - $, - loginWithBasicAuthScenario: loginWithBasicAuthScenario, - ); - - await forwardEmailScenario.execute(); - }, + scenarioBuilder: ($) => ForwardEmailScenario($), ); } \ No newline at end of file diff --git a/integration_test/tests/compose/send_email_test.dart b/integration_test/tests/compose/send_email_test.dart index 7ff763c7b..f987e5030 100644 --- a/integration_test/tests/compose/send_email_test.dart +++ b/integration_test/tests/compose/send_email_test.dart @@ -1,24 +1,9 @@ import '../../base/test_base.dart'; -import '../../scenarios/login_with_basic_auth_scenario.dart'; import '../../scenarios/send_email_scenario.dart'; void main() { TestBase().runPatrolTest( description: 'Should see success toast when send email successfully', - test: ($) async { - final loginWithBasicAuthScenario = LoginWithBasicAuthScenario($, - username: const String.fromEnvironment('USERNAME'), - hostUrl: const String.fromEnvironment('BASIC_AUTH_URL'), - email: const String.fromEnvironment('BASIC_AUTH_EMAIL'), - password: const String.fromEnvironment('PASSWORD'), - ); - final sendEmailScenario = SendEmailScenario($, - loginWithBasicAuthScenario: loginWithBasicAuthScenario, - additionalRecipient: const String.fromEnvironment('ADDITIONAL_MAIL_RECIPIENT'), - subject: 'Test subject', - content: 'Test content'); - - await sendEmailScenario.execute(); - }, + scenarioBuilder: ($) => SendEmailScenario($), ); } \ No newline at end of file diff --git a/integration_test/tests/login/login_with_basic_auth_test.dart b/integration_test/tests/login/login_with_basic_auth_test.dart index 12ae045de..8d224f913 100644 --- a/integration_test/tests/login/login_with_basic_auth_test.dart +++ b/integration_test/tests/login/login_with_basic_auth_test.dart @@ -4,15 +4,12 @@ import '../../scenarios/login_with_basic_auth_scenario.dart'; void main() { TestBase().runPatrolTest( description: 'Should see thread view when login with basic auth successfully', - test: ($) async { - final loginWithBasicAuthScenario = LoginWithBasicAuthScenario($, - username: const String.fromEnvironment('USERNAME'), - hostUrl: const String.fromEnvironment('BASIC_AUTH_URL'), - email: const String.fromEnvironment('BASIC_AUTH_EMAIL'), - password: const String.fromEnvironment('PASSWORD'), - ); - - await loginWithBasicAuthScenario.execute(); - } + scenarioBuilder: ($) => LoginWithBasicAuthScenario( + $, + username: const String.fromEnvironment('USERNAME'), + hostUrl: const String.fromEnvironment('BASIC_AUTH_URL'), + email: const String.fromEnvironment('BASIC_AUTH_EMAIL'), + password: const String.fromEnvironment('PASSWORD'), + ), ); } \ No newline at end of file diff --git a/integration_test/tests/search/search_email_by_date_time_and_sort_order_relevance_test.dart b/integration_test/tests/search/search_email_by_date_time_and_sort_order_relevance_test.dart index 6fd8e3987..f3923d426 100644 --- a/integration_test/tests/search/search_email_by_date_time_and_sort_order_relevance_test.dart +++ b/integration_test/tests/search/search_email_by_date_time_and_sort_order_relevance_test.dart @@ -1,44 +1,9 @@ import '../../base/test_base.dart'; -import '../../models/provisioning_email.dart'; -import '../../scenarios/login_with_basic_auth_scenario.dart'; import '../../scenarios/search_email_by_date_time_and_sort_order_relevance_scenario.dart'; void main() { TestBase().runPatrolTest( description: 'Should see list email displayed by date time `Last 7 days` and sort order `Relevance` 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 = 'relevance'; - const listUsername = ['Alice', 'Brian', 'Charlotte', 'David', 'Emma']; - - final listProvisioningEmail = listUsername - .map((username) => ProvisioningEmail( - toEmail: '${username.toLowerCase()}@example.com', - subject: queryString, - content: '$queryString to user $username', - )) - .toList(); - - final searchEmailByDatetimeAndSortOrderRelevanceScenario = SearchEmailByDatetimeAndSortOrderRelevanceScenario( - $, - loginWithBasicAuthScenario: loginWithBasicAuthScenario, - queryString: queryString, - listProvisioningEmail: listProvisioningEmail, - ); - - await searchEmailByDatetimeAndSortOrderRelevanceScenario.execute(); - }, + scenarioBuilder: ($) => SearchEmailByDatetimeAndSortOrderRelevanceScenario($), ); } \ No newline at end of file diff --git a/integration_test/tests/search/search_email_with_sort_order_test.dart b/integration_test/tests/search/search_email_with_sort_order_test.dart index 1f6001e87..be98a5136 100644 --- a/integration_test/tests/search/search_email_with_sort_order_test.dart +++ b/integration_test/tests/search/search_email_with_sort_order_test.dart @@ -1,35 +1,9 @@ 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(); - }, + scenarioBuilder: ($) => SearchEmailWithSortOrderScenario($), ); } \ No newline at end of file diff --git a/integration_test/tests/search/search_result_highlights_test.dart b/integration_test/tests/search/search_result_highlights_test.dart index 19ca947a2..fd94c5c05 100644 --- a/integration_test/tests/search/search_result_highlights_test.dart +++ b/integration_test/tests/search/search_result_highlights_test.dart @@ -1,36 +1,9 @@ import '../../base/test_base.dart'; -import '../../scenarios/login_with_basic_auth_scenario.dart'; import '../../scenarios/search_result_highlights_scenario.dart'; void main() { TestBase().runPatrolTest( description: 'Should see highlighted keyword in search result', - test: ($) async { - const keyword = 'Search snippet results'; - - const longContentWithSearchKeywordAtTheStart = "$keyword Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s"; - const longContentWithSearchKeywordAtTheMiddle = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. $keyword Lorem Ipsum has been the industry's standard dummy text ever since the 1500s"; - const longContentWithSearchKeywordAtTheEnd = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s $keyword"; - - final loginWithBasicAuthScenario = LoginWithBasicAuthScenario($, - username: const String.fromEnvironment('USERNAME'), - hostUrl: const String.fromEnvironment('BASIC_AUTH_URL'), - email: const String.fromEnvironment('BASIC_AUTH_EMAIL'), - password: const String.fromEnvironment('PASSWORD'), - ); - - final searchResultHighlightsScenario = SearchResultHighlightsScenario( - $, - loginWithBasicAuthScenario: loginWithBasicAuthScenario, - keyword: keyword, - longEmailContents: [ - longContentWithSearchKeywordAtTheStart, - longContentWithSearchKeywordAtTheMiddle, - longContentWithSearchKeywordAtTheEnd - ], - ); - - await searchResultHighlightsScenario.execute(); - } + scenarioBuilder: ($) => SearchResultHighlightsScenario($), ); } \ No newline at end of file diff --git a/integration_test/tests/search/search_suggestion_highlights_test.dart b/integration_test/tests/search/search_suggestion_highlights_test.dart index 22f4c8d43..e1a72816c 100644 --- a/integration_test/tests/search/search_suggestion_highlights_test.dart +++ b/integration_test/tests/search/search_suggestion_highlights_test.dart @@ -1,36 +1,9 @@ import '../../base/test_base.dart'; -import '../../scenarios/login_with_basic_auth_scenario.dart'; import '../../scenarios/search_suggestion_highlights_scenario.dart'; void main() { TestBase().runPatrolTest( description: 'Should see highlighted keyword in search suggestion', - test: ($) async { - const keyword = 'Search snippet suggestions'; - - const longContentWithSearchKeywordAtTheStart = "$keyword Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s"; - const longContentWithSearchKeywordAtTheMiddle = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. $keyword Lorem Ipsum has been the industry's standard dummy text ever since the 1500s"; - const longContentWithSearchKeywordAtTheEnd = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s $keyword"; - - final loginWithBasicAuthScenario = LoginWithBasicAuthScenario($, - username: const String.fromEnvironment('USERNAME'), - hostUrl: const String.fromEnvironment('BASIC_AUTH_URL'), - email: const String.fromEnvironment('BASIC_AUTH_EMAIL'), - password: const String.fromEnvironment('PASSWORD'), - ); - - final searchResultHighlightsScenario = SearchSuggestionHighlightsScenario( - $, - loginWithBasicAuthScenario: loginWithBasicAuthScenario, - keyword: keyword, - longEmailContents: [ - longContentWithSearchKeywordAtTheStart, - longContentWithSearchKeywordAtTheMiddle, - longContentWithSearchKeywordAtTheEnd - ], - ); - - await searchResultHighlightsScenario.execute(); - } + scenarioBuilder: ($) => SearchSuggestionHighlightsScenario($), ); } \ No newline at end of file diff --git a/integration_test/tests/web_socket/web_socket_test.dart b/integration_test/tests/web_socket/web_socket_test.dart index 0168229ab..b823b86d7 100644 --- a/integration_test/tests/web_socket/web_socket_test.dart +++ b/integration_test/tests/web_socket/web_socket_test.dart @@ -1,25 +1,9 @@ import '../../base/test_base.dart'; -import '../../scenarios/login_with_basic_auth_scenario.dart'; import '../../scenarios/web_socket_update_ui_scenario.dart'; void main() { TestBase().runPatrolTest( description: 'Should see thread view updated per web socket message', - test: ($) async { - final loginWithBasicAuthScenario = LoginWithBasicAuthScenario($, - username: const String.fromEnvironment('USERNAME'), - hostUrl: const String.fromEnvironment('BASIC_AUTH_URL'), - email: const String.fromEnvironment('BASIC_AUTH_EMAIL'), - password: const String.fromEnvironment('PASSWORD'), - ); - - final webSocketUpdateUiScenario = WebSocketUpdateUiScenario($, - loginWithBasicAuthScenario: loginWithBasicAuthScenario, - subject: 'web socket subject', - content: 'web socket content', - ); - - await webSocketUpdateUiScenario.execute(); - } + scenarioBuilder: ($) => WebSocketUpdateUiScenario($), ); } \ No newline at end of file