import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:votianlt_app/app_theme.dart'; import 'package:votianlt_app/cargo_items_view.dart'; import 'package:votianlt_app/jobs_view.dart'; import 'package:votianlt_app/models/job.dart'; import 'package:votianlt_app/models/job_progress.dart'; import 'package:votianlt_app/task_view.dart'; Job jobWithOptionalTask({ bool closedStation = true, String status = 'IN_PROGRESS', }) => Job.fromJson({ 'id': 'job-1', 'jobNumber': 'TEST-1', 'status': status, 'completedStationOrders': closedStation ? [0] : [], 'deliveryStations': [ { 'stationOrder': 0, 'tasks': [ { 'id': 'optional', 'jobId': 'job-1', 'optional': true, 'completed': false, 'description': 'Optionale Bestätigung', 'taskOrder': 0, 'taskSpecificData': { 'taskType': 'CONFIRMATION', 'buttonText': 'Jetzt bestätigen', }, }, ], }, {'stationOrder': 1, 'tasks': []}, ], }); void main() { for (final status in ['IN_PROGRESS', 'COMPLETED']) { testWidgets( 'optional task cannot open a dialog after station closure ($status)', (tester) async { final job = jobWithOptionalTask(status: status); await tester.pumpWidget( MaterialApp(home: TaskView(job: job, stationOrder: 0)), ); await tester.pump(); final task = find.text('Optionale Bestätigung'); expect(task, findsOneWidget); final tile = tester.widget( find.ancestor(of: task, matching: find.byType(InkWell)).first, ); expect(tile.onTap, isNull); await tester.tap(task); await tester.pump(); expect(find.byType(AlertDialog), findsNothing); expect(find.text('Station abgeschlossen'), findsOneWidget); await tester.pumpWidget(const SizedBox.shrink()); }, ); } testWidgets('optional task remains executable at an open station', ( tester, ) async { await tester.pumpWidget( MaterialApp( home: TaskView( job: jobWithOptionalTask(closedStation: false), stationOrder: 0, ), ), ); await tester.pump(); await tester.tap(find.text('Optionale Bestätigung')); await tester.pump(); expect(find.byType(AlertDialog), findsOneWidget); expect(find.text('Jetzt bestätigen'), findsOneWidget); await tester.pumpWidget(const SizedBox.shrink()); }); testWidgets( 'an already open dialog cannot complete a task after the job closes', (tester) async { Widget view(Job job) => MaterialApp( home: TaskView( key: const ValueKey('task-view'), job: job, stationOrder: 0, ), ); await tester.pumpWidget(view(jobWithOptionalTask(closedStation: false))); await tester.pump(); await tester.tap(find.text('Optionale Bestätigung')); await tester.pump(); expect(find.byType(AlertDialog), findsOneWidget); await tester.pumpWidget(view(jobWithOptionalTask(status: 'COMPLETED'))); await tester.pump(); await tester.tap(find.text('Jetzt bestätigen')); await tester.pumpAndSettle(); expect(find.byType(AlertDialog), findsNothing); final taskCard = tester.widget( find .ancestor( of: find.text('Optionale Bestätigung'), matching: find.byType(Card), ) .first, ); expect( taskCard.elevation, 0, ); // still open and locked, never marked completed expect(find.text('Station abgeschlossen'), findsOneWidget); await tester.pumpWidget(const SizedBox.shrink()); }, ); test('completed job card is green with optional tasks still open', () { final job = jobWithOptionalTask(status: 'COMPLETED'); expect(jobCardBackgroundColor(JobProgress(job)), AppColors.successSoft); expect(job.tasks.single.completed, isFalse); }); test('offline final station completion makes the job card green', () { final job = jobWithOptionalTask(); expect( jobCardBackgroundColor(JobProgress(job, localCompletedStations: {1})), AppColors.successSoft, ); expect(jobCardBackgroundColor(JobProgress(job)), AppColors.warningSoft); expect( deliveryStationCardBackgroundColor( job.deliveryStations.first, {}, isClosed: true, ), AppColors.successSoft, ); }); }