| // 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 'dart:async'; |
| |
| import 'package:flutter/material.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| |
| const Key key = Key('testContainer'); |
| const Color trueColor = Colors.red; |
| const Color falseColor = Colors.green; |
| |
| /// Mock widget which plays the role of a button -- it can emit notifications |
| /// that [MaterialState] values are now in or out of play. |
| class _InnerWidget extends StatefulWidget { |
| const _InnerWidget({required this.onValueChanged, required this.controller}); |
| final ValueChanged<bool> onValueChanged; |
| final StreamController<bool> controller; |
| |
| @override |
| _InnerWidgetState createState() => _InnerWidgetState(); |
| } |
| |
| class _InnerWidgetState extends State<_InnerWidget> { |
| @override |
| void initState() { |
| super.initState(); |
| widget.controller.stream.listen((bool val) => widget.onValueChanged(val)); |
| } |
| @override |
| Widget build(BuildContext context) => Container(); |
| } |
| |
| class _MyWidget extends StatefulWidget { |
| const _MyWidget({ |
| required this.controller, |
| required this.evaluator, |
| required this.materialState, |
| }); |
| |
| /// Wrapper around `MaterialStateMixin.isPressed/isHovered/isFocused/etc`. |
| final bool Function(_MyWidgetState state) evaluator; |
| |
| /// Stream passed down to the child [_InnerWidget] to begin the process. |
| /// This plays the role of an actual user interaction in the wild, but allows |
| /// us to engage the system without mocking pointers/hovers etc. |
| final StreamController<bool> controller; |
| |
| /// The value we're watching in the given test. |
| final MaterialState materialState; |
| |
| @override |
| State createState() => _MyWidgetState(); |
| } |
| |
| class _MyWidgetState extends State<_MyWidget> with MaterialStateMixin { |
| |
| @override |
| Widget build(BuildContext context) { |
| return ColoredBox( |
| key: key, |
| color: widget.evaluator(this) ? trueColor : falseColor, |
| child: _InnerWidget( |
| onValueChanged: updateMaterialState(widget.materialState), |
| controller: widget.controller, |
| ), |
| ); |
| } |
| } |
| |
| void main() { |
| Future<void> verify(WidgetTester tester, Widget widget, StreamController<bool> controller,) async { |
| await tester.pumpWidget(MaterialApp(home: Scaffold(body: widget))); |
| // Set the value to True |
| controller.sink.add(true); |
| await tester.pumpAndSettle(); |
| expect(tester.widget<ColoredBox>(find.byKey(key)).color, trueColor); |
| |
| // Set the value to False |
| controller.sink.add(false); |
| await tester.pumpAndSettle(); |
| expect(tester.widget<ColoredBox>(find.byKey(key)).color, falseColor); |
| } |
| |
| testWidgets('MaterialState.pressed is tracked', (WidgetTester tester) async { |
| final StreamController<bool> controller = StreamController<bool>(); |
| final _MyWidget widget = _MyWidget( |
| controller: controller, |
| evaluator: (_MyWidgetState state) => state.isPressed, |
| materialState: MaterialState.pressed, |
| ); |
| await verify(tester, widget, controller); |
| }); |
| |
| testWidgets('MaterialState.focused is tracked', (WidgetTester tester) async { |
| final StreamController<bool> controller = StreamController<bool>(); |
| final _MyWidget widget = _MyWidget( |
| controller: controller, |
| evaluator: (_MyWidgetState state) => state.isFocused, |
| materialState: MaterialState.focused, |
| ); |
| await verify(tester, widget, controller); |
| }); |
| |
| testWidgets('MaterialState.hovered is tracked', (WidgetTester tester) async { |
| final StreamController<bool> controller = StreamController<bool>(); |
| final _MyWidget widget = _MyWidget( |
| controller: controller, |
| evaluator: (_MyWidgetState state) => state.isHovered, |
| materialState: MaterialState.hovered, |
| ); |
| await verify(tester, widget, controller); |
| }); |
| |
| testWidgets('MaterialState.disabled is tracked', (WidgetTester tester) async { |
| final StreamController<bool> controller = StreamController<bool>(); |
| final _MyWidget widget = _MyWidget( |
| controller: controller, |
| evaluator: (_MyWidgetState state) => state.isDisabled, |
| materialState: MaterialState.disabled, |
| ); |
| await verify(tester, widget, controller); |
| }); |
| |
| testWidgets('MaterialState.selected is tracked', (WidgetTester tester) async { |
| final StreamController<bool> controller = StreamController<bool>(); |
| final _MyWidget widget = _MyWidget( |
| controller: controller, |
| evaluator: (_MyWidgetState state) => state.isSelected, |
| materialState: MaterialState.selected, |
| ); |
| await verify(tester, widget, controller); |
| }); |
| |
| testWidgets('MaterialState.scrolledUnder is tracked', (WidgetTester tester) async { |
| final StreamController<bool> controller = StreamController<bool>(); |
| final _MyWidget widget = _MyWidget( |
| controller: controller, |
| evaluator: (_MyWidgetState state) => state.isScrolledUnder, |
| materialState: MaterialState.scrolledUnder, |
| ); |
| await verify(tester, widget, controller); |
| }); |
| |
| testWidgets('MaterialState.dragged is tracked', (WidgetTester tester) async { |
| final StreamController<bool> controller = StreamController<bool>(); |
| final _MyWidget widget = _MyWidget( |
| controller: controller, |
| evaluator: (_MyWidgetState state) => state.isDragged, |
| materialState: MaterialState.dragged, |
| ); |
| await verify(tester, widget, controller); |
| }); |
| |
| testWidgets('MaterialState.error is tracked', (WidgetTester tester) async { |
| final StreamController<bool> controller = StreamController<bool>(); |
| final _MyWidget widget = _MyWidget( |
| controller: controller, |
| evaluator: (_MyWidgetState state) => state.isErrored, |
| materialState: MaterialState.error, |
| ); |
| await verify(tester, widget, controller); |
| }); |
| } |