import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:hepan_everyday/app/tp_startup.dart'; import 'package:hepan_everyday/app/tp_launch_page.dart'; void main() { testWidgets( 'home paints before gradual reveal and cannot be tapped until complete', (tester) async { final ready = Completer(); var serviceStarts = 0, taps = 0, boots = 0; await tester.pumpWidget( TpStartup( bootstrap: () { boots++; expect(find.byType(TpLaunchPage), findsOneWidget); return ready.future; }, onHomeReady: () { serviceStarts++; expect(find.text('课程详情'), findsOneWidget); }, ), ); ready.complete( MaterialApp( home: Center( child: TextButton( onPressed: () => taps++, child: const Text('课程详情'), ), ), ), ); await tester.pump(); await tester.pump(); expect(serviceStarts, 1); await tester.pump(const Duration(milliseconds: 100)); final overlay = tester.widget( find.byKey(const Key('startup-brand-overlay')), ); expect(overlay.opacity, inExclusiveRange(0, 1)); await tester.tap(find.text('课程详情'), warnIfMissed: false); expect(taps, 0); await tester.pumpAndSettle(); expect(find.byType(TpLaunchPage), findsNothing); await tester.tap(find.text('课程详情')); expect(taps, 1); tester.binding.handleAppLifecycleStateChanged(AppLifecycleState.paused); tester.binding.handleAppLifecycleStateChanged(AppLifecycleState.resumed); await tester.pumpAndSettle(); expect(boots, 1); expect(serviceStarts, 1); expect(find.byType(TpLaunchPage), findsNothing); }, ); testWidgets( 'bootstrap failure presents a working retry instead of a blank screen', (tester) async { var attempts = 0; await tester.pumpWidget( TpStartup( bootstrap: () async { if (++attempts == 1) throw StateError('plugin unavailable'); return const MaterialApp(home: Text('已恢复启动')); }, ), ); await tester.pumpAndSettle(); expect(find.text('启动未完成,请重试'), findsOneWidget); expect(tester.takeException(), isNull); await tester.tap(find.text('重新打开')); await tester.pumpAndSettle(); expect(find.text('已恢复启动'), findsOneWidget); expect(attempts, 2); expect(tester.takeException(), isNull); }, ); testWidgets('reduced motion reveals home without a timed fade', ( tester, ) async { await tester.pumpWidget( MediaQuery( data: const MediaQueryData(disableAnimations: true), child: TpStartup( bootstrap: () async => const MaterialApp(home: Text('首页')), ), ), ); await tester.pump(); await tester.pump(); expect(find.text('首页'), findsOneWidget); expect(find.byType(TpLaunchPage), findsNothing); }); testWidgets( 'late bootstrap completion after disposal does not start services', (tester) async { final ready = Completer(); var serviceStarts = 0; await tester.pumpWidget( TpStartup( bootstrap: () => ready.future, onHomeReady: () => serviceStarts++, ), ); await tester.pumpWidget(const SizedBox()); ready.complete(const MaterialApp(home: Text('旧首页'))); await tester.pumpAndSettle(); expect(serviceStarts, 0); expect(find.text('旧首页'), findsNothing); expect(tester.takeException(), isNull); }, ); }