1208 lines
42 KiB
Dart
1208 lines
42 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/rendering.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
void main() {
|
|
group('LookupBoundary.dependOnInheritedWidgetOfExactType', () {
|
|
testWidgets('respects boundary', (WidgetTester tester) async {
|
|
InheritedWidget? containerThroughBoundary;
|
|
InheritedWidget? containerStoppedAtBoundary;
|
|
|
|
final Key inheritedKey = UniqueKey();
|
|
|
|
await tester.pumpWidget(MyInheritedWidget(
|
|
value: 2,
|
|
key: inheritedKey,
|
|
child: LookupBoundary(
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
containerThroughBoundary = context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
|
|
containerStoppedAtBoundary = LookupBoundary.dependOnInheritedWidgetOfExactType<MyInheritedWidget>(context);
|
|
return const SizedBox.expand();
|
|
},
|
|
),
|
|
),
|
|
));
|
|
|
|
expect(containerThroughBoundary, equals(tester.widget(find.byKey(inheritedKey))));
|
|
expect(containerStoppedAtBoundary, isNull);
|
|
});
|
|
|
|
testWidgets('ignores ancestor boundary', (WidgetTester tester) async {
|
|
InheritedWidget? inheritedWidget;
|
|
|
|
final Key inheritedKey = UniqueKey();
|
|
|
|
await tester.pumpWidget(LookupBoundary(
|
|
child: MyInheritedWidget(
|
|
value: 2,
|
|
key: inheritedKey,
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
inheritedWidget = LookupBoundary.dependOnInheritedWidgetOfExactType<MyInheritedWidget>(context);
|
|
return const SizedBox.expand();
|
|
},
|
|
),
|
|
),
|
|
));
|
|
|
|
expect(inheritedWidget, equals(tester.widget(find.byKey(inheritedKey))));
|
|
});
|
|
|
|
testWidgets('finds widget before boundary', (WidgetTester tester) async {
|
|
InheritedWidget? containerThroughBoundary;
|
|
InheritedWidget? containerStoppedAtBoundary;
|
|
|
|
final Key inheritedKey = UniqueKey();
|
|
|
|
await tester.pumpWidget(MyInheritedWidget(
|
|
value: 2,
|
|
child: LookupBoundary(
|
|
child: MyInheritedWidget(
|
|
key: inheritedKey,
|
|
value: 1,
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
containerThroughBoundary = context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
|
|
containerStoppedAtBoundary = LookupBoundary.dependOnInheritedWidgetOfExactType<MyInheritedWidget>(context);
|
|
return const SizedBox.expand();
|
|
},
|
|
),
|
|
),
|
|
),
|
|
));
|
|
|
|
expect(containerThroughBoundary, equals(tester.widget(find.byKey(inheritedKey))));
|
|
expect(containerStoppedAtBoundary, equals(tester.widget(find.byKey(inheritedKey))));
|
|
});
|
|
|
|
testWidgets('creates dependency', (WidgetTester tester) async {
|
|
MyInheritedWidget? inheritedWidget;
|
|
|
|
final Widget widgetTree = DidChangeDependencySpy(
|
|
onDidChangeDependencies: (BuildContext context) {
|
|
inheritedWidget = LookupBoundary.dependOnInheritedWidgetOfExactType<MyInheritedWidget>(context);
|
|
},
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
MyInheritedWidget(
|
|
value: 1,
|
|
child: widgetTree,
|
|
),
|
|
);
|
|
expect(inheritedWidget!.value, 1);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
|
|
await tester.pumpWidget(
|
|
MyInheritedWidget(
|
|
value: 2,
|
|
child: widgetTree,
|
|
),
|
|
);
|
|
expect(inheritedWidget!.value, 2);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 2);
|
|
});
|
|
|
|
testWidgets('causes didChangeDependencies to be called on move even if dependency was not fulfilled due to boundary', (WidgetTester tester) async {
|
|
MyInheritedWidget? inheritedWidget;
|
|
final Key globalKey = GlobalKey();
|
|
|
|
final Widget widgetTree = DidChangeDependencySpy(
|
|
key: globalKey,
|
|
onDidChangeDependencies: (BuildContext context) {
|
|
inheritedWidget = LookupBoundary.dependOnInheritedWidgetOfExactType<MyInheritedWidget>(context);
|
|
},
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
MyInheritedWidget(
|
|
value: 1,
|
|
child: LookupBoundary(
|
|
child: widgetTree,
|
|
),
|
|
),
|
|
);
|
|
expect(inheritedWidget, isNull);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
|
|
// Value of inherited widget changes, but there should be no dependency due to boundary.
|
|
await tester.pumpWidget(
|
|
MyInheritedWidget(
|
|
value: 2,
|
|
child: LookupBoundary(
|
|
child: widgetTree,
|
|
),
|
|
),
|
|
);
|
|
expect(inheritedWidget, isNull);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
|
|
// Widget is moved, didChangeDependencies is called, but dependency is still not found due to boundary.
|
|
await tester.pumpWidget(
|
|
SizedBox(
|
|
child: MyInheritedWidget(
|
|
value: 2,
|
|
child: LookupBoundary(
|
|
child: widgetTree,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
expect(inheritedWidget, isNull);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 2);
|
|
|
|
await tester.pumpWidget(
|
|
SizedBox(
|
|
child: MyInheritedWidget(
|
|
value: 2,
|
|
child: LookupBoundary(
|
|
child: MyInheritedWidget(
|
|
value: 4,
|
|
child: widgetTree,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
expect(inheritedWidget!.value, 4);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 3);
|
|
});
|
|
|
|
testWidgets('causes didChangeDependencies to be called on move even if dependency was non-existant', (WidgetTester tester) async {
|
|
MyInheritedWidget? inheritedWidget;
|
|
final Key globalKey = GlobalKey();
|
|
|
|
final Widget widgetTree = DidChangeDependencySpy(
|
|
key: globalKey,
|
|
onDidChangeDependencies: (BuildContext context) {
|
|
inheritedWidget = LookupBoundary.dependOnInheritedWidgetOfExactType<MyInheritedWidget>(context);
|
|
},
|
|
);
|
|
|
|
await tester.pumpWidget(widgetTree);
|
|
expect(inheritedWidget, isNull);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
|
|
// Widget moved, didChangeDependencies must be called.
|
|
await tester.pumpWidget(
|
|
SizedBox(
|
|
child: widgetTree,
|
|
),
|
|
);
|
|
expect(inheritedWidget, isNull);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 2);
|
|
|
|
// Widget moved, didChangeDependencies must be called.
|
|
await tester.pumpWidget(
|
|
MyInheritedWidget(
|
|
value: 6,
|
|
child: SizedBox(
|
|
child: widgetTree,
|
|
),
|
|
),
|
|
);
|
|
expect(inheritedWidget!.value, 6);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 3);
|
|
});
|
|
});
|
|
|
|
group('LookupBoundary.getElementForInheritedWidgetOfExactType', () {
|
|
testWidgets('respects boundary', (WidgetTester tester) async {
|
|
InheritedElement? containerThroughBoundary;
|
|
InheritedElement? containerStoppedAtBoundary;
|
|
|
|
final Key inheritedKey = UniqueKey();
|
|
|
|
await tester.pumpWidget(MyInheritedWidget(
|
|
value: 2,
|
|
key: inheritedKey,
|
|
child: LookupBoundary(
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
containerThroughBoundary = context.getElementForInheritedWidgetOfExactType<MyInheritedWidget>();
|
|
containerStoppedAtBoundary = LookupBoundary.getElementForInheritedWidgetOfExactType<MyInheritedWidget>(context);
|
|
return const SizedBox.expand();
|
|
},
|
|
),
|
|
),
|
|
));
|
|
|
|
expect(containerThroughBoundary, equals(tester.element(find.byKey(inheritedKey))));
|
|
expect(containerStoppedAtBoundary, isNull);
|
|
});
|
|
|
|
testWidgets('ignores ancestor boundary', (WidgetTester tester) async {
|
|
InheritedElement? inheritedWidget;
|
|
|
|
final Key inheritedKey = UniqueKey();
|
|
|
|
await tester.pumpWidget(LookupBoundary(
|
|
child: MyInheritedWidget(
|
|
value: 2,
|
|
key: inheritedKey,
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
inheritedWidget = LookupBoundary.getElementForInheritedWidgetOfExactType<MyInheritedWidget>(context);
|
|
return const SizedBox.expand();
|
|
},
|
|
),
|
|
),
|
|
));
|
|
|
|
expect(inheritedWidget, equals(tester.element(find.byKey(inheritedKey))));
|
|
});
|
|
|
|
testWidgets('finds widget before boundary', (WidgetTester tester) async {
|
|
InheritedElement? containerThroughBoundary;
|
|
InheritedElement? containerStoppedAtBoundary;
|
|
|
|
final Key inheritedKey = UniqueKey();
|
|
|
|
await tester.pumpWidget(MyInheritedWidget(
|
|
value: 2,
|
|
child: LookupBoundary(
|
|
child: MyInheritedWidget(
|
|
key: inheritedKey,
|
|
value: 1,
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
containerThroughBoundary = context.getElementForInheritedWidgetOfExactType<MyInheritedWidget>();
|
|
containerStoppedAtBoundary = LookupBoundary.getElementForInheritedWidgetOfExactType<MyInheritedWidget>(context);
|
|
return const SizedBox.expand();
|
|
},
|
|
),
|
|
),
|
|
),
|
|
));
|
|
|
|
expect(containerThroughBoundary, equals(tester.element(find.byKey(inheritedKey))));
|
|
expect(containerStoppedAtBoundary, equals(tester.element(find.byKey(inheritedKey))));
|
|
});
|
|
|
|
testWidgets('does not creates dependency', (WidgetTester tester) async {
|
|
|
|
final Widget widgetTree = DidChangeDependencySpy(
|
|
onDidChangeDependencies: (BuildContext context) {
|
|
LookupBoundary.getElementForInheritedWidgetOfExactType<MyInheritedWidget>(context);
|
|
},
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
MyInheritedWidget(
|
|
value: 1,
|
|
child: widgetTree,
|
|
),
|
|
);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
|
|
await tester.pumpWidget(
|
|
MyInheritedWidget(
|
|
value: 2,
|
|
child: widgetTree,
|
|
),
|
|
);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
});
|
|
|
|
testWidgets('does not cause didChangeDependencies to be called on move when found', (WidgetTester tester) async {
|
|
final Key globalKey = GlobalKey();
|
|
|
|
final Widget widgetTree = DidChangeDependencySpy(
|
|
key: globalKey,
|
|
onDidChangeDependencies: (BuildContext context) {
|
|
LookupBoundary.getElementForInheritedWidgetOfExactType<MyInheritedWidget>(context);
|
|
},
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
MyInheritedWidget(
|
|
value: 1,
|
|
child: LookupBoundary(
|
|
child: widgetTree,
|
|
),
|
|
),
|
|
);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
|
|
// Value of inherited widget changes, but there should be no dependency due to boundary.
|
|
await tester.pumpWidget(
|
|
MyInheritedWidget(
|
|
value: 2,
|
|
child: LookupBoundary(
|
|
child: widgetTree,
|
|
),
|
|
),
|
|
);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
|
|
// Widget is moved, didChangeDependencies is called, but dependency is still not found due to boundary.
|
|
await tester.pumpWidget(
|
|
SizedBox(
|
|
child: MyInheritedWidget(
|
|
value: 2,
|
|
child: LookupBoundary(
|
|
child: widgetTree,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
|
|
await tester.pumpWidget(
|
|
SizedBox(
|
|
child: MyInheritedWidget(
|
|
value: 2,
|
|
child: LookupBoundary(
|
|
child: MyInheritedWidget(
|
|
value: 4,
|
|
child: widgetTree,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
});
|
|
|
|
testWidgets('does not cause didChangeDependencies to be called on move when nothing was found', (WidgetTester tester) async {
|
|
final Key globalKey = GlobalKey();
|
|
|
|
final Widget widgetTree = DidChangeDependencySpy(
|
|
key: globalKey,
|
|
onDidChangeDependencies: (BuildContext context) {
|
|
LookupBoundary.getElementForInheritedWidgetOfExactType<MyInheritedWidget>(context);
|
|
},
|
|
);
|
|
|
|
await tester.pumpWidget(widgetTree);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
|
|
// Widget moved, didChangeDependencies must be called.
|
|
await tester.pumpWidget(
|
|
SizedBox(
|
|
child: widgetTree,
|
|
),
|
|
);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
|
|
// Widget moved, didChangeDependencies must be called.
|
|
await tester.pumpWidget(
|
|
MyInheritedWidget(
|
|
value: 6,
|
|
child: SizedBox(
|
|
child: widgetTree,
|
|
),
|
|
),
|
|
);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
});
|
|
});
|
|
|
|
group('LookupBoundary.findAncestorWidgetOfExactType', () {
|
|
testWidgets('respects boundary', (WidgetTester tester) async {
|
|
Widget? containerThroughBoundary;
|
|
Widget? containerStoppedAtBoundary;
|
|
Widget? boundaryThroughBoundary;
|
|
Widget? boundaryStoppedAtBoundary;
|
|
|
|
final Key containerKey = UniqueKey();
|
|
final Key boundaryKey = UniqueKey();
|
|
|
|
await tester.pumpWidget(Container(
|
|
key: containerKey,
|
|
child: LookupBoundary(
|
|
key: boundaryKey,
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
containerThroughBoundary = context.findAncestorWidgetOfExactType<Container>();
|
|
containerStoppedAtBoundary = LookupBoundary.findAncestorWidgetOfExactType<Container>(context);
|
|
boundaryThroughBoundary = context.findAncestorWidgetOfExactType<LookupBoundary>();
|
|
boundaryStoppedAtBoundary = LookupBoundary.findAncestorWidgetOfExactType<LookupBoundary>(context);
|
|
return const SizedBox.expand();
|
|
},
|
|
),
|
|
),
|
|
));
|
|
|
|
expect(containerThroughBoundary, equals(tester.widget(find.byKey(containerKey))));
|
|
expect(containerStoppedAtBoundary, isNull);
|
|
expect(boundaryThroughBoundary, equals(tester.widget(find.byKey(boundaryKey))));
|
|
expect(boundaryStoppedAtBoundary, equals(tester.widget(find.byKey(boundaryKey))));
|
|
});
|
|
|
|
testWidgets('finds right widget before boundary', (WidgetTester tester) async {
|
|
Widget? containerThroughBoundary;
|
|
Widget? containerStoppedAtBoundary;
|
|
|
|
final Key outerContainerKey = UniqueKey();
|
|
final Key innerContainerKey = UniqueKey();
|
|
|
|
await tester.pumpWidget(Container(
|
|
key: outerContainerKey,
|
|
child: LookupBoundary(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(10),
|
|
color: Colors.blue,
|
|
child: Container(
|
|
key: innerContainerKey,
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
containerThroughBoundary = context.findAncestorWidgetOfExactType<Container>();
|
|
containerStoppedAtBoundary = LookupBoundary.findAncestorWidgetOfExactType<Container>(context);
|
|
return const SizedBox.expand();
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
));
|
|
|
|
expect(containerThroughBoundary, equals(tester.widget(find.byKey(innerContainerKey))));
|
|
expect(containerStoppedAtBoundary, equals(tester.widget(find.byKey(innerContainerKey))));
|
|
});
|
|
|
|
testWidgets('works if nothing is found', (WidgetTester tester) async {
|
|
Widget? containerStoppedAtBoundary;
|
|
|
|
await tester.pumpWidget(Builder(
|
|
builder: (BuildContext context) {
|
|
containerStoppedAtBoundary = LookupBoundary.findAncestorWidgetOfExactType<Container>(context);
|
|
return const SizedBox.expand();
|
|
},
|
|
));
|
|
|
|
expect(containerStoppedAtBoundary, isNull);
|
|
});
|
|
|
|
testWidgets('does not establish a dependency', (WidgetTester tester) async {
|
|
Widget? containerThroughBoundary;
|
|
Widget? containerStoppedAtBoundary;
|
|
Widget? containerStoppedAtBoundaryUnfulfilled;
|
|
|
|
final Key innerContainerKey = UniqueKey();
|
|
final Key globalKey = GlobalKey();
|
|
|
|
final Widget widgetTree = LookupBoundary(
|
|
child: Container(
|
|
key: innerContainerKey,
|
|
child: DidChangeDependencySpy(
|
|
key: globalKey,
|
|
onDidChangeDependencies: (BuildContext context) {
|
|
containerThroughBoundary = context.findAncestorWidgetOfExactType<Container>();
|
|
containerStoppedAtBoundary = LookupBoundary.findAncestorWidgetOfExactType<Container>(context);
|
|
containerStoppedAtBoundaryUnfulfilled = LookupBoundary.findAncestorWidgetOfExactType<Material>(context);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpWidget(widgetTree);
|
|
|
|
expect(containerThroughBoundary, equals(tester.widget(find.byKey(innerContainerKey))));
|
|
expect(containerStoppedAtBoundary, equals(tester.widget(find.byKey(innerContainerKey))));
|
|
expect(containerStoppedAtBoundaryUnfulfilled, isNull);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
|
|
await tester.pumpWidget(
|
|
SizedBox( // Changes tree structure, triggers global key move of DidChangeDependencySpy.
|
|
child: widgetTree,
|
|
),
|
|
);
|
|
|
|
// Tree restructuring above would have called didChangeDependencies if dependency had been established.
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
});
|
|
});
|
|
|
|
group('LookupBoundary.findAncestorStateOfType', () {
|
|
testWidgets('respects boundary', (WidgetTester tester) async {
|
|
State? containerThroughBoundary;
|
|
State? containerStoppedAtBoundary;
|
|
|
|
final Key containerKey = UniqueKey();
|
|
|
|
await tester.pumpWidget(MyStatefulContainer(
|
|
key: containerKey,
|
|
child: LookupBoundary(
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
containerThroughBoundary = context.findAncestorStateOfType<MyStatefulContainerState>();
|
|
containerStoppedAtBoundary = LookupBoundary.findAncestorStateOfType<MyStatefulContainerState>(context);
|
|
return const SizedBox.expand();
|
|
},
|
|
),
|
|
),
|
|
));
|
|
|
|
expect(containerThroughBoundary, equals(tester.state(find.byKey(containerKey))));
|
|
expect(containerStoppedAtBoundary, isNull);
|
|
});
|
|
|
|
testWidgets('finds right widget before boundary', (WidgetTester tester) async {
|
|
State? containerThroughBoundary;
|
|
State? containerStoppedAtBoundary;
|
|
|
|
final Key outerContainerKey = UniqueKey();
|
|
final Key innerContainerKey = UniqueKey();
|
|
|
|
await tester.pumpWidget(MyStatefulContainer(
|
|
key: outerContainerKey,
|
|
child: LookupBoundary(
|
|
child: MyStatefulContainer(
|
|
child: MyStatefulContainer(
|
|
key: innerContainerKey,
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
containerThroughBoundary = context.findAncestorStateOfType<MyStatefulContainerState>();
|
|
containerStoppedAtBoundary = LookupBoundary.findAncestorStateOfType<MyStatefulContainerState>(context);
|
|
return const SizedBox.expand();
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
));
|
|
|
|
expect(containerThroughBoundary, equals(tester.state(find.byKey(innerContainerKey))));
|
|
expect(containerStoppedAtBoundary, equals(tester.state(find.byKey(innerContainerKey))));
|
|
});
|
|
|
|
testWidgets('works if nothing is found', (WidgetTester tester) async {
|
|
State? containerStoppedAtBoundary;
|
|
|
|
await tester.pumpWidget(Builder(
|
|
builder: (BuildContext context) {
|
|
containerStoppedAtBoundary = LookupBoundary.findAncestorStateOfType<MyStatefulContainerState>(context);
|
|
return const SizedBox.expand();
|
|
},
|
|
));
|
|
|
|
expect(containerStoppedAtBoundary, isNull);
|
|
});
|
|
|
|
testWidgets('does not establish a dependency', (WidgetTester tester) async {
|
|
State? containerThroughBoundary;
|
|
State? containerStoppedAtBoundary;
|
|
State? containerStoppedAtBoundaryUnfulfilled;
|
|
|
|
final Key innerContainerKey = UniqueKey();
|
|
final Key globalKey = GlobalKey();
|
|
|
|
final Widget widgetTree = LookupBoundary(
|
|
child: MyStatefulContainer(
|
|
key: innerContainerKey,
|
|
child: DidChangeDependencySpy(
|
|
key: globalKey,
|
|
onDidChangeDependencies: (BuildContext context) {
|
|
containerThroughBoundary = context.findAncestorStateOfType<MyStatefulContainerState>();
|
|
containerStoppedAtBoundary = LookupBoundary.findAncestorStateOfType<MyStatefulContainerState>(context);
|
|
containerStoppedAtBoundaryUnfulfilled = LookupBoundary.findAncestorStateOfType<MyOtherStatefulContainerState>(context);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpWidget(widgetTree);
|
|
|
|
expect(containerThroughBoundary, equals(tester.state(find.byKey(innerContainerKey))));
|
|
expect(containerStoppedAtBoundary, equals(tester.state(find.byKey(innerContainerKey))));
|
|
expect(containerStoppedAtBoundaryUnfulfilled, isNull);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
|
|
await tester.pumpWidget(
|
|
SizedBox( // Changes tree structure, triggers global key move of DidChangeDependencySpy.
|
|
child: widgetTree,
|
|
),
|
|
);
|
|
|
|
// Tree restructuring above would have called didChangeDependencies if dependency had been established.
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
});
|
|
});
|
|
|
|
group('LookupBoundary.findRootAncestorStateOfType', () {
|
|
testWidgets('respects boundary', (WidgetTester tester) async {
|
|
State? containerThroughBoundary;
|
|
State? containerStoppedAtBoundary;
|
|
|
|
final Key containerKey = UniqueKey();
|
|
|
|
await tester.pumpWidget(MyStatefulContainer(
|
|
key: containerKey,
|
|
child: LookupBoundary(
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
containerThroughBoundary = context.findRootAncestorStateOfType<MyStatefulContainerState>();
|
|
containerStoppedAtBoundary = LookupBoundary.findRootAncestorStateOfType<MyStatefulContainerState>(context);
|
|
return const SizedBox.expand();
|
|
},
|
|
),
|
|
),
|
|
));
|
|
|
|
expect(containerThroughBoundary, equals(tester.state(find.byKey(containerKey))));
|
|
expect(containerStoppedAtBoundary, isNull);
|
|
});
|
|
|
|
testWidgets('finds right widget before boundary', (WidgetTester tester) async {
|
|
State? containerThroughBoundary;
|
|
State? containerStoppedAtBoundary;
|
|
|
|
final Key outerContainerKey = UniqueKey();
|
|
final Key innerContainerKey = UniqueKey();
|
|
|
|
await tester.pumpWidget(MyStatefulContainer(
|
|
key: outerContainerKey,
|
|
child: LookupBoundary(
|
|
child: MyStatefulContainer(
|
|
key: innerContainerKey,
|
|
child: MyStatefulContainer(
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
containerThroughBoundary = context.findRootAncestorStateOfType<MyStatefulContainerState>();
|
|
containerStoppedAtBoundary = LookupBoundary.findRootAncestorStateOfType<MyStatefulContainerState>(context);
|
|
return const SizedBox.expand();
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
));
|
|
|
|
expect(containerThroughBoundary, equals(tester.state(find.byKey(outerContainerKey))));
|
|
expect(containerStoppedAtBoundary, equals(tester.state(find.byKey(innerContainerKey))));
|
|
});
|
|
|
|
testWidgets('works if nothing is found', (WidgetTester tester) async {
|
|
State? containerStoppedAtBoundary;
|
|
|
|
await tester.pumpWidget(Builder(
|
|
builder: (BuildContext context) {
|
|
containerStoppedAtBoundary = LookupBoundary.findRootAncestorStateOfType<MyStatefulContainerState>(context);
|
|
return const SizedBox.expand();
|
|
},
|
|
));
|
|
|
|
expect(containerStoppedAtBoundary, isNull);
|
|
});
|
|
|
|
testWidgets('does not establish a dependency', (WidgetTester tester) async {
|
|
State? containerThroughBoundary;
|
|
State? containerStoppedAtBoundary;
|
|
State? containerStoppedAtBoundaryUnfulfilled;
|
|
|
|
final Key innerContainerKey = UniqueKey();
|
|
final Key globalKey = GlobalKey();
|
|
|
|
final Widget widgetTree = LookupBoundary(
|
|
child: MyStatefulContainer(
|
|
key: innerContainerKey,
|
|
child: DidChangeDependencySpy(
|
|
key: globalKey,
|
|
onDidChangeDependencies: (BuildContext context) {
|
|
containerThroughBoundary = context.findRootAncestorStateOfType<MyStatefulContainerState>();
|
|
containerStoppedAtBoundary = LookupBoundary.findRootAncestorStateOfType<MyStatefulContainerState>(context);
|
|
containerStoppedAtBoundaryUnfulfilled = LookupBoundary.findRootAncestorStateOfType<MyOtherStatefulContainerState>(context);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpWidget(widgetTree);
|
|
|
|
expect(containerThroughBoundary, equals(tester.state(find.byKey(innerContainerKey))));
|
|
expect(containerStoppedAtBoundary, equals(tester.state(find.byKey(innerContainerKey))));
|
|
expect(containerStoppedAtBoundaryUnfulfilled, isNull);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
|
|
await tester.pumpWidget(
|
|
SizedBox( // Changes tree structure, triggers global key move of DidChangeDependencySpy.
|
|
child: widgetTree,
|
|
),
|
|
);
|
|
|
|
// Tree restructuring above would have called didChangeDependencies if dependency had been established.
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
});
|
|
});
|
|
|
|
group('LookupBoundary.findAncestorRenderObjectOfType', () {
|
|
testWidgets('respects boundary', (WidgetTester tester) async {
|
|
RenderPadding? paddingThroughBoundary;
|
|
RenderPadding? passingStoppedAtBoundary;
|
|
|
|
final Key paddingKey = UniqueKey();
|
|
|
|
await tester.pumpWidget(Padding(
|
|
padding: EdgeInsets.zero,
|
|
key: paddingKey,
|
|
child: LookupBoundary(
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
paddingThroughBoundary = context.findAncestorRenderObjectOfType<RenderPadding>();
|
|
passingStoppedAtBoundary = LookupBoundary.findAncestorRenderObjectOfType<RenderPadding>(context);
|
|
return const SizedBox.expand();
|
|
},
|
|
),
|
|
),
|
|
));
|
|
|
|
expect(paddingThroughBoundary, equals(tester.renderObject(find.byKey(paddingKey))));
|
|
expect(passingStoppedAtBoundary, isNull);
|
|
});
|
|
|
|
testWidgets('finds right widget before boundary', (WidgetTester tester) async {
|
|
RenderPadding? paddingThroughBoundary;
|
|
RenderPadding? paddingStoppedAtBoundary;
|
|
|
|
final Key outerPaddingKey = UniqueKey();
|
|
final Key innerPaddingKey = UniqueKey();
|
|
|
|
await tester.pumpWidget(Padding(
|
|
padding: EdgeInsets.zero,
|
|
key: outerPaddingKey,
|
|
child: LookupBoundary(
|
|
child: Padding(
|
|
padding: EdgeInsets.zero,
|
|
child: Padding(
|
|
padding: EdgeInsets.zero,
|
|
key: innerPaddingKey,
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
paddingThroughBoundary = context.findAncestorRenderObjectOfType<RenderPadding>();
|
|
paddingStoppedAtBoundary = LookupBoundary.findAncestorRenderObjectOfType<RenderPadding>(context);
|
|
return const SizedBox.expand();
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
));
|
|
|
|
expect(paddingThroughBoundary, equals(tester.renderObject(find.byKey(innerPaddingKey))));
|
|
expect(paddingStoppedAtBoundary, equals(tester.renderObject(find.byKey(innerPaddingKey))));
|
|
});
|
|
|
|
testWidgets('works if nothing is found', (WidgetTester tester) async {
|
|
RenderPadding? paddingStoppedAtBoundary;
|
|
|
|
await tester.pumpWidget(Builder(
|
|
builder: (BuildContext context) {
|
|
paddingStoppedAtBoundary = LookupBoundary.findAncestorRenderObjectOfType<RenderPadding>(context);
|
|
return const SizedBox.expand();
|
|
},
|
|
));
|
|
|
|
expect(paddingStoppedAtBoundary, isNull);
|
|
});
|
|
|
|
testWidgets('does not establish a dependency', (WidgetTester tester) async {
|
|
RenderPadding? paddingThroughBoundary;
|
|
RenderPadding? paddingStoppedAtBoundary;
|
|
RenderWrap? wrapStoppedAtBoundaryUnfulfilled;
|
|
|
|
final Key innerPaddingKey = UniqueKey();
|
|
final Key globalKey = GlobalKey();
|
|
|
|
final Widget widgetTree = LookupBoundary(
|
|
child: Padding(
|
|
padding: EdgeInsets.zero,
|
|
key: innerPaddingKey,
|
|
child: DidChangeDependencySpy(
|
|
key: globalKey,
|
|
onDidChangeDependencies: (BuildContext context) {
|
|
paddingThroughBoundary = context.findAncestorRenderObjectOfType<RenderPadding>();
|
|
paddingStoppedAtBoundary = LookupBoundary.findAncestorRenderObjectOfType<RenderPadding>(context);
|
|
wrapStoppedAtBoundaryUnfulfilled = LookupBoundary.findAncestorRenderObjectOfType<RenderWrap>(context);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpWidget(widgetTree);
|
|
|
|
expect(paddingThroughBoundary, equals(tester.renderObject(find.byKey(innerPaddingKey))));
|
|
expect(paddingStoppedAtBoundary, equals(tester.renderObject(find.byKey(innerPaddingKey))));
|
|
expect(wrapStoppedAtBoundaryUnfulfilled, isNull);
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
|
|
await tester.pumpWidget(
|
|
SizedBox( // Changes tree structure, triggers global key move of DidChangeDependencySpy.
|
|
child: widgetTree,
|
|
),
|
|
);
|
|
|
|
// Tree restructuring above would have called didChangeDependencies if dependency had been established.
|
|
expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
|
|
});
|
|
});
|
|
|
|
group('LookupBoundary.visitAncestorElements', () {
|
|
testWidgets('respects boundary', (WidgetTester tester) async {
|
|
final List<Element> throughBoundary = <Element>[];
|
|
final List<Element> stoppedAtBoundary = <Element>[];
|
|
final List<Element> stoppedAtBoundaryTerminatedEarly = <Element>[];
|
|
|
|
final Key level0 = UniqueKey();
|
|
final Key level1 = UniqueKey();
|
|
final Key level2 = UniqueKey();
|
|
final Key level3 = UniqueKey();
|
|
final Key level4 = UniqueKey();
|
|
|
|
await tester.pumpWidget(Container(
|
|
key: level0,
|
|
child: Container(
|
|
key: level1,
|
|
child: LookupBoundary(
|
|
key: level2,
|
|
child: Container(
|
|
key: level3,
|
|
child: Container(
|
|
key: level4,
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
context.visitAncestorElements((Element element) {
|
|
throughBoundary.add(element);
|
|
return element.widget.key != level0;
|
|
});
|
|
LookupBoundary.visitAncestorElements(context, (Element element) {
|
|
stoppedAtBoundary.add(element);
|
|
return element.widget.key != level0;
|
|
});
|
|
LookupBoundary.visitAncestorElements(context, (Element element) {
|
|
stoppedAtBoundaryTerminatedEarly.add(element);
|
|
return element.widget.key != level3;
|
|
});
|
|
return const SizedBox();
|
|
}
|
|
)
|
|
)
|
|
)
|
|
)
|
|
),
|
|
));
|
|
|
|
expect(throughBoundary, <Element>[
|
|
tester.element(find.byKey(level4)),
|
|
tester.element(find.byKey(level3)),
|
|
tester.element(find.byKey(level2)),
|
|
tester.element(find.byKey(level1)),
|
|
tester.element(find.byKey(level0)),
|
|
]);
|
|
|
|
expect(stoppedAtBoundary, <Element>[
|
|
tester.element(find.byKey(level4)),
|
|
tester.element(find.byKey(level3)),
|
|
tester.element(find.byKey(level2)),
|
|
]);
|
|
|
|
expect(stoppedAtBoundaryTerminatedEarly, <Element>[
|
|
tester.element(find.byKey(level4)),
|
|
tester.element(find.byKey(level3)),
|
|
]);
|
|
});
|
|
});
|
|
|
|
group('LookupBoundary.visitChildElements', () {
|
|
testWidgets('respects boundary', (WidgetTester tester) async {
|
|
final Key root = UniqueKey();
|
|
final Key child1 = UniqueKey();
|
|
final Key child2 = UniqueKey();
|
|
final Key child3 = UniqueKey();
|
|
|
|
await tester.pumpWidget(Column(
|
|
key: root,
|
|
children: <Widget>[
|
|
LookupBoundary(
|
|
key: child1,
|
|
child: Container(),
|
|
),
|
|
Container(
|
|
key: child2,
|
|
child: LookupBoundary(
|
|
child: Container(),
|
|
),
|
|
),
|
|
Container(
|
|
key: child3,
|
|
),
|
|
],
|
|
));
|
|
|
|
final List<Element> throughBoundary = <Element>[];
|
|
final List<Element> stoppedAtBoundary = <Element>[];
|
|
|
|
final BuildContext context = tester.element(find.byKey(root));
|
|
|
|
context.visitChildElements((Element element) {
|
|
throughBoundary.add(element);
|
|
});
|
|
LookupBoundary.visitChildElements(context, (Element element) {
|
|
stoppedAtBoundary.add(element);
|
|
});
|
|
|
|
expect(throughBoundary, <Element>[
|
|
tester.element(find.byKey(child1)),
|
|
tester.element(find.byKey(child2)),
|
|
tester.element(find.byKey(child3)),
|
|
]);
|
|
|
|
expect(stoppedAtBoundary, <Element>[
|
|
tester.element(find.byKey(child2)),
|
|
tester.element(find.byKey(child3)),
|
|
]);
|
|
|
|
});
|
|
});
|
|
|
|
group('LookupBoundary.debugIsHidingAncestorWidgetOfExactType', () {
|
|
testWidgets('is hiding', (WidgetTester tester) async {
|
|
bool? isHidden;
|
|
await tester.pumpWidget(Container(
|
|
padding: const EdgeInsets.all(10),
|
|
color: Colors.blue,
|
|
child: LookupBoundary(
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
isHidden = LookupBoundary.debugIsHidingAncestorWidgetOfExactType<Container>(context);
|
|
return Container();
|
|
},
|
|
),
|
|
),
|
|
));
|
|
expect(isHidden, isTrue);
|
|
});
|
|
|
|
testWidgets('is not hiding entity within boundary', (WidgetTester tester) async {
|
|
bool? isHidden;
|
|
await tester.pumpWidget(Container(
|
|
padding: const EdgeInsets.all(10),
|
|
color: Colors.blue,
|
|
child: LookupBoundary(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(10),
|
|
color: Colors.red,
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
isHidden = LookupBoundary.debugIsHidingAncestorWidgetOfExactType<Container>(context);
|
|
return Container();
|
|
},
|
|
),
|
|
),
|
|
),
|
|
));
|
|
expect(isHidden, isFalse);
|
|
});
|
|
|
|
testWidgets('is not hiding if no boundary exists', (WidgetTester tester) async {
|
|
bool? isHidden;
|
|
await tester.pumpWidget(Container(
|
|
padding: const EdgeInsets.all(10),
|
|
color: Colors.blue,
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
isHidden = LookupBoundary.debugIsHidingAncestorWidgetOfExactType<Container>(context);
|
|
return Container();
|
|
},
|
|
),
|
|
));
|
|
expect(isHidden, isFalse);
|
|
});
|
|
|
|
testWidgets('is not hiding if no boundary and no entity exists', (WidgetTester tester) async {
|
|
bool? isHidden;
|
|
await tester.pumpWidget(Builder(
|
|
builder: (BuildContext context) {
|
|
isHidden = LookupBoundary.debugIsHidingAncestorWidgetOfExactType<Container>(context);
|
|
return Container();
|
|
},
|
|
));
|
|
expect(isHidden, isFalse);
|
|
});
|
|
});
|
|
|
|
group('LookupBoundary.debugIsHidingAncestorStateOfType', () {
|
|
testWidgets('is hiding', (WidgetTester tester) async {
|
|
bool? isHidden;
|
|
await tester.pumpWidget(MyStatefulContainer(
|
|
child: LookupBoundary(
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
isHidden = LookupBoundary.debugIsHidingAncestorStateOfType<MyStatefulContainerState>(context);
|
|
return Container();
|
|
},
|
|
),
|
|
),
|
|
));
|
|
expect(isHidden, isTrue);
|
|
});
|
|
|
|
testWidgets('is not hiding entity within boundary', (WidgetTester tester) async {
|
|
bool? isHidden;
|
|
await tester.pumpWidget(MyStatefulContainer(
|
|
child: LookupBoundary(
|
|
child: MyStatefulContainer(
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
isHidden = LookupBoundary.debugIsHidingAncestorStateOfType<MyStatefulContainerState>(context);
|
|
return Container();
|
|
},
|
|
),
|
|
),
|
|
),
|
|
));
|
|
expect(isHidden, isFalse);
|
|
});
|
|
|
|
testWidgets('is not hiding if no boundary exists', (WidgetTester tester) async {
|
|
bool? isHidden;
|
|
await tester.pumpWidget(MyStatefulContainer(
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
isHidden = LookupBoundary.debugIsHidingAncestorStateOfType<MyStatefulContainerState>(context);
|
|
return Container();
|
|
},
|
|
),
|
|
));
|
|
expect(isHidden, isFalse);
|
|
});
|
|
|
|
testWidgets('is not hiding if no boundary and no entity exists', (WidgetTester tester) async {
|
|
bool? isHidden;
|
|
await tester.pumpWidget(Builder(
|
|
builder: (BuildContext context) {
|
|
isHidden = LookupBoundary.debugIsHidingAncestorStateOfType<MyStatefulContainerState>(context);
|
|
return Container();
|
|
},
|
|
));
|
|
expect(isHidden, isFalse);
|
|
});
|
|
});
|
|
|
|
group('LookupBoundary.debugIsHidingAncestorRenderObjectOfType', () {
|
|
testWidgets('is hiding', (WidgetTester tester) async {
|
|
bool? isHidden;
|
|
await tester.pumpWidget(Padding(
|
|
padding: EdgeInsets.zero,
|
|
child: LookupBoundary(
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
isHidden = LookupBoundary.debugIsHidingAncestorRenderObjectOfType<RenderPadding>(context);
|
|
return Container();
|
|
},
|
|
),
|
|
),
|
|
));
|
|
expect(isHidden, isTrue);
|
|
});
|
|
|
|
testWidgets('is not hiding entity within boundary', (WidgetTester tester) async {
|
|
bool? isHidden;
|
|
await tester.pumpWidget(Padding(
|
|
padding: EdgeInsets.zero,
|
|
child: LookupBoundary(
|
|
child: Padding(
|
|
padding: EdgeInsets.zero,
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
isHidden = LookupBoundary.debugIsHidingAncestorRenderObjectOfType<RenderPadding>(context);
|
|
return Container();
|
|
},
|
|
),
|
|
),
|
|
),
|
|
));
|
|
expect(isHidden, isFalse);
|
|
});
|
|
|
|
testWidgets('is not hiding if no boundary exists', (WidgetTester tester) async {
|
|
bool? isHidden;
|
|
await tester.pumpWidget(Padding(
|
|
padding: EdgeInsets.zero,
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
isHidden = LookupBoundary.debugIsHidingAncestorRenderObjectOfType<RenderPadding>(context);
|
|
return Container();
|
|
},
|
|
),
|
|
));
|
|
expect(isHidden, isFalse);
|
|
});
|
|
|
|
testWidgets('is not hiding if no boundary and no entity exists', (WidgetTester tester) async {
|
|
bool? isHidden;
|
|
await tester.pumpWidget(Builder(
|
|
builder: (BuildContext context) {
|
|
isHidden = LookupBoundary.debugIsHidingAncestorRenderObjectOfType<RenderPadding>(context);
|
|
return Container();
|
|
},
|
|
));
|
|
expect(isHidden, isFalse);
|
|
});
|
|
});
|
|
}
|
|
|
|
class MyStatefulContainer extends StatefulWidget {
|
|
const MyStatefulContainer({super.key, required this.child});
|
|
|
|
final Widget child;
|
|
|
|
@override
|
|
State<MyStatefulContainer> createState() => MyStatefulContainerState();
|
|
}
|
|
|
|
class MyStatefulContainerState extends State<MyStatefulContainer> {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return widget.child;
|
|
}
|
|
}
|
|
|
|
class MyOtherStatefulContainerState extends State<MyStatefulContainer> {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return widget.child;
|
|
}
|
|
}
|
|
|
|
class MyInheritedWidget extends InheritedWidget {
|
|
const MyInheritedWidget({super.key, required this.value, required super.child});
|
|
|
|
final int value;
|
|
|
|
@override
|
|
bool updateShouldNotify(MyInheritedWidget oldWidget) => oldWidget.value != value;
|
|
}
|
|
|
|
class DidChangeDependencySpy extends StatefulWidget {
|
|
const DidChangeDependencySpy({super.key, required this.onDidChangeDependencies});
|
|
|
|
final OnDidChangeDependencies onDidChangeDependencies;
|
|
|
|
@override
|
|
State<DidChangeDependencySpy> createState() => _DidChangeDependencySpyState();
|
|
}
|
|
|
|
class _DidChangeDependencySpyState extends State<DidChangeDependencySpy> {
|
|
int didChangeDependenciesCount = 0;
|
|
|
|
@override
|
|
void didChangeDependencies() {
|
|
super.didChangeDependencies();
|
|
didChangeDependenciesCount += 1;
|
|
widget.onDidChangeDependencies(context);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Container();
|
|
}
|
|
}
|
|
|
|
typedef OnDidChangeDependencies = void Function(BuildContext context);
|