1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "gtest/gtest.h"
16
17 #define private public
18 #define protected public
19 #include "test/mock/core/common/mock_resource_adapter.h"
20 #include "test/mock/core/common/mock_theme_manager.h"
21 #include "test/mock/core/pipeline/mock_pipeline_context.h"
22 #include "test/mock/core/render/mock_render_context.h"
23 #include "test/unittest/core/event/focus_core/focus_test_base.h"
24 #include "test/unittest/core/event/focus_core/page_focus_switch_test.h"
25 #include "test/unittest/core/pattern/test_ng.h"
26
27 #include "base/log/log_wrapper.h"
28 #include "core/components/container_modal/container_modal_constants.h"
29 #include "core/components/flex/flex_element.h"
30 #include "core/components/theme/theme_constants.h"
31 #include "core/components_ng/base/ui_node.h"
32 #include "core/components_ng/base/view_stack_processor.h"
33 #include "core/components_ng/event/focus_hub.h"
34 #include "core/components_ng/pattern/bubble/bubble_pattern.h"
35 #include "core/components_ng/pattern/button/button_pattern.h"
36 #include "core/components_ng/pattern/container_modal/container_modal_pattern.h"
37 #include "core/components_ng/pattern/container_modal/container_modal_theme.h"
38 #include "core/components_ng/pattern/container_modal/container_modal_view.h"
39 #include "core/components_ng/pattern/dialog/dialog_pattern.h"
40 #include "core/components_ng/pattern/image/image_layout_property.h"
41 #include "core/components_ng/pattern/image/image_pattern.h"
42 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
43 #include "core/components_ng/pattern/menu/menu_pattern.h"
44 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
45 #include "core/components_ng/pattern/pattern.h"
46 #include "core/components_ng/pattern/root/root_pattern.h"
47 #include "core/components_ng/pattern/stack/stack_pattern.h"
48 #include "core/components_ng/pattern/text/text_pattern.h"
49 #include "core/components_ng/pattern/text_picker/textpicker_column_pattern.h"
50 #include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h"
51 #include "core/event/focus_axis_event.h"
52 #include "core/event/key_event.h"
53 #include "core/pipeline/base/composed_element.h"
54 #include "core/pipeline_ng/pipeline_context.h"
55 #include "frameworks/bridge/common/utils/engine_helper.h"
56
57 using namespace testing;
58 using namespace testing::ext;
59 namespace OHOS::Ace::NG {
60
61 struct PageFocusSwitchCase {
62 std::string newPageType;
63 bool isAutoFocusTransfer;
64 bool isHasDefaultFocus;
65 bool expectResults;
PageFocusSwitchCaseOHOS::Ace::NG::PageFocusSwitchCase66 PageFocusSwitchCase(
67 const std::string& newPageType, bool isAutoFocusTransfer, bool isHasDefaultFocus, bool expectResults)
68 : newPageType(newPageType), isAutoFocusTransfer(isAutoFocusTransfer), isHasDefaultFocus(isHasDefaultFocus),
69 expectResults(expectResults)
70 {}
71 };
72
73 const std::vector<PageFocusSwitchCase> PAGE_FOCUS_SWITCH_CASE = { PageFocusSwitchCase("page", true, true, true),
74 PageFocusSwitchCase("page", true, false, true), PageFocusSwitchCase("dialog", true, true, true),
75 PageFocusSwitchCase("menu", true, true, true), PageFocusSwitchCase("popup", true, true, true),
76 PageFocusSwitchCase("modalpage", true, true, true), PageFocusSwitchCase("sheetpag", true, true, true),
77 PageFocusSwitchCase("navigation", true, true, true), PageFocusSwitchCase("navbar", true, true, true),
78 PageFocusSwitchCase("navdestination", true, true, true), PageFocusSwitchCase("windowscene", true, true, true) };
79
SetUpTestSuite()80 void PageFocusSwitchTestNG::SetUpTestSuite()
81 {
82 MockPipelineContext::SetUp();
83 GTEST_LOG_(INFO) << "PageFocusSwitchTestNG SetUpTestCase";
84 }
85
TearDownTestSuite()86 void PageFocusSwitchTestNG::TearDownTestSuite()
87 {
88 MockPipelineContext::TearDown();
89 GTEST_LOG_(INFO) << "PageFocusSwitchTestNG TearDownTestCase";
90 }
91
92 HWTEST_F(PageFocusSwitchTestNG, FocusWindowTestNG001, TestSize.Level1)
93 {
94 int32_t caseNum = 1;
95 bool initResult = InitFocusTestBaseNG();
96 EXPECT_TRUE(initResult);
97 for (const auto& testCase : PAGE_FOCUS_SWITCH_CASE) {
98 // get newPageType and creat node tree
99 if (testCase.newPageType == "Page") {
100 // creat root node
101 auto rootNode = FrameNodeOnTree::CreateFrameNode(V2::ROOT_ETS_TAG, -1, AceType::MakeRefPtr<RootPattern>());
102 auto rootFocusHub = rootNode->GetOrCreateFocusHub();
103 // creat node
104 auto oldpagePattern = AceType::MakeRefPtr<PagePattern>(AceType::MakeRefPtr<PageInfo>());
105 auto oldPageNode = FrameNodeOnTree::CreateFrameNode(V2::PAGE_ETS_TAG, -1, oldpagePattern);
106 auto oldFocusHub = oldPageNode->GetOrCreateFocusHub();
107 rootNode->AddChild(oldPageNode);
108 auto focusManager = PipelineContext::GetCurrentContext()->GetFocusManager();
109 if (testCase.isAutoFocusTransfer) {
110 auto delegate = EngineHelper::GetCurrentDelegateSafely();
111 CHECK_NULL_VOID(delegate);
112 delegate->SetAutoFocusTransfer(testCase.isAutoFocusTransfer);
113 }
114 auto newpagePattern = AceType::MakeRefPtr<PagePattern>(AceType::MakeRefPtr<PageInfo>());
115 auto newPageNode = FrameNodeOnTree::CreateFrameNode(V2::PAGE_ETS_TAG, -1, newpagePattern);
116 auto newFocusHub = newPageNode->GetOrCreateFocusHub();
117 oldPageNode->AddChild(newPageNode);
118 // set default focus
119 if (testCase.isHasDefaultFocus) {
120 oldFocusHub->SetDefaultFocusNode(newFocusHub);
121 }
122 // check old node lost focus ,new node get focus
123 auto currentFocusNode = focusManager_->GetFocusManager(newPageNode);
124 EXPECT_EQ(oldPageNode, currentFocusNode);
125 EXPECT_NE(newPageNode, currentFocusNode);
126 } else if (testCase.newPageType == "dialog") {
127 auto rootNode = FrameNodeOnTree::CreateFrameNode(V2::ROOT_ETS_TAG, -1, AceType::MakeRefPtr<RootPattern>());
128 auto rootFocusHub = rootNode->GetOrCreateFocusHub();
129 auto dialogPattern = AceType::MakeRefPtr<DialogPattern>(nullptr, nullptr);
130 auto oldDialogNode = FrameNodeOnTree::CreateFrameNode(V2::DIALOG_ETS_TAG, -1, dialogPattern);
131 auto oldFocusHub = oldDialogNode->GetOrCreateFocusHub();
132 rootNode->AddChild(oldDialogNode);
133 if (testCase.isAutoFocusTransfer) {
134 auto delegate = EngineHelper::GetCurrentDelegateSafely();
135 CHECK_NULL_VOID(delegate);
136 delegate->SetAutoFocusTransfer(testCase.isAutoFocusTransfer);
137 }
138 auto newdialogPattern = AceType::MakeRefPtr<DialogPattern>(nullptr, nullptr);
139 auto newDialogNode = FrameNodeOnTree::CreateFrameNode(V2::DIALOG_ETS_TAG, -1, newdialogPattern);
140 auto newFocusHub = newDialogNode->GetOrCreateFocusHub();
141 oldDialogNode->AddChild(newDialogNode);
142
143 if (testCase.isHasDefaultFocus) {
144 oldFocusHub->SetDefaultFocusNode(newFocusHub);
145 }
146 auto currentFocusNode = focusManager_->GetFocusManager(newDialogNode);
147 CHECK_NULL_VOID(currentFocusNode);
148 EXPECT_EQ(oldDialogNode, currentFocusNode);
149 EXPECT_NE(newDialogNode, currentFocusNode);
150
151 } else if (testCase.newPageType == "menu") {
152 auto rootNode = FrameNodeOnTree::CreateFrameNode(V2::ROOT_ETS_TAG, -1, AceType::MakeRefPtr<RootPattern>());
153 auto rootFocusHub = rootNode->GetOrCreateFocusHub();
154 auto menuPattern = AceType::MakeRefPtr<MenuPattern>(-1, "Menu", MenuType::MENU);
155 auto oldMenuNode = FrameNodeOnTree::CreateFrameNode(V2::MENU_ETS_TAG, -1, menuPattern);
156 auto focusManager = PipelineContext::GetCurrentContext()->GetFocusManager();
157 auto oldFocusHub = oldMenuNode->GetOrCreateFocusHub();
158 rootNode->AddChild(oldMenuNode);
159 if (testCase.isAutoFocusTransfer) {
160 auto delegate = EngineHelper::GetCurrentDelegateSafely();
161 CHECK_NULL_VOID(delegate);
162 delegate->SetAutoFocusTransfer(testCase.isAutoFocusTransfer);
163 }
164 auto newMenuNode = FrameNodeOnTree::CreateFrameNode(V2::MENU_ETS_TAG, -1, menuPattern);
165 auto newFocusHub = newMenuNode->GetOrCreateFocusHub();
166 oldMenuNode->AddChild(newMenuNode);
167 if (testCase.isHasDefaultFocus) {
168 oldFocusHub->SetDefaultFocusNode(newFocusHub);
169 }
170 auto currentFocusNode = focusManager_->GetFocusManager(newMenuNode);
171 CHECK_NULL_VOID(currentFocusNode);
172 EXPECT_EQ(oldMenuNode, currentFocusNode);
173 EXPECT_NE(newMenuNode, currentFocusNode);
174 } else if (testCase.newPageType == "popup") {
175 auto rootNode = FrameNodeOnTree::CreateFrameNode(V2::ROOT_ETS_TAG, -1, AceType::MakeRefPtr<RootPattern>());
176 auto rootFocusHub = rootNode->GetOrCreateFocusHub();
177 auto bubblePattern = AceType::MakeRefPtr<BubblePattern>();
178 auto oldPopupNode = FrameNodeOnTree::CreateFrameNode(V2::POPUP_ETS_TAG, -1, bubblePattern);
179 auto focusManager = PipelineContext::GetCurrentContext()->GetFocusManager();
180 auto oldFocusHub = oldPopupNode->GetOrCreateFocusHub();
181 rootNode->AddChild(oldPopupNode);
182 if (testCase.isAutoFocusTransfer) {
183 auto delegate = EngineHelper::GetCurrentDelegateSafely();
184 CHECK_NULL_VOID(delegate);
185 delegate->SetAutoFocusTransfer(testCase.isAutoFocusTransfer);
186 }
187 auto newPopupNode = FrameNodeOnTree::CreateFrameNode(V2::POPUP_ETS_TAG, -1, bubblePattern);
188 auto newFocusHub = newPopupNode->GetOrCreateFocusHub();
189 oldPopupNode->AddChild(newPopupNode);
190 if (testCase.isHasDefaultFocus) {
191 oldFocusHub->SetDefaultFocusNode(newFocusHub);
192 }
193 auto currentFocusNode = focusManager_->GetFocusManager(newPopupNode);
194 CHECK_NULL_VOID(currentFocusNode);
195 EXPECT_EQ(oldPopupNode, currentFocusNode);
196 EXPECT_NE(newPopupNode, currentFocusNode);
197 } else if (testCase.newPageType == "modalpage") {
198 auto rootNode = FrameNodeOnTree::CreateFrameNode(V2::ROOT_ETS_TAG, -1, AceType::MakeRefPtr<RootPattern>());
199 auto rootFocusHub = rootNode->GetOrCreateFocusHub();
200 auto modalPattern = AceType::MakeRefPtr<ModalPresentationPattern>(-1, ModalTransition::DEFAULT, nullptr);
201 auto oldModelpageNode = FrameNodeOnTree::CreateFrameNode(V2::MODAL_PAGE_TAG, -1, modalPattern);
202 rootNode->AddChild(oldModelpageNode);
203 auto focusManager = PipelineContext::GetCurrentContext()->GetFocusManager();
204 auto oldFocusHub = oldModelpageNode->GetOrCreateFocusHub();
205 if (testCase.isAutoFocusTransfer) {
206 auto delegate = EngineHelper::GetCurrentDelegateSafely();
207 CHECK_NULL_VOID(delegate);
208 delegate->SetAutoFocusTransfer(testCase.isAutoFocusTransfer);
209 }
210 auto newModelpageNode = FrameNodeOnTree::CreateFrameNode(V2::MODAL_PAGE_TAG, -1, modalPattern);
211 oldModelpageNode->AddChild(newModelpageNode);
212 auto newFocusHub = newModelpageNode->GetOrCreateFocusHub();
213 if (testCase.isHasDefaultFocus) {
214 oldFocusHub->SetDefaultFocusNode(newFocusHub);
215 }
216 auto currentFocusNode = focusManager_->GetFocusManager(newModelpageNode);
217 CHECK_NULL_VOID(currentFocusNode);
218 EXPECT_EQ(oldModelpageNode, currentFocusNode);
219 EXPECT_NE(newModelpageNode, currentFocusNode);
220 } else if (testCase.newPageType == "sheetpag") {
221 auto rootNode = FrameNodeOnTree::CreateFrameNode(V2::ROOT_ETS_TAG, -1, AceType::MakeRefPtr<RootPattern>());
222 auto rootFocusHub = rootNode->GetOrCreateFocusHub();
223 auto sheetPattern = AceType::MakeRefPtr<SheetPresentationPattern>(-1, "", nullptr);
224 auto oldSheetpageNode = FrameNodeOnTree::CreateFrameNode(V2::SHEET_PAGE_TAG, -1, sheetPattern);
225 rootNode->AddChild(oldSheetpageNode);
226 auto focusManager = PipelineContext::GetCurrentContext()->GetFocusManager();
227 auto oldFocusHub = oldSheetpageNode->GetOrCreateFocusHub();
228 if (testCase.isAutoFocusTransfer) {
229 auto delegate = EngineHelper::GetCurrentDelegateSafely();
230 CHECK_NULL_VOID(delegate);
231 delegate->SetAutoFocusTransfer(testCase.isAutoFocusTransfer);
232 }
233 auto newSheetpageNode = FrameNodeOnTree::CreateFrameNode(V2::SHEET_PAGE_TAG, -1, sheetPattern);
234 oldSheetpageNode->AddChild(newSheetpageNode);
235 auto newFocusHub = newSheetpageNode->GetOrCreateFocusHub();
236 if (testCase.isHasDefaultFocus) {
237 oldFocusHub->SetDefaultFocusNode(newFocusHub);
238 }
239 auto currentFocusNode = focusManager_->GetFocusManager(newSheetpageNode);
240 CHECK_NULL_VOID(currentFocusNode);
241 EXPECT_EQ(oldSheetpageNode, currentFocusNode);
242 EXPECT_NE(newSheetpageNode, currentFocusNode);
243 } else if (testCase.newPageType == "navigation") {
244 auto rootNode = FrameNodeOnTree::CreateFrameNode(V2::ROOT_ETS_TAG, -1, AceType::MakeRefPtr<RootPattern>());
245 auto rootFocusHub = rootNode->GetOrCreateFocusHub();
246 auto navigationPattern = AceType::MakeRefPtr<NavigationPattern>();
247 auto oldNavigationNode =
248 FrameNodeOnTree::CreateFrameNode(V2::NAVIGATION_VIEW_ETS_TAG, -1, navigationPattern);
249 rootNode->AddChild(oldNavigationNode);
250 auto focusManager = PipelineContext::GetCurrentContext()->GetFocusManager();
251 auto oldFocusHub = oldNavigationNode->GetOrCreateFocusHub();
252 if (testCase.isAutoFocusTransfer) {
253 auto delegate = EngineHelper::GetCurrentDelegateSafely();
254 CHECK_NULL_VOID(delegate);
255 delegate->SetAutoFocusTransfer(testCase.isAutoFocusTransfer);
256 }
257 auto newNavigationNode =
258 FrameNodeOnTree::CreateFrameNode(V2::NAVIGATION_VIEW_ETS_TAG, -1, navigationPattern);
259 oldNavigationNode->AddChild(newNavigationNode);
260 auto newFocusHub = newNavigationNode->GetOrCreateFocusHub();
261 if (testCase.isHasDefaultFocus) {
262 oldFocusHub->SetDefaultFocusNode(newFocusHub);
263 }
264 auto currentFocusNode = focusManager_->GetFocusManager(newNavigationNode);
265 CHECK_NULL_VOID(currentFocusNode);
266 EXPECT_EQ(oldNavigationNode, currentFocusNode);
267 EXPECT_NE(newNavigationNode, currentFocusNode);
268
269 } else if (testCase.newPageType == "navbar") {
270 auto rootNode = FrameNodeOnTree::CreateFrameNode(V2::ROOT_ETS_TAG, -1, AceType::MakeRefPtr<RootPattern>());
271 auto rootFocusHub = rootNode->GetOrCreateFocusHub();
272 auto navbarPattern = AceType::MakeRefPtr<NavBarPattern>();
273 auto oldNavbarNode = FrameNodeOnTree::CreateFrameNode(V2::NAVBAR_ETS_TAG, -1, navbarPattern);
274 rootNode->AddChild(oldNavbarNode);
275 auto focusManager = PipelineContext::GetCurrentContext()->GetFocusManager();
276 auto oldFocusHub = oldNavbarNode->GetOrCreateFocusHub();
277 if (testCase.isAutoFocusTransfer) {
278 auto delegate = EngineHelper::GetCurrentDelegateSafely();
279 CHECK_NULL_VOID(delegate);
280 delegate->SetAutoFocusTransfer(testCase.isAutoFocusTransfer);
281 }
282 auto newNavbarNode = FrameNodeOnTree::CreateFrameNode(V2::NAVBAR_ETS_TAG, -1, navbarPattern);
283 oldNavbarNode->AddChild(newNavbarNode);
284 auto newFocusHub = newNavbarNode->GetOrCreateFocusHub();
285 if (testCase.isHasDefaultFocus) {
286 oldFocusHub->SetDefaultFocusNode(newFocusHub);
287 }
288 auto currentFocusNode = focusManager_->GetFocusManager(newNavbarNode);
289 CHECK_NULL_VOID(currentFocusNode);
290 EXPECT_EQ(oldNavbarNode, currentFocusNode);
291 EXPECT_NE(newNavbarNode, currentFocusNode);
292 } else if (testCase.newPageType == "navdestination") {
293 auto rootNode = FrameNodeOnTree::CreateFrameNode(V2::ROOT_ETS_TAG, -1, AceType::MakeRefPtr<RootPattern>());
294 auto rootFocusHub = rootNode->GetOrCreateFocusHub();
295 auto navdestinationPattern = AceType::MakeRefPtr<NavDestinationPattern>(nullptr);
296 auto oldNavdestinationNode =
297 FrameNodeOnTree::CreateFrameNode(V2::NAVDESTINATION_VIEW_ETS_TAG, -1, navdestinationPattern);
298 rootNode->AddChild(oldNavdestinationNode);
299 auto focusManager = PipelineContext::GetCurrentContext()->GetFocusManager();
300 auto oldFocusHub = oldNavdestinationNode->GetOrCreateFocusHub();
301 if (testCase.isAutoFocusTransfer) {
302 auto delegate = EngineHelper::GetCurrentDelegateSafely();
303 CHECK_NULL_VOID(delegate);
304 delegate->SetAutoFocusTransfer(testCase.isAutoFocusTransfer);
305 }
306 auto newNavdestinationNode =
307 FrameNodeOnTree::CreateFrameNode(V2::NAVDESTINATION_VIEW_ETS_TAG, -1, navdestinationPattern);
308 oldNavdestinationNode->AddChild(newNavdestinationNode);
309 auto newFocusHub = newNavdestinationNode->GetOrCreateFocusHub();
310 if (testCase.isHasDefaultFocus) {
311 oldFocusHub->SetDefaultFocusNode(newFocusHub);
312 }
313 auto currentFocusNode = focusManager_->GetFocusManager(newNavdestinationNode);
314 CHECK_NULL_VOID(currentFocusNode);
315 EXPECT_EQ(oldNavdestinationNode, currentFocusNode);
316 EXPECT_NE(newNavdestinationNode, currentFocusNode);
317
318 } else if (testCase.newPageType == "windowscene") {
319 auto rootNode = FrameNodeOnTree::CreateFrameNode(V2::ROOT_ETS_TAG, -1, AceType::MakeRefPtr<RootPattern>());
320 auto rootFocusHub = rootNode->GetOrCreateFocusHub();
321 auto windowscenePattern = AceType::MakeRefPtr<Pattern>();
322 auto oldWindowscene = FrameNodeOnTree::CreateFrameNode(V2::WINDOW_SCENE_ETS_TAG, -1, windowscenePattern);
323 rootNode->AddChild(oldWindowscene);
324 auto focusManager = PipelineContext::GetCurrentContext()->GetFocusManager();
325 auto oldFocusHub = oldWindowscene->GetOrCreateFocusHub();
326 if (testCase.isAutoFocusTransfer) {
327 auto delegate = EngineHelper::GetCurrentDelegateSafely();
328 CHECK_NULL_VOID(delegate);
329 delegate->SetAutoFocusTransfer(testCase.isAutoFocusTransfer);
330 }
331 auto newWindowscene = FrameNodeOnTree::CreateFrameNode(V2::WINDOW_SCENE_ETS_TAG, -1, windowscenePattern);
332 auto newFocusHub = newWindowscene->GetOrCreateFocusHub();
333 oldWindowscene->AddChild(newWindowscene);
334 if (testCase.isHasDefaultFocus) {
335 oldFocusHub->SetDefaultFocusNode(newFocusHub);
336 }
337 auto currentFocusNode = focusManager_->GetFocusManager(newWindowscene);
338 CHECK_NULL_VOID(currentFocusNode);
339 EXPECT_EQ(oldWindowscene, currentFocusNode);
340 EXPECT_NE(newWindowscene, currentFocusNode);
341 }
342 ++caseNum;
343 }
344 }
345 } // namespace OHOS::Ace::NG
346