Port touch-based tests from embedder integration test (flutter/engine#38234)
* Port touch-based tests from embedder integration test * Remove RegisterTouchScreen and related variables * Update embedded child view size
This commit is contained in:
@@ -86,12 +86,8 @@ constexpr auto kTestUiStackRef = ChildRef{kTestUiStack};
|
||||
|
||||
constexpr fuchsia_test_utils::Color kParentBackgroundColor = {0x00, 0x00, 0xFF,
|
||||
0xFF}; // Blue
|
||||
constexpr fuchsia_test_utils::Color kParentTappedColor = {0x00, 0x00, 0x00,
|
||||
0xFF}; // Black
|
||||
constexpr fuchsia_test_utils::Color kChildBackgroundColor = {0xFF, 0x00, 0xFF,
|
||||
0xFF}; // Pink
|
||||
constexpr fuchsia_test_utils::Color kChildTappedColor = {0xFF, 0xFF, 0x00,
|
||||
0xFF}; // Yellow
|
||||
|
||||
// TODO(fxb/64201): Remove forced opacity colors when Flatland is enabled.
|
||||
constexpr fuchsia_test_utils::Color kOverlayBackgroundColor1 = {
|
||||
@@ -160,60 +156,18 @@ class FlutterEmbedderTest : public ::loop_fixture::RealLoop,
|
||||
callback = nullptr,
|
||||
zx::duration timeout = kTestTimeout);
|
||||
|
||||
// Simulates a tap at location (x, y).
|
||||
void InjectTap(int32_t x, int32_t y);
|
||||
|
||||
// Injects an input event, and posts a task to retry after
|
||||
// `kTapRetryInterval`.
|
||||
//
|
||||
// We post the retry task because the first input event we send to Flutter may
|
||||
// be lost. The reason the first event may be lost is that there is a race
|
||||
// condition as the scene owner starts up.
|
||||
//
|
||||
// More specifically: in order for our app
|
||||
// to receive the injected input, two things must be true before we inject
|
||||
// touch input:
|
||||
// * The Scenic root view must have been installed, and
|
||||
// * The Input Pipeline must have received a viewport to inject touch into.
|
||||
//
|
||||
// The problem we have is that the `is_rendering` signal that we monitor only
|
||||
// guarantees us the view is ready. If the viewport is not ready in Input
|
||||
// Pipeline at that time, it will drop the touch event.
|
||||
//
|
||||
// TODO(fxbug.dev/96986): Improve synchronization and remove retry logic.
|
||||
void TryInject(int32_t x, int32_t y);
|
||||
|
||||
private:
|
||||
fuchsia::ui::scenic::Scenic* scenic() { return scenic_.get(); }
|
||||
|
||||
void SetUpRealmBase();
|
||||
|
||||
// Registers a fake touch screen device with an injection coordinate space
|
||||
// spanning [-1000, 1000] on both axes.
|
||||
void RegisterTouchScreen();
|
||||
|
||||
fuchsia::ui::scenic::ScenicPtr scenic_;
|
||||
fuchsia::ui::test::input::RegistryPtr input_registry_;
|
||||
fuchsia::ui::test::input::TouchScreenPtr fake_touchscreen_;
|
||||
fuchsia::ui::test::scene::ControllerPtr scene_provider_;
|
||||
fuchsia::ui::observation::geometry::ViewTreeWatcherPtr view_tree_watcher_;
|
||||
|
||||
// Wrapped in optional since the view is not created until the middle of SetUp
|
||||
component_testing::RealmBuilder realm_builder_;
|
||||
std::unique_ptr<component_testing::RealmRoot> realm_;
|
||||
|
||||
// The typical latency on devices we've tested is ~60 msec. The retry interval
|
||||
// is chosen to be a) Long enough that it's unlikely that we send a new tap
|
||||
// while a previous tap is still being
|
||||
// processed. That is, it should be far more likely that a new tap is sent
|
||||
// because the first tap was lost, than because the system is just running
|
||||
// slowly.
|
||||
// b) Short enough that we don't slow down tryjobs.
|
||||
//
|
||||
// The first property is important to avoid skewing the latency metrics that
|
||||
// we collect. For an explanation of why a tap might be lost, see the
|
||||
// documentation for TryInject().
|
||||
static constexpr auto kTapRetryInterval = zx::sec(1);
|
||||
};
|
||||
|
||||
void FlutterEmbedderTest::SetUpRealmBase() {
|
||||
@@ -374,9 +328,6 @@ void FlutterEmbedderTest::LaunchParentViewInRealm(
|
||||
}
|
||||
realm_ = std::make_unique<RealmRoot>(realm_builder_.Build());
|
||||
|
||||
// Register fake touch screen device.
|
||||
RegisterTouchScreen();
|
||||
|
||||
// Instruct Test UI Stack to present parent-view's View.
|
||||
std::optional<zx_koid_t> view_ref_koid;
|
||||
scene_provider_ = realm_->Connect<fuchsia::ui::test::scene::Controller>();
|
||||
@@ -443,36 +394,6 @@ bool FlutterEmbedderTest::TakeScreenshotUntil(
|
||||
timeout);
|
||||
}
|
||||
|
||||
void FlutterEmbedderTest::RegisterTouchScreen() {
|
||||
FML_LOG(INFO) << "Registering fake touch screen";
|
||||
input_registry_ = realm_->Connect<fuchsia::ui::test::input::Registry>();
|
||||
input_registry_.set_error_handler(
|
||||
[](auto) { FML_LOG(ERROR) << "Error from input helper"; });
|
||||
bool touchscreen_registered = false;
|
||||
fuchsia::ui::test::input::RegistryRegisterTouchScreenRequest request;
|
||||
request.set_device(fake_touchscreen_.NewRequest());
|
||||
input_registry_->RegisterTouchScreen(
|
||||
std::move(request),
|
||||
[&touchscreen_registered]() { touchscreen_registered = true; });
|
||||
RunLoopUntil([&touchscreen_registered] { return touchscreen_registered; });
|
||||
FML_LOG(INFO) << "Touchscreen registered";
|
||||
}
|
||||
|
||||
void FlutterEmbedderTest::InjectTap(int32_t x, int32_t y) {
|
||||
fuchsia::ui::test::input::TouchScreenSimulateTapRequest tap_request;
|
||||
tap_request.mutable_tap_location()->x = x;
|
||||
tap_request.mutable_tap_location()->y = y;
|
||||
fake_touchscreen_->SimulateTap(std::move(tap_request), [x, y]() {
|
||||
FML_LOG(INFO) << "Tap injected at (" << x << ", " << y << ")";
|
||||
});
|
||||
}
|
||||
|
||||
void FlutterEmbedderTest::TryInject(int32_t x, int32_t y) {
|
||||
InjectTap(x, y);
|
||||
async::PostDelayedTask(
|
||||
dispatcher(), [this, x, y] { TryInject(x, y); }, kTapRetryInterval);
|
||||
}
|
||||
|
||||
TEST_F(FlutterEmbedderTest, Embedding) {
|
||||
LaunchParentViewInRealm();
|
||||
|
||||
@@ -489,53 +410,6 @@ TEST_F(FlutterEmbedderTest, Embedding) {
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_F(FlutterEmbedderTest, HittestEmbedding) {
|
||||
LaunchParentViewInRealm();
|
||||
|
||||
// Take screenshot until we see the child-view's embedded color.
|
||||
ASSERT_TRUE(TakeScreenshotUntil(kChildBackgroundColor));
|
||||
|
||||
// Simulate a tap at the center of the child view.
|
||||
TryInject(/* x = */ 0, /* y = */ 0);
|
||||
|
||||
// Take screenshot until we see the child-view's tapped color.
|
||||
ASSERT_TRUE(TakeScreenshotUntil(
|
||||
kChildTappedColor,
|
||||
[](std::map<fuchsia_test_utils::Color, size_t> histogram) {
|
||||
// Expect parent and child background colors, with parent color > child
|
||||
// color.
|
||||
EXPECT_GT(histogram[kParentBackgroundColor], 0u);
|
||||
EXPECT_EQ(histogram[kChildBackgroundColor], 0u);
|
||||
EXPECT_GT(histogram[kChildTappedColor], 0u);
|
||||
EXPECT_GT(histogram[kParentBackgroundColor],
|
||||
histogram[kChildTappedColor]);
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_F(FlutterEmbedderTest, HittestDisabledEmbedding) {
|
||||
LaunchParentViewInRealm({"--no-hitTestable"});
|
||||
|
||||
// Take screenshots until we see the child-view's embedded color.
|
||||
ASSERT_TRUE(TakeScreenshotUntil(kChildBackgroundColor));
|
||||
|
||||
// Simulate a tap at the center of the child view.
|
||||
TryInject(/* x = */ 0, /* y = */ 0);
|
||||
|
||||
// The parent-view should change color.
|
||||
ASSERT_TRUE(TakeScreenshotUntil(
|
||||
kParentTappedColor,
|
||||
[](std::map<fuchsia_test_utils::Color, size_t> histogram) {
|
||||
// Expect parent and child background colors, with parent color > child
|
||||
// color.
|
||||
EXPECT_EQ(histogram[kParentBackgroundColor], 0u);
|
||||
EXPECT_GT(histogram[kParentTappedColor], 0u);
|
||||
EXPECT_GT(histogram[kChildBackgroundColor], 0u);
|
||||
EXPECT_EQ(histogram[kChildTappedColor], 0u);
|
||||
EXPECT_GT(histogram[kParentTappedColor],
|
||||
histogram[kChildBackgroundColor]);
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_F(FlutterEmbedderTest, EmbeddingWithOverlay) {
|
||||
LaunchParentViewInRealm({"--showOverlay"});
|
||||
|
||||
@@ -555,33 +429,4 @@ TEST_F(FlutterEmbedderTest, EmbeddingWithOverlay) {
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_F(FlutterEmbedderTest, HittestEmbeddingWithOverlay) {
|
||||
LaunchParentViewInRealm({"--showOverlay"});
|
||||
|
||||
// Take screenshot until we see the child-view's embedded color.
|
||||
ASSERT_TRUE(TakeScreenshotUntil(kChildBackgroundColor));
|
||||
|
||||
// The bottom-left corner of the overlay is at the center of the screen,
|
||||
// which is at (0, 0) in the injection coordinate space. Inject a pointer
|
||||
// event just outside the overlay's bounds, and ensure that it goes to the
|
||||
// embedded view.
|
||||
TryInject(/* x = */ -1, /* y = */ 1);
|
||||
|
||||
// Take screenshot until we see the child-view's tapped color.
|
||||
ASSERT_TRUE(TakeScreenshotUntil(
|
||||
kChildTappedColor,
|
||||
[](std::map<fuchsia_test_utils::Color, size_t> histogram) {
|
||||
// Expect parent, overlay and child background colors.
|
||||
// With parent color > child color and overlay color > child color.
|
||||
const size_t overlay_pixel_count = OverlayPixelCount(histogram);
|
||||
EXPECT_GT(histogram[kParentBackgroundColor], 0u);
|
||||
EXPECT_GT(overlay_pixel_count, 0u);
|
||||
EXPECT_EQ(histogram[kChildBackgroundColor], 0u);
|
||||
EXPECT_GT(histogram[kChildTappedColor], 0u);
|
||||
EXPECT_GT(histogram[kParentBackgroundColor],
|
||||
histogram[kChildTappedColor]);
|
||||
EXPECT_GT(overlay_pixel_count, histogram[kChildTappedColor]);
|
||||
}));
|
||||
}
|
||||
|
||||
} // namespace flutter_embedder_test
|
||||
|
||||
@@ -13,6 +13,8 @@ dart_library("lib") {
|
||||
sources = [ "embedding-flutter-view.dart" ]
|
||||
|
||||
deps = [
|
||||
"//flutter/shell/platform/fuchsia/dart:args",
|
||||
"//flutter/shell/platform/fuchsia/dart:vector_math",
|
||||
"//flutter/tools/fuchsia/dart:fuchsia_services",
|
||||
"//flutter/tools/fuchsia/dart:zircon",
|
||||
"//flutter/tools/fuchsia/fidl:fuchsia.ui.app",
|
||||
|
||||
@@ -7,15 +7,37 @@ import 'dart:typed_data';
|
||||
import 'dart:io';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:args/args.dart';
|
||||
import 'package:fidl_fuchsia_ui_app/fidl_async.dart';
|
||||
import 'package:fidl_fuchsia_ui_views/fidl_async.dart';
|
||||
import 'package:fidl_fuchsia_ui_test_input/fidl_async.dart' as test_touch;
|
||||
import 'package:fuchsia_services/services.dart';
|
||||
import 'package:vector_math/vector_math_64.dart' as vector_math_64;
|
||||
import 'package:zircon/zircon.dart';
|
||||
|
||||
final _argsCsvFilePath = '/config/data/args.csv';
|
||||
|
||||
void main(List<String> args) {
|
||||
print('Launching embedding-flutter-view');
|
||||
TestApp app = TestApp(ChildView.gfx(_launchGfxChildView()));
|
||||
|
||||
args = args + _GetArgsFromConfigFile();
|
||||
final parser = ArgParser()
|
||||
..addFlag('showOverlay', defaultsTo: false)
|
||||
..addFlag('hitTestable', defaultsTo: true)
|
||||
..addFlag('focusable', defaultsTo: true);
|
||||
|
||||
final arguments = parser.parse(args);
|
||||
for (final option in arguments.options) {
|
||||
print('embedding-flutter-view args: $option: ${arguments[option]}');
|
||||
}
|
||||
|
||||
TestApp app = TestApp(
|
||||
ChildView.gfx(_launchGfxChildView()),
|
||||
showOverlay: arguments['showOverlay'],
|
||||
hitTestable: arguments['hitTestable'],
|
||||
focusable: arguments['focusable'],
|
||||
);
|
||||
|
||||
app.run();
|
||||
}
|
||||
|
||||
@@ -24,14 +46,22 @@ class TestApp {
|
||||
static const _blue = Color.fromARGB(255, 0, 0, 255);
|
||||
|
||||
final ChildView childView;
|
||||
final bool showOverlay;
|
||||
final bool hitTestable;
|
||||
final bool focusable;
|
||||
final _responseListener = test_touch.TouchInputListenerProxy();
|
||||
|
||||
Color _backgroundColor = _blue;
|
||||
|
||||
TestApp(this.childView) {}
|
||||
TestApp(
|
||||
this.childView,
|
||||
{this.showOverlay = false,
|
||||
this.hitTestable = true,
|
||||
this.focusable = true}) {
|
||||
}
|
||||
|
||||
void run() {
|
||||
childView.create((ByteData reply) {
|
||||
childView.create(hitTestable, focusable, (ByteData reply) {
|
||||
// Set up window callbacks.
|
||||
window.onPointerDataPacket = (PointerDataPacket packet) {
|
||||
this.pointerDataPacket(packet);
|
||||
@@ -67,13 +97,52 @@ class TestApp {
|
||||
final sceneBuilder = SceneBuilder()
|
||||
..pushClipRect(physicalBounds)
|
||||
..addPicture(Offset.zero, picture);
|
||||
// Child view should take up half the screen
|
||||
final childPhysicalSize = window.physicalSize * 0.5;
|
||||
|
||||
final childPhysicalSize = window.physicalSize * 0.25;
|
||||
// Alignment.center
|
||||
final windowCenter = size.center(Offset.zero);
|
||||
final windowPhysicalCenter = window.physicalSize.center(Offset.zero);
|
||||
final childPhysicalOffset = windowPhysicalCenter - childPhysicalSize.center(Offset.zero);
|
||||
|
||||
sceneBuilder
|
||||
..pushTransform(
|
||||
vector_math_64.Matrix4.translationValues(childPhysicalOffset.dx,
|
||||
childPhysicalOffset.dy,
|
||||
0.0).storage)
|
||||
..addPlatformView(childView.viewId,
|
||||
width: childPhysicalSize.width,
|
||||
height: size.height)
|
||||
height: childPhysicalSize.height)
|
||||
..pop();
|
||||
|
||||
if (showOverlay) {
|
||||
final containerSize = size * 0.5;
|
||||
// Alignment.center
|
||||
final containerOffset = windowCenter - containerSize.center(Offset.zero);
|
||||
|
||||
final overlaySize = containerSize * 0.5;
|
||||
// Alignment.topRight
|
||||
final overlayOffset = Offset(
|
||||
containerOffset.dx + containerSize.width - overlaySize.width,
|
||||
containerOffset.dy);
|
||||
final overlayPhysicalSize = overlaySize * pixelRatio;
|
||||
final overlayPhysicalOffset = overlayOffset * pixelRatio;
|
||||
final overlayPhysicalBounds = overlayPhysicalOffset & overlayPhysicalSize;
|
||||
|
||||
final recorder = PictureRecorder();
|
||||
final overlayCullRect = Offset.zero & overlayPhysicalSize; // in canvas physical coordinates
|
||||
final canvas = Canvas(recorder, overlayCullRect);
|
||||
canvas.scale(pixelRatio);
|
||||
|
||||
final paint = Paint()..color = Color.fromARGB(255, 0, 255, 0);
|
||||
canvas.drawRect(Offset.zero & overlaySize, paint);
|
||||
|
||||
final overlayPicture = recorder.endRecording();
|
||||
sceneBuilder
|
||||
..pushClipRect(overlayPhysicalBounds) // in window physical coordinates
|
||||
..addPicture(overlayPhysicalOffset, overlayPicture)
|
||||
..pop();
|
||||
}
|
||||
|
||||
sceneBuilder.pop();
|
||||
window.render(sceneBuilder.build());
|
||||
}
|
||||
@@ -124,15 +193,18 @@ class ChildView {
|
||||
assert(viewId != null);
|
||||
}
|
||||
|
||||
void create(PlatformMessageResponseCallback callback) {
|
||||
void create(
|
||||
bool hitTestable,
|
||||
bool focusable,
|
||||
PlatformMessageResponseCallback callback) {
|
||||
// Construct the dart:ui platform message to create the view, and when the
|
||||
// return callback is invoked, build the scene. At that point, it is safe
|
||||
// to embed the child view in the scene.
|
||||
final viewOcclusionHint = Rect.zero;
|
||||
final Map<String, dynamic> args = <String, dynamic>{
|
||||
'viewId': viewId,
|
||||
'hitTestable': true,
|
||||
'focusable': true,
|
||||
'hitTestable': hitTestable,
|
||||
'focusable': focusable,
|
||||
'viewOcclusionHintLTRB': <double>[
|
||||
viewOcclusionHint.left,
|
||||
viewOcclusionHint.top,
|
||||
@@ -173,3 +245,14 @@ ViewHolderToken _launchGfxChildView() {
|
||||
|
||||
return viewHolderToken;
|
||||
}
|
||||
|
||||
List<String> _GetArgsFromConfigFile() {
|
||||
List<String> args;
|
||||
final f = File(_argsCsvFilePath);
|
||||
if (!f.existsSync()) {
|
||||
return List.empty();
|
||||
}
|
||||
final fileContentCsv = f.readAsStringSync();
|
||||
args = fileContentCsv.split('\n');
|
||||
return args;
|
||||
}
|
||||
|
||||
@@ -112,6 +112,7 @@ namespace {
|
||||
// Types imported for the realm_builder library.
|
||||
using component_testing::ChildRef;
|
||||
using component_testing::ConfigValue;
|
||||
using component_testing::DirectoryContents;
|
||||
using component_testing::LocalComponent;
|
||||
using component_testing::LocalComponentHandles;
|
||||
using component_testing::ParentRef;
|
||||
@@ -324,6 +325,57 @@ class FlutterTapTest : public FlutterTapTestBase {
|
||||
};
|
||||
|
||||
class FlutterEmbedTapTest : public FlutterTapTestBase {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
PortableUITest::SetUp(false);
|
||||
|
||||
// Post a "just in case" quit task, if the test hangs.
|
||||
async::PostDelayedTask(
|
||||
dispatcher(),
|
||||
[] {
|
||||
FML_LOG(FATAL)
|
||||
<< "\n\n>> Test did not complete in time, terminating. <<\n\n";
|
||||
},
|
||||
kTimeout);
|
||||
}
|
||||
|
||||
void LaunchClientWithEmbeddedView() {
|
||||
BuildRealm();
|
||||
|
||||
// Get the display dimensions.
|
||||
FML_LOG(INFO) << "Waiting for scenic display info";
|
||||
scenic_ = realm_root()->template Connect<fuchsia::ui::scenic::Scenic>();
|
||||
scenic_->GetDisplayInfo([this](fuchsia::ui::gfx::DisplayInfo display_info) {
|
||||
display_width_ = display_info.width_in_px;
|
||||
display_height_ = display_info.height_in_px;
|
||||
FML_LOG(INFO) << "Got display_width = " << display_width_
|
||||
<< " and display_height = " << display_height_;
|
||||
});
|
||||
RunLoopUntil(
|
||||
[this] { return display_width_ != 0 && display_height_ != 0; });
|
||||
|
||||
// Register input injection device.
|
||||
FML_LOG(INFO) << "Registering input injection device";
|
||||
RegisterTouchScreen();
|
||||
|
||||
PortableUITest::LaunchClientWithEmbeddedView();
|
||||
}
|
||||
|
||||
// Helper method to add a component argument
|
||||
// This will be written into an args.csv file that can be parsed and read
|
||||
// by embedding-flutter-view.dart
|
||||
//
|
||||
// Note: You must call this method before LaunchClientWithEmbeddedView()
|
||||
// Realm Builder will not allow you to create a new directory / file in a
|
||||
// realm that's already been built
|
||||
void AddComponentArgument(std::string component_arg) {
|
||||
auto config_directory_contents = DirectoryContents();
|
||||
config_directory_contents.AddFile("args.csv", component_arg);
|
||||
realm_builder()->RouteReadOnlyDirectory(
|
||||
"config-data", {kEmbeddingFlutterViewRef},
|
||||
std::move(config_directory_contents));
|
||||
}
|
||||
|
||||
private:
|
||||
void ExtendRealm() override {
|
||||
FML_LOG(INFO) << "Extending realm";
|
||||
@@ -392,6 +444,9 @@ TEST_P(FlutterTapTest, FlutterTap) {
|
||||
/*expected_y=*/static_cast<float>(display_height() / 4.0f),
|
||||
/*component_name=*/"touch-input-view");
|
||||
});
|
||||
|
||||
// There should be 1 injected tap
|
||||
ASSERT_EQ(touch_injection_request_count(), 1);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(FlutterEmbedTapTestParameterized,
|
||||
@@ -405,19 +460,19 @@ TEST_P(FlutterEmbedTapTest, FlutterEmbedTap) {
|
||||
FML_LOG(INFO) << "Client launched";
|
||||
|
||||
{
|
||||
// Embedded child view takes up the left side of the screen
|
||||
// Embedded child view takes up the center of the screen
|
||||
// Expect a response from the child view if we inject a tap there
|
||||
InjectTap(-500, -500);
|
||||
InjectTap(0, 0);
|
||||
RunLoopUntil([this] {
|
||||
return LastEventReceivedMatches(
|
||||
/*expected_x=*/static_cast<float>(display_width() / 4.0f),
|
||||
/*expected_y=*/static_cast<float>(display_height() / 4.0f),
|
||||
/*expected_x=*/static_cast<float>(display_width() / 8.0f),
|
||||
/*expected_y=*/static_cast<float>(display_height() / 8.0f),
|
||||
/*component_name=*/"touch-input-view");
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
// Parent view takes up the right side of the screen
|
||||
// Parent view takes up the rest of the screen
|
||||
// Validate that parent can still receive taps
|
||||
InjectTap(500, 500);
|
||||
RunLoopUntil([this] {
|
||||
@@ -432,5 +487,63 @@ TEST_P(FlutterEmbedTapTest, FlutterEmbedTap) {
|
||||
ASSERT_EQ(touch_injection_request_count(), 2);
|
||||
}
|
||||
|
||||
TEST_P(FlutterEmbedTapTest, FlutterEmbedHittestDisabled) {
|
||||
FML_LOG(INFO) << "Initializing scene";
|
||||
AddComponentArgument("--no-hitTestable");
|
||||
LaunchClientWithEmbeddedView();
|
||||
FML_LOG(INFO) << "Client launched";
|
||||
|
||||
// Embedded child view takes up the center of the screen
|
||||
// hitTestable is turned off for the embedded child view
|
||||
// Expect the parent (embedding-flutter-view) to respond if we inject a tap
|
||||
// there
|
||||
InjectTap(0, 0);
|
||||
RunLoopUntil([this] {
|
||||
return LastEventReceivedMatches(
|
||||
/*expected_x=*/static_cast<float>(display_width() / 2.0f),
|
||||
/*expected_y=*/static_cast<float>(display_height() / 2.0f),
|
||||
/*component_name=*/"embedding-flutter-view");
|
||||
});
|
||||
|
||||
// There should be 1 injected tap
|
||||
ASSERT_EQ(touch_injection_request_count(), 1);
|
||||
}
|
||||
|
||||
TEST_P(FlutterEmbedTapTest, FlutterEmbedOverlayEnabled) {
|
||||
FML_LOG(INFO) << "Initializing scene";
|
||||
AddComponentArgument("--showOverlay");
|
||||
LaunchClientWithEmbeddedView();
|
||||
FML_LOG(INFO) << "Client launched";
|
||||
|
||||
{
|
||||
// The bottom-left corner of the overlay is at the center of the screen
|
||||
// Expect the overlay / parent view to respond if we inject a tap there
|
||||
// and not the embedded child view
|
||||
InjectTap(0, 0);
|
||||
RunLoopUntil([this] {
|
||||
return LastEventReceivedMatches(
|
||||
/*expected_x=*/static_cast<float>(display_width() / 2.0f),
|
||||
/*expected_y=*/static_cast<float>(display_height() / 2.0f),
|
||||
/*component_name=*/"embedding-flutter-view");
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
// The embedded child view is just outside of the bottom-left corner of the
|
||||
// overlay
|
||||
// Expect the embedded child view to still receive taps
|
||||
InjectTap(-1, -1);
|
||||
RunLoopUntil([this] {
|
||||
return LastEventReceivedMatches(
|
||||
/*expected_x=*/static_cast<float>(display_width() / 8.0f),
|
||||
/*expected_y=*/static_cast<float>(display_height() / 8.0f),
|
||||
/*component_name=*/"touch-input-view");
|
||||
});
|
||||
}
|
||||
|
||||
// There should be 2 injected taps
|
||||
ASSERT_EQ(touch_injection_request_count(), 2);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace touch_input_test::testing
|
||||
|
||||
@@ -69,6 +69,10 @@ class TestApp {
|
||||
for (PointerData data in packet.data) {
|
||||
print('touch-input-view received tap: ${data.toStringFull()}');
|
||||
|
||||
if (data.change == PointerChange.down) {
|
||||
this._backgroundColor = _yellow;
|
||||
}
|
||||
|
||||
if (data.change == PointerChange.down || data.change == PointerChange.move) {
|
||||
Incoming.fromSvcPath()
|
||||
..connectToService(_responseListener)
|
||||
|
||||
@@ -29,9 +29,16 @@ using fuchsia_test_utils::CheckViewExistsInSnapshot;
|
||||
|
||||
} // namespace
|
||||
|
||||
void PortableUITest::SetUp() {
|
||||
void PortableUITest::SetUp(bool build_realm) {
|
||||
SetUpRealmBase();
|
||||
ExtendRealm();
|
||||
|
||||
if (build_realm) {
|
||||
BuildRealm();
|
||||
}
|
||||
}
|
||||
|
||||
void PortableUITest::BuildRealm() {
|
||||
realm_ = std::make_unique<RealmRoot>(realm_builder_.Build());
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,11 @@ class PortableUITest : public ::loop_fixture::RealLoop {
|
||||
"flutter_jit_runner.cm";
|
||||
static constexpr auto kFlutterRunnerEnvironment = "flutter_runner_env";
|
||||
|
||||
void SetUp();
|
||||
void SetUp(bool build_realm = true);
|
||||
|
||||
// Calls the Build method for Realm Builder to build the realm
|
||||
// Can only be called once, panics otherwise
|
||||
void BuildRealm();
|
||||
|
||||
// Attaches a client view to the scene, and waits for it to render.
|
||||
void LaunchClient();
|
||||
|
||||
Reference in New Issue
Block a user