Skip to content

Commit

Permalink
make FakeView not send Scene and semantics to the engine (#138849)
Browse files Browse the repository at this point in the history
`FakeView` wraps the same underlying `FlutterView`. Sending semantics updates and Scene objects from multiple fake views into the same engine `FlutterView` violates contracts with the engine. This PR stubs out `render` and `updateSemantics` methods in `FakeView` classes to prevent that.

This unblocks flutter/engine#48251, which implements multi-view semantics for web.
  • Loading branch information
yjbanov authored Nov 22, 2023
1 parent c7d4b32 commit 14549b3
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 60 deletions.
33 changes: 33 additions & 0 deletions packages/flutter/test/widgets/multi_view_testing.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// 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 'dart:ui';

import 'package:flutter_test/flutter_test.dart';

class FakeView extends TestFlutterView {
FakeView(FlutterView view, { this.viewId = 100 }) : super(
view: view,
platformDispatcher: view.platformDispatcher as TestPlatformDispatcher,
display: view.display as TestDisplay,
);

@override
final int viewId;

@override
void render(Scene scene) {
// Do not render the scene in the engine. The engine only observes one
// instance of FlutterView (the _view), and it is generally expected that
// the framework will render no more than one `Scene` per frame.
}

@override
void updateSemantics(SemanticsUpdate update) {
// Do not send the update to the engine. The engine only observes one
// instance of FlutterView (the _view). Sending semantic updates meant for
// different views to the same engine view does not work as the updates do
// not produce consistent semantics trees.
}
}
15 changes: 2 additions & 13 deletions packages/flutter/test/widgets/multi_view_tree_updates_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';

import 'multi_view_testing.dart';

void main() {
testWidgetsWithLeakTracking('Widgets in view update as expected', (WidgetTester tester) async {
final Widget widget = View(
Expand Down Expand Up @@ -209,14 +209,3 @@ Future<void> pumpWidgetWithoutViewWrapper({required WidgetTester tester, require
tester.binding.scheduleFrame();
return tester.binding.pump();
}

class FakeView extends TestFlutterView{
FakeView(FlutterView view, { this.viewId = 100 }) : super(
view: view,
platformDispatcher: view.platformDispatcher as TestPlatformDispatcher,
display: view.display as TestDisplay,
);

@override
final int viewId;
}
13 changes: 2 additions & 11 deletions packages/flutter/test/widgets/tree_shape_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';

import 'multi_view_testing.dart';

void main() {
testWidgetsWithLeakTracking('Providing a RenderObjectWidget directly to the RootWidget fails', (WidgetTester tester) async {
// No render tree exists to attach the RenderObjectWidget to.
Expand Down Expand Up @@ -1149,14 +1151,3 @@ Future<void> pumpWidgetWithoutViewWrapper({required WidgetTester tester, require
tester.binding.scheduleFrame();
return tester.binding.pump();
}

class FakeView extends TestFlutterView{
FakeView(FlutterView view, { this.viewId = 100 }) : super(
view: view,
platformDispatcher: view.platformDispatcher as TestPlatformDispatcher,
display: view.display as TestDisplay,
);

@override
final int viewId;
}
13 changes: 2 additions & 11 deletions packages/flutter/test/widgets/view_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';

import 'multi_view_testing.dart';

void main() {
testWidgetsWithLeakTracking('Widgets running with runApp can find View', (WidgetTester tester) async {
FlutterView? viewOf;
Expand Down Expand Up @@ -456,17 +458,6 @@ Future<void> pumpWidgetWithoutViewWrapper({required WidgetTester tester, require
return tester.binding.pump();
}

class FakeView extends TestFlutterView{
FakeView(FlutterView view, { this.viewId = 100 }) : super(
view: view,
platformDispatcher: view.platformDispatcher as TestPlatformDispatcher,
display: view.display as TestDisplay,
);

@override
final int viewId;
}

class SpyRenderWidget extends SizedBox {
const SpyRenderWidget({super.key, required this.label, required this.log, super.child});

Expand Down
14 changes: 2 additions & 12 deletions packages/flutter_test/test/multi_view_accessibility_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
// found in the LICENSE file.

import 'dart:convert';
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

import 'multi_view_testing.dart';

void main() {
testWidgets('Detects tap targets in all views', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
Expand Down Expand Up @@ -122,14 +123,3 @@ Future<void> pumpViews({required WidgetTester tester, required List<Widget> vie
tester.binding.scheduleFrame();
return tester.binding.pump();
}

class FakeView extends TestFlutterView{
FakeView(FlutterView view, { this.viewId = 100 }) : super(
view: view,
platformDispatcher: view.platformDispatcher as TestPlatformDispatcher,
display: view.display as TestDisplay,
);

@override
final int viewId;
}
15 changes: 2 additions & 13 deletions packages/flutter_test/test/multi_view_controller_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:ui';

import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

import 'multi_view_testing.dart';

void main() {
testWidgets('simulatedAccessibilityTraversal - start and end in same view', (WidgetTester tester) async {
await pumpViews(tester: tester);
Expand Down Expand Up @@ -219,14 +219,3 @@ Future<void> pumpViews({required WidgetTester tester}) {
tester.binding.scheduleFrame();
return tester.binding.pump();
}

class FakeView extends TestFlutterView{
FakeView(FlutterView view, { this.viewId = 100 }) : super(
view: view,
platformDispatcher: view.platformDispatcher as TestPlatformDispatcher,
display: view.display as TestDisplay,
);

@override
final int viewId;
}
33 changes: 33 additions & 0 deletions packages/flutter_test/test/multi_view_testing.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// 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 'dart:ui';

import 'package:flutter_test/flutter_test.dart';

class FakeView extends TestFlutterView {
FakeView(FlutterView view, { this.viewId = 100 }) : super(
view: view,
platformDispatcher: view.platformDispatcher as TestPlatformDispatcher,
display: view.display as TestDisplay,
);

@override
final int viewId;

@override
void render(Scene scene) {
// Do not render the scene in the engine. The engine only observes one
// instance of FlutterView (the _view), and it is generally expected that
// the framework will render no more than one `Scene` per frame.
}

@override
void updateSemantics(SemanticsUpdate update) {
// Do not send the update to the engine. The engine only observes one
// instance of FlutterView (the _view). Sending semantic updates meant for
// different views to the same engine view does not work as the updates do
// not produce consistent semantics trees.
}
}

0 comments on commit 14549b3

Please sign in to comment.