Flutter Windows Embedder
accessibility_plugin_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
6 
7 #include <memory>
8 
13 #include "flutter/shell/platform/windows/testing/engine_modifier.h"
14 #include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h"
15 #include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h"
16 #include "flutter/shell/platform/windows/testing/test_binary_messenger.h"
17 #include "flutter/shell/platform/windows/testing/windows_test.h"
18 #include "gmock/gmock.h"
19 #include "gtest/gtest.h"
20 
21 namespace flutter {
22 namespace testing {
23 
24 namespace {
25 
26 using ::testing::_;
27 using ::testing::NiceMock;
28 
29 static constexpr char kAccessibilityChannelName[] = "flutter/accessibility";
30 
31 class MockFlutterWindowsView : public FlutterWindowsView {
32  public:
33  MockFlutterWindowsView(FlutterWindowsEngine* engine,
34  std::unique_ptr<WindowBindingHandler> window)
36  engine,
37  std::move(window),
38  false,
39  BoxConstraints()) {}
40 
41  MOCK_METHOD(void, AnnounceAlert, (const std::wstring& text), ());
42 };
43 
44 } // namespace
45 
46 class AccessibilityPluginTest : public WindowsTest {
47  public:
49  virtual ~AccessibilityPluginTest() = default;
50 
51  protected:
52  FlutterWindowsEngine* engine() { return engine_.get(); }
53  TestBinaryMessenger* messenger() { return &messenger_; }
54 
55  void SetUp() override {
56  WindowsTest::SetUp();
57 
58  FlutterWindowsEngineBuilder builder{GetContext()};
59  engine_ = builder.Build();
60 
61  auto window = std::make_unique<NiceMock<MockWindowBindingHandler>>();
62  view_ = std::make_unique<NiceMock<MockFlutterWindowsView>>(
63  engine_.get(), std::move(window));
64 
65  EngineModifier modifier{engine_.get()};
66  modifier.SetSemanticsEnabled(true);
67  modifier.SetImplicitView(view_.get());
68 
69  plugin_ = std::make_unique<AccessibilityPlugin>(engine_.get());
70  AccessibilityPlugin::SetUp(&messenger_, plugin_.get());
71  }
72 
73  void SendAnnounceMessage(const std::string& message, EncodableValue view_id) {
74  EncodableMap data;
75  data[EncodableValue{"message"}] = EncodableValue{message};
76  data[EncodableValue{"viewId"}] = view_id;
77 
78  EncodableMap msg;
79  msg[EncodableValue{"type"}] = EncodableValue{"announce"};
80  msg[EncodableValue{"data"}] = EncodableValue{data};
81 
82  auto encoded =
84 
85  bool handled = messenger_.SimulateEngineMessage(
86  kAccessibilityChannelName, encoded->data(), encoded->size(),
87  [](const uint8_t* reply, size_t reply_size) {});
88 
89  EXPECT_TRUE(handled)
90  << "Message was not handled by the accessibility channel";
91  }
92 
93  MockFlutterWindowsView* view() { return view_.get(); }
94 
95  private:
96  std::unique_ptr<FlutterWindowsEngine> engine_;
97  std::unique_ptr<MockFlutterWindowsView> view_;
98  std::unique_ptr<AccessibilityPlugin> plugin_;
99  TestBinaryMessenger messenger_;
100 };
101 
102 TEST_F(AccessibilityPluginTest, DirectAnnounceCall) {
103  // Test calling Announce directly, bypassing the message channel
104  EXPECT_CALL(*view(), AnnounceAlert(::testing::Eq(L"Direct"))).Times(1);
105 
106  AccessibilityPlugin plugin(engine());
107  plugin.Announce(0, "Direct");
108 
109  ::testing::Mock::VerifyAndClearExpectations(view());
110 }
111 
112 TEST_F(AccessibilityPluginTest, AnnounceWithInt32ViewId) {
113  EXPECT_CALL(*view(), AnnounceAlert(::testing::Eq(L"Hello"))).Times(1);
114 
115  SendAnnounceMessage("Hello", EncodableValue{static_cast<int32_t>(0)});
116 
117  // Verify expectations are met
118  ::testing::Mock::VerifyAndClearExpectations(view());
119 }
120 
121 TEST_F(AccessibilityPluginTest, AnnounceWithInt64ViewId) {
122  EXPECT_CALL(*view(), AnnounceAlert(::testing::Eq(L"Hello World"))).Times(1);
123 
124  SendAnnounceMessage("Hello World", EncodableValue{static_cast<int64_t>(0)});
125 
126  // Verify expectations are met
127  ::testing::Mock::VerifyAndClearExpectations(view());
128 }
129 
130 TEST_F(AccessibilityPluginTest, AnnounceWithInvalidViewIdType) {
131  // Should not be called with invalid viewId type
132  EXPECT_CALL(*view(), AnnounceAlert(_)).Times(0);
133 
134  SendAnnounceMessage("Hello", EncodableValue{"invalid"});
135 }
136 TEST_F(AccessibilityPluginTest, AnnounceWithMissingMessage) {
137  // Should not be called when message is missing
138  EXPECT_CALL(*view(), AnnounceAlert(_)).Times(0);
139 
140  EncodableMap data;
141  data[EncodableValue{"viewId"}] = EncodableValue{static_cast<int32_t>(0)};
142 
143  EncodableMap msg;
144  msg[EncodableValue{"type"}] = EncodableValue{"announce"};
145  msg[EncodableValue{"data"}] = EncodableValue{data};
146 
147  auto encoded =
149 
150  messenger()->SimulateEngineMessage(
151  kAccessibilityChannelName, encoded->data(), encoded->size(),
152  [](const uint8_t* reply, size_t reply_size) {});
153 }
154 
155 } // namespace testing
156 } // namespace flutter
static void SetUp(BinaryMessenger *binary_messenger, AccessibilityPlugin *plugin)
virtual void Announce(const FlutterViewId view_id, const std::string_view message)
FlutterWindowsView(FlutterViewId view_id, FlutterWindowsEngine *engine, std::unique_ptr< WindowBindingHandler > window_binding, bool is_sized_to_content, const BoxConstraints &box_constraints, FlutterWindowsViewSizingDelegate *sizing_delegate=nullptr, std::shared_ptr< WindowsProcTable > windows_proc_table=nullptr)
std::unique_ptr< std::vector< uint8_t > > EncodeMessage(const T &message) const
Definition: message_codec.h:45
static const StandardMessageCodec & GetInstance(const StandardCodecSerializer *serializer=nullptr)
void SendAnnounceMessage(const std::string &message, EncodableValue view_id)
MOCK_METHOD(void, NotifyWinEventWrapper,(ui::AXPlatformNodeWin *, ax::mojom::Event),(override))
MockFlutterWindowsView(FlutterWindowsEngine *engine, std::unique_ptr< WindowBindingHandler > wbh)
static constexpr char kAccessibilityChannelName[]
std::u16string text
Win32Message message
TEST_F(AccessibilityPluginTest, DirectAnnounceCall)
std::map< EncodableValue, EncodableValue > EncodableMap
constexpr FlutterViewId kImplicitViewId