text_field_splash_test.dart 5.71 KB
Newer Older
1 2 3 4
// 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.

5
import 'package:flutter/gestures.dart' show kPressTimeout;
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/rendering.dart';

int confirmCount = 0;
int cancelCount = 0;

class TestInkSplash extends InkSplash {
  TestInkSplash({
    MaterialInkController controller,
    RenderBox referenceBox,
    Offset position,
    Color color,
    bool containedInkWell: false,
    RectCallback rectCallback,
    BorderRadius borderRadius,
    double radius,
    VoidCallback onRemoved,
  }) : super(
    controller: controller,
    referenceBox: referenceBox,
    position: position,
    color: color,
    containedInkWell: containedInkWell,
    rectCallback: rectCallback,
    borderRadius: borderRadius,
    radius: radius,
    onRemoved: onRemoved,
  );

  @override
  void confirm() {
    confirmCount += 1;
    super.confirm();
  }

  @override
  void cancel() {
    cancelCount += 1;
    super.cancel();
  }
}

class TestInkSplashFactory extends InteractiveInkFeatureFactory {
  const TestInkSplashFactory();

  @override
  InteractiveInkFeature create({
    MaterialInkController controller,
    RenderBox referenceBox,
    Offset position,
    Color color,
    bool containedInkWell: false,
    RectCallback rectCallback,
    BorderRadius borderRadius,
    double radius,
    VoidCallback onRemoved,
  }) {
    return new TestInkSplash(
      controller: controller,
      referenceBox: referenceBox,
      position: position,
      color: color,
      containedInkWell: containedInkWell,
      rectCallback: rectCallback,
      borderRadius: borderRadius,
      radius: radius,
      onRemoved: onRemoved,
    );
  }
}

void main() {
  testWidgets('Tap and no focus causes a splash', (WidgetTester tester) async {
    final Key textField1 = new UniqueKey();
    final Key textField2 = new UniqueKey();

    await tester.pumpWidget(
      new MaterialApp(
        home: new Theme(
          data: new ThemeData.light().copyWith(splashFactory: const TestInkSplashFactory()),
          child: new Material(
            child: new Container(
              alignment: Alignment.topLeft,
              child: new Column(
                children: <Widget>[
                  new TextField(
                    key: textField1,
                    decoration: const InputDecoration(
                      labelText: 'label',
                    ),
                  ),
                  new TextField(
                    key: textField2,
                    decoration: const InputDecoration(
                      labelText: 'label',
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      )
    );

    confirmCount = 0;
    cancelCount = 0;

    await tester.tap(find.byKey(textField1));
    await tester.pumpAndSettle();
    expect(confirmCount, 1);
    expect(cancelCount, 0);

    // textField1 already has the focus, no new splash
    await tester.tap(find.byKey(textField1));
    await tester.pumpAndSettle();
    expect(confirmCount, 1);
    expect(cancelCount, 0);

    // textField2 gets the focus and a splash
    await tester.tap(find.byKey(textField2));
    await tester.pumpAndSettle();
    expect(confirmCount, 2);
    expect(cancelCount, 0);

    // Tap outside of textField1's editable. It still gets focus and splash.
    await tester.tapAt(tester.getTopLeft(find.byKey(textField1)));
    await tester.pumpAndSettle();
    expect(confirmCount, 3);
    expect(cancelCount, 0);

    // Tap in the center of textField2's editable. It still gets the focus
    // and the splash. There is no splash cancel.
    await tester.tap(find.byKey(textField2));
    await tester.pumpAndSettle();
    expect(confirmCount, 4);
    expect(cancelCount, 0);
  });

  testWidgets('Splash cancel', (WidgetTester tester) async {
    await tester.pumpWidget(
      new MaterialApp(
        home: new Theme(
          data: new ThemeData.light().copyWith(splashFactory: const TestInkSplashFactory()),
          child: new Material(
            child: new ListView(
              children: <Widget>[
                const TextField(
                  decoration: const InputDecoration(
                    labelText: 'label1',
                  ),
                ),
                const TextField(
                  decoration: const InputDecoration(
                    labelText: 'label2',
                  ),
                ),
                new Container(
                  height: 1000.0,
                  color: const Color(0xFF00FF00),
                ),
              ],
            ),
          ),
        ),
      )
    );

    confirmCount = 0;
    cancelCount = 0;

    // Pointer is dragged below the textfield, splash is canceled.
    final TestGesture gesture1 = await tester.startGesture(tester.getCenter(find.text('label1')));
180 181

    // Splashes start on tapDown.
Josh Soref's avatar
Josh Soref committed
182 183
    // If the timeout is less than kPressTimeout the recognizer will just trigger
    // the onTapCancel callback. If the timeout is greater or equal to kPressTimeout
184 185 186
    // and less than kLongPressTimeout then onTapDown, onCancel will be called.
    await tester.pump(kPressTimeout);

187 188 189 190 191 192 193
    await gesture1.moveTo(const Offset(400.0, 300.0));
    await gesture1.up();
    expect(confirmCount, 0);
    expect(cancelCount, 1);

    // Pointer is dragged upwards causing a scroll, splash is canceled.
    final TestGesture gesture2 = await tester.startGesture(tester.getCenter(find.text('label2')));
194 195
    await tester.pump(kPressTimeout);
    await gesture2.moveBy(const Offset(0.0, -200.0));
196 197 198 199 200
    await gesture2.up();
    expect(confirmCount, 0);
    expect(cancelCount, 2);
  });
}