diff --git a/packages/material_ui/temporarily_disabled_tests/bottom_navigation_bar_test.dart b/packages/material_ui/test/bottom_navigation_bar_test.dart similarity index 99% rename from packages/material_ui/temporarily_disabled_tests/bottom_navigation_bar_test.dart rename to packages/material_ui/test/bottom_navigation_bar_test.dart index ca2a1ca474a3..f811f1db0730 100644 --- a/packages/material_ui/temporarily_disabled_tests/bottom_navigation_bar_test.dart +++ b/packages/material_ui/test/bottom_navigation_bar_test.dart @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -@Skip( - 'This file is skipped due to a cross-import that needs to be fixed. Tracked in https://github.com/flutter/flutter/issues/177028.', -) // This file is run as part of a reduced test set in CI on Mac and Windows // machines. @Tags(['reduced-test-set']) @@ -13,13 +10,14 @@ library; import 'dart:math'; import 'dart:ui'; -import 'package:material_ui/material_ui.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:vector_math/vector_math_64.dart' show Vector3; -import '../widgets/feedback_tester.dart'; -import '../widgets/semantics_tester.dart'; +import 'feedback_tester.dart'; +import 'finders.dart'; +import 'semantics_tester.dart'; void main() { testWidgets('BottomNavigationBar callback test', (WidgetTester tester) async { @@ -1716,15 +1714,15 @@ void main() { expect(find.text('A'), findsOneWidget); await tester.longPress(find.text('A')); - expect(find.byTooltip('A tooltip'), findsOneWidget); + expect(findByTooltip('A tooltip'), findsOneWidget); expect(find.text('B'), findsOneWidget); await tester.longPress(find.text('B')); - expect(find.byTooltip('B'), findsNothing); + expect(findByTooltip('B'), findsNothing); expect(find.text('C'), findsOneWidget); await tester.longPress(find.text('C')); - expect(find.byTooltip('C'), findsNothing); + expect(findByTooltip('C'), findsNothing); }); testWidgets('BottomNavigationBar limits width of tiles with long labels', ( diff --git a/packages/material_ui/test/feedback_tester.dart b/packages/material_ui/test/feedback_tester.dart new file mode 100644 index 000000000000..a08224959c0a --- /dev/null +++ b/packages/material_ui/test/feedback_tester.dart @@ -0,0 +1,51 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; + +/// Tracks how often feedback has been requested since its instantiation. +/// +/// It replaces the MockMethodCallHandler of [SystemChannels.platform] and +/// cannot be used in combination with other classes that do the same. +class FeedbackTester { + FeedbackTester() { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler( + SystemChannels.platform, + _handler, + ); + } + + /// Number of times haptic feedback was requested (vibration). + int get hapticCount => _hapticCount; + int _hapticCount = 0; + + /// Number of times the click sound was requested to play. + int get clickSoundCount => _clickSoundCount; + int _clickSoundCount = 0; + + Future _handler(MethodCall methodCall) async { + if (methodCall.method == 'HapticFeedback.vibrate') { + _hapticCount++; + } + if (methodCall.method == 'SystemSound.play' && + methodCall.arguments == SystemSoundType.click.toString()) { + _clickSoundCount++; + } + } + + /// Stops tracking. + void dispose() { + assert( + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.checkMockMessageHandler( + SystemChannels.platform.name, + _handler, + ), + ); + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler( + SystemChannels.platform, + null, + ); + } +} diff --git a/packages/material_ui/test/finders.dart b/packages/material_ui/test/finders.dart new file mode 100644 index 000000000000..df70ae699958 --- /dev/null +++ b/packages/material_ui/test/finders.dart @@ -0,0 +1,43 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; + +/// Finds [RawTooltip] or [Tooltip] widgets with the given `message`. +/// +/// ## Sample code +/// +/// ```dart +/// expect(find.byTooltip('Back'), findsOneWidget); +/// expect(find.byTooltip(RegExp('Back.*')), findsNWidgets(2)); +/// ``` +/// +/// If the `skipOffstage` argument is true (the default), then this skips +/// nodes that are [Offstage] or that are from inactive [Route]s. +/// +/// This was copied from flutter_test, which uses flutter/material.dart. +/// +// TODO(justinmc): Port flutter_test to material_ui, then delete this method and +// use that one. See https://github.com/flutter/flutter/issues/186966 +Finder findByTooltip(Pattern message, {bool skipOffstage = true}) { + return find.byWidgetPredicate((Widget widget) { + // Compare RawTooltip's semantics tooltip with the given message. + // However, Tooltip's message needs to be checked directly if: + // 1. Tooltip.excludeFromSemantics is true, since in this case Tooltip + // provides no semantics tooltip to the underlying RawTooltip. + // 2. Tooltip.message and Tooltip.richMessage are empty, since in this + // case no RawTooltip is created. + if (widget is Tooltip) { + final String tooltipMessage = widget.message ?? widget.richMessage!.toPlainText(); + if ((widget.excludeFromSemantics ?? false) || tooltipMessage.isEmpty) { + return message is RegExp ? message.hasMatch(tooltipMessage) : tooltipMessage == message; + } + } + return widget is RawTooltip && + (message is RegExp + ? message.hasMatch(widget.semanticsTooltip ?? '') + : widget.semanticsTooltip == message); + }, skipOffstage: skipOffstage); +} diff --git a/packages/material_ui/test/navigation_bar_test.dart b/packages/material_ui/test/navigation_bar_test.dart index 87a4e7a96cc4..63a6b585e75a 100644 --- a/packages/material_ui/test/navigation_bar_test.dart +++ b/packages/material_ui/test/navigation_bar_test.dart @@ -14,6 +14,7 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:material_ui/material_ui.dart'; +import 'finders.dart'; void main() { testWidgets('Navigation bar updates destinations when tapped', (WidgetTester tester) async { @@ -440,15 +441,15 @@ void main() { expect(find.text('A'), findsOneWidget); await tester.longPress(find.text('A')); - expect(_findByTooltip('A tooltip'), findsOneWidget); + expect(findByTooltip('A tooltip'), findsOneWidget); expect(find.text('B'), findsOneWidget); await tester.longPress(find.text('B')); - expect(_findByTooltip('B'), findsOneWidget); + expect(findByTooltip('B'), findsOneWidget); expect(find.text('C'), findsOneWidget); await tester.longPress(find.text('C')); - expect(_findByTooltip('C'), findsNothing); + expect(findByTooltip('C'), findsNothing); }); testWidgets('Navigation bar semantics', (WidgetTester tester) async { @@ -1814,40 +1815,3 @@ TextStyle _getLabelStyle(WidgetTester tester, String text) { .text .style!; } - -/// Finds [RawTooltip] or [Tooltip] widgets with the given `message`. -/// -/// ## Sample code -/// -/// ```dart -/// expect(find.byTooltip('Back'), findsOneWidget); -/// expect(find.byTooltip(RegExp('Back.*')), findsNWidgets(2)); -/// ``` -/// -/// If the `skipOffstage` argument is true (the default), then this skips -/// nodes that are [Offstage] or that are from inactive [Route]s. -/// -/// This was copied from flutter_test, which uses flutter/material.dart. -// TODO(justinmc): Port flutter_test to material_ui, then delete this method and -// use that one. -Finder _findByTooltip(Pattern message, {bool skipOffstage = true}) { - return find.byWidgetPredicate((Widget widget) { - // Compare RawTooltip's semantics tooltip with the given message. - // However, Tooltip's message needs to be checked directly if: - // 1. Tooltip.excludeFromSemantics is true, since in this case Tooltip - // provides no semantics tooltip to the underlying RawTooltip. - // 2. Tooltip.message and Tooltip.richMessage are empty, since in this - // case no RawTooltip is created. - if (widget is Tooltip) { - //if (widget.runtimeType == 'Tooltip') { - final String tooltipMessage = widget.message ?? widget.richMessage!.toPlainText(); - if ((widget.excludeFromSemantics ?? false) || tooltipMessage.isEmpty) { - return message is RegExp ? message.hasMatch(tooltipMessage) : tooltipMessage == message; - } - } - return widget is RawTooltip && - (message is RegExp - ? message.hasMatch(widget.semanticsTooltip ?? '') - : widget.semanticsTooltip == message); - }, skipOffstage: skipOffstage); -}