fix: Stationsabschluss absichern und Kundenformulare anpassen
Sperrt nachträgliche Aufgabenabschlüsse in App und Backend und zeigt erledigte Aufträge trotz offener optionaler Aufgaben grün an. Ergänzt Regressionstests, die Anredeauswahl und optionale Steuerangaben für Kunden. Enthält App-Version 0.9.25, Backend-Version 0.9.26 und das aktualisierte Frontend-Bundle.
This commit is contained in:
1 parent
8758c53e5b
commit
5e6044e4b1
16 files changed
+638
-69
No files matched your search
@@ -0,0 +1,145 @@
|
||||
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<InkWell>(
|
||||
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<Card>(
|
||||
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,
|
||||
);
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user