import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:marianum_mobile/widget/route_transition_gate.dart'; void main() { const gated = Key('gated-child'); const placeholder = Key('gate-placeholder'); Widget gatedPage() => Scaffold( body: RouteTransitionGate( placeholder: const SizedBox(key: placeholder), builder: (_) => const SizedBox(key: gated), ), ); Future pumpApp(WidgetTester tester) async { await tester.pumpWidget( MaterialApp(home: Builder(builder: (_) => const Scaffold())), ); } NavigatorState navigator(WidgetTester tester) => tester.state(find.byType(Navigator)); testWidgets('shows placeholder during push, child once settled', ( tester, ) async { await pumpApp(tester); unawaited( navigator(tester).push(MaterialPageRoute(builder: (_) => gatedPage())), ); await tester.pump(); await tester.pump(const Duration(milliseconds: 50)); expect(find.byKey(placeholder), findsOneWidget); expect(find.byKey(gated), findsNothing); await tester.pumpAndSettle(); expect(find.byKey(gated), findsOneWidget); expect(find.byKey(placeholder), findsNothing); }); testWidgets('swaps back to placeholder while the route pops', (tester) async { await pumpApp(tester); unawaited( navigator(tester).push(MaterialPageRoute(builder: (_) => gatedPage())), ); await tester.pumpAndSettle(); expect(find.byKey(gated), findsOneWidget); navigator(tester).pop(); await tester.pump(); await tester.pump(const Duration(milliseconds: 50)); expect(find.byKey(gated), findsNothing); expect(find.byKey(placeholder), findsOneWidget); }); testWidgets('gates during a secondary transition and recovers after pop', ( tester, ) async { await pumpApp(tester); unawaited( navigator(tester).push(MaterialPageRoute(builder: (_) => gatedPage())), ); await tester.pumpAndSettle(); expect(find.byKey(gated), findsOneWidget); unawaited( navigator(tester).push(MaterialPageRoute(builder: (_) => const Scaffold())), ); await tester.pump(); await tester.pump(const Duration(milliseconds: 50)); // Mid secondary transition the fragile subtree must be unmounted. expect(find.byKey(gated), findsNothing); await tester.pumpAndSettle(); navigator(tester).pop(); await tester.pumpAndSettle(); // Back at rest on the gated route: child is mounted again. expect(find.byKey(gated), findsOneWidget); expect(find.byKey(placeholder), findsNothing); }); testWidgets('holds the child back for one frame without a route animation', ( tester, ) async { // The tab case: no route animation ever runs, but the ancestors (and any // freshly inserted tab-transition Transform) do their first layout in this // very frame, so the fragile subtree must not be part of it. await tester.pumpWidget(MaterialApp(home: gatedPage())); expect(find.byKey(placeholder), findsOneWidget); expect(find.byKey(gated), findsNothing); await tester.pump(); expect(find.byKey(gated), findsOneWidget); expect(find.byKey(placeholder), findsNothing); }); }