blob: 515f1a1d33ead177332bdcd12e5beab18e90260b [file] [log] [blame]
// Copyright 2016 The Fuchsia 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:armadillo/recent.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';
void main() {
testWidgets('Dragging an ArmadilloLongPressDraggable',
(WidgetTester tester) async {
int ongoingDrags = 0;
// Create all the widgets.
GlobalKey overlayKey = new GlobalKey();
ArmadilloOverlay overlay = new ArmadilloOverlay(key: overlayKey);
GlobalKey draggableKey = new GlobalKey();
GlobalKey childKey = new GlobalKey();
GlobalKey childWhenDraggingKey = new GlobalKey();
ArmadilloLongPressDraggable<int> draggable =
new ArmadilloLongPressDraggable<int>(
key: draggableKey,
overlayKey: overlayKey,
child: new Container(
key: childKey,
width: 100.0,
height: 100.0,
color: const Color(0xFFFFFF00),
),
feedbackBuilder: (
Offset localDragStartPoint,
Size initialSize,
) {},
data: 1,
childWhenDragging: new Container(
key: childWhenDraggingKey,
width: 100.0,
height: 100.0,
color: const Color(0xFFFFFF00),
),
onDragStarted: () {
ongoingDrags++;
},
onDragEnded: () {
ongoingDrags--;
},
);
// Pump the widgets.
await tester.pumpWidget(
new Stack(
fit: StackFit.passthrough,
children: <Widget>[
new Center(child: draggable),
overlay,
],
),
);
// Initially only child is in the tree.
expect(find.byKey(overlayKey), findsOneWidget);
expect(find.byKey(draggableKey), findsOneWidget);
expect(find.byKey(childKey), findsOneWidget);
expect(find.byKey(childWhenDraggingKey), findsNothing);
expect(ongoingDrags, 0);
TestGesture gesture = await tester.startGesture(
tester.getCenter(find.byKey(draggableKey)),
);
await tester.pump(const Duration(milliseconds: 150));
// Verify the drag hasn't started yet.
expect(find.byKey(overlayKey), findsOneWidget);
expect(find.byKey(draggableKey), findsOneWidget);
expect(find.byKey(childKey), findsOneWidget);
expect(find.byKey(childWhenDraggingKey), findsNothing);
expect(ongoingDrags, 0);
await tester.pump(const Duration(milliseconds: 150));
// Verify the drag has started and childWhenDragging replaces child in the tree.
expect(ongoingDrags, 1);
expect(find.byKey(overlayKey), findsOneWidget);
expect(find.byKey(draggableKey), findsOneWidget);
expect(find.byKey(childKey), findsNothing);
expect(find.byKey(childWhenDraggingKey), findsOneWidget);
await gesture.up();
// Verify the drag has ended but we haven't removed the childWhenDragging yet.
expect(ongoingDrags, 0);
expect(find.byKey(overlayKey), findsOneWidget);
expect(find.byKey(draggableKey), findsOneWidget);
expect(find.byKey(childKey), findsNothing);
expect(find.byKey(childWhenDraggingKey), findsOneWidget);
// Start and finish 'animate back' animation.
await tester.pump();
await tester.pump(const Duration(milliseconds: 350));
// Still animating...
expect(find.byKey(childKey), findsNothing);
expect(find.byKey(childWhenDraggingKey), findsOneWidget);
await tester.pump(const Duration(milliseconds: 350));
// Verify we have replaced childWhenDragging with child.
expect(find.byKey(childKey), findsOneWidget);
expect(find.byKey(childWhenDraggingKey), findsNothing);
});
testWidgets('Dragging multiple ArmadilloLongPressDraggables is not possible',
(WidgetTester tester) async {
int ongoingDrags = 0;
// Create all the widgets.
GlobalKey overlayKey = new GlobalKey();
ArmadilloOverlay overlay = new ArmadilloOverlay(key: overlayKey);
GlobalKey draggableKey = new GlobalKey();
ArmadilloLongPressDraggable<int> draggable =
new ArmadilloLongPressDraggable<int>(
key: draggableKey,
overlayKey: overlayKey,
child: new Container(
width: 100.0,
height: 100.0,
color: const Color(0xFFFFFF00),
),
feedbackBuilder: (
Offset localDragStartPoint,
Size initialSize,
) {},
data: 1,
childWhenDragging: new Container(
width: 100.0,
height: 100.0,
color: const Color(0xFFFFFF00),
),
onDragStarted: () {
ongoingDrags++;
},
onDragEnded: () {
ongoingDrags--;
},
);
// Pump the widgets.
await tester.pumpWidget(
new Stack(
fit: StackFit.passthrough,
children: <Widget>[
new Center(child: draggable),
overlay,
],
),
);
expect(ongoingDrags, 0);
// Start one drag.
TestGesture gesture1 = await tester.startGesture(
tester.getCenter(find.byKey(draggableKey)),
pointer: 1,
);
await tester.pump(const Duration(milliseconds: 1));
// Start a second drag.
TestGesture gesture2 = await tester.startGesture(
tester.getCenter(find.byKey(draggableKey)),
pointer: 2,
);
await tester.pump(const Duration(milliseconds: 300));
// Verify only one of the drags triggers dragging.
expect(ongoingDrags, 1);
await tester.pump(const Duration(milliseconds: 300));
// Still only one drag.
expect(ongoingDrags, 1);
await gesture2.up();
// The second drag attempt was ignored so lifting that pointer doesn't
// trigger onDragEnded.
expect(ongoingDrags, 1);
await gesture1.up();
// The first drag attempt correctly triggers onDragEnded.
expect(ongoingDrags, 0);
});
testWidgets(
'Dragging an ArmadilloLongPressDraggable over an ArmadilloDragTarget',
(WidgetTester tester) async {
// Create all the widgets.
GlobalKey overlayKey = new GlobalKey();
ArmadilloOverlay overlay = new ArmadilloOverlay(key: overlayKey);
GlobalKey draggableKey = new GlobalKey();
ArmadilloLongPressDraggable<int> draggable =
new ArmadilloLongPressDraggable<int>(
key: draggableKey,
overlayKey: overlayKey,
child: new Container(
width: 100.0,
height: 100.0,
color: const Color(0xFFFFFF00),
),
feedbackBuilder: (
Offset localDragStartPoint,
Size initialSize,
) {},
data: 1,
);
GlobalKey acceptingDragTargetKey = new GlobalKey();
Map<int, Offset> acceptingCandidateData;
Map<dynamic, Offset> acceptingRejectedData;
ArmadilloDragTarget<int> acceptingDragTarget = new ArmadilloDragTarget<int>(
key: acceptingDragTargetKey,
onWillAccept: (int data, Offset point) {
assert(data == 1);
return true;
},
onAccept: (int data, Offset point, Velocity velocity) {
assert(data == 1);
},
builder: (
BuildContext context,
Map<int, Offset> candidateData,
Map<dynamic, Offset> rejectedData,
) {
acceptingCandidateData = candidateData;
acceptingRejectedData = rejectedData;
return new Container(
width: 100.0,
height: 100.0,
color: const Color(0xFFFFFF00),
);
},
);
GlobalKey unacceptingDragTargetKey = new GlobalKey();
Map<int, Offset> unacceptingCandidateData;
Map<dynamic, Offset> unacceptingRejectedData;
ArmadilloDragTarget<int> unacceptingDragTarget =
new ArmadilloDragTarget<int>(
key: unacceptingDragTargetKey,
onWillAccept: (int data, Offset point) {
assert(data == 1);
return false;
},
onAccept: (int data, Offset point, Velocity velocity) {
throw new AssertionError('onAccept shouldn\'t have been called!');
},
builder: (
BuildContext context,
Map<int, Offset> candidateData,
Map<dynamic, Offset> rejectedData,
) {
unacceptingCandidateData = candidateData;
unacceptingRejectedData = rejectedData;
return new Container(
width: 100.0,
height: 100.0,
color: const Color(0xFFFFFF00),
);
},
);
// Pump the widgets.
await tester.pumpWidget(
new Container(
width: 300.0,
height: 300.0,
child: new Stack(
fit: StackFit.passthrough,
children: <Widget>[
new Align(
alignment: FractionalOffset.topLeft,
child: unacceptingDragTarget,
),
new Align(
alignment: FractionalOffset.bottomRight,
child: acceptingDragTarget,
),
new Center(child: draggable),
overlay,
],
),
),
);
expect(find.byKey(overlayKey), findsOneWidget);
expect(find.byKey(draggableKey), findsOneWidget);
expect(find.byKey(acceptingDragTargetKey), findsOneWidget);
expect(find.byKey(unacceptingDragTargetKey), findsOneWidget);
// Start dragging the draggable.
TestGesture gesture = await tester.startGesture(
tester.getCenter(find.byKey(draggableKey)),
);
await tester.pump(const Duration(milliseconds: 300));
expect(unacceptingCandidateData.isEmpty, isTrue);
expect(unacceptingRejectedData.isEmpty, isTrue);
expect(acceptingCandidateData.isEmpty, isTrue);
expect(acceptingRejectedData.isEmpty, isTrue);
// Move over the accepting target.
await gesture.moveTo(tester.getCenter(find.byKey(acceptingDragTargetKey)));
// Verify we've accepted it.
expect(unacceptingCandidateData.isEmpty, isTrue);
expect(unacceptingRejectedData.isEmpty, isTrue);
expect(acceptingCandidateData.isEmpty, isFalse);
expect(acceptingRejectedData.isEmpty, isTrue);
expect(
acceptingCandidateData.values.single - Offset.zero,
tester.getCenter(find.byKey(acceptingDragTargetKey)) -
tester.getTopLeft(find.byKey(acceptingDragTargetKey)),
);
// Move over the unaccepting target.
await gesture.moveTo(
tester.getCenter(find.byKey(unacceptingDragTargetKey)),
);
// Verify we haven't accepted it.
expect(unacceptingCandidateData.isEmpty, isTrue);
expect(unacceptingRejectedData.isEmpty, isFalse);
expect(acceptingCandidateData.isEmpty, isTrue);
expect(acceptingRejectedData.isEmpty, isTrue);
expect(
unacceptingRejectedData.values.single - Offset.zero,
tester.getCenter(find.byKey(unacceptingDragTargetKey)) -
tester.getTopLeft(find.byKey(unacceptingDragTargetKey)),
);
});
testWidgets(
'Dragging an ArmadilloLongPressDraggable over overlapping ArmadilloDragTargets',
(WidgetTester tester) async {
// Create all the widgets.
GlobalKey overlayKey = new GlobalKey();
ArmadilloOverlay overlay = new ArmadilloOverlay(key: overlayKey);
GlobalKey draggableKey = new GlobalKey();
ArmadilloLongPressDraggable<int> draggable =
new ArmadilloLongPressDraggable<int>(
key: draggableKey,
overlayKey: overlayKey,
child: new Container(
width: 100.0,
height: 100.0,
color: const Color(0xFFFFFF00),
),
feedbackBuilder: (
Offset localDragStartPoint,
Size initialSize,
) {},
data: 1,
);
// NOTE: the three drag targets are all transparent to hit testing
// (transparent containers). So all will have a chance to accept or reject
// the candidate.
GlobalKey acceptingDragTargetKey1 = new GlobalKey();
Map<int, Offset> acceptingCandidateData1;
Map<dynamic, Offset> acceptingRejectedData1;
ArmadilloDragTarget<int> acceptingDragTarget1 =
new ArmadilloDragTarget<int>(
key: acceptingDragTargetKey1,
onWillAccept: (int data, Offset point) {
assert(data == 1);
return true;
},
onAccept: (int data, Offset point, Velocity velocity) {
assert(data == 1);
},
builder: (
BuildContext context,
Map<int, Offset> candidateData,
Map<dynamic, Offset> rejectedData,
) {
acceptingCandidateData1 = candidateData;
acceptingRejectedData1 = rejectedData;
return new Container(
width: 100.0,
height: 100.0,
);
},
);
GlobalKey acceptingDragTargetKey2 = new GlobalKey();
Map<int, Offset> acceptingCandidateData2;
Map<dynamic, Offset> acceptingRejectedData2;
ArmadilloDragTarget<int> acceptingDragTarget2 =
new ArmadilloDragTarget<int>(
key: acceptingDragTargetKey2,
onWillAccept: (int data, Offset point) {
assert(data == 1);
return true;
},
onAccept: (int data, Offset point, Velocity velocity) {
assert(data == 1);
},
builder: (
BuildContext context,
Map<int, Offset> candidateData,
Map<dynamic, Offset> rejectedData,
) {
acceptingCandidateData2 = candidateData;
acceptingRejectedData2 = rejectedData;
return new Container(
width: 100.0,
height: 100.0,
);
},
);
GlobalKey unacceptingDragTargetKey = new GlobalKey();
Map<int, Offset> unacceptingCandidateData;
Map<dynamic, Offset> unacceptingRejectedData;
ArmadilloDragTarget<int> unacceptingDragTarget =
new ArmadilloDragTarget<int>(
key: unacceptingDragTargetKey,
onWillAccept: (int data, Offset point) {
assert(data == 1);
return false;
},
onAccept: (int data, Offset point, Velocity velocity) {
throw new AssertionError('onAccept shouldn\'t have been called!');
},
builder: (
BuildContext context,
Map<int, Offset> candidateData,
Map<dynamic, Offset> rejectedData,
) {
unacceptingCandidateData = candidateData;
unacceptingRejectedData = rejectedData;
return new Container(
width: 100.0,
height: 100.0,
);
},
);
// Pump the widgets. Place all drag targets on top of each other.
await tester.pumpWidget(
new Container(
width: 300.0,
height: 300.0,
child: new Stack(
fit: StackFit.passthrough,
children: <Widget>[
new Align(
alignment: FractionalOffset.topLeft,
child: unacceptingDragTarget,
),
new Align(
alignment: FractionalOffset.topLeft,
child: acceptingDragTarget1,
),
new Align(
alignment: FractionalOffset.topLeft,
child: acceptingDragTarget2,
),
new Center(child: draggable),
overlay,
],
),
),
);
expect(find.byKey(overlayKey), findsOneWidget);
expect(find.byKey(draggableKey), findsOneWidget);
expect(find.byKey(acceptingDragTargetKey1), findsOneWidget);
expect(find.byKey(acceptingDragTargetKey2), findsOneWidget);
expect(find.byKey(unacceptingDragTargetKey), findsOneWidget);
// Begin dragging the draggable.
TestGesture gesture = await tester.startGesture(
tester.getCenter(find.byKey(draggableKey)),
);
await tester.pump(const Duration(milliseconds: 300));
expect(unacceptingCandidateData.isEmpty, isTrue);
expect(unacceptingRejectedData.isEmpty, isTrue);
expect(acceptingCandidateData1.isEmpty, isTrue);
expect(acceptingRejectedData1.isEmpty, isTrue);
expect(acceptingCandidateData2.isEmpty, isTrue);
expect(acceptingRejectedData2.isEmpty, isTrue);
// Move over the drag targets.
await gesture.moveTo(tester.getCenter(find.byKey(acceptingDragTargetKey1)));
// Verify all the drag targets have either accepted or rejected the
// draggable.
expect(unacceptingCandidateData.isEmpty, isTrue);
expect(unacceptingRejectedData.isEmpty, isFalse);
expect(acceptingCandidateData1.isEmpty, isFalse);
expect(acceptingRejectedData1.isEmpty, isTrue);
expect(acceptingCandidateData2.isEmpty, isFalse);
expect(acceptingRejectedData2.isEmpty, isTrue);
expect(
acceptingCandidateData1.values.single - Offset.zero,
tester.getCenter(find.byKey(acceptingDragTargetKey1)) -
tester.getTopLeft(find.byKey(acceptingDragTargetKey1)),
);
expect(
acceptingCandidateData2.values.single - Offset.zero,
tester.getCenter(find.byKey(acceptingDragTargetKey2)) -
tester.getTopLeft(find.byKey(acceptingDragTargetKey2)),
);
expect(
unacceptingRejectedData.values.single - Offset.zero,
tester.getCenter(find.byKey(unacceptingDragTargetKey)) -
tester.getTopLeft(find.byKey(unacceptingDragTargetKey)),
);
});
}