From 69c3d32e3c6100e3fd99908ca3d0acd5de9a08d2 Mon Sep 17 00:00:00 2001 From: dab246 Date: Fri, 23 Jan 2026 12:06:55 +0700 Subject: [PATCH] TF-4233 Fix the response success check to use key presence instead of value nullness. --- .../dialog/modal_list_action_button_widget.dart | 6 ++++++ .../robots/labels/create_label_modal_robot.dart | 10 +++++++--- .../scenarios/labels/edit_a_tag_scenario.dart | 3 ++- lib/features/labels/data/network/label_api.dart | 11 ++++++----- .../handle_label_action_type_extension.dart | 2 +- .../labels/presentation/label_controller.dart | 2 +- .../mixin/label_context_menu_mixin.dart | 10 ++++------ .../presentation/models/label_action_type.dart | 9 +++++++++ .../widgets/create_new_label_modal.dart | 9 +++++---- .../handle_label_action_type_extension.dart | 16 ++++++++-------- 10 files changed, 49 insertions(+), 29 deletions(-) diff --git a/core/lib/presentation/views/dialog/modal_list_action_button_widget.dart b/core/lib/presentation/views/dialog/modal_list_action_button_widget.dart index 38e6cb49a..88a3b1353 100644 --- a/core/lib/presentation/views/dialog/modal_list_action_button_widget.dart +++ b/core/lib/presentation/views/dialog/modal_list_action_button_widget.dart @@ -5,6 +5,8 @@ import 'package:flutter/material.dart'; class ModalListActionButtonWidget extends StatelessWidget { final String positiveLabel; final String negativeLabel; + final Key? positiveKey; + final Key? negativeKey; final VoidCallback onNegativeAction; final VoidCallback onPositiveAction; final EdgeInsetsGeometry? padding; @@ -18,6 +20,8 @@ class ModalListActionButtonWidget extends StatelessWidget { required this.onNegativeAction, this.isPositiveActionEnabled = true, this.padding, + this.positiveKey, + this.negativeKey, }); @override @@ -26,6 +30,7 @@ class ModalListActionButtonWidget extends StatelessWidget { constraints: const BoxConstraints(minWidth: 67), height: 48, child: ConfirmDialogButton( + key: negativeKey, label: negativeLabel, onTapAction: onNegativeAction, ), @@ -35,6 +40,7 @@ class ModalListActionButtonWidget extends StatelessWidget { constraints: const BoxConstraints(minWidth: 153), height: 48, child: ConfirmDialogButton( + key: positiveKey, label: positiveLabel, backgroundColor: isPositiveActionEnabled ? AppColor.primaryMain diff --git a/integration_test/robots/labels/create_label_modal_robot.dart b/integration_test/robots/labels/create_label_modal_robot.dart index e79a0a56c..9ebb8de28 100644 --- a/integration_test/robots/labels/create_label_modal_robot.dart +++ b/integration_test/robots/labels/create_label_modal_robot.dart @@ -1,8 +1,8 @@ import 'package:core/presentation/views/text/text_field_builder.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:tmail_ui_user/features/base/widget/label_input_field_builder.dart'; +import 'package:tmail_ui_user/features/labels/presentation/models/label_action_type.dart'; import 'package:tmail_ui_user/features/labels/presentation/widgets/create_new_label_modal.dart'; -import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import '../../base/core_robot.dart'; @@ -16,7 +16,11 @@ class CreateLabelModalRobot extends CoreRobot { .enterText(name); } - Future tapSaveButton() async { - await $(CreateNewLabelModal).$(AppLocalizations().save).tap(); + Future tapPositiveActionButton(LabelActionType actionType) async { + if (actionType == LabelActionType.create) { + await $(CreateNewLabelModal).$(#create_label_button_action).tap(); + } else { + await $(CreateNewLabelModal).$(#save_label_button_action).tap(); + } } } diff --git a/integration_test/scenarios/labels/edit_a_tag_scenario.dart b/integration_test/scenarios/labels/edit_a_tag_scenario.dart index 0682a7631..b802537a2 100644 --- a/integration_test/scenarios/labels/edit_a_tag_scenario.dart +++ b/integration_test/scenarios/labels/edit_a_tag_scenario.dart @@ -1,5 +1,6 @@ import 'package:core/utils/platform_info.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:tmail_ui_user/features/labels/presentation/models/label_action_type.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import '../../base/base_test_scenario.dart'; @@ -40,7 +41,7 @@ class EditATagScenario extends BaseTestScenario const newLabelName = 'New edit tag 1'; await createLabelModalRobot.enterNewLabelName(newLabelName); - await createLabelModalRobot.tapSaveButton(); + await createLabelModalRobot.tapPositiveActionButton(LabelActionType.edit); await _expectLabelWithNewNameUpdated(newLabelName); } diff --git a/lib/features/labels/data/network/label_api.dart b/lib/features/labels/data/network/label_api.dart index 2bb9f0fa7..cbbae1b2d 100644 --- a/lib/features/labels/data/network/label_api.dart +++ b/lib/features/labels/data/network/label_api.dart @@ -47,10 +47,11 @@ class LabelApi with HandleSetErrorMixin { SetLabelResponse.deserialize, ); - final labelCreated = response?.created?[generateCreateId]; + final labelIdsCreated = response?.created?.keys ?? []; - if (labelCreated != null) { - final newLabelCreated = labelCreated.copyWith( + if (labelIdsCreated.contains(generateCreateId)) { + final labelCreated = response?.created?[generateCreateId]; + final newLabelCreated = labelCreated!.copyWith( displayName: labelData.displayName, color: labelData.color, ); @@ -83,9 +84,9 @@ class LabelApi with HandleSetErrorMixin { SetLabelResponse.deserialize, ); - final labelUpdated = response?.updated?[labelId]; + final labelIdsUpdated = response?.updated?.keys ?? []; - if (labelUpdated != null) { + if (labelIdsUpdated.contains(labelId)) { final newLabelUpdated = newLabel.copyWith( id: labelId, keyword: labelRequest.labelKeyword, diff --git a/lib/features/labels/presentation/extensions/handle_label_action_type_extension.dart b/lib/features/labels/presentation/extensions/handle_label_action_type_extension.dart index 98c44a01e..2222cdf18 100644 --- a/lib/features/labels/presentation/extensions/handle_label_action_type_extension.dart +++ b/lib/features/labels/presentation/extensions/handle_label_action_type_extension.dart @@ -48,7 +48,7 @@ extension HandleLabelActionTypeExtension on LabelController { labels: labels, selectedLabel: label, actionType: LabelActionType.edit, - onCreateNewLabelCallback: (newLabel) => + onLabelActionCallback: (newLabel) => editLabel( accountId: accountId, selectedLabel: label, diff --git a/lib/features/labels/presentation/label_controller.dart b/lib/features/labels/presentation/label_controller.dart index d06ee05cf..fe555e40b 100644 --- a/lib/features/labels/presentation/label_controller.dart +++ b/lib/features/labels/presentation/label_controller.dart @@ -89,7 +89,7 @@ class LabelController extends BaseController with LabelContextMenuMixin { await DialogRouter().openDialogModal( child: CreateNewLabelModal( labels: labels, - onCreateNewLabelCallback: (label) => _createNewLabel(accountId, label), + onLabelActionCallback: (label) => _createNewLabel(accountId, label), ), dialogLabel: 'create-new-label-modal', ); diff --git a/lib/features/labels/presentation/mixin/label_context_menu_mixin.dart b/lib/features/labels/presentation/mixin/label_context_menu_mixin.dart index 8b60eb6d6..39ac5a2a0 100644 --- a/lib/features/labels/presentation/mixin/label_context_menu_mixin.dart +++ b/lib/features/labels/presentation/mixin/label_context_menu_mixin.dart @@ -12,6 +12,8 @@ import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; mixin LabelContextMenuMixin on PopupContextMenuActionMixin { + static const _labelActions = [LabelActionType.edit]; + Future _openLabelPopupMenuAction( BuildContext context, ImagePaths imagePaths, @@ -19,9 +21,7 @@ mixin LabelContextMenuMixin on PopupContextMenuActionMixin { RelativeRect position, OnLabelActionTypeCallback onLabelActionTypeCallback, ) async { - final listLabelAction = [LabelActionType.edit]; - - final popupMenuItems = listLabelAction + final popupMenuItems = _labelActions .map((actionType) => _buildLabelPopupMenuItem( label, actionType, @@ -89,9 +89,7 @@ mixin LabelContextMenuMixin on PopupContextMenuActionMixin { Label label, OnLabelActionTypeCallback onLabelActionTypeCallback, ) async { - final listLabelAction = [LabelActionType.edit]; - - final contextMenuActions = listLabelAction + final contextMenuActions = _labelActions .map((actionType) => _buildLabelContextMenuItem( actionType, AppLocalizations.of(context), diff --git a/lib/features/labels/presentation/models/label_action_type.dart b/lib/features/labels/presentation/models/label_action_type.dart index 6f79201c3..609f4d4cc 100644 --- a/lib/features/labels/presentation/models/label_action_type.dart +++ b/lib/features/labels/presentation/models/label_action_type.dart @@ -43,6 +43,15 @@ enum LabelActionType { } } + Key getModalPositiveActionKey() { + switch (this) { + case LabelActionType.create: + return const Key('create_label_button_action'); + case LabelActionType.edit: + return const Key('save_label_button_action'); + } + } + String getContextMenuIcon(ImagePaths imagePaths) { switch (this) { case LabelActionType.create: diff --git a/lib/features/labels/presentation/widgets/create_new_label_modal.dart b/lib/features/labels/presentation/widgets/create_new_label_modal.dart index b1768ea45..727b7b35d 100644 --- a/lib/features/labels/presentation/widgets/create_new_label_modal.dart +++ b/lib/features/labels/presentation/widgets/create_new_label_modal.dart @@ -25,18 +25,18 @@ import 'package:tmail_ui_user/features/mailbox_creator/presentation/extensions/v import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; -typedef OnCreateNewLabelCallback = Function(Label label); +typedef OnLabelActionCallback = Function(Label label); class CreateNewLabelModal extends StatefulWidget { final List