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>
This commit is contained in:
126
test/session_scope_test.dart
Normal file
126
test/session_scope_test.dart
Normal file
@ -0,0 +1,126 @@
|
||||
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);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user