import 'package:tane/ui/edge_fade.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { // A horizontal strip of [count] fixed-width boxes inside an EdgeFade-wrapped // SingleChildScrollView, laid out at the default 800px test surface width. Widget harness({ required int count, TextDirection direction = TextDirection.ltr, ScrollController? controller, }) { return Directionality( textDirection: direction, child: EdgeFade( child: SingleChildScrollView( controller: controller, scrollDirection: Axis.horizontal, child: Row( children: [ for (var i = 0; i < count; i++) const SizedBox(width: 100, height: 40), ], ), ), ), ); } EdgeFadeState state(WidgetTester tester) => tester.state(find.byType(EdgeFade)); testWidgets('no fade on either edge when content fits', (tester) async { await tester.pumpWidget(harness(count: 3)); // 300px < 800px await tester.pump(); // let the post-layout metrics notification land expect(state(tester).fadeLeft, isFalse); expect(state(tester).fadeRight, isFalse); expect(find.byIcon(Icons.chevron_left), findsNothing); expect(find.byIcon(Icons.chevron_right), findsNothing); }); testWidgets('a trailing chevron cue appears when the row overflows', (tester) async { await tester.pumpWidget(harness(count: 20)); await tester.pump(); expect(find.byIcon(Icons.chevron_right), findsOneWidget); expect(find.byIcon(Icons.chevron_left), findsNothing); }); testWidgets('LTR: at start only the trailing (right) edge fades', (tester) async { await tester.pumpWidget(harness(count: 20)); // 2000px > 800px await tester.pump(); expect(state(tester).fadeLeft, isFalse); expect(state(tester).fadeRight, isTrue); }); testWidgets('LTR: in the middle both edges fade', (tester) async { final controller = ScrollController(); addTearDown(controller.dispose); await tester.pumpWidget(harness(count: 20, controller: controller)); await tester.pump(); controller.jumpTo(600); await tester.pump(); expect(state(tester).fadeLeft, isTrue); expect(state(tester).fadeRight, isTrue); }); testWidgets('LTR: at the end only the leading (left) edge fades', (tester) async { final controller = ScrollController(); addTearDown(controller.dispose); await tester.pumpWidget(harness(count: 20, controller: controller)); await tester.pump(); controller.jumpTo(controller.position.maxScrollExtent); await tester.pump(); expect(state(tester).fadeLeft, isTrue); expect(state(tester).fadeRight, isFalse); }); testWidgets('RTL: at start only the LEFT edge fades (mirrored)', (tester) async { await tester .pumpWidget(harness(count: 20, direction: TextDirection.rtl)); await tester.pump(); expect(state(tester).fadeLeft, isTrue); expect(state(tester).fadeRight, isFalse); }); testWidgets('RTL: at the end only the RIGHT edge fades (mirrored)', (tester) async { final controller = ScrollController(); addTearDown(controller.dispose); await tester.pumpWidget(harness( count: 20, direction: TextDirection.rtl, controller: controller, )); await tester.pump(); controller.jumpTo(controller.position.maxScrollExtent); await tester.pump(); expect(state(tester).fadeLeft, isFalse); expect(state(tester).fadeRight, isTrue); }); testWidgets('RTL: no fade when content fits', (tester) async { await tester.pumpWidget(harness(count: 3, direction: TextDirection.rtl)); await tester.pump(); expect(state(tester).fadeLeft, isFalse); expect(state(tester).fadeRight, isFalse); }); testWidgets('fades clear when content shrinks to fit', (tester) async { await tester.pumpWidget(harness(count: 20)); await tester.pump(); expect(state(tester).fadeRight, isTrue); await tester.pumpWidget(harness(count: 3)); await tester.pump(); expect(state(tester).fadeLeft, isFalse); expect(state(tester).fadeRight, isFalse); }); testWidgets('scrolling by drag updates the fades', (tester) async { await tester.pumpWidget(harness(count: 20)); await tester.pump(); expect(state(tester).fadeLeft, isFalse); await tester.drag( find.byType(SingleChildScrollView), const Offset(-300, 0)); await tester.pump(); expect(state(tester).fadeLeft, isTrue); expect(state(tester).fadeRight, isTrue); }); }