fix: Tour-Datum — Leer-Texte, veraltete Antworten, Kalenderfenster

- Leer-Ansichten (Auswählen, Sortieren, Beladen, Ausliefern) nennen den
  gewählten Tag statt immer „heute": „Für den 02.09.2026 ist keine Tour
  zugewiesen." (TourDayText).
- TourBloc: Loads/Refreshes laufen nebenläufig; bei schnellem
  Datumswechsel konnte die langsamere Antwort des vorigen Tages die Tour
  des gewählten Tages überschreiben. Jetzt schreibt nur die jüngste
  Anfrage ihr Ergebnis.
- Kalender reicht 90 statt 14 Tage zurück (z. B. nachimportierte Touren
  vom Monatsanfang).
- Test: neuer Fahrer startet auf „heute", auch wenn der vorige einen
  anderen Tag gewählt hatte.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Dennis Nemec
2026-09-25 17:04:56 +02:00
parent a5215367fd
commit 2ff331294e
9 changed files with 188 additions and 19 deletions

View File

@ -106,12 +106,16 @@ void main() {
await send(tester, _login(423));
final fuer423 = carSelections.last;
expect(payments.loads, 1);
// 423 schaut sich einen anderen Tag an …
tourDates.last.pick(DateTime(2026, 9, 2));
// Abmelden und anderer Fahrer: nichts von 423 darf übrig bleiben.
await send(tester, const AuthLoggedOut());
await send(tester, _login(414));
expect(carSelections.last, isNot(same(fuer423)));
expect(tourDates.last, isNot(same(tourDates.first)));
// … der nächste Fahrer startet trotzdem auf „heute".
expect(tourDates.last.state, isNull);
expect(payments.loads, 2);
// Auch derselbe Fahrer nach erneutem Login lädt neu.

98
test/tour_date_test.dart Normal file
View File

@ -0,0 +1,98 @@
import 'dart:async';
import 'package:flutter_test/flutter_test.dart';
import 'package:hl_lieferservice/data/cache/attachment_cache.dart';
import 'package:hl_lieferservice/domain/entity/tour.dart';
import 'package:hl_lieferservice/domain/entity/tour_details.dart';
import 'package:hl_lieferservice/domain/repository/tour_repository.dart';
import 'package:hl_lieferservice/feature/delivery/bloc/tour_bloc.dart';
import 'package:hl_lieferservice/feature/delivery/bloc/tour_event.dart';
import 'package:hl_lieferservice/feature/delivery/bloc/tour_state.dart';
import 'package:hl_lieferservice/feature/delivery/model/tour_day_text.dart';
import 'package:hl_lieferservice/widget/operations/bloc/operation_bloc.dart';
/// Antwortet pro angefragtem Datum erst, wenn der Test es freigibt.
class _SlowTours implements TourRepository {
final pending = <DateTime?, Completer<TourDetails?>>{};
@override
Future<TourDetails?> getMyTourDetails({DateTime? date}) =>
(pending[date] = Completer<TourDetails?>()).future;
@override
dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
class _NoCache implements AttachmentCache {
@override
Future<void> retainOnly(Set<String> ids) async {}
@override
dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
TourDetails _tourAm(DateTime date) => TourDetails(
tour: Tour(id: 't-$date', accountId: 414, date: date, syncedAt: date),
deliveries: const [],
customers: const {},
contacts: const {},
articles: const {},
warehouses: const {},
notesByDeliveryId: const {},
creditsByDeliveryId: const {},
paymentsByDeliveryId: const {},
services: const [],
serviceValuesByDeliveryId: const {},
contactSourcesByDeliveryId: const {},
contactChannelsBySourceId: const {},
);
void main() {
group('TourDayText', () {
final now = DateTime(2026, 9, 25, 16, 30);
test('ohne Auswahl und am selben Tag: heute', () {
expect(TourDayText.of(null, now: now).afterFor, 'heute');
expect(TourDayText.of(DateTime(2026, 9, 25), now: now).when, 'heute');
});
test('morgen und gestern', () {
expect(TourDayText.of(DateTime(2026, 9, 26), now: now).when, 'morgen');
expect(TourDayText.of(DateTime(2026, 9, 24), now: now).when, 'gestern');
});
test('anderer Tag mit Datum und passender Präposition', () {
final t = TourDayText.of(DateTime(2026, 9, 2), now: now);
expect(t.afterFor, 'den 02.09.2026');
expect(t.when, 'am 02.09.2026');
});
});
test('langsame Antwort eines älteren Tages überschreibt nicht die neue Wahl',
() async {
final repo = _SlowTours();
final bloc = TourBloc(
tourRepository: repo,
opBloc: OperationBloc(),
attachmentCache: _NoCache(),
);
final erster = DateTime(2026, 9, 2);
final zweiter = DateTime(2026, 9, 25);
bloc.add(LoadTour.forDate(erster));
await Future<void>.delayed(Duration.zero);
bloc.add(LoadTour.forDate(zweiter));
await Future<void>.delayed(Duration.zero);
// Neuere Anfrage antwortet zuerst, die ältere danach.
repo.pending[zweiter]!.complete(_tourAm(zweiter));
await Future<void>.delayed(Duration.zero);
repo.pending[erster]!.complete(_tourAm(erster));
await Future<void>.delayed(Duration.zero);
final state = bloc.state as TourLoaded;
expect(state.details.tour.date, zweiter);
await bloc.close();
});
}