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(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( 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(); 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(); 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(), 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().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); } }, ); }