TF-3996 Add unit test for groupByCategory function

This commit is contained in:
dab246
2025-11-04 12:20:11 +07:00
committed by Dat H. Pham
parent e5745c8fdd
commit b040509475
2 changed files with 199 additions and 0 deletions
@@ -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<String> {
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 = <FakeContextMenuAction>[];
// 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']);
});
});
}
@@ -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<String> {
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 = <FakePopupAction>[];
// 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']);
});
});
}