| # Test UI Stack | |
| ## Overview | |
| The Test UI Stack is a Fuchsia package that leverages the | |
| [UITestRealm](../ui_test_realm/README.md) library to streamline UI realm setup | |
| for tests that depend on or interoperate with a UI layer, but that may not be | |
| concerned with the details of setting up that UI layer. | |
| The Test UI Stack provides UI-specific testing capabilities to test clients both in- | |
| and out-of-tree. See the | |
| [Test UI Stack RFC](///docs/contribute/governance/rfcs/0180_test_ui_stack.md) | |
| for more details. | |
| ## Scene Setup | |
| The Test UI Stack always creates a Scene Manager-owner scene with Scenic, | |
| accessibility protocols through a Fake A11y Manager, and production-like input | |
| support through the Input Pipeline library (integrated as a part of Scene Manager). | |
| ## Configurability | |
| The Test UI Stack supports configuring the underlying UITestRealm instance | |
| using the following arguments via Structured Configuration: | |
| - **display_rotation**: The rotation of the display, counter-clockwise, in 90-degree increments. | |
| - **display_width_px**: Width of the display, in pixels. | |
| - **display_height_px**: Height of the display, in pixels. | |
| - **display_refresh_rate_millihertz**: Refresh rate of the display, in millihertz (1/1000 Hz). | |
| - **device_pixel_ratio**: The conversion factor between logical and physical coordinates. | |
| ## Example Usage | |
| The pseudo-C++ snippet below outlines a basic touch input test using the Test UI | |
| Stack component. | |
| ``` | |
| // Client test code creates a RealmBuilder instance. | |
| component_testing::RealmBuilder realm_builder; | |
| // Instantiate Test UI Stack component by absolute URL in the test realm. | |
| realm_builder.AddChild("test-ui-stack", | |
| "fuchsia-pkg://fuchsia.com/test-ui-stack#meta/test-ui-stack.cm"); | |
| // Add a test view component to the test realm, and route required UI services | |
| // to it. | |
| realm_builder.AddChild("test-view", ...); | |
| realm_builder.AddRoute({ | |
| .capabilities = {Protocol{fuchsia::ui::scenic::Scenic::Name_}}, | |
| .source = ChildRef{"test-ui-stack"}, | |
| .targets = {"test-view"}}); | |
| // Expose fuchsia.ui.app.ViewProvider from the test view. | |
| realm_builder.AddRoute({ | |
| .capabilities = {Protocol{fuchsia::ui::app::ViewProvider::Name_}}, | |
| .source = ChildRef{"test-view"}, | |
| .targets = {ParentRef()}}); | |
| // Build the test realm. | |
| RealmRoot realm_root = realm_builder_.Build(); | |
| // Connect to the scene provider "helper service", and request to attach a | |
| // test view to the scene. | |
| std::optional<zx_koid_t> client_view_ref_koid; | |
| fuchsia::ui::observation::geometry::Provider geometry_provider; | |
| auto scene_provider = realm_root->Connect<fuchsia::ui::test::scene::Provider>(); | |
| auto view_provider = realm_root_->Connect<fuchsia::ui::app::ViewProvider>(); | |
| scene_provider->AttachView(std::move(view_provider), geometry_provider.NewRequest(), | |
| [&client_view_ref_koid](auto view_ref_koid) { | |
| // Save the client's ViewRef koid. | |
| client_view_ref_koid = view_ref_koid; | |
| }); | |
| // Wait for client view ref koid to become available. | |
| RunLoopUntil([&client_view_ref_koid] { | |
| return client_view_ref_koid.has_value(); | |
| }); | |
| // Use registered geometry provider to wait for client view to render. | |
| ASSERT_TRUE(geometry_provider.is_bound()); | |
| geometry_provider.Watch(...); | |
| RunLoopUntil(...); | |
| // Connect to input synthesis helper service, and use to inject input. | |
| auto input_synthesis = realm_root->Connect<fuchsia::ui::test::input::Touch>(); | |
| input_synthesis->InjectTap(...); | |
| ``` |