blob: 811a2b8227b9001f2728672c6dd124cfb05f83c4 [file] [log] [blame]
// 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/gestures.dart' show kPressTimeout;
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,
ShapeBorder customBorder,
double radius,
VoidCallback onRemoved,
TextDirection textDirection
}) : super(
controller: controller,
referenceBox: referenceBox,
position: position,
color: color,
containedInkWell: containedInkWell,
rectCallback: rectCallback,
borderRadius: borderRadius,
customBorder: customBorder,
radius: radius,
onRemoved: onRemoved,
textDirection: textDirection,
);
@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,
ShapeBorder customBorder,
double radius,
VoidCallback onRemoved,
TextDirection textDirection,
}) {
return TestInkSplash(
controller: controller,
referenceBox: referenceBox,
position: position,
color: color,
containedInkWell: containedInkWell,
rectCallback: rectCallback,
borderRadius: borderRadius,
customBorder: customBorder,
radius: radius,
onRemoved: onRemoved,
textDirection: textDirection,
);
}
}
void main() {
testWidgets('Tap and no focus causes a splash', (WidgetTester tester) async {
final Key textField1 = UniqueKey();
final Key textField2 = UniqueKey();
await tester.pumpWidget(
MaterialApp(
home: Theme(
data: ThemeData.light().copyWith(splashFactory: const TestInkSplashFactory()),
child: Material(
child: Container(
alignment: Alignment.topLeft,
child: Column(
children: <Widget>[
TextField(
key: textField1,
decoration: const InputDecoration(
labelText: 'label',
),
),
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(
MaterialApp(
home: Theme(
data: ThemeData.light().copyWith(splashFactory: const TestInkSplashFactory()),
child: Material(
child: ListView(
children: <Widget>[
const TextField(
decoration: InputDecoration(
labelText: 'label1',
),
),
const TextField(
decoration: InputDecoration(
labelText: 'label2',
),
),
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')));
// Splashes start on tapDown.
// If the timeout is less than kPressTimeout the recognizer will just trigger
// the onTapCancel callback. If the timeout is greater or equal to kPressTimeout
// and less than kLongPressTimeout then onTapDown, onCancel will be called.
await tester.pump(kPressTimeout);
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')));
await tester.pump(kPressTimeout);
await gesture2.moveBy(const Offset(0.0, -200.0));
await gesture2.up();
expect(confirmCount, 0);
expect(cancelCount, 2);
});
}