Allow task completion even if signatories are still empty, put an indicator for completed tasks with incomplete details.
This commit is contained in:
@@ -11,6 +11,8 @@ import 'package:tasq/models/task.dart';
|
||||
import 'package:tasq/models/ticket.dart';
|
||||
import 'package:tasq/models/user_office.dart';
|
||||
import 'package:tasq/models/team.dart';
|
||||
import 'package:tasq/utils/app_time.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:tasq/models/team_member.dart';
|
||||
import 'package:tasq/providers/notifications_provider.dart';
|
||||
import 'package:tasq/providers/profile_provider.dart';
|
||||
@@ -23,6 +25,7 @@ import 'package:tasq/screens/tasks/tasks_list_screen.dart';
|
||||
import 'package:tasq/screens/tickets/tickets_list_screen.dart';
|
||||
import 'package:tasq/screens/tickets/ticket_detail_screen.dart';
|
||||
import 'package:tasq/screens/teams/teams_screen.dart';
|
||||
import 'package:tasq/screens/shared/permissions_screen.dart';
|
||||
import 'package:tasq/providers/teams_provider.dart';
|
||||
import 'package:tasq/widgets/app_shell.dart';
|
||||
|
||||
@@ -40,6 +43,17 @@ class FakeNotificationsController implements NotificationsController {
|
||||
String? taskId,
|
||||
}) async {}
|
||||
|
||||
@override
|
||||
Future<void> createNotification({
|
||||
required List<String> userIds,
|
||||
required String type,
|
||||
required String actorId,
|
||||
Map<String, dynamic>? fields,
|
||||
String? pushTitle,
|
||||
String? pushBody,
|
||||
Map<String, dynamic>? pushData,
|
||||
}) async {}
|
||||
|
||||
@override
|
||||
Future<void> markRead(String id) async {}
|
||||
|
||||
@@ -48,6 +62,21 @@ class FakeNotificationsController implements NotificationsController {
|
||||
|
||||
@override
|
||||
Future<void> markReadForTask(String taskId) async {}
|
||||
|
||||
@override
|
||||
Future<void> registerFcmToken(String token) async {}
|
||||
|
||||
@override
|
||||
Future<void> unregisterFcmToken(String token) async {}
|
||||
|
||||
@override
|
||||
Future<void> sendPush({
|
||||
List<String>? tokens,
|
||||
List<String>? userIds,
|
||||
required String title,
|
||||
required String body,
|
||||
Map<String, dynamic>? data,
|
||||
}) async {}
|
||||
}
|
||||
|
||||
// test doubles for controllers that allow us to intercept create operations
|
||||
@@ -228,6 +257,39 @@ void main() {
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('Completed task with missing details shows warning icon', (
|
||||
tester,
|
||||
) async {
|
||||
await _setSurfaceSize(tester, const Size(1024, 800));
|
||||
AppTime.initialize();
|
||||
|
||||
// create a finished task with no signatories or actionTaken
|
||||
final now = DateTime.now();
|
||||
final incompleteTask = Task.fromMap({
|
||||
'id': 't1',
|
||||
'status': 'completed',
|
||||
'title': 'Incomplete',
|
||||
'description': '',
|
||||
'created_at': now.toIso8601String(),
|
||||
'priority': 1,
|
||||
});
|
||||
|
||||
await _pumpScreen(
|
||||
tester,
|
||||
const TasksListScreen(),
|
||||
overrides: [
|
||||
...baseOverrides(),
|
||||
tasksProvider.overrideWith((ref) => Stream.value([incompleteTask])),
|
||||
],
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// warning icon should appear next to status badge in both desktop and
|
||||
// mobile rows; in this layout smoke test we just ensure at least one is
|
||||
// present.
|
||||
expect(find.byIcon(Icons.warning_amber_rounded), findsWidgets);
|
||||
});
|
||||
|
||||
testWidgets('Offices screen renders without layout exceptions', (
|
||||
tester,
|
||||
) async {
|
||||
@@ -262,15 +324,41 @@ void main() {
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('App shell shows Geofence test nav item for admin', (
|
||||
testWidgets('Permissions screen renders without layout exceptions', (
|
||||
tester,
|
||||
) async {
|
||||
await _setSurfaceSize(tester, const Size(1024, 800));
|
||||
await _pumpScreen(
|
||||
tester,
|
||||
const AppScaffold(child: SizedBox()),
|
||||
const PermissionsScreen(),
|
||||
overrides: baseOverrides(),
|
||||
);
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 16));
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('App shell shows Geofence test nav item for admin', (
|
||||
tester,
|
||||
) async {
|
||||
await _setSurfaceSize(tester, const Size(1024, 800));
|
||||
// AppScaffold needs a GoRouter state above it; create a minimal router.
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: baseOverrides(),
|
||||
child: MaterialApp.router(
|
||||
routerConfig: GoRouter(
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: '/',
|
||||
builder: (context, state) =>
|
||||
const AppScaffold(child: SizedBox()),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Geofence test'), findsOneWidget);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user