// Author: fruit.com.cn // 职责:验证首页跨页动画的目标保留、连点打断和减少动画行为。 import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:fruitshorts/pages/recommend/home_tab_motion_controller.dart'; const _midpoint = Duration(milliseconds: 90); const _finish = Duration(milliseconds: 300); Widget _pager(HomeTabMotionController controller, List accepted) => MaterialApp( home: PageView( controller: controller, onPageChanged: (index) { if (controller.acceptsSelection(index)) accepted.add(index); }, children: const [ ColoredBox(color: Colors.black), ColoredBox(color: Colors.red), ColoredBox(color: Colors.grey), ], ), ); void main() { testWidgets( 'should_ignore_intermediate_page_when_clicking_across_two_pages', (tester) async { int? settled; final controller = HomeTabMotionController( onSettled: (index) => settled = index, ); addTearDown(controller.dispose); final accepted = []; await tester.pumpWidget(_pager(controller, accepted)); final transition = controller.selectPage(2, reduceMotion: false); await tester.pump(); await tester.pump(_midpoint); expect(controller.pagePosition, inExclusiveRange(0.0, 2.0)); expect(controller.acceptsSelection(1), isFalse); expect(accepted, isNot(contains(1))); await tester.pump(_finish); await transition; expect(controller.pagePosition, 2); expect(settled, 2); expect(controller.acceptsSelection(1), isTrue); }, ); testWidgets('should_keep_last_target_when_clicks_interrupt_each_other', ( tester, ) async { int? settled; final controller = HomeTabMotionController( onSettled: (index) => settled = index, ); addTearDown(controller.dispose); await tester.pumpWidget(_pager(controller, [])); final first = controller.selectPage(2, reduceMotion: false); await tester.pump(); await tester.pump(_midpoint); final last = controller.selectPage(0, reduceMotion: false); await tester.pump(); expect(controller.acceptsSelection(2), isFalse); await tester.pump(_finish); await Future.wait([first, last]); expect(controller.pagePosition, 0); expect(settled, 0); }); testWidgets('should_jump_to_target_when_reduced_motion_is_enabled', ( tester, ) async { int? settled; final controller = HomeTabMotionController( onSettled: (index) => settled = index, ); addTearDown(controller.dispose); await tester.pumpWidget(_pager(controller, [])); await controller.selectPage(2, reduceMotion: true); expect(controller.pagePosition, 2); expect(settled, 2); }); testWidgets('should_release_target_when_user_drag_interrupts_animation', ( tester, ) async { final controller = HomeTabMotionController(onSettled: (_) {}); addTearDown(controller.dispose); await tester.pumpWidget(_pager(controller, [])); final transition = controller.selectPage(2, reduceMotion: false); await tester.pump(); await tester.pump(_midpoint); final gesture = await tester.startGesture( tester.getCenter(find.byType(PageView)), ); await gesture.moveBy(const Offset(60, 0)); await tester.pump(); await transition; expect(controller.acceptsSelection(0), isTrue); expect(controller.acceptsSelection(1), isTrue); await gesture.up(); await tester.pumpAndSettle(); }); }