ink_paint_test.dart 10.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
// Copyright 2017 The Chromium 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/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';

import '../rendering/mock_canvas.dart';

void main() {
Ian Hickson's avatar
Ian Hickson committed
12
  testWidgets('The InkWell widget renders an ink splash', (WidgetTester tester) async {
13 14
    const Color highlightColor = const Color(0xAAFF0000);
    const Color splashColor = const Color(0xAA0000FF);
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
    final BorderRadius borderRadius = new BorderRadius.circular(6.0);

    await tester.pumpWidget(
      new Material(
        child: new Center(
          child: new Container(
            width: 200.0,
            height: 60.0,
            child: new InkWell(
              borderRadius: borderRadius,
              highlightColor: highlightColor,
              splashColor: splashColor,
              onTap: () { },
            ),
          ),
        ),
      ),
    );

34
    final Offset center = tester.getCenter(find.byType(InkWell));
35 36
    final TestGesture gesture = await tester.startGesture(center);
    await tester.pump(); // start gesture
37
    await tester.pump(const Duration(milliseconds: 200)); // wait for splash to be well under way
38

39
    final RenderBox box = Material.of(tester.element(find.byType(InkWell))) as dynamic;
40 41 42
    expect(
      box,
      paints
43
        ..clipRRect(rrect: new RRect.fromLTRBR(300.0, 270.0, 500.0, 330.0, const Radius.circular(6.0)))
44 45
        ..circle(x: 400.0, y: 300.0, radius: 21.0, color: splashColor)
        ..rrect(
46
          rrect: new RRect.fromLTRBR(300.0, 270.0, 500.0, 330.0, const Radius.circular(6.0)),
47 48 49 50 51 52
          color: highlightColor,
        )
    );

    await gesture.up();
  });
53

Ian Hickson's avatar
Ian Hickson committed
54
  testWidgets('The InkWell widget renders an ink ripple', (WidgetTester tester) async {
55 56
    const Color highlightColor = const Color(0xAAFF0000);
    const Color splashColor = const Color(0xB40000FF);
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
    final BorderRadius borderRadius = new BorderRadius.circular(6.0);

    await tester.pumpWidget(
      new Material(
        child: new Center(
          child: new Container(
            width: 100.0,
            height: 100.0,
            child: new InkWell(
              borderRadius: borderRadius,
              highlightColor: highlightColor,
              splashColor: splashColor,
              onTap: () { },
              radius: 100.0,
              splashFactory: InkRipple.splashFactory,
            ),
          ),
        ),
      ),
    );

    final Offset tapDownOffset = tester.getTopLeft(find.byType(InkWell));
    final Offset inkWellCenter = tester.getCenter(find.byType(InkWell));
    //final TestGesture gesture = await tester.startGesture(tapDownOffset);
    await tester.tapAt(tapDownOffset);
    await tester.pump(); // start gesture

    final RenderBox box = Material.of(tester.element(find.byType(InkWell))) as dynamic;

    bool offsetsAreClose(Offset a, Offset b) => (a - b).distance < 1.0;
    bool radiiAreClose(double a, double b) => (a - b).abs() < 1.0;

    // Initially the ripple's center is where the tap occurred,
    expect(box, paints..something((Symbol method, List<dynamic> arguments) {
      if (method != #drawCircle)
        return false;
      final Offset center = arguments[0];
      final double radius = arguments[1];
      final Paint paint = arguments[2];
      if (offsetsAreClose(center, tapDownOffset) && radius == 30.0 && paint.color.alpha == 0)
        return true;
      throw '''
        Expected: center == $tapDownOffset, radius == 30.0, alpha == 0
        Found: center == $center radius == $radius alpha == ${paint.color.alpha}''';
    }));

    // The ripple fades in for 75ms. During that time its alpha is eased from
104
    // 0 to the splashColor's alpha value and its center moves towards the
105 106 107 108 109 110 111 112 113
    // center of the ink well.
    await tester.pump(const Duration(milliseconds: 50));
    expect(box, paints..something((Symbol method, List<dynamic> arguments) {
      if (method != #drawCircle)
        return false;
      final Offset center = arguments[0];
      final double radius = arguments[1];
      final Paint paint = arguments[2];
      final Offset expectedCenter = tapDownOffset + const Offset(17.0, 17.0);
114
      const double expectedRadius = 56.0;
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
      if (offsetsAreClose(center, expectedCenter) && radiiAreClose(radius, expectedRadius) && paint.color.alpha == 120)
        return true;
      throw '''
        Expected: center == $expectedCenter, radius == $expectedRadius, alpha == 120
        Found: center == $center radius == $radius alpha == ${paint.color.alpha}''';
    }));

    // At 75ms the ripple has fade in: it's alpha matches the splashColor's
    // alpha and its center has moved closer to the ink well's center.
    await tester.pump(const Duration(milliseconds: 25));
    expect(box, paints..something((Symbol method, List<dynamic> arguments) {
      if (method != #drawCircle)
        return false;
      final Offset center = arguments[0];
      final double radius = arguments[1];
      final Paint paint = arguments[2];
      final Offset expectedCenter = tapDownOffset + const Offset(29.0, 29.0);
132
      const double expectedRadius = 73.0;
133 134 135 136 137 138 139 140 141 142
      if (offsetsAreClose(center, expectedCenter) && radiiAreClose(radius, expectedRadius) && paint.color.alpha == 180)
        return true;
      throw '''
        Expected: center == $expectedCenter, radius == $expectedRadius, alpha == 180
        Found: center == $center radius == $radius alpha == ${paint.color.alpha}''';
    }));

    // At this point the splash radius has expanded to its limit: 5 past the
    // ink well's radius parameter. The splash center has moved to its final
    // location at the inkwell's center and the fade-out is about to start.
143 144
    // The fade-out begins at 225ms = 50ms + 25ms + 150ms.
    await tester.pump(const Duration(milliseconds: 150));
145 146 147 148 149 150 151
    expect(box, paints..something((Symbol method, List<dynamic> arguments) {
      if (method != #drawCircle)
        return false;
      final Offset center = arguments[0];
      final double radius = arguments[1];
      final Paint paint = arguments[2];
      final Offset expectedCenter = inkWellCenter;
152
      const double expectedRadius = 105.0;
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
      if (offsetsAreClose(center, expectedCenter) && radiiAreClose(radius, expectedRadius) && paint.color.alpha == 180)
        return true;
      throw '''
        Expected: center == $expectedCenter, radius == $expectedRadius, alpha == 180
        Found: center == $center radius == $radius alpha == ${paint.color.alpha}''';
    }));

    // After another 150ms the fade-out is complete.
    await tester.pump(const Duration(milliseconds: 150));
    expect(box, paints..something((Symbol method, List<dynamic> arguments) {
      if (method != #drawCircle)
        return false;
      final Offset center = arguments[0];
      final double radius = arguments[1];
      final Paint paint = arguments[2];
      final Offset expectedCenter = inkWellCenter;
169
      const double expectedRadius = 105.0;
170 171 172 173 174 175
      if (offsetsAreClose(center, expectedCenter) && radiiAreClose(radius, expectedRadius) && paint.color.alpha == 0)
        return true;
      throw '''
        Expected: center == $expectedCenter, radius == $expectedRadius, alpha == 0
        Found: center == $center radius == $radius alpha == ${paint.color.alpha}''';
    }));
Ian Hickson's avatar
Ian Hickson committed
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
  });

  testWidgets('Does the Ink widget render anything', (WidgetTester tester) async {
    await tester.pumpWidget(
      new Material(
        child: new Center(
          child: new Ink(
            color: Colors.blue,
            width: 200.0,
            height: 200.0,
            child: new InkWell(
              splashColor: Colors.green,
              onTap: () { },
            ),
          ),
        ),
      ),
    );
194

Ian Hickson's avatar
Ian Hickson committed
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
    final Offset center = tester.getCenter(find.byType(InkWell));
    final TestGesture gesture = await tester.startGesture(center);
    await tester.pump(); // start gesture
    await tester.pump(const Duration(milliseconds: 200)); // wait for splash to be well under way

    final RenderBox box = Material.of(tester.element(find.byType(InkWell))) as dynamic;
    expect(
      box,
      paints
        ..rect(rect: new Rect.fromLTRB(300.0, 200.0, 500.0, 400.0), color: new Color(Colors.blue.value))
        ..circle(color: new Color(Colors.green.value))
    );

    await tester.pumpWidget(
      new Material(
        child: new Center(
          child: new Ink(
            color: Colors.red,
            width: 200.0,
            height: 200.0,
            child: new InkWell(
              splashColor: Colors.green,
              onTap: () { },
            ),
          ),
        ),
      ),
    );

    expect(Material.of(tester.element(find.byType(InkWell))), same(box));

    expect(
      box,
      paints
        ..rect(rect: new Rect.fromLTRB(300.0, 200.0, 500.0, 400.0), color: new Color(Colors.red.value))
        ..circle(color: new Color(Colors.green.value))
    );

    await tester.pumpWidget(
      new Material(
        child: new Center(
          child: new InkWell( // this is at a different depth in the tree so it's now a new InkWell
            splashColor: Colors.green,
            onTap: () { },
          ),
        ),
      ),
    );

    expect(Material.of(tester.element(find.byType(InkWell))), same(box));

    expect(box, isNot(paints..rect()));
    expect(box, isNot(paints..circle()));

    await gesture.up();
250
  });
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280

  testWidgets('Cancel an InkRipple that was disposed when its animation ended', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/14391
    await tester.pumpWidget(
      new Material(
        child: new Center(
          child: new Container(
            width: 100.0,
            height: 100.0,
            child: new InkWell(
              onTap: () { },
              radius: 100.0,
              splashFactory: InkRipple.splashFactory,
            ),
          ),
        ),
      ),
    );

    final Offset tapDownOffset = tester.getTopLeft(find.byType(InkWell));
    await tester.tapAt(tapDownOffset);
    await tester.pump(); // start splash
    await tester.pump(const Duration(milliseconds: 375)); // _kFadeOutDuration, in_ripple.dart

    final TestGesture gesture = await tester.startGesture(tapDownOffset);
    await tester.pump(); // start gesture
    await gesture.moveTo(const Offset(0.0, 0.0));
    await gesture.up(); // generates a tap cancel
    await tester.pumpAndSettle();
  });
281
}