import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:agenda_tasks/features/tasks/domain/entities/task_entity.dart'; import 'package:agenda_tasks/features/tasks/domain/enums/priority.dart'; import 'package:agenda_tasks/features/tasks/presentation/widgets/task_tile.dart'; import '../../../../helpers/test_helpers.dart'; void main() { group('TaskTile', () { late TaskEntity testTask; late bool toggleCalled; late bool tapCalled; late bool deleteCalled; late bool rescheduleCalled; setUp(() { toggleCalled = false; tapCalled = false; deleteCalled = false; rescheduleCalled = false; testTask = TaskEntity( id: 'test-task-1', title: 'Test Task Title', description: 'Test task description', date: DateTime(2026, 2, 3), priority: Priority.medium, isDone: false, ); }); Widget buildTaskTile({TaskEntity? task}) { return createTestableWidget( TaskTile( task: task ?? testTask, onToggle: () => toggleCalled = true, onTap: () => tapCalled = true, onDelete: () => deleteCalled = true, onReschedule: () => rescheduleCalled = true, ), ); } testWidgets('should display task title', (tester) async { await tester.pumpWidget(buildTaskTile()); await tester.pumpAndSettle(); expect(find.text('Test Task Title'), findsOneWidget); }); testWidgets('should display task description', (tester) async { await tester.pumpWidget(buildTaskTile()); await tester.pumpAndSettle(); expect(find.text('Test task description'), findsOneWidget); }); testWidgets('should not display description when null', (tester) async { final taskWithoutDesc = TaskEntity( id: 'test-task-2', title: 'Task Without Description', date: DateTime(2026, 2, 3), ); await tester.pumpWidget(buildTaskTile(task: taskWithoutDesc)); await tester.pumpAndSettle(); expect(find.text('Task Without Description'), findsOneWidget); // Only title should be visible, no description text }); testWidgets('should display checkbox unchecked when task is not done', (tester) async { await tester.pumpWidget(buildTaskTile()); await tester.pumpAndSettle(); final checkbox = tester.widget(find.byType(Checkbox)); expect(checkbox.value, false); }); testWidgets('should display checkbox checked when task is done', (tester) async { final doneTask = testTask.copyWith(isDone: true); await tester.pumpWidget(buildTaskTile(task: doneTask)); await tester.pumpAndSettle(); final checkbox = tester.widget(find.byType(Checkbox)); expect(checkbox.value, true); }); testWidgets('should call onToggle when checkbox is tapped', (tester) async { await tester.pumpWidget(buildTaskTile()); await tester.pumpAndSettle(); await tester.tap(find.byType(Checkbox)); await tester.pumpAndSettle(); expect(toggleCalled, true); }); testWidgets('should call onTap when card is tapped', (tester) async { await tester.pumpWidget(buildTaskTile()); await tester.pumpAndSettle(); // Tap on the task title area (InkWell) await tester.tap(find.text('Test Task Title')); await tester.pumpAndSettle(); expect(tapCalled, true); }); testWidgets('should show popup menu when more button is tapped', (tester) async { await tester.pumpWidget(buildTaskTile()); await tester.pumpAndSettle(); // Find and tap the popup menu button await tester.tap(find.byType(PopupMenuButton)); await tester.pumpAndSettle(); // Menu items should be visible expect(find.text('Move to tomorrow'), findsOneWidget); expect(find.text('Delete'), findsOneWidget); }); testWidgets('should call onReschedule when reschedule menu item is tapped', (tester) async { await tester.pumpWidget(buildTaskTile()); await tester.pumpAndSettle(); // Open popup menu await tester.tap(find.byType(PopupMenuButton)); await tester.pumpAndSettle(); // Tap reschedule option await tester.tap(find.text('Move to tomorrow')); await tester.pumpAndSettle(); expect(rescheduleCalled, true); }); testWidgets('should show delete confirmation dialog when delete menu item is tapped', (tester) async { await tester.pumpWidget(buildTaskTile()); await tester.pumpAndSettle(); // Open popup menu await tester.tap(find.byType(PopupMenuButton)); await tester.pumpAndSettle(); // Tap delete option - find the one in the popup menu (second occurrence) final deleteTexts = find.text('Delete'); await tester.tap(deleteTexts.last); await tester.pumpAndSettle(); // Confirmation dialog should appear expect(find.text('Delete Task'), findsOneWidget); expect(find.text('Are you sure you want to delete this task?'), findsOneWidget); }); testWidgets('should call onDelete when delete is confirmed', (tester) async { await tester.pumpWidget(buildTaskTile()); await tester.pumpAndSettle(); // Open popup menu await tester.tap(find.byType(PopupMenuButton)); await tester.pumpAndSettle(); // Tap delete option in popup menu final deleteTexts = find.text('Delete'); await tester.tap(deleteTexts.last); await tester.pumpAndSettle(); // Dialog should be visible - find Delete button in dialog (the TextButton) final dialogDeleteButtons = find.widgetWithText(TextButton, 'Delete'); await tester.tap(dialogDeleteButtons); await tester.pumpAndSettle(); expect(deleteCalled, true); }); testWidgets('should display strikethrough text when task is done', (tester) async { final doneTask = testTask.copyWith(isDone: true); await tester.pumpWidget(buildTaskTile(task: doneTask)); await tester.pumpAndSettle(); final titleFinder = find.text('Test Task Title'); expect(titleFinder, findsOneWidget); final titleWidget = tester.widget(titleFinder); expect(titleWidget.style?.decoration, TextDecoration.lineThrough); }); group('priority colors', () { testWidgets('should display red indicator for high priority', (tester) async { final highPriorityTask = testTask.copyWith(priority: Priority.high); await tester.pumpWidget(buildTaskTile(task: highPriorityTask)); await tester.pumpAndSettle(); // Find the priority indicator container final containers = tester.widgetList(find.byType(Container)); final priorityIndicator = containers.where((c) { final decoration = c.decoration; if (decoration is BoxDecoration && c.constraints?.maxWidth == 5) { return decoration.color == Colors.red.shade700; } return false; }); expect(priorityIndicator, isNotEmpty); }); testWidgets('should display orange indicator for medium priority', (tester) async { final mediumPriorityTask = testTask.copyWith(priority: Priority.medium); await tester.pumpWidget(buildTaskTile(task: mediumPriorityTask)); await tester.pumpAndSettle(); final containers = tester.widgetList(find.byType(Container)); final priorityIndicator = containers.where((c) { final decoration = c.decoration; if (decoration is BoxDecoration && c.constraints?.maxWidth == 5) { return decoration.color == Colors.orange.shade700; } return false; }); expect(priorityIndicator, isNotEmpty); }); testWidgets('should display green indicator for low priority', (tester) async { final lowPriorityTask = testTask.copyWith(priority: Priority.low); await tester.pumpWidget(buildTaskTile(task: lowPriorityTask)); await tester.pumpAndSettle(); final containers = tester.widgetList(find.byType(Container)); final priorityIndicator = containers.where((c) { final decoration = c.decoration; if (decoration is BoxDecoration && c.constraints?.maxWidth == 5) { return decoration.color == Colors.green.shade700; } return false; }); expect(priorityIndicator, isNotEmpty); }); }); }); }