Unverified Commit a2424602 authored by Taha Tesser's avatar Taha Tesser Committed by GitHub

Make `Tooltip` state class public (#100553)

parent 2e5ad37b
......@@ -223,15 +223,15 @@ class Tooltip extends StatefulWidget {
/// * [Feedback], for providing platform-specific feedback to certain actions.
final bool? enableFeedback;
static final List<_TooltipState> _openedTooltips = <_TooltipState>[];
static final List<TooltipState> _openedTooltips = <TooltipState>[];
// Causes any current tooltips to be concealed. Only called for mouse hover enter
// detections. Won't conceal the supplied tooltip.
static void _concealOtherTooltips(_TooltipState current) {
static void _concealOtherTooltips(TooltipState current) {
if (_openedTooltips.isNotEmpty) {
// Avoid concurrent modification.
final List<_TooltipState> openedTooltips = _openedTooltips.toList();
for (final _TooltipState state in openedTooltips) {
final List<TooltipState> openedTooltips = _openedTooltips.toList();
for (final TooltipState state in openedTooltips) {
if (state == current) {
continue;
}
......@@ -255,8 +255,8 @@ class Tooltip extends StatefulWidget {
static bool dismissAllToolTips() {
if (_openedTooltips.isNotEmpty) {
// Avoid concurrent modification.
final List<_TooltipState> openedTooltips = _openedTooltips.toList();
for (final _TooltipState state in openedTooltips) {
final List<TooltipState> openedTooltips = _openedTooltips.toList();
for (final TooltipState state in openedTooltips) {
state._dismissTooltip(immediately: true);
}
return true;
......@@ -265,7 +265,7 @@ class Tooltip extends StatefulWidget {
}
@override
State<Tooltip> createState() => _TooltipState();
State<Tooltip> createState() => TooltipState();
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
......@@ -295,7 +295,11 @@ class Tooltip extends StatefulWidget {
}
}
class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
/// Contains the state for a [Tooltip].
///
/// This class can be used to programmatically show the Tooltip, see the
/// [ensureTooltipVisible] method.
class TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
static const double _defaultVerticalOffset = 24.0;
static const bool _defaultPreferBelow = true;
static const EdgeInsetsGeometry _defaultMargin = EdgeInsets.zero;
......@@ -308,25 +312,25 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
static const TooltipTriggerMode _defaultTriggerMode = TooltipTriggerMode.longPress;
static const bool _defaultEnableFeedback = true;
late double height;
late EdgeInsetsGeometry padding;
late EdgeInsetsGeometry margin;
late Decoration decoration;
late TextStyle textStyle;
late double verticalOffset;
late bool preferBelow;
late bool excludeFromSemantics;
late double _height;
late EdgeInsetsGeometry _padding;
late EdgeInsetsGeometry _margin;
late Decoration _decoration;
late TextStyle _textStyle;
late double _verticalOffset;
late bool _preferBelow;
late bool _excludeFromSemantics;
late AnimationController _controller;
OverlayEntry? _entry;
Timer? _dismissTimer;
Timer? _showTimer;
late Duration showDuration;
late Duration hoverShowDuration;
late Duration waitDuration;
late Duration _showDuration;
late Duration _hoverShowDuration;
late Duration _waitDuration;
late bool _mouseIsConnected;
bool _pressActivated = false;
late TooltipTriggerMode triggerMode;
late bool enableFeedback;
late TooltipTriggerMode _triggerMode;
late bool _enableFeedback;
late bool _isConcealed;
late bool _forceRemoval;
late bool _visible;
......@@ -436,9 +440,9 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
// still concealed or not.
_forceRemoval = true;
if (_pressActivated) {
_dismissTimer ??= Timer(showDuration, _controller.reverse);
_dismissTimer ??= Timer(_showDuration, _controller.reverse);
} else {
_dismissTimer ??= Timer(hoverShowDuration, _controller.reverse);
_dismissTimer ??= Timer(_hoverShowDuration, _controller.reverse);
}
_pressActivated = false;
}
......@@ -450,7 +454,7 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
ensureTooltipVisible();
return;
}
_showTimer ??= Timer(waitDuration, ensureTooltipVisible);
_showTimer ??= Timer(_waitDuration, ensureTooltipVisible);
}
void _concealTooltip() {
......@@ -519,7 +523,7 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
return true;
}
static final Set<_TooltipState> _mouseIn = <_TooltipState>{};
static final Set<TooltipState> _mouseIn = <TooltipState>{};
void _handleMouseEnter() {
if (mounted) {
......@@ -553,20 +557,20 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
textDirection: Directionality.of(context),
child: _TooltipOverlay(
richMessage: widget.richMessage ?? TextSpan(text: widget.message),
height: height,
padding: padding,
margin: margin,
height: _height,
padding: _padding,
margin: _margin,
onEnter: _mouseIsConnected ? (_) => _handleMouseEnter() : null,
onExit: _mouseIsConnected ? (_) => _handleMouseExit() : null,
decoration: decoration,
textStyle: textStyle,
decoration: _decoration,
textStyle: _textStyle,
animation: CurvedAnimation(
parent: _controller,
curve: Curves.fastOutSlowIn,
),
target: target,
verticalOffset: verticalOffset,
preferBelow: preferBelow,
verticalOffset: _verticalOffset,
preferBelow: _preferBelow,
),
);
_entry = OverlayEntry(builder: (BuildContext context) => overlay);
......@@ -632,8 +636,8 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
void _handlePress() {
_pressActivated = true;
final bool tooltipCreated = ensureTooltipVisible();
if (tooltipCreated && enableFeedback) {
if (triggerMode == TooltipTriggerMode.longPress)
if (tooltipCreated && _enableFeedback) {
if (_triggerMode == TooltipTriggerMode.longPress)
Feedback.forLongPress(context);
else
Feedback.forTap(context);
......@@ -673,22 +677,22 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
);
}
height = widget.height ?? tooltipTheme.height ?? _getDefaultTooltipHeight();
padding = widget.padding ?? tooltipTheme.padding ?? _getDefaultPadding();
margin = widget.margin ?? tooltipTheme.margin ?? _defaultMargin;
verticalOffset = widget.verticalOffset ?? tooltipTheme.verticalOffset ?? _defaultVerticalOffset;
preferBelow = widget.preferBelow ?? tooltipTheme.preferBelow ?? _defaultPreferBelow;
excludeFromSemantics = widget.excludeFromSemantics ?? tooltipTheme.excludeFromSemantics ?? _defaultExcludeFromSemantics;
decoration = widget.decoration ?? tooltipTheme.decoration ?? defaultDecoration;
textStyle = widget.textStyle ?? tooltipTheme.textStyle ?? defaultTextStyle;
waitDuration = widget.waitDuration ?? tooltipTheme.waitDuration ?? _defaultWaitDuration;
showDuration = widget.showDuration ?? tooltipTheme.showDuration ?? _defaultShowDuration;
hoverShowDuration = widget.showDuration ?? tooltipTheme.showDuration ?? _defaultHoverShowDuration;
triggerMode = widget.triggerMode ?? tooltipTheme.triggerMode ?? _defaultTriggerMode;
enableFeedback = widget.enableFeedback ?? tooltipTheme.enableFeedback ?? _defaultEnableFeedback;
_height = widget.height ?? tooltipTheme.height ?? _getDefaultTooltipHeight();
_padding = widget.padding ?? tooltipTheme.padding ?? _getDefaultPadding();
_margin = widget.margin ?? tooltipTheme.margin ?? _defaultMargin;
_verticalOffset = widget.verticalOffset ?? tooltipTheme.verticalOffset ?? _defaultVerticalOffset;
_preferBelow = widget.preferBelow ?? tooltipTheme.preferBelow ?? _defaultPreferBelow;
_excludeFromSemantics = widget.excludeFromSemantics ?? tooltipTheme.excludeFromSemantics ?? _defaultExcludeFromSemantics;
_decoration = widget.decoration ?? tooltipTheme.decoration ?? defaultDecoration;
_textStyle = widget.textStyle ?? tooltipTheme.textStyle ?? defaultTextStyle;
_waitDuration = widget.waitDuration ?? tooltipTheme.waitDuration ?? _defaultWaitDuration;
_showDuration = widget.showDuration ?? tooltipTheme.showDuration ?? _defaultShowDuration;
_hoverShowDuration = widget.showDuration ?? tooltipTheme.showDuration ?? _defaultHoverShowDuration;
_triggerMode = widget.triggerMode ?? tooltipTheme.triggerMode ?? _defaultTriggerMode;
_enableFeedback = widget.enableFeedback ?? tooltipTheme.enableFeedback ?? _defaultEnableFeedback;
Widget result = Semantics(
label: excludeFromSemantics
label: _excludeFromSemantics
? null
: _tooltipMessage,
child: widget.child,
......@@ -698,9 +702,9 @@ class _TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
if (_visible) {
result = GestureDetector(
behavior: HitTestBehavior.opaque,
onLongPress: (triggerMode == TooltipTriggerMode.longPress) ?
onLongPress: (_triggerMode == TooltipTriggerMode.longPress) ?
_handlePress : null,
onTap: (triggerMode == TooltipTriggerMode.tap) ? _handlePress : null,
onTap: (_triggerMode == TooltipTriggerMode.tap) ? _handlePress : null,
excludeFromSemantics: true,
child: result,
);
......
......@@ -14,23 +14,6 @@ import '../rendering/mock_canvas.dart';
import '../widgets/semantics_tester.dart';
import 'feedback_tester.dart';
void _ensureTooltipVisible(GlobalKey key) {
// This function uses "as dynamic"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.
// ignore: avoid_dynamic_calls
(key.currentState as dynamic).ensureTooltipVisible();
}
const String tooltipText = 'TIP';
Finder _findTooltipContainer(String tooltipText) {
......@@ -42,7 +25,7 @@ Finder _findTooltipContainer(String tooltipText) {
void main() {
testWidgets('Does tooltip end up in the right place - center', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -56,7 +39,7 @@ void main() {
left: 300.0,
top: 0.0,
child: Tooltip(
key: key,
key: tooltipKey,
message: tooltipText,
height: 20.0,
padding: const EdgeInsets.all(5.0),
......@@ -76,7 +59,7 @@ void main() {
),
),
);
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
/********************* 800x600 screen
......@@ -99,7 +82,7 @@ void main() {
});
testWidgets('Does tooltip end up in the right place - center with padding outside overlay', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -115,7 +98,7 @@ void main() {
left: 300.0,
top: 0.0,
child: Tooltip(
key: key,
key: tooltipKey,
message: tooltipText,
height: 20.0,
padding: const EdgeInsets.all(5.0),
......@@ -136,7 +119,7 @@ void main() {
),
),
);
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
/************************ 800x600 screen
......@@ -161,7 +144,7 @@ void main() {
});
testWidgets('Does tooltip end up in the right place - top left', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -175,7 +158,7 @@ void main() {
left: 0.0,
top: 0.0,
child: Tooltip(
key: key,
key: tooltipKey,
message: tooltipText,
height: 20.0,
padding: const EdgeInsets.all(5.0),
......@@ -195,7 +178,7 @@ void main() {
),
),
);
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
/********************* 800x600 screen
......@@ -215,7 +198,7 @@ void main() {
});
testWidgets('Does tooltip end up in the right place - center prefer above fits', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -229,7 +212,7 @@ void main() {
left: 400.0,
top: 300.0,
child: Tooltip(
key: key,
key: tooltipKey,
message: tooltipText,
height: 100.0,
padding: EdgeInsets.zero,
......@@ -249,7 +232,7 @@ void main() {
),
),
);
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
/********************* 800x600 screen
......@@ -271,7 +254,7 @@ void main() {
});
testWidgets('Does tooltip end up in the right place - center prefer above does not fit', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -285,7 +268,7 @@ void main() {
left: 400.0,
top: 299.0,
child: Tooltip(
key: key,
key: tooltipKey,
message: tooltipText,
height: 190.0,
padding: EdgeInsets.zero,
......@@ -305,7 +288,7 @@ void main() {
),
),
);
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
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:
......@@ -338,7 +321,7 @@ void main() {
});
testWidgets('Does tooltip end up in the right place - center prefer below fits', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -352,7 +335,7 @@ void main() {
left: 400.0,
top: 300.0,
child: Tooltip(
key: key,
key: tooltipKey,
message: tooltipText,
height: 190.0,
padding: EdgeInsets.zero,
......@@ -372,7 +355,7 @@ void main() {
),
),
);
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
/********************* 800x600 screen
......@@ -393,7 +376,7 @@ void main() {
});
testWidgets('Does tooltip end up in the right place - way off to the right', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -407,7 +390,7 @@ void main() {
left: 1600.0,
top: 300.0,
child: Tooltip(
key: key,
key: tooltipKey,
message: tooltipText,
height: 10.0,
padding: EdgeInsets.zero,
......@@ -427,7 +410,7 @@ void main() {
),
),
);
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
/********************* 800x600 screen
......@@ -450,7 +433,7 @@ void main() {
});
testWidgets('Does tooltip end up in the right place - near the edge', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -464,7 +447,7 @@ void main() {
left: 780.0,
top: 300.0,
child: Tooltip(
key: key,
key: tooltipKey,
message: tooltipText,
height: 10.0,
padding: EdgeInsets.zero,
......@@ -484,7 +467,7 @@ void main() {
),
),
);
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
/********************* 800x600 screen
......@@ -508,7 +491,7 @@ void main() {
testWidgets('Custom tooltip margin', (WidgetTester tester) async {
const double customMarginValue = 10.0;
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -517,7 +500,7 @@ void main() {
OverlayEntry(
builder: (BuildContext context) {
return Tooltip(
key: key,
key: tooltipKey,
message: tooltipText,
padding: EdgeInsets.zero,
margin: const EdgeInsets.all(customMarginValue),
......@@ -532,7 +515,7 @@ void main() {
),
),
);
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final Offset topLeftTipInGlobal = tester.getTopLeft(
......@@ -565,10 +548,10 @@ void main() {
});
testWidgets('Default tooltip message textStyle - light', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
await tester.pumpWidget(MaterialApp(
home: Tooltip(
key: key,
key: tooltipKey,
message: tooltipText,
child: Container(
width: 100.0,
......@@ -577,7 +560,7 @@ void main() {
),
),
));
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final TextStyle textStyle = tester.widget<Text>(find.text(tooltipText)).style!;
......@@ -588,13 +571,13 @@ void main() {
});
testWidgets('Default tooltip message textStyle - dark', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
brightness: Brightness.dark,
),
home: Tooltip(
key: key,
key: tooltipKey,
message: tooltipText,
child: Container(
width: 100.0,
......@@ -603,7 +586,7 @@ void main() {
),
),
));
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final TextStyle textStyle = tester.widget<Text>(find.text(tooltipText)).style!;
......@@ -614,10 +597,10 @@ void main() {
});
testWidgets('Custom tooltip message textStyle', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
await tester.pumpWidget(MaterialApp(
home: Tooltip(
key: key,
key: tooltipKey,
textStyle: const TextStyle(
color: Colors.orange,
decoration: TextDecoration.underline,
......@@ -630,7 +613,7 @@ void main() {
),
),
));
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final TextStyle textStyle = tester.widget<Text>(find.text(tooltipText)).style!;
......@@ -676,10 +659,10 @@ void main() {
// A Material widget is needed as an ancestor of the Text widget.
// It is invalid to have text in a Material application that
// does not have a Material ancestor.
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
await tester.pumpWidget(MaterialApp(
home: Tooltip(
key: key,
key: tooltipKey,
message: tooltipText,
child: Container(
width: 100.0,
......@@ -688,7 +671,7 @@ void main() {
),
),
));
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final TextStyle textStyle = tester.widget<DefaultTextStyle>(
......@@ -706,7 +689,7 @@ void main() {
});
testWidgets('Does tooltip end up with the right default size, shape, and color', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -715,7 +698,7 @@ void main() {
OverlayEntry(
builder: (BuildContext context) {
return Tooltip(
key: key,
key: tooltipKey,
message: tooltipText,
child: const SizedBox(
width: 0.0,
......@@ -728,7 +711,7 @@ void main() {
),
),
);
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final RenderBox tip = tester.renderObject(
......@@ -744,11 +727,11 @@ void main() {
testWidgets('Tooltip default size, shape, and color test for Desktop', (WidgetTester tester) async {
// Regressing test for https://github.com/flutter/flutter/issues/68601
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
await tester.pumpWidget(
MaterialApp(
home: Tooltip(
key: key,
key: tooltipKey,
message: tooltipText,
child: const SizedBox(
width: 0.0,
......@@ -757,8 +740,7 @@ void main() {
),
),
);
// ignore: avoid_dynamic_calls
(key.currentState as dynamic).ensureTooltipVisible();
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final RenderParagraph tooltipRenderParagraph = tester.renderObject<RenderParagraph>(find.text(tooltipText));
......@@ -776,7 +758,7 @@ void main() {
}, variant: const TargetPlatformVariant(<TargetPlatform>{TargetPlatform.macOS, TargetPlatform.linux, TargetPlatform.windows}));
testWidgets('Can tooltip decoration be customized', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
const Decoration customDecoration = ShapeDecoration(
shape: StadiumBorder(),
color: Color(0x80800000),
......@@ -789,7 +771,7 @@ void main() {
OverlayEntry(
builder: (BuildContext context) {
return Tooltip(
key: key,
key: tooltipKey,
decoration: customDecoration,
message: tooltipText,
child: const SizedBox(
......@@ -803,7 +785,7 @@ void main() {
),
),
);
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final RenderBox tip = tester.renderObject(
......@@ -1248,8 +1230,8 @@ void main() {
testWidgets('Does tooltip contribute semantics', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
final GlobalKey key = GlobalKey();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
......@@ -1263,7 +1245,7 @@ void main() {
left: 780.0,
top: 300.0,
child: Tooltip(
key: key,
key: tooltipKey,
message: tooltipText,
child: const SizedBox(width: 10.0, height: 10.0),
),
......@@ -1290,7 +1272,7 @@ void main() {
expect(semantics, hasSemantics(expected, ignoreTransform: true, ignoreRect: true));
// This triggers a rebuild of the semantics because the tree changes.
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
......@@ -1376,13 +1358,13 @@ void main() {
});
testWidgets('Tooltip text displays with richMessage', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
const String textSpan1Text = 'I am a rich tooltip message. ';
const String textSpan2Text = 'I am another span of a rich tooltip message';
await tester.pumpWidget(
MaterialApp(
home: Tooltip(
key: key,
key: tooltipKey,
richMessage: const TextSpan(
text: textSpan1Text,
children: <InlineSpan>[
......@@ -1399,7 +1381,7 @@ void main() {
),
),
);
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final RichText richText = tester.widget<RichText>(find.byType(RichText));
......
......@@ -9,23 +9,6 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
void _ensureTooltipVisible(GlobalKey key) {
// This function uses "as dynamic" 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.
// ignore: avoid_dynamic_calls
(key.currentState as dynamic).ensureTooltipVisible();
}
const String tooltipText = 'TIP';
void main() {
......@@ -162,13 +145,13 @@ void main() {
});
testWidgets('Tooltip does not trigger manually when in TooltipVisibility with visible = false', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
await tester.pumpWidget(
MaterialApp(
home: TooltipVisibility(
visible: false,
child: Tooltip(
key: key,
key: tooltipKey,
message: tooltipText,
child: const SizedBox(width: 100.0, height: 100.0),
),
......@@ -176,19 +159,19 @@ void main() {
),
);
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump();
expect(find.text(tooltipText), findsNothing);
});
testWidgets('Tooltip triggers manually when in TooltipVisibility with visible = true', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
await tester.pumpWidget(
MaterialApp(
home: TooltipVisibility(
visible: true,
child: Tooltip(
key: key,
key: tooltipKey,
message: tooltipText,
child: const SizedBox(width: 100.0, height: 100.0),
),
......@@ -196,7 +179,7 @@ void main() {
),
);
_ensureTooltipVisible(key);
tooltipKey.currentState?.ensureTooltipVisible();
await tester.pump();
expect(find.text(tooltipText), findsOneWidget);
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment