Files
Holzleitner-Lieferservice-App/test/session_scope_test.dart
Dennis Nemec dce4447fcc fix: fahrerbezogene Daten bei jeder Anmeldung neu laden
Tour, Datum, Fahrzeuge, Fahrzeugauswahl und Phase lebten bisher pro
Server-Umgebung, nicht pro Anmeldung. Nach Abmelden von 423 und Anmelden
von 414 lieferte der gecachte CarsBloc weiter die Fahrzeuge von 423.

Neu: SessionScope unter dem AuthBloc legt diese Blocs bei jeder Anmeldung
(neuer Fahrer oder Re-Login) komplett neu an; alles wird frisch vom
Server geholt. Token-Refresh desselben Fahrers zählt nicht als neue
Anmeldung. Zahlungsmethoden werden ebenfalls nach jeder Anmeldung neu
geladen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 16:47:25 +02:00

127 lines
4.1 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:hl_lieferservice/data/network/auth_session_event.dart';
import 'package:hl_lieferservice/data/network/keycloak_oidc_token_provider.dart';
import 'package:hl_lieferservice/domain/entity/payment_method.dart';
import 'package:hl_lieferservice/domain/repository/payment_methods_repository.dart';
import 'package:hl_lieferservice/feature/authentication/bloc/auth_bloc.dart';
import 'package:hl_lieferservice/feature/car_selection/bloc/bloc.dart';
import 'package:hl_lieferservice/feature/delivery/bloc/tour_date_cubit.dart';
import 'package:hl_lieferservice/feature/payment_methods/bloc/payment_methods_cubit.dart';
import 'package:hl_lieferservice/widget/operations/bloc/operation_bloc.dart';
import 'package:hl_lieferservice/widget/session_scope.dart';
/// Token-Provider ohne Keycloak: der Test steuert Login/Logout über [emit].
class _FakeTokenProvider implements KeycloakOidcTokenProvider {
final _events = StreamController<AuthSessionEvent>.broadcast();
void emit(AuthSessionEvent event) => _events.add(event);
@override
Stream<AuthSessionEvent> get events => _events.stream;
@override
dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
class _CountingPaymentMethods implements PaymentMethodsRepository {
int loads = 0;
@override
Future<List<PaymentMethod>> list({bool includeInactive = false}) async {
loads++;
return const [];
}
@override
dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
AuthLoggedIn _login(int personalnummer) =>
AuthLoggedIn({'personalnummer': personalnummer, 'name': 'Fahrer'});
void main() {
late _FakeTokenProvider provider;
late _CountingPaymentMethods payments;
late List<CarSelectBloc> carSelections;
late List<TourDateCubit> tourDates;
Future<void> pumpApp(WidgetTester tester) async {
provider = _FakeTokenProvider();
payments = _CountingPaymentMethods();
carSelections = [];
tourDates = [];
await tester.pumpWidget(
MultiBlocProvider(
providers: [
BlocProvider(create: (_) => OperationBloc()),
BlocProvider(
create: (context) => AuthBloc(
tokenProvider: provider,
operationBloc: context.read<OperationBloc>(),
),
),
BlocProvider(
create: (_) => PaymentMethodsCubit(repository: payments),
),
],
child: SessionScope(
environmentId: 'test',
child: MaterialApp(
home: Builder(
builder: (context) {
carSelections.add(context.read<CarSelectBloc>());
tourDates.add(context.read<TourDateCubit>());
return const SizedBox.shrink();
},
),
),
),
),
);
}
Future<void> send(WidgetTester tester, AuthSessionEvent event) async {
provider.emit(event);
await tester.pumpAndSettle();
}
testWidgets('jede Anmeldung bekommt frische Fahrer-Blocs', (tester) async {
await pumpApp(tester);
await send(tester, _login(423));
final fuer423 = carSelections.last;
expect(payments.loads, 1);
// 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)));
expect(payments.loads, 2);
// Auch derselbe Fahrer nach erneutem Login lädt neu.
final fuer414 = carSelections.last;
await send(tester, const AuthLoggedOut());
await send(tester, _login(414));
expect(carSelections.last, isNot(same(fuer414)));
expect(payments.loads, 3);
});
testWidgets('Token-Refresh desselben Fahrers behält die Blocs',
(tester) async {
await pumpApp(tester);
await send(tester, _login(423));
final vorher = carSelections.last;
await send(tester, _login(423));
expect(carSelections.last, same(vorher));
expect(payments.loads, 1);
});
}