add some new features

This commit is contained in:
2026-10-29 15:03:48 +01:00
parent c876405a8f
commit 20012db615
39 changed files with 2908 additions and 97 deletions
+191
View File
@@ -0,0 +1,191 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:get/get.dart';
import 'package:ertl_filament_verwaltung/controller/bauteil_controller.dart';
import 'package:ertl_filament_verwaltung/controller/bauteil_auswertung_controller.dart';
import 'package:ertl_filament_verwaltung/helper/storage_keys.dart';
import 'package:ertl_filament_verwaltung/main.dart';
import 'package:ertl_filament_verwaltung/models/bauteil_auswertung_model.dart';
import 'package:ertl_filament_verwaltung/models/bauteil_model.dart';
import 'package:ertl_filament_verwaltung/pages/bauteil_auswertung_view.dart';
import 'package:ertl_filament_verwaltung/pages/bauteil_view.dart';
import 'package:ertl_filament_verwaltung/services/get_storage_services.dart';
import 'package:ertl_filament_verwaltung/theme/app_theme.dart';
import 'helpers/memory_storage_service.dart';
void main() {
late MemoryStorageService storage;
BauteilModel part(String id, DateTime date, double? price) => BauteilModel(
bauteilId: id,
erstelltAm: date,
name: 'Bauteil $id',
verwendung: 'Werkstatt',
druckdauerMinuten: 30,
gewichtGramm: 100,
abfallGramm: 10,
gesamtpreis: price,
filamente: [
const BauteilFilamentModel(filamentId: 'rolle', verbrauchGramm: 110),
],
);
setUp(() {
Get.testMode = true;
storage = MemoryStorageService();
storage.tables[StorageKeys.bauteile] = [
part('alt', DateTime(2025, 12, 31, 23), 10).toJson(),
part('vormittag', DateTime(2026, 1, 2, 8), 2.5).toJson(),
part('nachmittag', DateTime(2026, 1, 2, 16), 3.25).toJson(),
part('januar', DateTime(2026, 1, 3, 12), 0).toJson(),
part('ohne', DateTime(2026, 2, 1, 8), null).toJson(),
];
Get.put<GetStorageService>(storage);
});
tearDown(() => Get.reset());
test('Groups and sums all stored parts by year, month and day with unknown prices labelled', () {
final controller = Get.put(BauteilAuswertungController());
expect(controller.zeitraum.value, BauteilZeitraum.monat);
expect(controller.bauteile.map((item) => item.bauteilId), [
'ohne',
'januar',
'nachmittag',
'vormittag',
'alt',
]);
expect(controller.gesamtsumme, 15.75);
expect(controller.ohnePreis, 1);
expect(controller.gruppen.map((group) => group.summe), [0, 5.75, 10]);
expect(controller.gruppen.first.ohnePreis, 1);
expect(
controller.gruppenTitel(controller.gruppen[1].beginn),
'Monat 01.2026',
);
controller.waehleZeitraum(BauteilZeitraum.jahr);
expect(controller.gruppen.map((group) => group.summe), [5.75, 10]);
expect(controller.gruppen.first.bauteile, hasLength(4));
expect(
controller.gruppenTitel(controller.gruppen.first.beginn),
'Jahr 2026',
);
controller.waehleZeitraum(BauteilZeitraum.tag);
expect(controller.gruppen, hasLength(4));
final sameDay = controller.gruppen.firstWhere(
(group) => group.beginn == DateTime(2026, 1, 2),
);
expect(sameDay.summe, 5.75);
expect(sameDay.bauteile.map((item) => item.bauteilId), [
'nachmittag',
'vormittag',
]);
expect(controller.gruppenTitel(sameDay.beginn), '02.01.2026');
expect(
controller.gruppen.fold<int>(
0,
(sum, group) => sum + group.bauteile.length,
),
5,
);
expect(storage.getModelList(StorageKeys.bauteile), hasLength(5));
});
testWidgets(
'Appbar opens report, selection works at 320px and back retains part draft',
(tester) async {
tester.view.physicalSize = const Size(320, 900);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
await tester.pumpWidget(const MyApp());
await tester.pumpAndSettle();
Get.toNamed(BauteilView.routeName);
await tester.pumpAndSettle();
final parts = Get.find<BauteilController>();
parts.nameController.text = 'Mein Entwurf';
await tester.tap(find.byTooltip('Bauteile auswerten'));
await tester.pumpAndSettle();
expect(Get.currentRoute, BauteilAuswertungView.routeName);
expect(find.text('Gesamtsumme'), findsOneWidget);
expect(find.text('Bauteilauswertung'), findsOneWidget);
final report = Get.find<BauteilAuswertungController>();
expect(report.gruppen, hasLength(3));
await tester.tap(find.text('Jahr'));
await tester.pumpAndSettle();
expect(report.gruppen, hasLength(2));
expect(find.text('Jahr 2026'), findsOneWidget);
await tester.tap(find.text('Tag'));
await tester.pumpAndSettle();
expect(report.gruppen, hasLength(4));
tester.view.physicalSize = const Size(1280, 900);
await tester.pumpAndSettle();
expect(tester.takeException(), isNull);
await tester.tap(find.byTooltip('Zurück zu den Bauteilen'));
await tester.pumpAndSettle();
expect(Get.currentRoute, BauteilView.routeName);
expect(parts.nameController.text, 'Mein Entwurf');
expect(Get.isRegistered<BauteilAuswertungController>(), isFalse);
storage.tables[StorageKeys.bauteile]!.add(
part('neu', DateTime(2027), 4.25).toJson(),
);
await tester.tap(find.byTooltip('Bauteile auswerten'));
await tester.pumpAndSettle();
expect(Get.find<BauteilAuswertungController>().gesamtsumme, 20);
expect(tester.takeException(), isNull);
},
);
testWidgets(
'Every part is reachable by scrolling and grouping never changes total',
(tester) async {
tester.view.physicalSize = const Size(320, 640);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
final controller = Get.put(BauteilAuswertungController());
await tester.pumpWidget(
GetMaterialApp(
theme: AppTheme.light,
home: const BauteilAuswertungView(),
),
);
await tester.pumpAndSettle();
for (final period in BauteilZeitraum.values) {
controller.waehleZeitraum(period);
await tester.pumpAndSettle();
await tester.scrollUntilVisible(
find.text('Bauteil alt'),
350,
scrollable: find.byType(Scrollable).first,
);
await tester.pumpAndSettle();
expect(find.text('Bauteil alt'), findsOneWidget);
expect(controller.gesamtsumme, 15.75);
expect(tester.takeException(), isNull);
}
},
);
testWidgets(
'Empty report shows zero and an empty message for all groupings',
(tester) async {
storage.tables.clear();
final controller = Get.put(BauteilAuswertungController());
await tester.pumpWidget(
GetMaterialApp(
theme: AppTheme.light,
home: const BauteilAuswertungView(),
),
);
await tester.pumpAndSettle();
for (final period in BauteilZeitraum.values) {
controller.waehleZeitraum(period);
await tester.pumpAndSettle();
expect(controller.gesamtsumme, 0);
expect(controller.gruppen, isEmpty);
expect(find.text('Noch keine Bauteile gespeichert.'), findsOneWidget);
expect(tester.takeException(), isNull);
}
},
);
}