TaskTile tests: display, interactions, popup menu, delete confirmation, priority colors. FilterChips tests: display, selection, visual state changes.
250 lines
8.4 KiB
Dart
250 lines
8.4 KiB
Dart
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<Checkbox>(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<Checkbox>(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<String>));
|
|
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<String>));
|
|
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<String>));
|
|
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<String>));
|
|
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<Text>(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<Container>(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<Container>(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<Container>(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);
|
|
});
|
|
});
|
|
});
|
|
}
|