material_state_mixin_test.dart 5.66 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// 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 {
17
  const _InnerWidget({required this.onValueChanged, required this.controller});
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
  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,
40
  });
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

  /// 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) {
61
    return ColoredBox(
62 63 64 65 66 67 68 69 70 71 72
      key: key,
      color: widget.evaluator(this) ? trueColor : falseColor,
      child: _InnerWidget(
        onValueChanged: updateMaterialState(widget.materialState),
        controller: widget.controller,
      ),
    );
  }
}

void main() {
73
  Future<void> verify(WidgetTester tester, Widget widget, StreamController<bool> controller,) async {
74 75 76 77
    await tester.pumpWidget(MaterialApp(home: Scaffold(body: widget)));
    // Set the value to True
    controller.sink.add(true);
    await tester.pumpAndSettle();
78
    expect(tester.widget<ColoredBox>(find.byKey(key)).color, trueColor);
79 80 81 82

    // Set the value to False
    controller.sink.add(false);
    await tester.pumpAndSettle();
83
    expect(tester.widget<ColoredBox>(find.byKey(key)).color, falseColor);
84 85 86 87 88 89 90 91 92
  }

  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,
    );
93
    await verify(tester, widget, controller);
94 95 96 97 98 99 100 101 102
  });

  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,
    );
103
    await verify(tester, widget, controller);
104 105 106 107 108 109 110 111 112
  });

  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,
    );
113
    await verify(tester, widget, controller);
114 115 116 117 118 119 120 121 122
  });

  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,
    );
123
    await verify(tester, widget, controller);
124 125 126 127 128 129 130 131 132
  });

  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,
    );
133
    await verify(tester, widget, controller);
134 135 136 137 138 139 140 141 142
  });

  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,
    );
143
    await verify(tester, widget, controller);
144 145 146 147 148 149 150 151 152
  });

  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,
    );
153
    await verify(tester, widget, controller);
154 155 156 157 158 159 160 161 162
  });

  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,
    );
163
    await verify(tester, widget, controller);
164 165
  });
}