diff --git a/test/features/base/extensions/context_menu_action_list_ext_test.dart b/test/features/base/extensions/context_menu_action_list_ext_test.dart new file mode 100644 index 000000000..b01ff2f56 --- /dev/null +++ b/test/features/base/extensions/context_menu_action_list_ext_test.dart @@ -0,0 +1,100 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:tmail_ui_user/features/base/extensions/context_menu_action_list_extension.dart'; +import 'package:tmail_ui_user/features/base/widget/context_menu/context_menu_item_action.dart'; + +/// Fake subclass to test grouping +class FakeContextMenuAction extends ContextMenuItemAction { + FakeContextMenuAction(super.action, {super.key, super.category}); + + @override + String get actionName => action; +} + +void main() { + group('ContextMenuActionListExt.groupByCategory', () { + test('should group actions by category correctly', () { + // Arrange + final actions = [ + FakeContextMenuAction('Cut', category: 0), + FakeContextMenuAction('Copy', category: 0), + FakeContextMenuAction('Paste', category: 1), + FakeContextMenuAction('SelectAll', category: 2), + FakeContextMenuAction('Other', category: -1), + ]; + + // Act + final grouped = actions.groupByCategory(); + + // Assert + expect(grouped.length, 4); + expect(grouped.keys, orderedEquals([0, 1, 2, -1])); // sorted, -1 last + + expect(grouped[0]!.map((a) => a.action).toList(), ['Cut', 'Copy']); + expect(grouped[1]!.map((a) => a.action).toList(), ['Paste']); + expect(grouped[2]!.map((a) => a.action).toList(), ['SelectAll']); + expect(grouped[-1]!.map((a) => a.action).toList(), ['Other']); + }); + + test('should return empty map when list is empty', () { + // Arrange + final actions = []; + + // Act + final grouped = actions.groupByCategory(); + + // Assert + expect(grouped, isEmpty); + }); + + test('should correctly sort integer keys ascending and move -1 to bottom', + () { + // Arrange + final actions = [ + FakeContextMenuAction('ActionA', category: 3), + FakeContextMenuAction('ActionB', category: 1), + FakeContextMenuAction('ActionC', category: -1), + FakeContextMenuAction('ActionD', category: 2), + ]; + + // Act + final grouped = actions.groupByCategory(); + + // Assert + expect(grouped.keys.toList(), orderedEquals([1, 2, 3, -1])); + }); + + test('should handle multiple actions with same category', () { + // Arrange + final actions = [ + FakeContextMenuAction('Cut', category: 0), + FakeContextMenuAction('Copy', category: 0), + FakeContextMenuAction('Paste', category: 1), + ]; + + // Act + final grouped = actions.groupByCategory(); + + // Assert + expect(grouped[0]!.length, 2); + expect(grouped[1]!.length, 1); + }); + + test('should place all -1 category items at the end regardless of order', + () { + // Arrange + final actions = [ + FakeContextMenuAction('Unknown1', category: -1), + FakeContextMenuAction('Edit', category: 0), + FakeContextMenuAction('Unknown2', category: -1), + ]; + + // Act + final grouped = actions.groupByCategory(); + + // Assert + expect(grouped.keys.toList(), orderedEquals([0, -1])); + expect( + grouped[-1]!.map((a) => a.action).toList(), ['Unknown1', 'Unknown2']); + }); + }); +} diff --git a/test/features/base/extensions/popup_menu_action_list_extension_test.dart b/test/features/base/extensions/popup_menu_action_list_extension_test.dart new file mode 100644 index 000000000..dac42392b --- /dev/null +++ b/test/features/base/extensions/popup_menu_action_list_extension_test.dart @@ -0,0 +1,99 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:tmail_ui_user/features/base/extensions/popup_menu_action_list_extension.dart'; +import 'package:tmail_ui_user/features/base/model/popup_menu_item_action.dart'; + +/// A simple fake implementation of PopupMenuItemAction +class FakePopupAction extends PopupMenuItemAction { + FakePopupAction(super.action, {super.key, super.category}); + + @override + String get actionName => action; +} + +void main() { + group('PopupMenuActionListExtension.groupByCategory', () { + test('should group actions by category correctly', () { + // Arrange + final actions = [ + FakePopupAction('A1', category: 1), + FakePopupAction('A2', category: 1), + FakePopupAction('B1', category: 2), + FakePopupAction('C1', category: 3), + FakePopupAction('NoCategory', category: -1), + ]; + + // Act + final grouped = actions.groupByCategory(); + + // Assert + expect(grouped.length, 4); + expect(grouped.keys, orderedEquals([1, 2, 3, -1])); // sorted with -1 last + + expect(grouped[1]!.map((e) => e.action), ['A1', 'A2']); + expect(grouped[2]!.map((e) => e.action), ['B1']); + expect(grouped[3]!.map((e) => e.action), ['C1']); + expect(grouped[-1]!.map((e) => e.action), ['NoCategory']); + }); + + test('should return empty map when list is empty', () { + // Arrange + final actions = []; + + // Act + final grouped = actions.groupByCategory(); + + // Assert + expect(grouped, isEmpty); + }); + + test('should correctly sort integer keys ascending and move -1 to bottom', + () { + // Arrange + final actions = [ + FakePopupAction('A', category: 5), + FakePopupAction('B', category: 2), + FakePopupAction('C', category: -1), + FakePopupAction('D', category: 3), + ]; + + // Act + final grouped = actions.groupByCategory(); + + // Assert + expect(grouped.keys.toList(), orderedEquals([2, 3, 5, -1])); + }); + + test('should handle multiple actions with same category', () { + // Arrange + final actions = [ + FakePopupAction('A1', category: 0), + FakePopupAction('A2', category: 0), + FakePopupAction('B1', category: 1), + ]; + + // Act + final grouped = actions.groupByCategory(); + + // Assert + expect(grouped[0]!.length, 2); + expect(grouped[1]!.length, 1); + }); + + test('should place all -1 category items at the end regardless of position', + () { + // Arrange + final actions = [ + FakePopupAction('No1', category: -1), + FakePopupAction('Cat1', category: 0), + FakePopupAction('No2', category: -1), + ]; + + // Act + final grouped = actions.groupByCategory(); + + // Assert + expect(grouped.keys.toList(), orderedEquals([0, -1])); + expect(grouped[-1]!.map((e) => e.action).toList(), ['No1', 'No2']); + }); + }); +}