// Copyright 2014 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; class Page extends StatefulWidget { const Page({super.key, required this.title, required this.onDispose}); final String title; final void Function()? onDispose; @override State createState() => _PageState(); } class _PageState extends State { @override void dispose() { widget.onDispose?.call(); super.dispose(); } @override Widget build(BuildContext context) { return Center(child: FilledButton(onPressed: () {}, child: Text(widget.title))); } } void main() { // Regression test for https://github.com/flutter/flutter/issues/21506. testWidgets('InkSplash receives textDirection', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('Button Border Test')), body: Center(child: ElevatedButton(child: const Text('Test'), onPressed: () {})), ), ), ); await tester.tap(find.text('Test')); // start ink animation which asserts for a textDirection. await tester.pumpAndSettle(const Duration(milliseconds: 30)); expect(tester.takeException(), isNull); }); testWidgets('Material2 - InkWell with NoSplash splashFactory paints nothing', ( WidgetTester tester, ) async { Widget buildFrame({InteractiveInkFeatureFactory? splashFactory}) { return MaterialApp( theme: ThemeData(useMaterial3: false), home: Scaffold( body: Center( child: Material( child: InkWell(splashFactory: splashFactory, onTap: () {}, child: const Text('test')), ), ), ), ); } // NoSplash.splashFactory, no splash circles drawn await tester.pumpWidget(buildFrame(splashFactory: NoSplash.splashFactory)); { final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test'))); final MaterialInkController material = Material.of(tester.element(find.text('test'))); await tester.pump(const Duration(milliseconds: 200)); expect(material, paintsExactlyCountTimes(#drawCircle, 0)); await gesture.up(); await tester.pumpAndSettle(); } // Default splashFactory (from Theme.of().splashFactory), one splash circle drawn. await tester.pumpWidget(buildFrame()); { final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test'))); final MaterialInkController material = Material.of(tester.element(find.text('test'))); await tester.pump(const Duration(milliseconds: 200)); expect(material, paintsExactlyCountTimes(#drawCircle, 1)); await gesture.up(); await tester.pumpAndSettle(); } }); testWidgets('Material3 - InkWell with NoSplash splashFactory paints nothing', ( WidgetTester tester, ) async { Widget buildFrame({InteractiveInkFeatureFactory? splashFactory}) { return MaterialApp( home: Scaffold( body: Center( child: Material( child: InkWell(splashFactory: splashFactory, onTap: () {}, child: const Text('test')), ), ), ), ); } // NoSplash.splashFactory, one rect is drawn for the highlight. await tester.pumpWidget(buildFrame(splashFactory: NoSplash.splashFactory)); { final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test'))); final MaterialInkController material = Material.of(tester.element(find.text('test'))); await tester.pump(const Duration(milliseconds: 200)); expect(material, paintsExactlyCountTimes(#drawRect, 1)); await gesture.up(); await tester.pumpAndSettle(); } // Default splashFactory (from Theme.of().splashFactory), two rects are drawn for the splash and highlight. await tester.pumpWidget(buildFrame()); { final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test'))); final MaterialInkController material = Material.of(tester.element(find.text('test'))); await tester.pump(const Duration(milliseconds: 200)); expect(material, paintsExactlyCountTimes(#drawRect, (kIsWeb ? 1 : 2))); await gesture.up(); await tester.pumpAndSettle(); } }); // Regression test for https://github.com/flutter/flutter/issues/136441. testWidgets('PageView item can dispose when widget with NoSplash.splashFactory is tapped', ( WidgetTester tester, ) async { final PageController controller = PageController(); final List disposedPageIndexes = []; await tester.pumpWidget( MaterialApp( theme: ThemeData(splashFactory: NoSplash.splashFactory), home: Scaffold( body: PageView.builder( controller: controller, itemBuilder: (BuildContext context, int index) { return Page( title: 'Page $index', onDispose: () { disposedPageIndexes.add(index); }, ); }, itemCount: 3, ), ), ), ); controller.jumpToPage(1); await tester.pumpAndSettle(); await tester.tap(find.text('Page 1')); await tester.pumpAndSettle(); controller.jumpToPage(0); await tester.pumpAndSettle(); expect(disposedPageIndexes, [0, 1]); controller.dispose(); }); }