import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:tasq/models/task.dart'; import 'package:tasq/models/profile.dart'; import 'package:tasq/screens/tasks/task_detail_screen.dart'; import 'package:tasq/providers/tasks_provider.dart'; import 'package:tasq/providers/profile_provider.dart'; import 'package:tasq/providers/notifications_provider.dart'; import 'package:tasq/providers/tickets_provider.dart'; import 'package:tasq/utils/app_time.dart'; // Fake controller to capture updates class FakeTasksController extends TasksController { FakeTasksController() : super(null); String? lastStatus; Map? lastUpdates; @override Future createTask({ required String title, required String description, String? officeId, String? ticketId, String? requestType, String? requestTypeOther, String? requestCategory, }) async {} @override Future updateTask({ required String taskId, String? requestType, String? requestTypeOther, String? requestCategory, String? status, String? requestedBy, String? notedBy, String? receivedBy, }) async { final m = {}; if (requestType != null) { m['requestType'] = requestType; } if (requestTypeOther != null) { m['requestTypeOther'] = requestTypeOther; } if (requestCategory != null) { m['requestCategory'] = requestCategory; } if (requestedBy != null) { m['requestedBy'] = requestedBy; } if (notedBy != null) { m['notedBy'] = notedBy; } if (receivedBy != null) { m['receivedBy'] = receivedBy; } if (status != null) { m['status'] = status; } lastUpdates = m; } @override Future updateTaskStatus({ required String taskId, required String status, }) async { lastStatus = status; } } // lightweight notifications controller stub used in widget tests class _FakeNotificationsController implements NotificationsController { @override Future createMentionNotifications({ required List userIds, required String actorId, required int messageId, String? ticketId, String? taskId, }) async {} @override Future markRead(String id) async {} @override Future markReadForTicket(String ticketId) async {} @override Future markReadForTask(String taskId) async {} } void main() { testWidgets('details badges show when metadata present', (tester) async { AppTime.initialize(); // initial task without metadata final emptyTask = Task( id: 'tsk-1', ticketId: null, title: 'No metadata', description: '', officeId: 'office-1', status: 'queued', priority: 1, queueOrder: null, createdAt: DateTime.now(), creatorId: 'u1', startedAt: null, completedAt: null, requestType: null, requestTypeOther: null, requestCategory: null, ); await tester.pumpWidget( ProviderScope( overrides: [ tasksProvider.overrideWith((ref) => Stream.value([emptyTask])), taskAssignmentsProvider.overrideWith((ref) => const Stream.empty()), currentProfileProvider.overrideWith( (ref) => Stream.value( Profile(id: 'u1', role: 'admin', fullName: 'Admin'), ), ), notificationsControllerProvider.overrideWithValue( _FakeNotificationsController(), ), notificationsProvider.overrideWith((ref) => const Stream.empty()), ticketsProvider.overrideWith((ref) => const Stream.empty()), officesProvider.overrideWith((ref) => const Stream.empty()), profilesProvider.overrideWith( (ref) => Stream.value(const []), ), taskMessagesProvider.overrideWith((ref, id) => const Stream.empty()), ], child: MaterialApp(home: TaskDetailScreen(taskId: 'tsk-1')), ), ); await tester.pump(); await tester.pump(const Duration(milliseconds: 100)); // metadata absent; editor controls may still show 'Type'/'Category' labels but // there should be no actual values present. expect(find.text('Repair'), findsNothing); expect(find.text('Hardware'), findsNothing); }); testWidgets('badges show when metadata provided', (tester) async { AppTime.initialize(); final task = Task( id: 'tsk-1', ticketId: null, title: 'Has metadata', description: '', officeId: 'office-1', status: 'queued', priority: 1, queueOrder: null, createdAt: DateTime.now(), creatorId: 'u1', startedAt: null, completedAt: null, requestType: 'Repair', requestTypeOther: null, requestCategory: 'Hardware', ); await tester.pumpWidget( ProviderScope( overrides: [ tasksProvider.overrideWith((ref) => Stream.value([task])), taskAssignmentsProvider.overrideWith((ref) => const Stream.empty()), currentProfileProvider.overrideWith( (ref) => Stream.value( Profile(id: 'u1', role: 'admin', fullName: 'Admin'), ), ), notificationsControllerProvider.overrideWithValue( _FakeNotificationsController(), ), notificationsProvider.overrideWith((ref) => const Stream.empty()), ticketsProvider.overrideWith((ref) => const Stream.empty()), officesProvider.overrideWith((ref) => const Stream.empty()), profilesProvider.overrideWith( (ref) => Stream.value(const []), ), taskMessagesProvider.overrideWith((ref, id) => const Stream.empty()), ], child: MaterialApp(home: TaskDetailScreen(taskId: 'tsk-1')), ), ); await tester.pump(); await tester.pump(const Duration(milliseconds: 100)); // the selected values should be visible expect(find.text('Repair'), findsOneWidget); expect(find.text('Hardware'), findsOneWidget); }); }