mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
parent
dbf8cd4b10
commit
0343555af1
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
@ -13,17 +11,17 @@ import 'package:flutter/gestures.dart';
|
||||
|
||||
class HoverClient extends StatefulWidget {
|
||||
const HoverClient({
|
||||
Key key,
|
||||
Key? key,
|
||||
this.onHover,
|
||||
this.child,
|
||||
this.onEnter,
|
||||
this.onExit,
|
||||
}) : super(key: key);
|
||||
|
||||
final ValueChanged<bool> onHover;
|
||||
final Widget child;
|
||||
final VoidCallback onEnter;
|
||||
final VoidCallback onExit;
|
||||
final ValueChanged<bool>? onHover;
|
||||
final Widget? child;
|
||||
final VoidCallback? onEnter;
|
||||
final VoidCallback? onExit;
|
||||
|
||||
@override
|
||||
HoverClientState createState() => HoverClientState();
|
||||
@ -32,19 +30,19 @@ class HoverClient extends StatefulWidget {
|
||||
class HoverClientState extends State<HoverClient> {
|
||||
void _onExit(PointerExitEvent details) {
|
||||
if (widget.onExit != null) {
|
||||
widget.onExit();
|
||||
widget.onExit!();
|
||||
}
|
||||
if (widget.onHover != null) {
|
||||
widget.onHover(false);
|
||||
widget.onHover!(false);
|
||||
}
|
||||
}
|
||||
|
||||
void _onEnter(PointerEnterEvent details) {
|
||||
if (widget.onEnter != null) {
|
||||
widget.onEnter();
|
||||
widget.onEnter!();
|
||||
}
|
||||
if (widget.onHover != null) {
|
||||
widget.onHover(true);
|
||||
widget.onHover!(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,10 +57,10 @@ class HoverClientState extends State<HoverClient> {
|
||||
}
|
||||
|
||||
class HoverFeedback extends StatefulWidget {
|
||||
const HoverFeedback({Key key, this.onEnter, this.onExit}) : super(key: key);
|
||||
const HoverFeedback({Key? key, this.onEnter, this.onExit}) : super(key: key);
|
||||
|
||||
final VoidCallback onEnter;
|
||||
final VoidCallback onExit;
|
||||
final VoidCallback? onEnter;
|
||||
final VoidCallback? onExit;
|
||||
|
||||
@override
|
||||
_HoverFeedbackState createState() => _HoverFeedbackState();
|
||||
@ -87,9 +85,9 @@ class _HoverFeedbackState extends State<HoverFeedback> {
|
||||
|
||||
void main() {
|
||||
testWidgets('detects pointer enter', (WidgetTester tester) async {
|
||||
PointerEnterEvent enter;
|
||||
PointerHoverEvent move;
|
||||
PointerExitEvent exit;
|
||||
PointerEnterEvent? enter;
|
||||
PointerHoverEvent? move;
|
||||
PointerExitEvent? exit;
|
||||
await tester.pumpWidget(Center(
|
||||
child: MouseRegion(
|
||||
child: Container(
|
||||
@ -111,18 +109,18 @@ void main() {
|
||||
exit = null;
|
||||
await gesture.moveTo(const Offset(400.0, 300.0));
|
||||
expect(move, isNotNull);
|
||||
expect(move.position, equals(const Offset(400.0, 300.0)));
|
||||
expect(move.localPosition, equals(const Offset(50.0, 50.0)));
|
||||
expect(move!.position, equals(const Offset(400.0, 300.0)));
|
||||
expect(move!.localPosition, equals(const Offset(50.0, 50.0)));
|
||||
expect(enter, isNotNull);
|
||||
expect(enter.position, equals(const Offset(400.0, 300.0)));
|
||||
expect(enter.localPosition, equals(const Offset(50.0, 50.0)));
|
||||
expect(enter!.position, equals(const Offset(400.0, 300.0)));
|
||||
expect(enter!.localPosition, equals(const Offset(50.0, 50.0)));
|
||||
expect(exit, isNull);
|
||||
});
|
||||
|
||||
testWidgets('detects pointer exiting', (WidgetTester tester) async {
|
||||
PointerEnterEvent enter;
|
||||
PointerHoverEvent move;
|
||||
PointerExitEvent exit;
|
||||
PointerEnterEvent? enter;
|
||||
PointerHoverEvent? move;
|
||||
PointerExitEvent? exit;
|
||||
await tester.pumpWidget(Center(
|
||||
child: MouseRegion(
|
||||
child: Container(
|
||||
@ -147,14 +145,14 @@ void main() {
|
||||
expect(move, isNull);
|
||||
expect(enter, isNull);
|
||||
expect(exit, isNotNull);
|
||||
expect(exit.position, equals(const Offset(1.0, 1.0)));
|
||||
expect(exit.localPosition, equals(const Offset(-349.0, -249.0)));
|
||||
expect(exit!.position, equals(const Offset(1.0, 1.0)));
|
||||
expect(exit!.localPosition, equals(const Offset(-349.0, -249.0)));
|
||||
});
|
||||
|
||||
testWidgets('triggers pointer enter when a mouse is connected', (WidgetTester tester) async {
|
||||
PointerEnterEvent enter;
|
||||
PointerHoverEvent move;
|
||||
PointerExitEvent exit;
|
||||
PointerEnterEvent? enter;
|
||||
PointerHoverEvent? move;
|
||||
PointerExitEvent? exit;
|
||||
await tester.pumpWidget(Center(
|
||||
child: MouseRegion(
|
||||
child: const SizedBox(
|
||||
@ -173,15 +171,15 @@ void main() {
|
||||
addTearDown(gesture.removePointer);
|
||||
expect(move, isNull);
|
||||
expect(enter, isNotNull);
|
||||
expect(enter.position, equals(const Offset(400.0, 300.0)));
|
||||
expect(enter.localPosition, equals(const Offset(50.0, 50.0)));
|
||||
expect(enter!.position, equals(const Offset(400.0, 300.0)));
|
||||
expect(enter!.localPosition, equals(const Offset(50.0, 50.0)));
|
||||
expect(exit, isNull);
|
||||
});
|
||||
|
||||
testWidgets('triggers pointer exit when a mouse is disconnected', (WidgetTester tester) async {
|
||||
PointerEnterEvent enter;
|
||||
PointerHoverEvent move;
|
||||
PointerExitEvent exit;
|
||||
PointerEnterEvent? enter;
|
||||
PointerHoverEvent? move;
|
||||
PointerExitEvent? exit;
|
||||
await tester.pumpWidget(Center(
|
||||
child: MouseRegion(
|
||||
child: const SizedBox(
|
||||
@ -195,7 +193,7 @@ void main() {
|
||||
));
|
||||
await tester.pump();
|
||||
|
||||
TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
|
||||
TestGesture? gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
|
||||
await gesture.addPointer(location: const Offset(400, 300));
|
||||
addTearDown(() => gesture?.removePointer);
|
||||
await tester.pump();
|
||||
@ -207,8 +205,8 @@ void main() {
|
||||
expect(move, isNull);
|
||||
expect(enter, isNull);
|
||||
expect(exit, isNotNull);
|
||||
expect(exit.position, equals(const Offset(400.0, 300.0)));
|
||||
expect(exit.localPosition, equals(const Offset(50.0, 50.0)));
|
||||
expect(exit!.position, equals(const Offset(400.0, 300.0)));
|
||||
expect(exit!.localPosition, equals(const Offset(50.0, 50.0)));
|
||||
exit = null;
|
||||
await tester.pump();
|
||||
expect(move, isNull);
|
||||
@ -217,9 +215,9 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('triggers pointer enter when widget appears', (WidgetTester tester) async {
|
||||
PointerEnterEvent enter;
|
||||
PointerHoverEvent move;
|
||||
PointerExitEvent exit;
|
||||
PointerEnterEvent? enter;
|
||||
PointerHoverEvent? move;
|
||||
PointerExitEvent? exit;
|
||||
await tester.pumpWidget(const Center(
|
||||
child: SizedBox(
|
||||
width: 100.0,
|
||||
@ -248,15 +246,15 @@ void main() {
|
||||
await tester.pump();
|
||||
expect(move, isNull);
|
||||
expect(enter, isNotNull);
|
||||
expect(enter.position, equals(const Offset(400.0, 300.0)));
|
||||
expect(enter.localPosition, equals(const Offset(50.0, 50.0)));
|
||||
expect(enter!.position, equals(const Offset(400.0, 300.0)));
|
||||
expect(enter!.localPosition, equals(const Offset(50.0, 50.0)));
|
||||
expect(exit, isNull);
|
||||
});
|
||||
|
||||
testWidgets("doesn't trigger pointer exit when widget disappears", (WidgetTester tester) async {
|
||||
PointerEnterEvent enter;
|
||||
PointerHoverEvent move;
|
||||
PointerExitEvent exit;
|
||||
PointerEnterEvent? enter;
|
||||
PointerHoverEvent? move;
|
||||
PointerExitEvent? exit;
|
||||
await tester.pumpWidget(Center(
|
||||
child: MouseRegion(
|
||||
child: const SizedBox(
|
||||
@ -288,9 +286,9 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('triggers pointer enter when widget moves in', (WidgetTester tester) async {
|
||||
PointerEnterEvent enter;
|
||||
PointerHoverEvent move;
|
||||
PointerExitEvent exit;
|
||||
PointerEnterEvent? enter;
|
||||
PointerHoverEvent? move;
|
||||
PointerExitEvent? exit;
|
||||
await tester.pumpWidget(Container(
|
||||
alignment: Alignment.topLeft,
|
||||
child: MouseRegion(
|
||||
@ -324,16 +322,16 @@ void main() {
|
||||
));
|
||||
await tester.pump();
|
||||
expect(enter, isNotNull);
|
||||
expect(enter.position, equals(const Offset(401.0, 301.0)));
|
||||
expect(enter.localPosition, equals(const Offset(51.0, 51.0)));
|
||||
expect(enter!.position, equals(const Offset(401.0, 301.0)));
|
||||
expect(enter!.localPosition, equals(const Offset(51.0, 51.0)));
|
||||
expect(move, isNull);
|
||||
expect(exit, isNull);
|
||||
});
|
||||
|
||||
testWidgets('triggers pointer exit when widget moves out', (WidgetTester tester) async {
|
||||
PointerEnterEvent enter;
|
||||
PointerHoverEvent move;
|
||||
PointerExitEvent exit;
|
||||
PointerEnterEvent? enter;
|
||||
PointerHoverEvent? move;
|
||||
PointerExitEvent? exit;
|
||||
await tester.pumpWidget(Container(
|
||||
alignment: Alignment.center,
|
||||
child: MouseRegion(
|
||||
@ -369,14 +367,14 @@ void main() {
|
||||
expect(enter, isNull);
|
||||
expect(move, isNull);
|
||||
expect(exit, isNotNull);
|
||||
expect(exit.position, equals(const Offset(400, 300)));
|
||||
expect(exit.localPosition, equals(const Offset(50, 50)));
|
||||
expect(exit!.position, equals(const Offset(400, 300)));
|
||||
expect(exit!.localPosition, equals(const Offset(50, 50)));
|
||||
});
|
||||
|
||||
testWidgets('detects hover from touch devices', (WidgetTester tester) async {
|
||||
PointerEnterEvent enter;
|
||||
PointerHoverEvent move;
|
||||
PointerExitEvent exit;
|
||||
PointerEnterEvent? enter;
|
||||
PointerHoverEvent? move;
|
||||
PointerExitEvent? exit;
|
||||
await tester.pumpWidget(Center(
|
||||
child: MouseRegion(
|
||||
child: Container(
|
||||
@ -398,8 +396,8 @@ void main() {
|
||||
exit = null;
|
||||
await gesture.moveTo(const Offset(400.0, 300.0));
|
||||
expect(move, isNotNull);
|
||||
expect(move.position, equals(const Offset(400.0, 300.0)));
|
||||
expect(move.localPosition, equals(const Offset(50.0, 50.0)));
|
||||
expect(move!.position, equals(const Offset(400.0, 300.0)));
|
||||
expect(move!.localPosition, equals(const Offset(50.0, 50.0)));
|
||||
expect(enter, isNull);
|
||||
expect(exit, isNull);
|
||||
});
|
||||
@ -589,21 +587,21 @@ void main() {
|
||||
addTearDown(gesture.removePointer);
|
||||
|
||||
await tester.pump();
|
||||
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic);
|
||||
expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic);
|
||||
|
||||
await gesture.moveTo(const Offset(5, 5));
|
||||
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text);
|
||||
expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text);
|
||||
|
||||
await gesture.moveTo(const Offset(100, 100));
|
||||
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic);
|
||||
expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic);
|
||||
});
|
||||
|
||||
testWidgets('MouseRegion uses updated callbacks', (WidgetTester tester) async {
|
||||
final List<String> logs = <String>[];
|
||||
Widget hoverableContainer({
|
||||
PointerEnterEventListener onEnter,
|
||||
PointerHoverEventListener onHover,
|
||||
PointerExitEventListener onExit,
|
||||
PointerEnterEventListener? onEnter,
|
||||
PointerHoverEventListener? onHover,
|
||||
PointerExitEventListener? onExit,
|
||||
}) {
|
||||
return Container(
|
||||
alignment: Alignment.topLeft,
|
||||
@ -894,7 +892,7 @@ void main() {
|
||||
);
|
||||
|
||||
// Plug-in a mouse and move it to the center of the container.
|
||||
TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
|
||||
TestGesture? gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
|
||||
await gesture.addPointer(location: Offset.zero);
|
||||
addTearDown(() => gesture?.removePointer());
|
||||
await tester.pumpAndSettle();
|
||||
@ -1072,7 +1070,7 @@ void main() {
|
||||
bool hovered = false;
|
||||
final List<bool> logHovered = <bool>[];
|
||||
bool moved = false;
|
||||
StateSetter mySetState;
|
||||
late StateSetter mySetState;
|
||||
|
||||
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
|
||||
await gesture.addPointer(location: const Offset(5, 5));
|
||||
@ -1140,14 +1138,14 @@ void main() {
|
||||
// | ——————————— | 130
|
||||
// —————————————————————— 150
|
||||
// x 0 20 50 100 130 150
|
||||
Widget tripleRegions({bool opaqueC, void Function(String) addLog}) {
|
||||
Widget tripleRegions({bool? opaqueC, required void Function(String) addLog}) {
|
||||
// Same as MouseRegion, but when opaque is null, use the default value.
|
||||
Widget mouseRegionWithOptionalOpaque({
|
||||
void Function(PointerEnterEvent e) onEnter,
|
||||
void Function(PointerHoverEvent e) onHover,
|
||||
void Function(PointerExitEvent e) onExit,
|
||||
Widget child,
|
||||
bool opaque,
|
||||
void Function(PointerEnterEvent e)? onEnter,
|
||||
void Function(PointerHoverEvent e)? onHover,
|
||||
void Function(PointerExitEvent e)? onExit,
|
||||
Widget? child,
|
||||
bool? opaque,
|
||||
}) {
|
||||
if (opaque == null) {
|
||||
return MouseRegion(onEnter: onEnter, onHover: onHover, onExit: onExit, child: child);
|
||||
@ -1492,7 +1490,7 @@ void main() {
|
||||
await gesture.moveTo(const Offset(5, 5));
|
||||
|
||||
expect(logPaints, <String>['paint']);
|
||||
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden);
|
||||
expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden);
|
||||
expect(logEnters, <String>['enter']);
|
||||
logPaints.clear();
|
||||
logEnters.clear();
|
||||
@ -1511,7 +1509,7 @@ void main() {
|
||||
));
|
||||
|
||||
expect(logPaints, <String>['paint']);
|
||||
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text);
|
||||
expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text);
|
||||
expect(logEnters, isEmpty);
|
||||
logPaints.clear();
|
||||
logEnters.clear();
|
||||
@ -1545,7 +1543,7 @@ void main() {
|
||||
|
||||
expect(logPaints, <String>['paint']);
|
||||
expect(logEnters, <String>['enter']);
|
||||
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text);
|
||||
expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text);
|
||||
logPaints.clear();
|
||||
logEnters.clear();
|
||||
|
||||
@ -1566,7 +1564,7 @@ void main() {
|
||||
|
||||
expect(logPaints, <String>['paint']);
|
||||
expect(logEnters, isEmpty);
|
||||
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden);
|
||||
expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden);
|
||||
logPaints.clear();
|
||||
logEnters.clear();
|
||||
|
||||
@ -1586,7 +1584,7 @@ void main() {
|
||||
));
|
||||
|
||||
expect(logPaints, <String>['paint']);
|
||||
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text);
|
||||
expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text);
|
||||
expect(logEnters, isEmpty);
|
||||
logPaints.clear();
|
||||
logEnters.clear();
|
||||
@ -1638,7 +1636,7 @@ void main() {
|
||||
expect(logEnters, <String>['enter']);
|
||||
expect(logExits, isEmpty);
|
||||
expect(logCursors, isNotEmpty);
|
||||
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click);
|
||||
expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click);
|
||||
logEnters.clear();
|
||||
logExits.clear();
|
||||
logCursors.clear();
|
||||
@ -1673,7 +1671,7 @@ void main() {
|
||||
expect(logEnters, isEmpty);
|
||||
expect(logExits, isEmpty);
|
||||
expect(logCursors, isEmpty);
|
||||
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click);
|
||||
expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click);
|
||||
});
|
||||
|
||||
testWidgets("RenderMouseRegion's debugFillProperties when default", (WidgetTester tester) async {
|
||||
@ -1737,8 +1735,8 @@ void main() {
|
||||
class _Scaffold extends StatelessWidget {
|
||||
const _Scaffold({this.topLeft, this.background});
|
||||
|
||||
final Widget topLeft;
|
||||
final Widget background;
|
||||
final Widget? topLeft;
|
||||
final Widget? background;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -1746,7 +1744,7 @@ class _Scaffold extends StatelessWidget {
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Stack(
|
||||
children: <Widget>[
|
||||
if (background != null) background,
|
||||
if (background != null) background!,
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: topLeft,
|
||||
@ -1758,8 +1756,8 @@ class _Scaffold extends StatelessWidget {
|
||||
}
|
||||
|
||||
class _DelegatedPainter extends CustomPainter {
|
||||
_DelegatedPainter({this.key, this.onPaint});
|
||||
final Key key;
|
||||
_DelegatedPainter({this.key, required this.onPaint});
|
||||
final Key? key;
|
||||
final VoidCallback onPaint;
|
||||
|
||||
@override
|
||||
@ -1804,7 +1802,7 @@ class _HoverClientWithClosuresState extends State<_HoverClientWithClosures> {
|
||||
// A column that aligns to the top left.
|
||||
class _ColumnContainer extends StatelessWidget {
|
||||
const _ColumnContainer({
|
||||
@required this.children,
|
||||
required this.children,
|
||||
}) : assert(children != null);
|
||||
|
||||
final List<Widget> children;
|
||||
|
||||
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
@ -18,12 +16,12 @@ void checkTree(WidgetTester tester, List<BoxDecoration> expectedDecorations) {
|
||||
expect(element.renderObject, isA<RenderStack>());
|
||||
final RenderStack renderObject = element.renderObject as RenderStack;
|
||||
try {
|
||||
RenderObject child = renderObject.firstChild;
|
||||
RenderObject? child = renderObject.firstChild;
|
||||
for (final BoxDecoration decoration in expectedDecorations) {
|
||||
expect(child, isA<RenderDecoratedBox>());
|
||||
final RenderDecoratedBox decoratedBox = child as RenderDecoratedBox;
|
||||
final RenderDecoratedBox decoratedBox = child! as RenderDecoratedBox;
|
||||
expect(decoratedBox.decoration, equals(decoration));
|
||||
final StackParentData decoratedBoxParentData = decoratedBox.parentData as StackParentData;
|
||||
final StackParentData decoratedBoxParentData = decoratedBox.parentData! as StackParentData;
|
||||
child = decoratedBoxParentData.nextSibling;
|
||||
}
|
||||
expect(child, isNull);
|
||||
@ -34,10 +32,13 @@ void checkTree(WidgetTester tester, List<BoxDecoration> expectedDecorations) {
|
||||
}
|
||||
|
||||
class MockMultiChildRenderObjectWidget extends MultiChildRenderObjectWidget {
|
||||
MockMultiChildRenderObjectWidget({ Key key, List<Widget> children }) : super(key: key, children: children);
|
||||
MockMultiChildRenderObjectWidget({ Key? key, required List<Widget> children }) : super(key: key, children: children);
|
||||
|
||||
@override
|
||||
RenderObject createRenderObject(BuildContext context) => null;
|
||||
RenderObject createRenderObject(BuildContext context) {
|
||||
assert(false);
|
||||
return FakeRenderObject();
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
@ -354,17 +355,11 @@ void main() {
|
||||
|
||||
checkTree(tester, <BoxDecoration>[kBoxDecorationB, kBoxDecorationC]);
|
||||
});
|
||||
|
||||
// Regression test for https://github.com/flutter/flutter/issues/37136.
|
||||
test('provides useful assertion message when one of the children is null', () {
|
||||
bool assertionTriggered = false;
|
||||
try {
|
||||
MockMultiChildRenderObjectWidget(children: const <Widget>[null]);
|
||||
} catch (e) {
|
||||
expect(e.toString(), contains("MockMultiChildRenderObjectWidget's children must not contain any null values,"));
|
||||
assertionTriggered = true;
|
||||
}
|
||||
|
||||
expect(assertionTriggered, isTrue);
|
||||
});
|
||||
}
|
||||
|
||||
class FakeRenderObject extends RenderBox {
|
||||
@override
|
||||
void performLayout() {
|
||||
size = constraints.biggest;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
@ -68,7 +66,7 @@ void main() {
|
||||
List<String> _getChildOrder(RenderFlex flex) {
|
||||
final List<String> childOrder = <String>[];
|
||||
flex.visitChildren((RenderObject child) {
|
||||
childOrder.add(((child as RenderParagraph).text as TextSpan).text);
|
||||
childOrder.add(((child as RenderParagraph).text as TextSpan).text!);
|
||||
});
|
||||
return childOrder;
|
||||
}
|
||||
|
||||
@ -2,15 +2,13 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'test_widgets.dart';
|
||||
|
||||
class TestCustomPainter extends CustomPainter {
|
||||
TestCustomPainter({ this.log, this.name });
|
||||
TestCustomPainter({ required this.log, required this.name });
|
||||
|
||||
final List<String> log;
|
||||
final String name;
|
||||
|
||||
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@ -60,11 +58,11 @@ void main() {
|
||||
final NavigatorState navigator = tester.state(find.byType(Navigator));
|
||||
final List<String> log = <String>[];
|
||||
observer
|
||||
..onPushed = (Route<dynamic> route, Route<dynamic> previousRoute) {
|
||||
log.add('${route.settings.name} pushed, previous route: ${previousRoute.settings.name}');
|
||||
..onPushed = (Route<dynamic>? route, Route<dynamic>? previousRoute) {
|
||||
log.add('${route!.settings.name} pushed, previous route: ${previousRoute!.settings.name}');
|
||||
}
|
||||
..onRemoved = (Route<dynamic> route, Route<dynamic> previousRoute) {
|
||||
log.add('${route.settings.name} removed, previous route: ${previousRoute?.settings?.name}');
|
||||
..onRemoved = (Route<dynamic>? route, Route<dynamic>? previousRoute) {
|
||||
log.add('${route!.settings.name} removed, previous route: ${previousRoute?.settings.name}');
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -2,14 +2,14 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../flutter_test_alternative.dart' show Fake;
|
||||
|
||||
void main() {
|
||||
testWidgets('Restoration Smoke Test', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(const TestWidget());
|
||||
@ -306,7 +306,7 @@ void main() {
|
||||
await tester.pumpWidget(const TestWidget());
|
||||
expect(findRoute('home', count: 0), findsOneWidget);
|
||||
|
||||
final Route<Object> oldRoute = ModalRoute.of(tester.element(find.text('Route: home')));
|
||||
final Route<Object> oldRoute = ModalRoute.of(tester.element(find.text('Route: home')))!;
|
||||
expect(oldRoute.settings.name, 'home');
|
||||
|
||||
tester.state<NavigatorState>(find.byType(Navigator)).restorableReplace(newRouteBuilder: _routeBuilder, arguments: 'Foo', oldRoute: oldRoute);
|
||||
@ -342,7 +342,7 @@ void main() {
|
||||
await tester.pumpWidget(const TestWidget());
|
||||
expect(findRoute('home', count: 0), findsOneWidget);
|
||||
|
||||
final Route<Object> oldRoute = ModalRoute.of(tester.element(find.text('Route: home')));
|
||||
final Route<Object> oldRoute = ModalRoute.of(tester.element(find.text('Route: home')))!;
|
||||
expect(oldRoute.settings.name, 'home');
|
||||
|
||||
tester.state<NavigatorState>(find.byType(Navigator)).restorableReplace(newRouteBuilder: _routeBuilder, arguments: 'Foo', oldRoute: oldRoute);
|
||||
@ -362,7 +362,7 @@ void main() {
|
||||
expect(findRoute('home', count: 0, skipOffstage: false), findsOneWidget);
|
||||
expect(findRoute('Anchor', count: 1), findsOneWidget);
|
||||
|
||||
final Route<Object> anchor = ModalRoute.of(tester.element(find.text('Route: Anchor')));
|
||||
final Route<Object> anchor = ModalRoute.of(tester.element(find.text('Route: Anchor')))!;
|
||||
expect(anchor.settings.name, 'Anchor');
|
||||
|
||||
tester.state<NavigatorState>(find.byType(Navigator)).restorableReplaceRouteBelow(newRouteBuilder: _routeBuilder, arguments: 'Foo', anchorRoute: anchor);
|
||||
@ -408,7 +408,7 @@ void main() {
|
||||
expect(findRoute('home', count: 0, skipOffstage: false), findsOneWidget);
|
||||
expect(findRoute('Anchor', count: 1), findsOneWidget);
|
||||
|
||||
final Route<Object> anchor = ModalRoute.of(tester.element(find.text('Route: Anchor')));
|
||||
final Route<Object> anchor = ModalRoute.of(tester.element(find.text('Route: Anchor')))!;
|
||||
expect(anchor.settings.name, 'Anchor');
|
||||
|
||||
tester.state<NavigatorState>(find.byType(Navigator)).restorableReplaceRouteBelow(newRouteBuilder: _routeBuilder, arguments: 'Foo', anchorRoute: anchor);
|
||||
@ -479,22 +479,22 @@ void main() {
|
||||
expect(findRoute('Foo'), findsOneWidget);
|
||||
|
||||
// Push is in progress.
|
||||
final ModalRoute<Object> route1 = ModalRoute.of(tester.element(find.text('Route: Foo')));
|
||||
final String route1id = route1.restorationScopeId.value;
|
||||
final ModalRoute<Object> route1 = ModalRoute.of(tester.element(find.text('Route: Foo')))!;
|
||||
final String route1id = route1.restorationScopeId.value!;
|
||||
expect(route1id, isNotNull);
|
||||
expect(route1.settings.name, 'Foo');
|
||||
expect(route1.animation.isCompleted, isFalse);
|
||||
expect(route1.animation.isDismissed, isFalse);
|
||||
expect(route1.animation!.isCompleted, isFalse);
|
||||
expect(route1.animation!.isDismissed, isFalse);
|
||||
expect(route1.isActive, isTrue);
|
||||
|
||||
await tester.restartAndRestore();
|
||||
|
||||
expect(findRoute('Foo'), findsOneWidget);
|
||||
expect(findRoute('home', skipOffstage: false), findsOneWidget);
|
||||
final ModalRoute<Object> route2 = ModalRoute.of(tester.element(find.text('Route: Foo')));
|
||||
final ModalRoute<Object> route2 = ModalRoute.of(tester.element(find.text('Route: Foo')))!;
|
||||
expect(route2, isNot(same(route1)));
|
||||
expect(route1.restorationScopeId.value, route1id);
|
||||
expect(route2.animation.isCompleted, isTrue);
|
||||
expect(route2.animation!.isCompleted, isTrue);
|
||||
expect(route2.isActive, isTrue);
|
||||
});
|
||||
|
||||
@ -506,14 +506,14 @@ void main() {
|
||||
tester.state<NavigatorState>(find.byType(Navigator)).restorablePushNamed('Foo');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final ModalRoute<Object> route1 = ModalRoute.of(tester.element(find.text('Route: Foo')));
|
||||
final ModalRoute<Object> route1 = ModalRoute.of(tester.element(find.text('Route: Foo')))!;
|
||||
int notifyCount = 0;
|
||||
route1.restorationScopeId.addListener(() {
|
||||
notifyCount++;
|
||||
});
|
||||
expect(route1.isActive, isTrue);
|
||||
expect(route1.restorationScopeId.value, isNotNull);
|
||||
expect(route1.animation.isCompleted, isTrue);
|
||||
expect(route1.animation!.isCompleted, isTrue);
|
||||
expect(notifyCount, 0);
|
||||
|
||||
tester.state<NavigatorState>(find.byType(Navigator)).pop();
|
||||
@ -524,8 +524,8 @@ void main() {
|
||||
// Pop is in progress.
|
||||
expect(route1.restorationScopeId.value, isNull);
|
||||
expect(route1.settings.name, 'Foo');
|
||||
expect(route1.animation.isCompleted, isFalse);
|
||||
expect(route1.animation.isDismissed, isFalse);
|
||||
expect(route1.animation!.isCompleted, isFalse);
|
||||
expect(route1.animation!.isDismissed, isFalse);
|
||||
expect(route1.isActive, isFalse);
|
||||
|
||||
await tester.restartAndRestore();
|
||||
@ -622,7 +622,7 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
expect(findRoute('route5'), findsOneWidget);
|
||||
|
||||
final Route<Object> route = ModalRoute.of(tester.element(find.text('Route: route3', skipOffstage: false)));
|
||||
final Route<Object> route = ModalRoute.of(tester.element(find.text('Route: route3', skipOffstage: false)))!;
|
||||
expect(route.settings.name, 'route3');
|
||||
tester.state<NavigatorState>(find.byType(Navigator)).removeRoute(route);
|
||||
await tester.pumpAndSettle();
|
||||
@ -655,7 +655,7 @@ void main() {
|
||||
routeFuture.present('Foo');
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Route: Foo'), findsOneWidget);
|
||||
expect(routeFuture.route.settings.name, 'Foo');
|
||||
expect(routeFuture.route!.settings.name, 'Foo');
|
||||
expect(routeFuture.isPresent, isTrue);
|
||||
expect(routeFuture.enabled, isTrue);
|
||||
|
||||
@ -665,7 +665,7 @@ void main() {
|
||||
final RestorableRouteFuture<int> restoredRouteFuture = tester
|
||||
.state<RouteFutureWidgetState>(find.byType(RouteFutureWidget, skipOffstage: false))
|
||||
.routeFuture;
|
||||
expect(restoredRouteFuture.route.settings.name, 'Foo');
|
||||
expect(restoredRouteFuture.route!.settings.name, 'Foo');
|
||||
expect(restoredRouteFuture.isPresent, isTrue);
|
||||
expect(restoredRouteFuture.enabled, isTrue);
|
||||
|
||||
@ -699,7 +699,7 @@ void main() {
|
||||
routeFuture.present('Foo');
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Route: Foo'), findsOneWidget);
|
||||
expect(routeFuture.route.settings.name, 'Foo');
|
||||
expect(routeFuture.route!.settings.name, 'Foo');
|
||||
expect(routeFuture.isPresent, isTrue);
|
||||
expect(routeFuture.enabled, isFalse);
|
||||
|
||||
@ -713,7 +713,7 @@ void main() {
|
||||
tester.state<NavigatorState>(find.byType(Navigator)).restorablePushNamed('Bar');
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final Route<Object> oldRoute = ModalRoute.of(tester.element(find.text('Route: Bar')));
|
||||
final Route<Object> oldRoute = ModalRoute.of(tester.element(find.text('Route: Bar')))!;
|
||||
expect(oldRoute.settings.name, 'Bar');
|
||||
|
||||
final Matcher throwsArgumentsAssertionError = throwsA(isAssertionError.having(
|
||||
@ -740,7 +740,7 @@ void main() {
|
||||
throwsArgumentsAssertionError,
|
||||
);
|
||||
expect(
|
||||
() => tester.state<NavigatorState>(find.byType(Navigator)).restorablePushNamedAndRemoveUntil('Foo', (Route<Object> _) => false, arguments: Object()),
|
||||
() => tester.state<NavigatorState>(find.byType(Navigator)).restorablePushNamedAndRemoveUntil('Foo', (Route<Object?> _) => false, arguments: Object()),
|
||||
throwsArgumentsAssertionError,
|
||||
);
|
||||
expect(
|
||||
@ -752,7 +752,7 @@ void main() {
|
||||
throwsArgumentsAssertionError,
|
||||
);
|
||||
expect(
|
||||
() => tester.state<NavigatorState>(find.byType(Navigator)).restorablePushAndRemoveUntil(_routeBuilder, (Route<Object> _) => false, arguments: Object()),
|
||||
() => tester.state<NavigatorState>(find.byType(Navigator)).restorablePushAndRemoveUntil(_routeBuilder, (Route<Object?> _) => false, arguments: Object()),
|
||||
throwsArgumentsAssertionError,
|
||||
);
|
||||
expect(
|
||||
@ -765,27 +765,27 @@ void main() {
|
||||
);
|
||||
|
||||
expect(
|
||||
() => tester.state<NavigatorState>(find.byType(Navigator)).restorablePush((BuildContext _, Object __) => null),
|
||||
() => tester.state<NavigatorState>(find.byType(Navigator)).restorablePush((BuildContext _, Object? __) => FakeRoute()),
|
||||
throwsBuilderAssertionError,
|
||||
skip: isBrowser, // https://github.com/flutter/flutter/issues/33615
|
||||
);
|
||||
expect(
|
||||
() => tester.state<NavigatorState>(find.byType(Navigator)).restorablePushReplacement((BuildContext _, Object __) => null),
|
||||
() => tester.state<NavigatorState>(find.byType(Navigator)).restorablePushReplacement((BuildContext _, Object? __) => FakeRoute()),
|
||||
throwsBuilderAssertionError,
|
||||
skip: isBrowser, // https://github.com/flutter/flutter/issues/33615
|
||||
);
|
||||
expect(
|
||||
() => tester.state<NavigatorState>(find.byType(Navigator)).restorablePushAndRemoveUntil((BuildContext _, Object __) => null, (Route<Object> _) => false),
|
||||
() => tester.state<NavigatorState>(find.byType(Navigator)).restorablePushAndRemoveUntil((BuildContext _, Object? __) => FakeRoute(), (Route<Object?> _) => false),
|
||||
throwsBuilderAssertionError,
|
||||
skip: isBrowser, // https://github.com/flutter/flutter/issues/33615
|
||||
);
|
||||
expect(
|
||||
() => tester.state<NavigatorState>(find.byType(Navigator)).restorableReplace(newRouteBuilder: (BuildContext _, Object __) => null, oldRoute: oldRoute),
|
||||
() => tester.state<NavigatorState>(find.byType(Navigator)).restorableReplace(newRouteBuilder: (BuildContext _, Object? __) => FakeRoute(), oldRoute: oldRoute),
|
||||
throwsBuilderAssertionError,
|
||||
skip: isBrowser, // https://github.com/flutter/flutter/issues/33615
|
||||
);
|
||||
expect(
|
||||
() => tester.state<NavigatorState>(find.byType(Navigator)).restorableReplaceRouteBelow(newRouteBuilder: (BuildContext _, Object __) => null, anchorRoute: oldRoute),
|
||||
() => tester.state<NavigatorState>(find.byType(Navigator)).restorableReplaceRouteBelow(newRouteBuilder: (BuildContext _, Object? __) => FakeRoute(), anchorRoute: oldRoute),
|
||||
throwsBuilderAssertionError,
|
||||
skip: isBrowser, // https://github.com/flutter/flutter/issues/33615
|
||||
);
|
||||
@ -983,17 +983,17 @@ void main() {
|
||||
});
|
||||
}
|
||||
|
||||
Route<void> _routeBuilder(BuildContext context, Object arguments) {
|
||||
Route<void> _routeBuilder(BuildContext context, Object? arguments) {
|
||||
return MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) {
|
||||
return RouteWidget(
|
||||
name: arguments as String,
|
||||
name: arguments! as String,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Route<void> _routeFutureBuilder(BuildContext context, Object arguments) {
|
||||
Route<void> _routeFutureBuilder(BuildContext context, Object? arguments) {
|
||||
return MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) {
|
||||
return RouteFutureWidget();
|
||||
@ -1026,7 +1026,7 @@ class PagedTestNavigator extends StatefulWidget {
|
||||
class PagedTestNavigatorState extends State<PagedTestNavigator> with RestorationMixin {
|
||||
final RestorableString _routes = RestorableString('r-home');
|
||||
|
||||
void addPage(String name, {bool restoreState = true, int index}) {
|
||||
void addPage(String name, {bool restoreState = true, int? index}) {
|
||||
assert(!name.contains(','));
|
||||
assert(!name.startsWith('r-'));
|
||||
final List<String> routes = _routes.value.split(',');
|
||||
@ -1058,12 +1058,12 @@ class PagedTestNavigatorState extends State<PagedTestNavigator> with Restoration
|
||||
restorationScopeId: 'nav',
|
||||
onPopPage: (Route<dynamic> route, dynamic result) {
|
||||
if (route.didPop(result)) {
|
||||
removePage(route.settings.name);
|
||||
removePage(route.settings.name!);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
pages: _routes.value.isEmpty ? const <Page<Object>>[] : _routes.value.split(',').map((String name) {
|
||||
pages: _routes.value.isEmpty ? const <Page<Object?>>[] : _routes.value.split(',').map((String name) {
|
||||
if (name.startsWith('r-')) {
|
||||
name = name.substring(2);
|
||||
return TestPage(
|
||||
@ -1082,7 +1082,7 @@ class PagedTestNavigatorState extends State<PagedTestNavigator> with Restoration
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return RouteWidget(
|
||||
name: settings.name,
|
||||
name: settings.name!,
|
||||
arguments: settings.arguments,
|
||||
);
|
||||
},
|
||||
@ -1095,7 +1095,7 @@ class PagedTestNavigatorState extends State<PagedTestNavigator> with Restoration
|
||||
String get restorationId => 'router';
|
||||
|
||||
@override
|
||||
void restoreState(RestorationBucket oldBucket, bool initialRestore) {
|
||||
void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
|
||||
registerForRestoration(_routes, 'routes');
|
||||
}
|
||||
|
||||
@ -1107,7 +1107,7 @@ class PagedTestNavigatorState extends State<PagedTestNavigator> with Restoration
|
||||
}
|
||||
|
||||
class TestPage extends Page<void> {
|
||||
const TestPage({LocalKey key, String name, String restorationId}) : super(name: name, key: key, restorationId: restorationId);
|
||||
const TestPage({LocalKey? key, required String name, String? restorationId}) : super(name: name, key: key, restorationId: restorationId);
|
||||
|
||||
@override
|
||||
Route<void> createRoute(BuildContext context) {
|
||||
@ -1115,7 +1115,7 @@ class TestPage extends Page<void> {
|
||||
settings: this,
|
||||
builder: (BuildContext context) {
|
||||
return RouteWidget(
|
||||
name: name,
|
||||
name: name!,
|
||||
);
|
||||
}
|
||||
);
|
||||
@ -1125,7 +1125,7 @@ class TestPage extends Page<void> {
|
||||
class TestWidget extends StatelessWidget {
|
||||
const TestWidget({this.restorationId = 'app'});
|
||||
|
||||
final String restorationId;
|
||||
final String? restorationId;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -1141,7 +1141,7 @@ class TestWidget extends StatelessWidget {
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return RouteWidget(
|
||||
name: settings.name,
|
||||
name: settings.name!,
|
||||
arguments: settings.arguments,
|
||||
);
|
||||
},
|
||||
@ -1154,10 +1154,10 @@ class TestWidget extends StatelessWidget {
|
||||
}
|
||||
|
||||
class RouteWidget extends StatefulWidget {
|
||||
const RouteWidget({Key key, this.name, this.arguments}) : super(key: key);
|
||||
const RouteWidget({Key? key, required this.name, this.arguments}) : super(key: key);
|
||||
|
||||
final String name;
|
||||
final Object arguments;
|
||||
final Object? arguments;
|
||||
|
||||
@override
|
||||
State<RouteWidget> createState() => RouteWidgetState();
|
||||
@ -1167,7 +1167,7 @@ class RouteWidgetState extends State<RouteWidget> with RestorationMixin {
|
||||
final RestorableInt counter = RestorableInt(0);
|
||||
|
||||
@override
|
||||
void restoreState(RestorationBucket oldBucket, bool initialRestore) {
|
||||
void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
|
||||
registerForRestoration(counter, 'counter');
|
||||
}
|
||||
|
||||
@ -1208,15 +1208,15 @@ class RouteFutureWidget extends StatefulWidget {
|
||||
}
|
||||
|
||||
class RouteFutureWidgetState extends State<RouteFutureWidget> with RestorationMixin {
|
||||
RestorableRouteFuture<int> routeFuture;
|
||||
int value;
|
||||
late RestorableRouteFuture<int> routeFuture;
|
||||
int? value;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
routeFuture = RestorableRouteFuture<int>(
|
||||
onPresent: (NavigatorState navigatorState, Object arguments) {
|
||||
return navigatorState.restorablePushNamed(arguments as String);
|
||||
onPresent: (NavigatorState navigatorState, Object? arguments) {
|
||||
return navigatorState.restorablePushNamed(arguments! as String);
|
||||
},
|
||||
onComplete: (int i) {
|
||||
setState(() {
|
||||
@ -1227,7 +1227,7 @@ class RouteFutureWidgetState extends State<RouteFutureWidget> with RestorationMi
|
||||
}
|
||||
|
||||
@override
|
||||
void restoreState(RestorationBucket oldBucket, bool initialRestore) {
|
||||
void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
|
||||
registerForRestoration(routeFuture, 'routeFuture');
|
||||
}
|
||||
|
||||
@ -1248,7 +1248,7 @@ class RouteFutureWidgetState extends State<RouteFutureWidget> with RestorationMi
|
||||
}
|
||||
}
|
||||
|
||||
Finder findRoute(String name, { Object arguments, int count, bool skipOffstage = true }) => _RouteFinder(name, arguments: arguments, count: count, skipOffstage: skipOffstage);
|
||||
Finder findRoute(String name, { Object? arguments, int? count, bool skipOffstage = true }) => _RouteFinder(name, arguments: arguments, count: count, skipOffstage: skipOffstage);
|
||||
|
||||
Future<void> tapRouteCounter(String name, WidgetTester tester) async {
|
||||
await tester.tap(find.text('Route: $name'));
|
||||
@ -1259,8 +1259,8 @@ class _RouteFinder extends MatchFinder {
|
||||
_RouteFinder(this.name, { this.arguments, this.count, bool skipOffstage = true }) : super(skipOffstage: skipOffstage);
|
||||
|
||||
final String name;
|
||||
final Object arguments;
|
||||
final int count;
|
||||
final Object? arguments;
|
||||
final int? count;
|
||||
|
||||
@override
|
||||
String get description {
|
||||
@ -1293,3 +1293,5 @@ class _RouteFinder extends MatchFinder {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class FakeRoute extends Fake implements Route<void> {}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
@ -13,10 +11,10 @@ import 'package:flutter/rendering.dart';
|
||||
import '../rendering/rendering_tester.dart';
|
||||
|
||||
class _CustomPhysics extends ClampingScrollPhysics {
|
||||
const _CustomPhysics({ ScrollPhysics parent }) : super(parent: parent);
|
||||
const _CustomPhysics({ ScrollPhysics? parent }) : super(parent: parent);
|
||||
|
||||
@override
|
||||
_CustomPhysics applyTo(ScrollPhysics ancestor) {
|
||||
_CustomPhysics applyTo(ScrollPhysics? ancestor) {
|
||||
return _CustomPhysics(parent: buildParent(ancestor));
|
||||
}
|
||||
|
||||
@ -27,9 +25,9 @@ class _CustomPhysics extends ClampingScrollPhysics {
|
||||
}
|
||||
|
||||
Widget buildTest({
|
||||
ScrollController controller,
|
||||
ScrollController? controller,
|
||||
String title = 'TTTTTTTT',
|
||||
Key key,
|
||||
Key? key,
|
||||
bool expanded = true,
|
||||
}) {
|
||||
return Localizations(
|
||||
@ -298,7 +296,7 @@ void main() {
|
||||
initialScrollOffset: 50.0,
|
||||
);
|
||||
|
||||
double scrollOffset;
|
||||
late double scrollOffset;
|
||||
controller.addListener(() {
|
||||
scrollOffset = controller.offset;
|
||||
});
|
||||
@ -594,15 +592,15 @@ void main() {
|
||||
)),
|
||||
);
|
||||
|
||||
PhysicalModelLayer _dfsFindPhysicalLayer(ContainerLayer layer) {
|
||||
PhysicalModelLayer? _dfsFindPhysicalLayer(ContainerLayer layer) {
|
||||
expect(layer, isNotNull);
|
||||
Layer child = layer.firstChild;
|
||||
Layer? child = layer.firstChild;
|
||||
while (child != null) {
|
||||
if (child is PhysicalModelLayer) {
|
||||
return child;
|
||||
}
|
||||
if (child is ContainerLayer) {
|
||||
final PhysicalModelLayer candidate = _dfsFindPhysicalLayer(child);
|
||||
final PhysicalModelLayer? candidate = _dfsFindPhysicalLayer(child);
|
||||
if (candidate != null) {
|
||||
return candidate;
|
||||
}
|
||||
@ -612,11 +610,11 @@ void main() {
|
||||
return null;
|
||||
}
|
||||
|
||||
final ContainerLayer nestedScrollViewLayer = find.byType(NestedScrollView).evaluate().first.renderObject.debugLayer;
|
||||
void _checkPhysicalLayer({@required double elevation}) {
|
||||
final PhysicalModelLayer layer = _dfsFindPhysicalLayer(nestedScrollViewLayer);
|
||||
final ContainerLayer nestedScrollViewLayer = find.byType(NestedScrollView).evaluate().first.renderObject!.debugLayer!;
|
||||
void _checkPhysicalLayer({required double elevation}) {
|
||||
final PhysicalModelLayer? layer = _dfsFindPhysicalLayer(nestedScrollViewLayer);
|
||||
expect(layer, isNotNull);
|
||||
expect(layer.elevation, equals(elevation));
|
||||
expect(layer!.elevation, equals(elevation));
|
||||
}
|
||||
|
||||
int expectedBuildCount = 0;
|
||||
@ -861,8 +859,8 @@ void main() {
|
||||
double appBarHeight = tester.renderObject<RenderBox>(find.byType(AppBar)).size.height;
|
||||
expect(appBarHeight, 104.0);
|
||||
final double scrollExtent = appBarHeight - 50.0;
|
||||
expect(globalKey.currentState.outerController.offset, 0.0);
|
||||
expect(globalKey.currentState.innerController.offset, 0.0);
|
||||
expect(globalKey.currentState!.outerController.offset, 0.0);
|
||||
expect(globalKey.currentState!.innerController.offset, 0.0);
|
||||
|
||||
// The scroll gesture should occur in the inner body, so the whole
|
||||
// scroll view is scrolled.
|
||||
@ -878,9 +876,9 @@ void main() {
|
||||
expect(appBarHeight, 104.0);
|
||||
// The outer scroll controller should show an offset of the applied
|
||||
// scrollExtent.
|
||||
expect(globalKey.currentState.outerController.offset, 54.0);
|
||||
expect(globalKey.currentState!.outerController.offset, 54.0);
|
||||
// the inner scroll controller should not have scrolled.
|
||||
expect(globalKey.currentState.innerController.offset, 0.0);
|
||||
expect(globalKey.currentState!.innerController.offset, 0.0);
|
||||
});
|
||||
|
||||
testWidgets('Scrolling by exactly the outer extent does not scroll the inner body', (WidgetTester tester) async {
|
||||
@ -893,8 +891,8 @@ void main() {
|
||||
double appBarHeight = tester.renderObject<RenderBox>(find.byType(AppBar)).size.height;
|
||||
expect(appBarHeight, 104.0);
|
||||
final double scrollExtent = appBarHeight;
|
||||
expect(globalKey.currentState.outerController.offset, 0.0);
|
||||
expect(globalKey.currentState.innerController.offset, 0.0);
|
||||
expect(globalKey.currentState!.outerController.offset, 0.0);
|
||||
expect(globalKey.currentState!.innerController.offset, 0.0);
|
||||
|
||||
// The scroll gesture should occur in the inner body, so the whole
|
||||
// scroll view is scrolled.
|
||||
@ -910,9 +908,9 @@ void main() {
|
||||
expect(appBarHeight, 104.0);
|
||||
// The outer scroll controller should show an offset of the applied
|
||||
// scrollExtent.
|
||||
expect(globalKey.currentState.outerController.offset, 104.0);
|
||||
expect(globalKey.currentState!.outerController.offset, 104.0);
|
||||
// the inner scroll controller should not have scrolled.
|
||||
expect(globalKey.currentState.innerController.offset, 0.0);
|
||||
expect(globalKey.currentState!.innerController.offset, 0.0);
|
||||
});
|
||||
|
||||
testWidgets('Scrolling by greater than the outer extent scrolls the inner body', (WidgetTester tester) async {
|
||||
@ -925,8 +923,8 @@ void main() {
|
||||
double appBarHeight = tester.renderObject<RenderBox>(find.byType(AppBar)).size.height;
|
||||
expect(appBarHeight, 104.0);
|
||||
final double scrollExtent = appBarHeight + 50.0;
|
||||
expect(globalKey.currentState.outerController.offset, 0.0);
|
||||
expect(globalKey.currentState.innerController.offset, 0.0);
|
||||
expect(globalKey.currentState!.outerController.offset, 0.0);
|
||||
expect(globalKey.currentState!.innerController.offset, 0.0);
|
||||
|
||||
// The scroll gesture should occur in the inner body, so the whole
|
||||
// scroll view is scrolled.
|
||||
@ -942,11 +940,11 @@ void main() {
|
||||
expect(appBarHeight, 104.0);
|
||||
// The outer scroll controller should show an offset of the applied
|
||||
// scrollExtent.
|
||||
expect(globalKey.currentState.outerController.offset, appBarHeight);
|
||||
expect(globalKey.currentState!.outerController.offset, appBarHeight);
|
||||
// the inner scroll controller should have scrolled equivalent to the
|
||||
// difference between the applied scrollExtent and the outer extent.
|
||||
expect(
|
||||
globalKey.currentState.innerController.offset,
|
||||
globalKey.currentState!.innerController.offset,
|
||||
scrollExtent - appBarHeight,
|
||||
);
|
||||
});
|
||||
@ -958,8 +956,8 @@ void main() {
|
||||
double appBarHeight = tester.renderObject<RenderBox>(find.byType(AppBar)).size.height;
|
||||
expect(appBarHeight, 200.0);
|
||||
final double scrollExtent = appBarHeight - 50.0;
|
||||
expect(globalKey.currentState.outerController.offset, 0.0);
|
||||
expect(globalKey.currentState.innerController.offset, 0.0);
|
||||
expect(globalKey.currentState!.outerController.offset, 0.0);
|
||||
expect(globalKey.currentState!.innerController.offset, 0.0);
|
||||
|
||||
// The scroll gesture should occur in the inner body, so the whole
|
||||
// scroll view is scrolled.
|
||||
@ -975,9 +973,9 @@ void main() {
|
||||
expect(appBarHeight, 104.0);
|
||||
// The outer scroll controller should show an offset of the applied
|
||||
// scrollExtent.
|
||||
expect(globalKey.currentState.outerController.offset, 150.0);
|
||||
expect(globalKey.currentState!.outerController.offset, 150.0);
|
||||
// the inner scroll controller should not have scrolled.
|
||||
expect(globalKey.currentState.innerController.offset, 0.0);
|
||||
expect(globalKey.currentState!.innerController.offset, 0.0);
|
||||
});
|
||||
|
||||
testWidgets('scrolling by exactly the expanded outer extent does not scroll the inner body', (WidgetTester tester) async {
|
||||
@ -987,8 +985,8 @@ void main() {
|
||||
double appBarHeight = tester.renderObject<RenderBox>(find.byType(AppBar)).size.height;
|
||||
expect(appBarHeight, 200.0);
|
||||
final double scrollExtent = appBarHeight;
|
||||
expect(globalKey.currentState.outerController.offset, 0.0);
|
||||
expect(globalKey.currentState.innerController.offset, 0.0);
|
||||
expect(globalKey.currentState!.outerController.offset, 0.0);
|
||||
expect(globalKey.currentState!.innerController.offset, 0.0);
|
||||
|
||||
// The scroll gesture should occur in the inner body, so the whole
|
||||
// scroll view is scrolled.
|
||||
@ -1004,9 +1002,9 @@ void main() {
|
||||
expect(appBarHeight, 104.0);
|
||||
// The outer scroll controller should show an offset of the applied
|
||||
// scrollExtent.
|
||||
expect(globalKey.currentState.outerController.offset, 200.0);
|
||||
expect(globalKey.currentState!.outerController.offset, 200.0);
|
||||
// the inner scroll controller should not have scrolled.
|
||||
expect(globalKey.currentState.innerController.offset, 0.0);
|
||||
expect(globalKey.currentState!.innerController.offset, 0.0);
|
||||
});
|
||||
|
||||
testWidgets('scrolling by greater than the expanded outer extent scrolls the inner body', (WidgetTester tester) async {
|
||||
@ -1016,8 +1014,8 @@ void main() {
|
||||
double appBarHeight = tester.renderObject<RenderBox>(find.byType(AppBar)).size.height;
|
||||
expect(appBarHeight, 200.0);
|
||||
final double scrollExtent = appBarHeight + 50.0;
|
||||
expect(globalKey.currentState.outerController.offset, 0.0);
|
||||
expect(globalKey.currentState.innerController.offset, 0.0);
|
||||
expect(globalKey.currentState!.outerController.offset, 0.0);
|
||||
expect(globalKey.currentState!.innerController.offset, 0.0);
|
||||
|
||||
// The scroll gesture should occur in the inner body, so the whole
|
||||
// scroll view is scrolled.
|
||||
@ -1033,10 +1031,10 @@ void main() {
|
||||
expect(appBarHeight, 104.0);
|
||||
// The outer scroll controller should show an offset of the applied
|
||||
// scrollExtent.
|
||||
expect(globalKey.currentState.outerController.offset, 200.0);
|
||||
expect(globalKey.currentState!.outerController.offset, 200.0);
|
||||
// the inner scroll controller should have scrolled equivalent to the
|
||||
// difference between the applied scrollExtent and the outer extent.
|
||||
expect(globalKey.currentState.innerController.offset, 50.0);
|
||||
expect(globalKey.currentState!.innerController.offset, 50.0);
|
||||
});
|
||||
|
||||
testWidgets('NestedScrollViewState.outerController should correspond to NestedScrollView.controller', (
|
||||
@ -1059,11 +1057,11 @@ void main() {
|
||||
|
||||
expect(
|
||||
scrollController.offset,
|
||||
globalKey.currentState.outerController.offset,
|
||||
globalKey.currentState!.outerController.offset,
|
||||
);
|
||||
expect(
|
||||
tester.widget<NestedScrollView>(find.byType(NestedScrollView)).controller.offset,
|
||||
globalKey.currentState.outerController.offset,
|
||||
tester.widget<NestedScrollView>(find.byType(NestedScrollView)).controller!.offset,
|
||||
globalKey.currentState!.outerController.offset,
|
||||
);
|
||||
});
|
||||
|
||||
@ -1074,21 +1072,21 @@ void main() {
|
||||
key: globalKey1,
|
||||
expanded: false,
|
||||
));
|
||||
expect(globalKey1.currentState.outerController.position.pixels, 0.0);
|
||||
expect(globalKey1.currentState.innerController.position.pixels, 0.0);
|
||||
expect(globalKey1.currentState!.outerController.position.pixels, 0.0);
|
||||
expect(globalKey1.currentState!.innerController.position.pixels, 0.0);
|
||||
final double appBarHeight = tester.renderObject<RenderBox>(find.byType(AppBar)).size.height;
|
||||
|
||||
// Manipulating Inner
|
||||
globalKey1.currentState.innerController.jumpTo(100.0);
|
||||
expect(globalKey1.currentState.innerController.position.pixels, 100.0);
|
||||
globalKey1.currentState!.innerController.jumpTo(100.0);
|
||||
expect(globalKey1.currentState!.innerController.position.pixels, 100.0);
|
||||
expect(
|
||||
globalKey1.currentState.outerController.position.pixels,
|
||||
globalKey1.currentState!.outerController.position.pixels,
|
||||
appBarHeight,
|
||||
);
|
||||
globalKey1.currentState.innerController.jumpTo(0.0);
|
||||
expect(globalKey1.currentState.innerController.position.pixels, 0.0);
|
||||
globalKey1.currentState!.innerController.jumpTo(0.0);
|
||||
expect(globalKey1.currentState!.innerController.position.pixels, 0.0);
|
||||
expect(
|
||||
globalKey1.currentState.outerController.position.pixels,
|
||||
globalKey1.currentState!.outerController.position.pixels,
|
||||
appBarHeight,
|
||||
);
|
||||
|
||||
@ -1098,16 +1096,16 @@ void main() {
|
||||
key: globalKey2,
|
||||
expanded: false,
|
||||
));
|
||||
expect(globalKey2.currentState.outerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState.innerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState!.outerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState!.innerController.position.pixels, 0.0);
|
||||
|
||||
// Manipulating Outer
|
||||
globalKey2.currentState.outerController.jumpTo(100.0);
|
||||
expect(globalKey2.currentState.innerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState.outerController.position.pixels, 100.0);
|
||||
globalKey2.currentState.outerController.jumpTo(0.0);
|
||||
expect(globalKey2.currentState.innerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState.outerController.position.pixels, 0.0);
|
||||
globalKey2.currentState!.outerController.jumpTo(100.0);
|
||||
expect(globalKey2.currentState!.innerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState!.outerController.position.pixels, 100.0);
|
||||
globalKey2.currentState!.outerController.jumpTo(0.0);
|
||||
expect(globalKey2.currentState!.innerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState!.outerController.position.pixels, 0.0);
|
||||
});
|
||||
|
||||
testWidgets('outer: not scrolled, inner: scrolled', (WidgetTester tester) async {
|
||||
@ -1116,22 +1114,22 @@ void main() {
|
||||
key: globalKey1,
|
||||
expanded: false,
|
||||
));
|
||||
expect(globalKey1.currentState.outerController.position.pixels, 0.0);
|
||||
globalKey1.currentState.innerController.position.setPixels(10.0);
|
||||
expect(globalKey1.currentState.innerController.position.pixels, 10.0);
|
||||
expect(globalKey1.currentState!.outerController.position.pixels, 0.0);
|
||||
globalKey1.currentState!.innerController.position.setPixels(10.0);
|
||||
expect(globalKey1.currentState!.innerController.position.pixels, 10.0);
|
||||
final double appBarHeight = tester.renderObject<RenderBox>(find.byType(AppBar)).size.height;
|
||||
|
||||
// Manipulating Inner
|
||||
globalKey1.currentState.innerController.jumpTo(100.0);
|
||||
expect(globalKey1.currentState.innerController.position.pixels, 100.0);
|
||||
globalKey1.currentState!.innerController.jumpTo(100.0);
|
||||
expect(globalKey1.currentState!.innerController.position.pixels, 100.0);
|
||||
expect(
|
||||
globalKey1.currentState.outerController.position.pixels,
|
||||
globalKey1.currentState!.outerController.position.pixels,
|
||||
appBarHeight,
|
||||
);
|
||||
globalKey1.currentState.innerController.jumpTo(0.0);
|
||||
expect(globalKey1.currentState.innerController.position.pixels, 0.0);
|
||||
globalKey1.currentState!.innerController.jumpTo(0.0);
|
||||
expect(globalKey1.currentState!.innerController.position.pixels, 0.0);
|
||||
expect(
|
||||
globalKey1.currentState.outerController.position.pixels,
|
||||
globalKey1.currentState!.outerController.position.pixels,
|
||||
appBarHeight,
|
||||
);
|
||||
|
||||
@ -1141,17 +1139,17 @@ void main() {
|
||||
key: globalKey2,
|
||||
expanded: false,
|
||||
));
|
||||
expect(globalKey2.currentState.outerController.position.pixels, 0.0);
|
||||
globalKey2.currentState.innerController.position.setPixels(10.0);
|
||||
expect(globalKey2.currentState.innerController.position.pixels, 10.0);
|
||||
expect(globalKey2.currentState!.outerController.position.pixels, 0.0);
|
||||
globalKey2.currentState!.innerController.position.setPixels(10.0);
|
||||
expect(globalKey2.currentState!.innerController.position.pixels, 10.0);
|
||||
|
||||
// Manipulating Outer
|
||||
globalKey2.currentState.outerController.jumpTo(100.0);
|
||||
expect(globalKey2.currentState.innerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState.outerController.position.pixels, 100.0);
|
||||
globalKey2.currentState.outerController.jumpTo(0.0);
|
||||
expect(globalKey2.currentState.innerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState.outerController.position.pixels, 0.0);
|
||||
globalKey2.currentState!.outerController.jumpTo(100.0);
|
||||
expect(globalKey2.currentState!.innerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState!.outerController.position.pixels, 100.0);
|
||||
globalKey2.currentState!.outerController.jumpTo(0.0);
|
||||
expect(globalKey2.currentState!.innerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState!.outerController.position.pixels, 0.0);
|
||||
});
|
||||
|
||||
testWidgets('outer: scrolled, inner: not scrolled', (WidgetTester tester) async {
|
||||
@ -1160,22 +1158,22 @@ void main() {
|
||||
key: globalKey1,
|
||||
expanded: false,
|
||||
));
|
||||
expect(globalKey1.currentState.innerController.position.pixels, 0.0);
|
||||
globalKey1.currentState.outerController.position.setPixels(10.0);
|
||||
expect(globalKey1.currentState.outerController.position.pixels, 10.0);
|
||||
expect(globalKey1.currentState!.innerController.position.pixels, 0.0);
|
||||
globalKey1.currentState!.outerController.position.setPixels(10.0);
|
||||
expect(globalKey1.currentState!.outerController.position.pixels, 10.0);
|
||||
final double appBarHeight = tester.renderObject<RenderBox>(find.byType(AppBar)).size.height;
|
||||
|
||||
// Manipulating Inner
|
||||
globalKey1.currentState.innerController.jumpTo(100.0);
|
||||
expect(globalKey1.currentState.innerController.position.pixels, 100.0);
|
||||
globalKey1.currentState!.innerController.jumpTo(100.0);
|
||||
expect(globalKey1.currentState!.innerController.position.pixels, 100.0);
|
||||
expect(
|
||||
globalKey1.currentState.outerController.position.pixels,
|
||||
globalKey1.currentState!.outerController.position.pixels,
|
||||
appBarHeight,
|
||||
);
|
||||
globalKey1.currentState.innerController.jumpTo(0.0);
|
||||
expect(globalKey1.currentState.innerController.position.pixels, 0.0);
|
||||
globalKey1.currentState!.innerController.jumpTo(0.0);
|
||||
expect(globalKey1.currentState!.innerController.position.pixels, 0.0);
|
||||
expect(
|
||||
globalKey1.currentState.outerController.position.pixels,
|
||||
globalKey1.currentState!.outerController.position.pixels,
|
||||
appBarHeight,
|
||||
);
|
||||
|
||||
@ -1185,17 +1183,17 @@ void main() {
|
||||
key: globalKey2,
|
||||
expanded: false,
|
||||
));
|
||||
expect(globalKey2.currentState.innerController.position.pixels, 0.0);
|
||||
globalKey2.currentState.outerController.position.setPixels(10.0);
|
||||
expect(globalKey2.currentState.outerController.position.pixels, 10.0);
|
||||
expect(globalKey2.currentState!.innerController.position.pixels, 0.0);
|
||||
globalKey2.currentState!.outerController.position.setPixels(10.0);
|
||||
expect(globalKey2.currentState!.outerController.position.pixels, 10.0);
|
||||
|
||||
// Manipulating Outer
|
||||
globalKey2.currentState.outerController.jumpTo(100.0);
|
||||
expect(globalKey2.currentState.innerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState.outerController.position.pixels, 100.0);
|
||||
globalKey2.currentState.outerController.jumpTo(0.0);
|
||||
expect(globalKey2.currentState.innerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState.outerController.position.pixels, 0.0);
|
||||
globalKey2.currentState!.outerController.jumpTo(100.0);
|
||||
expect(globalKey2.currentState!.innerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState!.outerController.position.pixels, 100.0);
|
||||
globalKey2.currentState!.outerController.jumpTo(0.0);
|
||||
expect(globalKey2.currentState!.innerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState!.outerController.position.pixels, 0.0);
|
||||
});
|
||||
|
||||
testWidgets('outer: scrolled, inner: scrolled', (WidgetTester tester) async {
|
||||
@ -1204,23 +1202,23 @@ void main() {
|
||||
key: globalKey1,
|
||||
expanded: false,
|
||||
));
|
||||
globalKey1.currentState.innerController.position.setPixels(10.0);
|
||||
expect(globalKey1.currentState.innerController.position.pixels, 10.0);
|
||||
globalKey1.currentState.outerController.position.setPixels(10.0);
|
||||
expect(globalKey1.currentState.outerController.position.pixels, 10.0);
|
||||
globalKey1.currentState!.innerController.position.setPixels(10.0);
|
||||
expect(globalKey1.currentState!.innerController.position.pixels, 10.0);
|
||||
globalKey1.currentState!.outerController.position.setPixels(10.0);
|
||||
expect(globalKey1.currentState!.outerController.position.pixels, 10.0);
|
||||
final double appBarHeight = tester.renderObject<RenderBox>(find.byType(AppBar)).size.height;
|
||||
|
||||
// Manipulating Inner
|
||||
globalKey1.currentState.innerController.jumpTo(100.0);
|
||||
expect(globalKey1.currentState.innerController.position.pixels, 100.0);
|
||||
globalKey1.currentState!.innerController.jumpTo(100.0);
|
||||
expect(globalKey1.currentState!.innerController.position.pixels, 100.0);
|
||||
expect(
|
||||
globalKey1.currentState.outerController.position.pixels,
|
||||
globalKey1.currentState!.outerController.position.pixels,
|
||||
appBarHeight,
|
||||
);
|
||||
globalKey1.currentState.innerController.jumpTo(0.0);
|
||||
expect(globalKey1.currentState.innerController.position.pixels, 0.0);
|
||||
globalKey1.currentState!.innerController.jumpTo(0.0);
|
||||
expect(globalKey1.currentState!.innerController.position.pixels, 0.0);
|
||||
expect(
|
||||
globalKey1.currentState.outerController.position.pixels,
|
||||
globalKey1.currentState!.outerController.position.pixels,
|
||||
appBarHeight,
|
||||
);
|
||||
|
||||
@ -1230,18 +1228,18 @@ void main() {
|
||||
key: globalKey2,
|
||||
expanded: false,
|
||||
));
|
||||
globalKey2.currentState.innerController.position.setPixels(10.0);
|
||||
expect(globalKey2.currentState.innerController.position.pixels, 10.0);
|
||||
globalKey2.currentState.outerController.position.setPixels(10.0);
|
||||
expect(globalKey2.currentState.outerController.position.pixels, 10.0);
|
||||
globalKey2.currentState!.innerController.position.setPixels(10.0);
|
||||
expect(globalKey2.currentState!.innerController.position.pixels, 10.0);
|
||||
globalKey2.currentState!.outerController.position.setPixels(10.0);
|
||||
expect(globalKey2.currentState!.outerController.position.pixels, 10.0);
|
||||
|
||||
// Manipulating Outer
|
||||
globalKey2.currentState.outerController.jumpTo(100.0);
|
||||
expect(globalKey2.currentState.innerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState.outerController.position.pixels, 100.0);
|
||||
globalKey2.currentState.outerController.jumpTo(0.0);
|
||||
expect(globalKey2.currentState.innerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState.outerController.position.pixels, 0.0);
|
||||
globalKey2.currentState!.outerController.jumpTo(100.0);
|
||||
expect(globalKey2.currentState!.innerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState!.outerController.position.pixels, 100.0);
|
||||
globalKey2.currentState!.outerController.jumpTo(0.0);
|
||||
expect(globalKey2.currentState!.innerController.position.pixels, 0.0);
|
||||
expect(globalKey2.currentState!.outerController.position.pixels, 0.0);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1254,9 +1252,9 @@ void main() {
|
||||
|
||||
group('NestedScrollView can float outer sliver with inner scroll view:', () {
|
||||
Widget buildFloatTest({
|
||||
GlobalKey appBarKey,
|
||||
GlobalKey nestedKey,
|
||||
ScrollController controller,
|
||||
GlobalKey? appBarKey,
|
||||
GlobalKey? nestedKey,
|
||||
ScrollController? controller,
|
||||
bool floating = false,
|
||||
bool pinned = false,
|
||||
bool snap = false,
|
||||
@ -1306,14 +1304,14 @@ void main() {
|
||||
}
|
||||
|
||||
double verifyGeometry({
|
||||
GlobalKey key,
|
||||
double paintExtent,
|
||||
required GlobalKey key,
|
||||
required double paintExtent,
|
||||
bool extentGreaterThan = false,
|
||||
bool extentLessThan = false,
|
||||
bool visible,
|
||||
required bool visible,
|
||||
}) {
|
||||
final RenderSliver target = key.currentContext.findRenderObject() as RenderSliver;
|
||||
final SliverGeometry geometry = target.geometry;
|
||||
final RenderSliver target = key.currentContext!.findRenderObject()! as RenderSliver;
|
||||
final SliverGeometry geometry = target.geometry!;
|
||||
expect(target.parent, isA<RenderSliverOverlapAbsorber>());
|
||||
expect(geometry.visible, visible);
|
||||
if (extentGreaterThan)
|
||||
@ -1461,7 +1459,7 @@ void main() {
|
||||
verifyGeometry(key: appBarKey, paintExtent: 0.0, visible: false);
|
||||
// The outer scroll view should be at its full extent, here the size of
|
||||
// the app bar.
|
||||
expect(nestedKey.currentState.outerController.offset, 56.0);
|
||||
expect(nestedKey.currentState!.outerController.offset, 56.0);
|
||||
|
||||
// Animate In
|
||||
|
||||
@ -1474,7 +1472,7 @@ void main() {
|
||||
expect(find.text('Item 1'), findsNothing);
|
||||
expect(find.text('Item 5'), findsOneWidget);
|
||||
verifyGeometry(key: appBarKey, paintExtent: 0.0, visible: false);
|
||||
expect(nestedKey.currentState.outerController.offset, 56.0);
|
||||
expect(nestedKey.currentState!.outerController.offset, 56.0);
|
||||
|
||||
await animateInGesture.moveBy(const Offset(0.0, -50.0)); // No float out
|
||||
await tester.pump();
|
||||
@ -1482,7 +1480,7 @@ void main() {
|
||||
expect(find.text('Item 1'), findsNothing);
|
||||
expect(find.text('Item 5'), findsOneWidget);
|
||||
verifyGeometry(key: appBarKey, paintExtent: 0.0, visible: false);
|
||||
expect(nestedKey.currentState.outerController.offset, 56.0);
|
||||
expect(nestedKey.currentState!.outerController.offset, 56.0);
|
||||
|
||||
// Trigger the snap open animation: drag down and release
|
||||
await animateInGesture.moveBy(const Offset(0.0, 10.0));
|
||||
@ -1501,7 +1499,7 @@ void main() {
|
||||
visible: true,
|
||||
);
|
||||
// The outer scroll offset should remain unchanged.
|
||||
expect(nestedKey.currentState.outerController.offset, 56.0);
|
||||
expect(nestedKey.currentState!.outerController.offset, 56.0);
|
||||
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
@ -1514,7 +1512,7 @@ void main() {
|
||||
extentGreaterThan: true,
|
||||
visible: true,
|
||||
);
|
||||
expect(nestedKey.currentState.outerController.offset, 56.0);
|
||||
expect(nestedKey.currentState!.outerController.offset, 56.0);
|
||||
|
||||
// The animation finishes when the appbar is full height.
|
||||
await tester.pumpAndSettle();
|
||||
@ -1522,7 +1520,7 @@ void main() {
|
||||
expect(find.text('Item 1'), findsNothing);
|
||||
expect(find.text('Item 5'), findsOneWidget);
|
||||
verifyGeometry(key: appBarKey, paintExtent: 56.0, visible: true);
|
||||
expect(nestedKey.currentState.outerController.offset, 56.0);
|
||||
expect(nestedKey.currentState!.outerController.offset, 56.0);
|
||||
|
||||
// Animate Out
|
||||
|
||||
@ -1543,7 +1541,7 @@ void main() {
|
||||
extentLessThan: true,
|
||||
visible: true,
|
||||
);
|
||||
expect(nestedKey.currentState.outerController.offset, 56.0);
|
||||
expect(nestedKey.currentState!.outerController.offset, 56.0);
|
||||
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
@ -1556,7 +1554,7 @@ void main() {
|
||||
extentLessThan: true,
|
||||
visible: true,
|
||||
);
|
||||
expect(nestedKey.currentState.outerController.offset, 56.0);
|
||||
expect(nestedKey.currentState!.outerController.offset, 56.0);
|
||||
|
||||
// The animation finishes when the appbar is no longer in view.
|
||||
await tester.pumpAndSettle();
|
||||
@ -1564,7 +1562,7 @@ void main() {
|
||||
expect(find.text('Item 1'), findsNothing);
|
||||
expect(find.text('Item 5'), findsOneWidget);
|
||||
verifyGeometry(key: appBarKey, paintExtent: 0.0, visible: false);
|
||||
expect(nestedKey.currentState.outerController.offset, 56.0);
|
||||
expect(nestedKey.currentState!.outerController.offset, 56.0);
|
||||
});
|
||||
|
||||
testWidgets('only snap expanded', (WidgetTester tester) async {
|
||||
@ -1597,7 +1595,7 @@ void main() {
|
||||
verifyGeometry(key: appBarKey, paintExtent: 0.0, visible: false);
|
||||
// The outer scroll view should be at its full extent, here the size of
|
||||
// the app bar.
|
||||
expect(nestedKey.currentState.outerController.offset, 200.0);
|
||||
expect(nestedKey.currentState!.outerController.offset, 200.0);
|
||||
|
||||
// Animate In
|
||||
|
||||
@ -1610,7 +1608,7 @@ void main() {
|
||||
expect(find.text('Item 1'), findsNothing);
|
||||
expect(find.text('Item 5'), findsOneWidget);
|
||||
verifyGeometry(key: appBarKey, paintExtent: 0.0, visible: false);
|
||||
expect(nestedKey.currentState.outerController.offset, 200.0);
|
||||
expect(nestedKey.currentState!.outerController.offset, 200.0);
|
||||
|
||||
await animateInGesture.moveBy(const Offset(0.0, -50.0)); // No float out
|
||||
await tester.pump();
|
||||
@ -1618,7 +1616,7 @@ void main() {
|
||||
expect(find.text('Item 1'), findsNothing);
|
||||
expect(find.text('Item 5'), findsOneWidget);
|
||||
verifyGeometry(key: appBarKey, paintExtent: 0.0, visible: false);
|
||||
expect(nestedKey.currentState.outerController.offset, 200.0);
|
||||
expect(nestedKey.currentState!.outerController.offset, 200.0);
|
||||
|
||||
// Trigger the snap open animation: drag down and release
|
||||
await animateInGesture.moveBy(const Offset(0.0, 10.0));
|
||||
@ -1637,7 +1635,7 @@ void main() {
|
||||
visible: true,
|
||||
);
|
||||
// The outer scroll offset should remain unchanged.
|
||||
expect(nestedKey.currentState.outerController.offset, 200.0);
|
||||
expect(nestedKey.currentState!.outerController.offset, 200.0);
|
||||
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
@ -1650,7 +1648,7 @@ void main() {
|
||||
extentGreaterThan: true,
|
||||
visible: true,
|
||||
);
|
||||
expect(nestedKey.currentState.outerController.offset, 200.0);
|
||||
expect(nestedKey.currentState!.outerController.offset, 200.0);
|
||||
|
||||
// The animation finishes when the appbar is full height.
|
||||
await tester.pumpAndSettle();
|
||||
@ -1658,7 +1656,7 @@ void main() {
|
||||
expect(find.text('Item 1'), findsNothing);
|
||||
expect(find.text('Item 5'), findsOneWidget);
|
||||
verifyGeometry(key: appBarKey, paintExtent: 200.0, visible: true);
|
||||
expect(nestedKey.currentState.outerController.offset, 200.0);
|
||||
expect(nestedKey.currentState!.outerController.offset, 200.0);
|
||||
|
||||
// Animate Out
|
||||
|
||||
@ -1679,7 +1677,7 @@ void main() {
|
||||
extentLessThan: true,
|
||||
visible: true,
|
||||
);
|
||||
expect(nestedKey.currentState.outerController.offset, 200.0);
|
||||
expect(nestedKey.currentState!.outerController.offset, 200.0);
|
||||
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
@ -1692,7 +1690,7 @@ void main() {
|
||||
extentLessThan: true,
|
||||
visible: true,
|
||||
);
|
||||
expect(nestedKey.currentState.outerController.offset, 200.0);
|
||||
expect(nestedKey.currentState!.outerController.offset, 200.0);
|
||||
|
||||
// The animation finishes when the appbar is no longer in view.
|
||||
await tester.pumpAndSettle();
|
||||
@ -1700,7 +1698,7 @@ void main() {
|
||||
expect(find.text('Item 1'), findsNothing);
|
||||
expect(find.text('Item 5'), findsOneWidget);
|
||||
verifyGeometry(key: appBarKey, paintExtent: 0.0, visible: false);
|
||||
expect(nestedKey.currentState.outerController.offset, 200.0);
|
||||
expect(nestedKey.currentState!.outerController.offset, 200.0);
|
||||
});
|
||||
|
||||
testWidgets('float pinned', (WidgetTester tester) async {
|
||||
@ -1912,7 +1910,7 @@ void main() {
|
||||
|
||||
class TestHeader extends SliverPersistentHeaderDelegate {
|
||||
const TestHeader({ this.key });
|
||||
final Key key;
|
||||
final Key? key;
|
||||
@override
|
||||
double get minExtent => 100.0;
|
||||
@override
|
||||
|
||||
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
|
||||
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ui' as ui show Image;
|
||||
|
||||
@ -30,21 +28,20 @@ Future<void> main() async {
|
||||
),
|
||||
);
|
||||
final RenderImage renderImage = tester.renderObject(find.byType(Image));
|
||||
final ui.Image image1 = renderImage.image;
|
||||
final ui.Image? image1 = renderImage.image;
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
final ui.Image image2 = renderImage.image;
|
||||
final ui.Image? image2 = renderImage.image;
|
||||
expect(image1, isNot(same(image2)));
|
||||
|
||||
|
||||
Navigator.pushNamed(imageKey.currentContext, '/page');
|
||||
Navigator.pushNamed(imageKey.currentContext!, '/page');
|
||||
await tester.pump(); // Starts the page animation.
|
||||
await tester.pump(const Duration(seconds: 1)); // Let the page animation complete.
|
||||
|
||||
// The image is now obscured by another page, it should not be changing
|
||||
// frames.
|
||||
final ui.Image image3 = renderImage.image;
|
||||
final ui.Image? image3 = renderImage.image;
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
final ui.Image image4 = renderImage.image;
|
||||
final ui.Image? image4 = renderImage.image;
|
||||
expect(image3, same(image4));
|
||||
});
|
||||
}
|
||||
|
||||
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -191,7 +189,7 @@ void main() {
|
||||
final Element element = find.byType(RepaintBoundary).first.evaluate().single;
|
||||
// The following line will send the layer to engine and cause crash if an
|
||||
// empty opacity layer is sent.
|
||||
final OffsetLayer offsetLayer = element.renderObject.debugLayer as OffsetLayer;
|
||||
final OffsetLayer offsetLayer = element.renderObject!.debugLayer! as OffsetLayer;
|
||||
await offsetLayer.toImage(const Rect.fromLTRB(0.0, 0.0, 1.0, 1.0));
|
||||
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/42767
|
||||
}
|
||||
|
||||
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
@ -52,7 +50,7 @@ void main() {
|
||||
final Key child2Key = UniqueKey();
|
||||
final Key child3Key = UniqueKey();
|
||||
|
||||
Widget buildFrame({ double spacing, TextDirection textDirection }) {
|
||||
Widget buildFrame({ required double spacing, required TextDirection textDirection }) {
|
||||
return Directionality(
|
||||
textDirection: textDirection,
|
||||
child: Align(
|
||||
@ -176,7 +174,7 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('OverflowBar intrinsic width', (WidgetTester tester) async {
|
||||
Widget buildFrame({ double width }) {
|
||||
Widget buildFrame({ required double width }) {
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Center(
|
||||
@ -207,7 +205,7 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('OverflowBar intrinsic height', (WidgetTester tester) async {
|
||||
Widget buildFrame({ double maxWidth }) {
|
||||
Widget buildFrame({ required double maxWidth }) {
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Center(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user