Skip to content

Commit 7dd53fe

Browse files
Reland (3): Removes single window assumptions from flutter_test (#122422)
Reland (3): Removes single window assumptions from `flutter_test`
1 parent 37fc9ed commit 7dd53fe

16 files changed

+2411
-1290
lines changed

packages/flutter/lib/src/widgets/binding.dart

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -901,15 +901,13 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
901901
/// Used by [runApp] to wrap the provided `rootWidget` in the default [View].
902902
///
903903
/// The [View] determines into what [FlutterView] the app is rendered into.
904-
/// For backwards-compatibility reasons, this method currently chooses
905-
/// [window] (which is a [FlutterView]) as the rendering target. This will
906-
/// change in a future version of Flutter.
904+
/// This is currently [PlatformDispatcher.implicitView] from [platformDispatcher].
907905
///
908906
/// The `rootWidget` widget provided to this method must not already be
909907
/// wrapped in a [View].
910908
Widget wrapWithDefaultView(Widget rootWidget) {
911909
return View(
912-
view: window,
910+
view: platformDispatcher.implicitView!,
913911
child: rootWidget,
914912
);
915913
}

packages/flutter/test/material/debug_test.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ void main() {
235235
' MediaQuery\n'
236236
' _MediaQueryFromView\n'
237237
' _ViewScope\n'
238-
' View-[GlobalObjectKey TestWindow#00000]\n'
238+
' View-[GlobalObjectKey TestFlutterView#00000]\n'
239239
' [root]\n'
240240
' Typically, the Scaffold widget is introduced by the MaterialApp\n'
241241
' or WidgetsApp widget at the top of your application widget tree.\n'
@@ -376,7 +376,7 @@ void main() {
376376
' MediaQuery\n'
377377
' _MediaQueryFromView\n'
378378
' _ViewScope\n'
379-
' View-[GlobalObjectKey TestWindow#00000]\n'
379+
' View-[GlobalObjectKey TestFlutterView#00000]\n'
380380
' [root]\n'
381381
' Typically, the ScaffoldMessenger widget is introduced by the\n'
382382
' MaterialApp at the top of your application widget tree.\n'

packages/flutter/test/material/scaffold_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2454,7 +2454,7 @@ void main() {
24542454
' MediaQuery\n'
24552455
' _MediaQueryFromView\n'
24562456
' _ViewScope\n'
2457-
' View-[GlobalObjectKey TestWindow#e6136]\n'
2457+
' View-[GlobalObjectKey TestFlutterView#e6136]\n'
24582458
' [root]\n'
24592459
' Typically, the ScaffoldMessenger widget is introduced by the\n'
24602460
' MaterialApp at the top of your application widget tree.\n',

packages/flutter/test/widgets/container_test.dart

Lines changed: 509 additions & 444 deletions
Large diffs are not rendered by default.

packages/flutter/test/widgets/custom_multi_child_layout_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ void main() {
374374
' creator: ConstrainedBox ← Container ← LayoutWithMissingId ←\n'
375375
' CustomMultiChildLayout ← Center ← MediaQuery ←\n'
376376
' _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
377-
' TestWindow#00000] ← [root]\n'
377+
' TestFlutterView#00000] ← [root]\n'
378378
' parentData: offset=Offset(0.0, 0.0); id=null\n'
379379
' constraints: MISSING\n'
380380
' size: MISSING\n'

packages/flutter/test/widgets/focus_manager_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1230,7 +1230,7 @@ void main() {
12301230
' │ primaryFocus: FocusNode#00000(Child 4 [PRIMARY FOCUS])\n'
12311231
' │ primaryFocusCreator: Container-[GlobalKey#00000] ← MediaQuery ←\n'
12321232
' │ _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
1233-
' │ TestWindow#00000] ← [root]\n'
1233+
' │ TestFlutterView#00000] ← [root]\n'
12341234
' │\n'
12351235
' └─rootScope: FocusScopeNode#00000(Root Focus Scope [IN FOCUS PATH])\n'
12361236
' │ IN FOCUS PATH\n'

packages/flutter/test/widgets/media_query_test.dart

Lines changed: 86 additions & 173 deletions
Large diffs are not rendered by default.

packages/flutter/test/widgets/slotted_render_object_widget_test.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,15 +223,15 @@ void main() {
223223
'_RenderDiagonal#00000 relayoutBoundary=up1\n'
224224
' │ creator: _Diagonal ← Align ← Directionality ← MediaQuery ←\n'
225225
' │ _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
226-
' │ TestWindow#00000] ← [root]\n'
226+
' │ TestFlutterView#00000] ← [root]\n'
227227
' │ parentData: offset=Offset(0.0, 0.0) (can use size)\n'
228228
' │ constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0)\n'
229229
' │ size: Size(190.0, 220.0)\n'
230230
' │\n'
231231
' ├─topLeft: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
232232
' │ creator: SizedBox ← _Diagonal ← Align ← Directionality ←\n'
233233
' │ MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
234-
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
234+
' │ View-[GlobalObjectKey TestFlutterView#00000] ← [root]\n'
235235
' │ parentData: offset=Offset(0.0, 0.0) (can use size)\n'
236236
' │ constraints: BoxConstraints(unconstrained)\n'
237237
' │ size: Size(80.0, 100.0)\n'
@@ -240,7 +240,7 @@ void main() {
240240
' └─bottomRight: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
241241
' creator: SizedBox ← _Diagonal ← Align ← Directionality ←\n'
242242
' MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
243-
' View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
243+
' View-[GlobalObjectKey TestFlutterView#00000] ← [root]\n'
244244
' parentData: offset=Offset(80.0, 100.0) (can use size)\n'
245245
' constraints: BoxConstraints(unconstrained)\n'
246246
' size: Size(110.0, 120.0)\n'

packages/flutter_test/lib/src/binding.dart

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,17 +182,18 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
182182
///
183183
/// This constructor overrides the [debugPrint] global hook to point to
184184
/// [debugPrintOverride], which can be overridden by subclasses.
185-
TestWidgetsFlutterBinding() : _window = TestWindow(window: ui.window) {
185+
TestWidgetsFlutterBinding() : platformDispatcher = TestPlatformDispatcher(
186+
platformDispatcher: PlatformDispatcher.instance,
187+
) {
186188
debugPrint = debugPrintOverride;
187189
debugDisableShadows = disableShadows;
188190
}
189191

190192
@override
191-
TestWindow get window => _window;
192-
final TestWindow _window;
193+
late final TestWindow window;
193194

194195
@override
195-
TestPlatformDispatcher get platformDispatcher => _window.platformDispatcher;
196+
final TestPlatformDispatcher platformDispatcher;
196197

197198
@override
198199
TestRestorationManager get restorationManager {
@@ -346,6 +347,12 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
346347

347348
@override
348349
void initInstances() {
350+
// This is intialized here because it's needed for the `super.initInstances`
351+
// call. It can't be handled as a ctor initializer because it's dependent
352+
// on `platformDispatcher`. It can't be handled in the ctor itself because
353+
// the base class ctor is called first and calls `initInstances`.
354+
window = TestWindow.fromPlatformDispatcher(platformDispatcher: platformDispatcher);
355+
349356
super.initInstances();
350357
_instance = this;
351358
timeDilation = 1.0; // just in case the developer has artificially changed it for development

packages/flutter_test/lib/src/controller.dart

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import 'event_simulation.dart';
1414
import 'finders.dart';
1515
import 'test_async_utils.dart';
1616
import 'test_pointer.dart';
17+
import 'window.dart';
1718

1819
/// The default drag touch slop used to break up a large drag into multiple
1920
/// smaller moves.
@@ -234,6 +235,37 @@ abstract class WidgetController {
234235
/// A reference to the current instance of the binding.
235236
final WidgetsBinding binding;
236237

238+
/// The [TestPlatformDispatcher] that is being used in this test.
239+
///
240+
/// This will be injected into the framework such that calls to
241+
/// [WidgetsBinding.platformDispatcher] will use this. This allows
242+
/// users to change platform specific properties for testing.
243+
///
244+
/// See also:
245+
///
246+
/// * [TestFlutterView] which allows changing view specific properties
247+
/// for testing
248+
/// * [view] and [viewOf] which are used to find
249+
/// [TestFlutterView]s from the widget tree
250+
TestPlatformDispatcher get platformDispatcher => binding.platformDispatcher as TestPlatformDispatcher;
251+
252+
/// The [TestFlutterView] provided by default when testing with
253+
/// [WidgetTester.pumpWidget].
254+
///
255+
/// If the test requires multiple views, it will need to use [viewOf] instead
256+
/// to ensure that the view related to the widget being evaluated is the one
257+
/// that gets updated.
258+
///
259+
/// See also:
260+
///
261+
/// * [viewOf], which can find a [TestFlutterView] related to a given finder.
262+
/// This is how to modify view properties for testing when dealing with
263+
/// multiple views.
264+
TestFlutterView get view {
265+
assert(platformDispatcher.views.length == 1, 'When testing with multiple views, use `viewOf` instead.');
266+
return platformDispatcher.views.single;
267+
}
268+
237269
/// Provides access to a [SemanticsController] for testing anything related to
238270
/// the [Semantics] tree.
239271
///
@@ -257,6 +289,26 @@ abstract class WidgetController {
257289
// TODO(ianh): verify that the return values are of type T and throw
258290
// a good message otherwise, in all the generic methods below
259291

292+
/// Finds the [TestFlutterView] that is the closest ancestor of the widget
293+
/// found by [finder].
294+
///
295+
/// [TestFlutterView] can be used to modify view specific properties for testing.
296+
///
297+
/// See also:
298+
///
299+
/// * [view] which returns the [TestFlutterView] used when only a single
300+
/// view is being used.
301+
TestFlutterView viewOf(Finder finder) {
302+
final View view = firstWidget<View>(
303+
find.ancestor(
304+
of: finder,
305+
matching: find.byType(View),
306+
)
307+
);
308+
309+
return view.view as TestFlutterView;
310+
}
311+
260312
/// Checks if `finder` exists in the tree.
261313
bool any(Finder finder) {
262314
TestAsyncUtils.guardSync();

0 commit comments

Comments
 (0)