mirror of
https://github.com/alibaba/flutter-go.git
synced 2025-07-08 10:15:53 +08:00
787 lines
26 KiB
Dart
787 lines
26 KiB
Dart
// Copyright 2015 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_web_ui/ui.dart';
|
|
|
|
import 'package:flutter_web_test/flutter_web_test.dart';
|
|
import 'package:flutter_web/gestures.dart';
|
|
import 'package:flutter_web/material.dart';
|
|
import 'package:flutter_web/rendering.dart';
|
|
import 'package:flutter_web/widgets.dart';
|
|
|
|
import '../widgets/semantics_tester.dart';
|
|
|
|
// TODO(yjbanov): use when haptic feedback uses platform channels.
|
|
//import 'feedback_tester.dart';
|
|
|
|
// This file uses "as dynamic" in a few places to defeat the static
|
|
// analysis. In general you want to avoid using this style in your
|
|
// code, as it will cause the analyzer to be unable to help you catch
|
|
// errors.
|
|
//
|
|
// In this case, we do it because we are trying to call internal
|
|
// methods of the tooltip code in order to test it. Normally, the
|
|
// state of a tooltip is a private class, but by using a GlobalKey we
|
|
// can get a handle to that object and by using "as dynamic" we can
|
|
// bypass the analyzer's type checks and call methods that we aren't
|
|
// supposed to be able to know about.
|
|
//
|
|
// It's ok to do this in tests, but you really don't want to do it in
|
|
// production code.
|
|
|
|
const String tooltipText = 'TIP';
|
|
|
|
void main() {
|
|
testWidgets('Does tooltip end up in the right place - center',
|
|
(WidgetTester tester) async {
|
|
final GlobalKey key = new GlobalKey();
|
|
await tester.pumpWidget(
|
|
new Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: new Overlay(
|
|
initialEntries: <OverlayEntry>[
|
|
new OverlayEntry(
|
|
builder: (BuildContext context) {
|
|
return new Stack(
|
|
children: <Widget>[
|
|
new Positioned(
|
|
left: 300.0,
|
|
top: 0.0,
|
|
child: new Tooltip(
|
|
key: key,
|
|
message: tooltipText,
|
|
height: 20.0,
|
|
padding: const EdgeInsets.all(5.0),
|
|
verticalOffset: 20.0,
|
|
preferBelow: false,
|
|
child: new Container(
|
|
width: 0.0,
|
|
height: 0.0,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
(key.currentState as dynamic)
|
|
.ensureTooltipVisible(); // before using "as dynamic" in your code, see note top of file
|
|
await tester.pump(const Duration(
|
|
seconds: 2)); // faded in, show timer started (and at 0.0)
|
|
|
|
/********************* 800x600 screen
|
|
* o * y=0
|
|
* | * }- 20.0 vertical offset, of which 10.0 is in the screen edge margin
|
|
* +----+ * \- (5.0 padding in height)
|
|
* | | * |- 20 height
|
|
* +----+ * /- (5.0 padding in height)
|
|
* *
|
|
*********************/
|
|
|
|
final RenderBox tip = tester
|
|
.renderObject(find.text(tooltipText))
|
|
.parent
|
|
.parent
|
|
.parent
|
|
.parent
|
|
.parent;
|
|
|
|
final Offset tipInGlobal =
|
|
tip.localToGlobal(tip.size.topCenter(Offset.zero));
|
|
// The exact position of the left side depends on the font the test framework
|
|
// happens to pick, so we don't test that.
|
|
expect(tipInGlobal.dx, 300.0);
|
|
expect(tipInGlobal.dy, 20.0);
|
|
});
|
|
|
|
testWidgets('Does tooltip end up in the right place - top left',
|
|
(WidgetTester tester) async {
|
|
final GlobalKey key = new GlobalKey();
|
|
await tester.pumpWidget(
|
|
new Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: new Overlay(
|
|
initialEntries: <OverlayEntry>[
|
|
new OverlayEntry(
|
|
builder: (BuildContext context) {
|
|
return new Stack(
|
|
children: <Widget>[
|
|
new Positioned(
|
|
left: 0.0,
|
|
top: 0.0,
|
|
child: new Tooltip(
|
|
key: key,
|
|
message: tooltipText,
|
|
height: 20.0,
|
|
padding: const EdgeInsets.all(5.0),
|
|
verticalOffset: 20.0,
|
|
preferBelow: false,
|
|
child: new Container(
|
|
width: 0.0,
|
|
height: 0.0,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
(key.currentState as dynamic)
|
|
.ensureTooltipVisible(); // before using "as dynamic" in your code, see note top of file
|
|
await tester.pump(const Duration(
|
|
seconds: 2)); // faded in, show timer started (and at 0.0)
|
|
|
|
/********************* 800x600 screen
|
|
*o * y=0
|
|
*| * }- 20.0 vertical offset, of which 10.0 is in the screen edge margin
|
|
*+----+ * \- (5.0 padding in height)
|
|
*| | * |- 20 height
|
|
*+----+ * /- (5.0 padding in height)
|
|
* *
|
|
*********************/
|
|
|
|
final RenderBox tip = tester
|
|
.renderObject(find.text(tooltipText))
|
|
.parent
|
|
.parent
|
|
.parent
|
|
.parent
|
|
.parent;
|
|
expect(tip.size.height,
|
|
equals(24.0)); // 14.0 height + 5.0 padding * 2 (top, bottom)
|
|
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)),
|
|
equals(const Offset(10.0, 20.0)));
|
|
});
|
|
|
|
testWidgets(
|
|
'Does tooltip end up in the right place - center prefer above fits',
|
|
(WidgetTester tester) async {
|
|
final GlobalKey key = new GlobalKey();
|
|
await tester.pumpWidget(
|
|
new Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: new Overlay(
|
|
initialEntries: <OverlayEntry>[
|
|
new OverlayEntry(
|
|
builder: (BuildContext context) {
|
|
return new Stack(
|
|
children: <Widget>[
|
|
new Positioned(
|
|
left: 400.0,
|
|
top: 300.0,
|
|
child: new Tooltip(
|
|
key: key,
|
|
message: tooltipText,
|
|
height: 100.0,
|
|
padding: const EdgeInsets.all(0.0),
|
|
verticalOffset: 100.0,
|
|
preferBelow: false,
|
|
child: new Container(
|
|
width: 0.0,
|
|
height: 0.0,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
(key.currentState as dynamic)
|
|
.ensureTooltipVisible(); // before using "as dynamic" in your code, see note top of file
|
|
await tester.pump(const Duration(
|
|
seconds: 2)); // faded in, show timer started (and at 0.0)
|
|
|
|
/********************* 800x600 screen
|
|
* ___ * }- 10.0 margin
|
|
* |___| * }-100.0 height
|
|
* | * }-100.0 vertical offset
|
|
* o * y=300.0
|
|
* *
|
|
* *
|
|
* *
|
|
*********************/
|
|
|
|
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent;
|
|
expect(tip.size.height, equals(100.0));
|
|
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)).dy, equals(100.0));
|
|
expect(
|
|
tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(200.0));
|
|
});
|
|
|
|
testWidgets(
|
|
'Does tooltip end up in the right place - center prefer above does not fit',
|
|
(WidgetTester tester) async {
|
|
final GlobalKey key = new GlobalKey();
|
|
await tester.pumpWidget(
|
|
new Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: new Overlay(
|
|
initialEntries: <OverlayEntry>[
|
|
new OverlayEntry(
|
|
builder: (BuildContext context) {
|
|
return new Stack(
|
|
children: <Widget>[
|
|
new Positioned(
|
|
left: 400.0,
|
|
top: 299.0,
|
|
child: new Tooltip(
|
|
key: key,
|
|
message: tooltipText,
|
|
height: 190.0,
|
|
padding: const EdgeInsets.all(0.0),
|
|
verticalOffset: 100.0,
|
|
preferBelow: false,
|
|
child: new Container(
|
|
width: 0.0,
|
|
height: 0.0,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
(key.currentState as dynamic)
|
|
.ensureTooltipVisible(); // before using "as dynamic" in your code, see note top of file
|
|
await tester.pump(const Duration(
|
|
seconds: 2)); // faded in, show timer started (and at 0.0)
|
|
|
|
// we try to put it here but it doesn't fit:
|
|
/********************* 800x600 screen
|
|
* ___ * }- 10.0 margin
|
|
* |___| * }-190.0 height (starts at y=9.0)
|
|
* | * }-100.0 vertical offset
|
|
* o * y=299.0
|
|
* *
|
|
* *
|
|
* *
|
|
*********************/
|
|
|
|
// so we put it here:
|
|
/********************* 800x600 screen
|
|
* *
|
|
* *
|
|
* o * y=299.0
|
|
* _|_ * }-100.0 vertical offset
|
|
* |___| * }-190.0 height
|
|
* * }- 10.0 margin
|
|
*********************/
|
|
|
|
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent;
|
|
expect(tip.size.height, equals(190.0));
|
|
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)).dy, equals(399.0));
|
|
expect(
|
|
tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(589.0));
|
|
});
|
|
|
|
testWidgets(
|
|
'Does tooltip end up in the right place - center prefer below fits',
|
|
(WidgetTester tester) async {
|
|
final GlobalKey key = new GlobalKey();
|
|
await tester.pumpWidget(
|
|
new Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: new Overlay(
|
|
initialEntries: <OverlayEntry>[
|
|
new OverlayEntry(
|
|
builder: (BuildContext context) {
|
|
return new Stack(
|
|
children: <Widget>[
|
|
new Positioned(
|
|
left: 400.0,
|
|
top: 300.0,
|
|
child: new Tooltip(
|
|
key: key,
|
|
message: tooltipText,
|
|
height: 190.0,
|
|
padding: const EdgeInsets.all(0.0),
|
|
verticalOffset: 100.0,
|
|
preferBelow: true,
|
|
child: new Container(
|
|
width: 0.0,
|
|
height: 0.0,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
(key.currentState as dynamic)
|
|
.ensureTooltipVisible(); // before using "as dynamic" in your code, see note top of file
|
|
await tester.pump(const Duration(
|
|
seconds: 2)); // faded in, show timer started (and at 0.0)
|
|
|
|
/********************* 800x600 screen
|
|
* *
|
|
* *
|
|
* o * y=300.0
|
|
* _|_ * }-100.0 vertical offset
|
|
* |___| * }-190.0 height
|
|
* * }- 10.0 margin
|
|
*********************/
|
|
|
|
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent;
|
|
expect(tip.size.height, equals(190.0));
|
|
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)).dy, equals(400.0));
|
|
expect(
|
|
tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(590.0));
|
|
});
|
|
|
|
testWidgets('Does tooltip end up in the right place - way off to the right',
|
|
(WidgetTester tester) async {
|
|
final GlobalKey key = new GlobalKey();
|
|
await tester.pumpWidget(
|
|
new Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: new Overlay(
|
|
initialEntries: <OverlayEntry>[
|
|
new OverlayEntry(
|
|
builder: (BuildContext context) {
|
|
return new Stack(
|
|
children: <Widget>[
|
|
new Positioned(
|
|
left: 1600.0,
|
|
top: 300.0,
|
|
child: new Tooltip(
|
|
key: key,
|
|
message: tooltipText,
|
|
height: 10.0,
|
|
padding: const EdgeInsets.all(0.0),
|
|
verticalOffset: 10.0,
|
|
preferBelow: true,
|
|
child: new Container(
|
|
width: 0.0,
|
|
height: 0.0,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
(key.currentState as dynamic)
|
|
.ensureTooltipVisible(); // before using "as dynamic" in your code, see note top of file
|
|
await tester.pump(const Duration(
|
|
seconds: 2)); // faded in, show timer started (and at 0.0)
|
|
|
|
/********************* 800x600 screen
|
|
* *
|
|
* *
|
|
* * y=300.0; target --> o
|
|
* ___| * }-10.0 vertical offset
|
|
* |___| * }-10.0 height
|
|
* *
|
|
* * }-10.0 margin
|
|
*********************/
|
|
|
|
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent;
|
|
expect(tip.size.height, equals(14.0));
|
|
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)).dy, equals(310.0));
|
|
expect(
|
|
tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dx, equals(790.0));
|
|
expect(
|
|
tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(324.0));
|
|
});
|
|
|
|
testWidgets('Does tooltip end up in the right place - near the edge',
|
|
(WidgetTester tester) async {
|
|
final GlobalKey key = new GlobalKey();
|
|
await tester.pumpWidget(
|
|
new Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: new Overlay(
|
|
initialEntries: <OverlayEntry>[
|
|
new OverlayEntry(
|
|
builder: (BuildContext context) {
|
|
return new Stack(
|
|
children: <Widget>[
|
|
new Positioned(
|
|
left: 780.0,
|
|
top: 300.0,
|
|
child: new Tooltip(
|
|
key: key,
|
|
message: tooltipText,
|
|
height: 10.0,
|
|
padding: const EdgeInsets.all(0.0),
|
|
verticalOffset: 10.0,
|
|
preferBelow: true,
|
|
child: new Container(
|
|
width: 0.0,
|
|
height: 0.0,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
(key.currentState as dynamic)
|
|
.ensureTooltipVisible(); // before using "as dynamic" in your code, see note top of file
|
|
await tester.pump(const Duration(
|
|
seconds: 2)); // faded in, show timer started (and at 0.0)
|
|
|
|
/********************* 800x600 screen
|
|
* *
|
|
* *
|
|
* o * y=300.0
|
|
* __| * }-10.0 vertical offset
|
|
* |___| * }-10.0 height
|
|
* *
|
|
* * }-10.0 margin
|
|
*********************/
|
|
|
|
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent;
|
|
expect(tip.size.height, equals(14.0));
|
|
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)).dy, equals(310.0));
|
|
expect(
|
|
tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dx, equals(790.0));
|
|
expect(
|
|
tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(324.0));
|
|
});
|
|
|
|
testWidgets('Tooltip stays around', (WidgetTester tester) async {
|
|
await tester.pumpWidget(new MaterialApp(
|
|
home: new Center(
|
|
child: new Tooltip(
|
|
message: tooltipText,
|
|
child: new Container(
|
|
width: 100.0,
|
|
height: 100.0,
|
|
color: Colors.green[500],
|
|
)))));
|
|
|
|
final Finder tooltip = find.byType(Tooltip);
|
|
TestGesture gesture = await tester.startGesture(tester.getCenter(tooltip));
|
|
await tester.pump(kLongPressTimeout);
|
|
await tester.pump(const Duration(milliseconds: 10));
|
|
await gesture.up();
|
|
expect(find.text(tooltipText), findsOneWidget);
|
|
await tester.tap(tooltip);
|
|
await tester.pump(const Duration(milliseconds: 10));
|
|
gesture = await tester.startGesture(tester.getCenter(tooltip));
|
|
await tester.pump();
|
|
await tester.pump(const Duration(milliseconds: 300));
|
|
expect(find.text(tooltipText), findsNothing);
|
|
await tester.pump(kLongPressTimeout);
|
|
expect(find.text(tooltipText), findsOneWidget);
|
|
await tester.pump(kLongPressTimeout);
|
|
expect(find.text(tooltipText), findsOneWidget);
|
|
gesture.up();
|
|
});
|
|
|
|
testWidgets('Does tooltip contribute semantics', (WidgetTester tester) async {
|
|
final SemanticsTester semantics = new SemanticsTester(tester);
|
|
|
|
final GlobalKey key = new GlobalKey();
|
|
await tester.pumpWidget(
|
|
new Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: new Overlay(
|
|
initialEntries: <OverlayEntry>[
|
|
new OverlayEntry(
|
|
builder: (BuildContext context) {
|
|
return new Stack(
|
|
children: <Widget>[
|
|
new Positioned(
|
|
left: 780.0,
|
|
top: 300.0,
|
|
child: new Tooltip(
|
|
key: key,
|
|
message: tooltipText,
|
|
child: new Container(width: 10.0, height: 10.0),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
|
|
final TestSemantics expected =
|
|
new TestSemantics.root(children: <TestSemantics>[
|
|
new TestSemantics.rootChild(
|
|
id: 1,
|
|
label: 'TIP',
|
|
textDirection: TextDirection.ltr,
|
|
),
|
|
]);
|
|
|
|
expect(semantics,
|
|
hasSemantics(expected, ignoreTransform: true, ignoreRect: true));
|
|
|
|
// before using "as dynamic" in your code, see note top of file
|
|
(key.currentState as dynamic)
|
|
.ensureTooltipVisible(); // this triggers a rebuild of the semantics because the tree changes
|
|
|
|
await tester.pump(const Duration(
|
|
seconds: 2)); // faded in, show timer started (and at 0.0)
|
|
|
|
expect(semantics,
|
|
hasSemantics(expected, ignoreTransform: true, ignoreRect: true));
|
|
|
|
semantics.dispose();
|
|
});
|
|
|
|
testWidgets('Tooltip overlay does not update', (WidgetTester tester) async {
|
|
Widget buildApp(String text) {
|
|
return new MaterialApp(
|
|
home: new Center(
|
|
child: new Tooltip(
|
|
message: text,
|
|
child: new Container(
|
|
width: 100.0,
|
|
height: 100.0,
|
|
color: Colors.green[500],
|
|
))));
|
|
}
|
|
|
|
await tester.pumpWidget(buildApp(tooltipText));
|
|
await tester.longPress(find.byType(Tooltip));
|
|
expect(find.text(tooltipText), findsOneWidget);
|
|
await tester.pumpWidget(buildApp('NEW'));
|
|
expect(find.text(tooltipText), findsOneWidget);
|
|
await tester.tapAt(const Offset(5.0, 5.0));
|
|
await tester.pump();
|
|
await tester.pump(const Duration(seconds: 1));
|
|
expect(find.text(tooltipText), findsNothing);
|
|
await tester.longPress(find.byType(Tooltip));
|
|
expect(find.text(tooltipText), findsNothing);
|
|
});
|
|
|
|
testWidgets('Tooltip text scales with textScaleFactor',
|
|
(WidgetTester tester) async {
|
|
Widget buildApp(String text, {double textScaleFactor}) {
|
|
return new MediaQuery(
|
|
data: new MediaQueryData(textScaleFactor: textScaleFactor),
|
|
child: new Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: new Navigator(
|
|
onGenerateRoute: (RouteSettings settings) {
|
|
return new MaterialPageRoute<void>(
|
|
builder: (BuildContext context) {
|
|
return new Center(
|
|
child: new Tooltip(
|
|
message: text,
|
|
child: new Container(
|
|
width: 100.0,
|
|
height: 100.0,
|
|
color: Colors.green[500],
|
|
),
|
|
),
|
|
);
|
|
});
|
|
},
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
await tester.pumpWidget(buildApp(tooltipText, textScaleFactor: 1.0));
|
|
await tester.longPress(find.byType(Tooltip));
|
|
expect(find.text(tooltipText), findsOneWidget);
|
|
expect(
|
|
tester.getSize(find.text(tooltipText)), equals(const Size(42.0, 14.0)));
|
|
RenderBox tip = tester.renderObject(find.text(tooltipText)).parent;
|
|
expect(tip.size.height, equals(32.0));
|
|
|
|
await tester.pumpWidget(buildApp(tooltipText, textScaleFactor: 4.0));
|
|
await tester.longPress(find.byType(Tooltip));
|
|
expect(find.text(tooltipText), findsOneWidget);
|
|
expect(tester.getSize(find.text(tooltipText)),
|
|
equals(const Size(168.0, 56.0)));
|
|
tip = tester.renderObject(find.text(tooltipText)).parent;
|
|
expect(tip.size.height, equals(56.0));
|
|
});
|
|
|
|
// TODO(yjbanov): we do not yet use channels for haptic feedback.
|
|
// testWidgets('Haptic feedback', (WidgetTester tester) async {
|
|
// final FeedbackTester feedback = new FeedbackTester();
|
|
// await tester.pumpWidget(
|
|
// new MaterialApp(
|
|
// home: new Center(
|
|
// child: new Tooltip(
|
|
// message: 'Foo',
|
|
// child: new Container(
|
|
// width: 100.0,
|
|
// height: 100.0,
|
|
// color: Colors.green[500],
|
|
// ),
|
|
// ),
|
|
// ),
|
|
// ),
|
|
// );
|
|
//
|
|
// await tester.longPress(find.byType(Tooltip));
|
|
// await tester.pumpAndSettle(const Duration(seconds: 1));
|
|
// expect(feedback.hapticCount, 1);
|
|
//
|
|
// feedback.dispose();
|
|
// });
|
|
|
|
testWidgets('Semantics included', (WidgetTester tester) async {
|
|
final SemanticsTester semantics = new SemanticsTester(tester);
|
|
|
|
await tester.pumpWidget(
|
|
new MaterialApp(
|
|
home: const Center(
|
|
child: const Tooltip(
|
|
message: 'Foo',
|
|
child: const Text('Bar'),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
semantics,
|
|
hasSemantics(
|
|
new TestSemantics.root(
|
|
children: <TestSemantics>[
|
|
new TestSemantics.rootChild(
|
|
children: <TestSemantics>[
|
|
new TestSemantics(
|
|
flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
|
|
children: <TestSemantics>[
|
|
new TestSemantics(
|
|
label: 'Foo\nBar',
|
|
textDirection: TextDirection.ltr,
|
|
)
|
|
],
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
ignoreRect: true,
|
|
ignoreId: true,
|
|
ignoreTransform: true));
|
|
|
|
semantics.dispose();
|
|
});
|
|
|
|
testWidgets('Semantics excluded', (WidgetTester tester) async {
|
|
final SemanticsTester semantics = new SemanticsTester(tester);
|
|
|
|
await tester.pumpWidget(
|
|
new MaterialApp(
|
|
home: const Center(
|
|
child: const Tooltip(
|
|
message: 'Foo',
|
|
child: const Text('Bar'),
|
|
excludeFromSemantics: true,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
semantics,
|
|
hasSemantics(
|
|
new TestSemantics.root(
|
|
children: <TestSemantics>[
|
|
new TestSemantics.rootChild(
|
|
children: <TestSemantics>[
|
|
new TestSemantics(
|
|
flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
|
|
children: <TestSemantics>[
|
|
new TestSemantics(
|
|
label: 'Bar',
|
|
textDirection: TextDirection.ltr,
|
|
)
|
|
],
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
ignoreRect: true,
|
|
ignoreId: true,
|
|
ignoreTransform: true));
|
|
|
|
semantics.dispose();
|
|
});
|
|
|
|
testWidgets('has semantic events', (WidgetTester tester) async {
|
|
final List<dynamic> semanticEvents = <dynamic>[];
|
|
SystemChannels.accessibility.setMockMessageHandler((dynamic message) {
|
|
semanticEvents.add(message);
|
|
return null;
|
|
});
|
|
final SemanticsTester semantics = new SemanticsTester(tester);
|
|
|
|
await tester.pumpWidget(
|
|
new MaterialApp(
|
|
home: new Center(
|
|
child: new Tooltip(
|
|
message: 'Foo',
|
|
child: new Container(
|
|
width: 100.0,
|
|
height: 100.0,
|
|
color: Colors.green[500],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.longPress(find.byType(Tooltip));
|
|
final RenderObject object = tester.firstRenderObject(find.byType(Tooltip));
|
|
|
|
expect(
|
|
semanticEvents,
|
|
unorderedEquals(<dynamic>[
|
|
<String, dynamic>{
|
|
'type': 'longPress',
|
|
'nodeId': findDebugSemantics(object).id,
|
|
'data': <String, dynamic>{},
|
|
},
|
|
<String, dynamic>{
|
|
'type': 'tooltip',
|
|
'data': <String, dynamic>{
|
|
'message': 'Foo',
|
|
},
|
|
},
|
|
]));
|
|
semantics.dispose();
|
|
SystemChannels.accessibility.setMockMessageHandler(null);
|
|
});
|
|
}
|
|
|
|
SemanticsNode findDebugSemantics(RenderObject object) {
|
|
if (object.debugSemantics != null) return object.debugSemantics;
|
|
return findDebugSemantics(object.parent);
|
|
}
|