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 <cstdint>
16 #include "gtest/hwext/gtest-tag.h"
17 #include "test/unittest/core/event/focus_hub_test_ng.h"
18
19 using namespace testing;
20 using namespace testing::ext;
21
22 namespace OHOS::Ace::NG {
23 struct HomeOrEndKeyInFocusGroupTestCase {
24 int32_t curFocusHub;
25 bool focusGroup1;
26 bool focusGroup2;
27 FocusIntension intension;
28 int32_t expect;
29 };
30
31 const vector<HomeOrEndKeyInFocusGroupTestCase> HomeOrEndKeyInFocusGroupTestCase001 {
32 { 1, false, false, FocusIntension::HOME, 11 },
33 { 1, true, false, FocusIntension::HOME, 11 },
34 { 1, false, true, FocusIntension::HOME, 14 },
35 { 1, true, true, FocusIntension::HOME, 14 },
36 { 1, false, false, FocusIntension::END, 11 },
37 { 1, true, false, FocusIntension::END, 13 },
38 { 1, false, true, FocusIntension::END, 15 },
39 { 1, true, true, FocusIntension::END, 15 },
40 { 3, false, false, FocusIntension::HOME, 13 },
41 { 3, true, false, FocusIntension::HOME, 11 },
42 { 3, false, true, FocusIntension::HOME, 14 },
43 { 3, true, true, FocusIntension::HOME, 14 },
44 { 3, false, false, FocusIntension::END, 13 },
45 { 3, true, false, FocusIntension::END, 13 },
46 { 3, false, true, FocusIntension::END, 15 },
47 { 3, true, true, FocusIntension::END, 15 },
48 };
49
50 struct ButtonNodes {
51 RefPtr<FrameNode> button1;
52 RefPtr<FrameNode> button2;
53 RefPtr<FrameNode> button3;
54 };
55
CreateTestTreeWithDefaultFocus()56 ButtonNodes CreateTestTreeWithDefaultFocus()
57 {
58 /*--page
59 --column1
60 --column2
61 --button4
62 --column3
63 --button1
64 --button2
65 --button3
66 --button5
67 */
68 auto context = MockPipelineContext::GetCurrent();
69 auto focusManager = context->GetOrCreateFocusManager();
70 auto pagePattern = AceType::MakeRefPtr<PagePattern>(AceType::MakeRefPtr<PageInfo>());
71 auto pageNode = FrameNode::CreateFrameNode(V2::PAGE_ETS_TAG, 1, pagePattern);
72 pageNode->onMainTree_ = true;
73 auto pageFocusHub = pageNode->GetOrCreateFocusHub();
74 context->rootNode_->AddChild(pageNode);
75 auto column1 = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, 2, AceType::MakeRefPtr<LinearLayoutPattern>(true));
76 auto column2 = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, 2, AceType::MakeRefPtr<LinearLayoutPattern>(true));
77 auto column3 = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, 2, AceType::MakeRefPtr<LinearLayoutPattern>(true));
78 column1->onMainTree_ = true;
79 column2->onMainTree_ = true;
80 column3->onMainTree_ = true;
81 auto columnFocusHub1 = column1->GetOrCreateFocusHub();
82 auto columnFocusHub2 = column2->GetOrCreateFocusHub();
83 auto columnFocusHub3 = column3->GetOrCreateFocusHub();
84 auto buttonNode1 = FrameNode::CreateFrameNode(V2::BUTTON_ETS_TAG, 11, AceType::MakeRefPtr<ButtonPattern>());
85 auto buttonNode2 = FrameNode::CreateFrameNode(V2::BUTTON_ETS_TAG, 12, AceType::MakeRefPtr<ButtonPattern>());
86 auto buttonNode3 = FrameNode::CreateFrameNode(V2::BUTTON_ETS_TAG, 13, AceType::MakeRefPtr<ButtonPattern>());
87 auto buttonNode4 = FrameNode::CreateFrameNode(V2::BUTTON_ETS_TAG, 14, AceType::MakeRefPtr<ButtonPattern>());
88 auto buttonNode5 = FrameNode::CreateFrameNode(V2::BUTTON_ETS_TAG, 15, AceType::MakeRefPtr<ButtonPattern>());
89 buttonNode1->onMainTree_ = true;
90 buttonNode2->onMainTree_ = true;
91 buttonNode3->onMainTree_ = true;
92 buttonNode5->onMainTree_ = true;
93 buttonNode4->onMainTree_ = true;
94 pageNode->AddChild(column1);
95 column1->AddChild(column2);
96 column2->AddChild(buttonNode4);
97 column2->AddChild(column3);
98 column3->AddChild(buttonNode1);
99 column3->AddChild(buttonNode2);
100 column3->AddChild(buttonNode3);
101 column2->AddChild(buttonNode5);
102 pagePattern->FocusViewShow();
103 context->FlushFocusView();
104 return { buttonNode1, buttonNode2, buttonNode3 };
105 }
106
107 /**
108 * @tc.name: IsLeafFocusScope001
109 * @tc.desc:
110 * @tc.type: FUNC
111 */
112 HWTEST_F(FocusHubTestNg, IsLeafFocusScope001, TestSize.Level1)
113 {
114 auto frameNode = AceType::MakeRefPtr<FrameNodeOnTree>(V2::ROW_ETS_TAG, -1, AceType::MakeRefPtr<Pattern>());
115 RefPtr<EventHub> eventHub = AceType::MakeRefPtr<EventHub>();
116 eventHub->AttachHost(frameNode);
117 auto focusHub = AceType::MakeRefPtr<FocusHub>(AceType::WeakClaim(AceType::RawPtr(eventHub)));
118
119 focusHub->tabStop_ = true;
120 focusHub->isSwitchByEnter_ = true;
121 focusHub->focusDepend_ = FocusDependence::SELF;
122 auto ret = focusHub->IsLeafFocusScope();
123 EXPECT_EQ(ret, false);
124
125 focusHub->tabStop_ = true;
126 focusHub->isSwitchByEnter_ = false;
127 ret = focusHub->IsLeafFocusScope();
128 EXPECT_EQ(ret, true);
129 }
130
131 /**
132 * @tc.name: PaintAllFocusState001
133 * @tc.desc:
134 * @tc.type: FUNC
135 */
136 HWTEST_F(FocusHubTestNg, PaintAllFocusState001, TestSize.Level1)
137 {
138 auto frameNode = AceType::MakeRefPtr<FrameNodeOnTree>(V2::ROW_ETS_TAG, -1,
139 AceType::MakeRefPtr<Pattern>());
140 auto frameNode1 = AceType::MakeRefPtr<FrameNodeOnTree>(V2::ROW_ETS_TAG, -1,
141 AceType::MakeRefPtr<Pattern>());
142 auto eventHub = AceType::MakeRefPtr<EventHub>();
143 auto eventHub1 = AceType::MakeRefPtr<EventHub>();
144 eventHub->AttachHost(frameNode);
145 eventHub1->AttachHost(frameNode1);
146 auto focusHub = frameNode->GetOrCreateFocusHub();
147 auto focusHub1 = frameNode1->GetOrCreateFocusHub();
148 OnPaintFocusStateFunc onPaintFocusCallback;
__anone5b8ad720102() 149 std::function<bool()> lambdaFunction = []() {
150 return false;
151 };
152 focusHub->onPaintFocusStateCallback_ = lambdaFunction;
153 focusHub->isFocusActiveWhenFocused_ = true;
154 EXPECT_FALSE(focusHub->PaintAllFocusState());
155
156 focusHub1->focusStyleType_ = FocusStyleType::INNER_BORDER;
157 focusHub1->isFocusActiveWhenFocused_ = true;
158 EXPECT_FALSE(focusHub1->PaintAllFocusState());
159 }
160
161 /**
162 * @tc.name: PaintAllFocusState074
163 * @tc.desc:
164 * @tc.type: FUNC
165 */
166 HWTEST_F(FocusHubTestNg, PaintAllFocusState002, TestSize.Level1)
167 {
168 auto themeManager = AceType::MakeRefPtr<MockThemeManager>();
169 MockPipelineContext::GetCurrent()->SetThemeManager(themeManager);
170 EXPECT_CALL(*themeManager, GetTheme(_)).WillRepeatedly(Return(AceType::MakeRefPtr<AppTheme>()));
171 auto frameNode = FrameNodeOnTree::CreateFrameNode("frameNode", 101,
172 AceType::MakeRefPtr<ButtonPattern>());
173 frameNode->GetOrCreateFocusHub();
174 auto focusHub = frameNode->GetFocusHub();
175 ASSERT_NE(focusHub, nullptr);
176 auto context = PipelineContext::GetCurrentContext();
177 ASSERT_NE(context, nullptr);
178 auto focusManager = context->GetOrCreateFocusManager();
179 ASSERT_NE(focusManager, nullptr);
180 focusManager->isFocusActive_ = true;
181
182 focusHub->focusStyleType_ = FocusStyleType::OUTER_BORDER;
183 OnPaintFocusStateFunc onPaintFocusCallback;
184 focusHub->onPaintFocusStateCallback_ = onPaintFocusCallback;
185 FocusBoxStyle focusBoxStyle;
186 CalcDimension strokeWidth(100);
187 CalcDimension margin(100);
188 Color color;
189
190 focusBoxStyle.strokeColor = color;
191 focusBoxStyle.strokeWidth = strokeWidth;
192 focusBoxStyle.margin = margin;
193 focusHub->box_.SetStyle(focusBoxStyle);
194 auto ret = focusHub->PaintAllFocusState();
195 EXPECT_TRUE(ret);
196
197 FocusBoxStyle focusBoxStyle1;
198 focusBoxStyle1.strokeColor = color;
199 focusBoxStyle1.margin = margin;
200 focusHub->box_.SetStyle(focusBoxStyle1);
201 ret = focusHub->PaintAllFocusState();
202 EXPECT_TRUE(ret);
203 }
204
205 /**
206 * @tc.name: PaintAllFocusState003
207 * @tc.desc:
208 * @tc.type: FUNC
209 */
210 HWTEST_F(FocusHubTestNg, PaintAllFocusState003, TestSize.Level1)
211 {
212 auto themeManager = AceType::MakeRefPtr<MockThemeManager>();
213 MockPipelineContext::GetCurrent()->SetThemeManager(themeManager);
214 EXPECT_CALL(*themeManager, GetTheme(_)).WillRepeatedly(Return(AceType::MakeRefPtr<AppTheme>()));
215 auto frameNode = FrameNodeOnTree::CreateFrameNode("frameNode", 101,
216 AceType::MakeRefPtr<ButtonPattern>());
217 frameNode->GetOrCreateFocusHub();
218 auto focusHub = frameNode->GetFocusHub();
219 ASSERT_NE(focusHub, nullptr);
220 auto context = PipelineContext::GetCurrentContext();
221 ASSERT_NE(context, nullptr);
222 auto focusManager = context->GetOrCreateFocusManager();
223 ASSERT_NE(focusManager, nullptr);
224 focusManager->isFocusActive_ = true;
225
226 focusHub->focusStyleType_ = FocusStyleType::OUTER_BORDER;
227 OnPaintFocusStateFunc onPaintFocusCallback;
228 focusHub->onPaintFocusStateCallback_ = onPaintFocusCallback;
229 FocusBoxStyle focusBoxStyle;
230 CalcDimension strokeWidth(100);
231 CalcDimension margin(100);
232 Color color;
233
234 FocusBoxStyle focusBoxStyle2;
235 focusBoxStyle2.strokeColor = color;
236 focusBoxStyle2.strokeWidth = strokeWidth;
237 focusHub->box_.SetStyle(focusBoxStyle2);
238 auto ret = focusHub->PaintAllFocusState();
239 EXPECT_TRUE(ret);
240
__anone5b8ad720202() 241 std::function<bool()> lambdaFunction = []() {
242 return false;
243 };
244 focusHub->onPaintFocusStateCallback_ = lambdaFunction;
245 FocusBoxStyle focusBoxStyle3;
246 focusBoxStyle3.margin = margin;
247 focusBoxStyle3.strokeWidth = strokeWidth;
248 focusHub->box_.SetStyle(focusBoxStyle3);
249 ret = focusHub->PaintAllFocusState();
250 EXPECT_FALSE(ret);
251 }
252
253 /**
254 * @tc.name: PaintInnerFocusState0048
255 * @tc.desc:
256 * @tc.type: FUNC
257 */
258 HWTEST_F(FocusHubTestNg, PaintInnerFocusState001, TestSize.Level1)
259 {
260 auto themeManager = AceType::MakeRefPtr<MockThemeManager>();
261 MockPipelineContext::GetCurrent()->SetThemeManager(themeManager);
262 EXPECT_CALL(*themeManager, GetTheme(_)).WillRepeatedly(Return(AceType::MakeRefPtr<AppTheme>()));
263 auto frameNode = AceType::MakeRefPtr<FrameNodeOnTree>(V2::ROW_ETS_TAG, -1,
264 AceType::MakeRefPtr<Pattern>());
265 auto child = AceType::MakeRefPtr<FrameNodeOnTree>(V2::BUTTON_ETS_TAG, -1,
266 AceType::MakeRefPtr<ButtonPattern>());
267 auto child2 = AceType::MakeRefPtr<FrameNodeOnTree>(V2::BUTTON_ETS_TAG, -1,
268 AceType::MakeRefPtr<ButtonPattern>());
269 child->GetOrCreateFocusHub();
270 child2->GetOrCreateFocusHub();
271 frameNode->AddChild(child);
272 frameNode->AddChild(child2);
273 RefPtr<EventHub> eventHub = AceType::MakeRefPtr<EventHub>();
274 eventHub->AttachHost(frameNode);
275 auto focusHub = AceType::MakeRefPtr<FocusHub>(AceType::WeakClaim(AceType::RawPtr(eventHub)));
276 auto context = PipelineContext::GetCurrentContext();
277 ASSERT_NE(context, nullptr);
278 FocusBoxStyle focusBoxStyle;
279 CalcDimension strokeWidth(100);
280 CalcDimension margin(100);
281 Color color;
282 focusBoxStyle.strokeColor = color;
283 focusBoxStyle.strokeWidth = strokeWidth;
284 focusBoxStyle.margin = margin;
285 focusHub->box_.SetStyle(focusBoxStyle);
286 RoundRect focusRectInner;
287 auto focusManager = context->GetOrCreateFocusManager();
288 ASSERT_NE(focusManager, nullptr);
289 focusManager->isFocusActive_ = true;
290 focusHub->focusType_ = FocusType::NODE;
291 EXPECT_TRUE(focusHub->PaintInnerFocusState(focusRectInner));
292
293 FocusBoxStyle focusBoxStyle1;
294 focusBoxStyle1.strokeColor = color;
295 focusBoxStyle1.margin = margin;
296 focusHub->box_.SetStyle(focusBoxStyle1);
297 EXPECT_TRUE(focusHub->PaintInnerFocusState(focusRectInner));
298
299 FocusBoxStyle focusBoxStyle2;
300 focusBoxStyle2.strokeColor = color;
301 focusBoxStyle2.strokeWidth = strokeWidth;
302 focusHub->box_.SetStyle(focusBoxStyle2);
303 EXPECT_TRUE(focusHub->PaintInnerFocusState(focusRectInner));
304 }
305
306 /**
307 * @tc.name: PaintInnerFocusState0048
308 * @tc.desc:
309 * @tc.type: FUNC
310 */
311 HWTEST_F(FocusHubTestNg, PaintInnerFocusState002, TestSize.Level1)
312 {
313 auto themeManager = AceType::MakeRefPtr<MockThemeManager>();
314 MockPipelineContext::GetCurrent()->SetThemeManager(themeManager);
315 EXPECT_CALL(*themeManager, GetTheme(_)).WillRepeatedly(Return(AceType::MakeRefPtr<AppTheme>()));
316 auto frameNode = AceType::MakeRefPtr<FrameNodeOnTree>(V2::ROW_ETS_TAG, -1,
317 AceType::MakeRefPtr<Pattern>());
318 auto child = AceType::MakeRefPtr<FrameNodeOnTree>(V2::BUTTON_ETS_TAG, -1,
319 AceType::MakeRefPtr<ButtonPattern>());
320 auto child2 = AceType::MakeRefPtr<FrameNodeOnTree>(V2::BUTTON_ETS_TAG, -1,
321 AceType::MakeRefPtr<ButtonPattern>());
322 child->GetOrCreateFocusHub();
323 child2->GetOrCreateFocusHub();
324 frameNode->AddChild(child);
325 frameNode->AddChild(child2);
326 RefPtr<EventHub> eventHub = AceType::MakeRefPtr<EventHub>();
327 eventHub->AttachHost(frameNode);
328 auto focusHub = AceType::MakeRefPtr<FocusHub>(AceType::WeakClaim(AceType::RawPtr(eventHub)));
329 auto context = PipelineContext::GetCurrentContext();
330 ASSERT_NE(context, nullptr);
331 FocusBoxStyle focusBoxStyle;
332 CalcDimension strokeWidth(100);
333 CalcDimension strokeWidth1("100");
334 CalcDimension margin(100);
335 Color color;
336 RoundRect focusRectInner;
337 auto focusManager = context->GetOrCreateFocusManager();
338 ASSERT_NE(focusManager, nullptr);
339 focusManager->isFocusActive_ = true;
340 focusHub->focusType_ = FocusType::NODE;
341
342 FocusBoxStyle focusBoxStyle3;
343 focusBoxStyle3.margin = margin;
344 focusBoxStyle3.strokeWidth = strokeWidth;
345 focusHub->box_.SetStyle(focusBoxStyle3);
346 EXPECT_TRUE(focusHub->PaintInnerFocusState(focusRectInner));
347
348 focusBoxStyle.strokeColor = color;
349 focusBoxStyle.strokeWidth = strokeWidth1;
350 focusBoxStyle.margin = margin;
351 focusHub->box_.SetStyle(focusBoxStyle);
352 EXPECT_TRUE(focusHub->PaintInnerFocusState(focusRectInner));
353 }
354
355 /**
356 * @tc.name: ChangeFocusByHomeorEndTest001
357 * @tc.desc:
358 * @tc.type: FUNC
359 */
360 HWTEST_F(FocusHubTestNg, ChangeFocusByHomeorEndTest001, TestSize.Level1)
361 {
362 ButtonNodes buttonNodes = CreateTestTreeWithDefaultFocus();
363 RefPtr<FrameNode> button1 = buttonNodes.button1;
364 RefPtr<FrameNode> button3 = buttonNodes.button3;
365 EXPECT_NE(button1, nullptr);
366 EXPECT_NE(button3, nullptr);
367 NonPointerEvent nonPointerEvent;
368 FocusEvent event { nonPointerEvent };
369 auto buttonFocusHub1 = button1->GetOrCreateFocusHub();
370 auto buttonFocusHub3 = button3->GetOrCreateFocusHub();
371 auto parent = buttonFocusHub1->GetParentFocusHub();
372 auto parent2 = parent->GetParentFocusHub();
373 auto parent3 = parent2->GetParentFocusHub();
374 auto page = parent3->GetParentFocusHub();
375 auto context = MockPipelineContext::GetCurrent();
376 auto focusManager = context->GetOrCreateFocusManager();
377 focusManager->isFocusActive_ = true;
378 for (auto& testcase : HomeOrEndKeyInFocusGroupTestCase001) {
379 if (testcase.focusGroup1) {
380 parent->SetFocusScopeId("2", true, true);
381 }
382 if (testcase.focusGroup2) {
383 parent2->SetFocusScopeId("3", true, true);
384 }
385 buttonFocusHub1->RequestFocusImmediately();
386 EXPECT_EQ(buttonFocusHub1->IsCurrentFocus(), true);
387 context->eventManager_->isTabJustTriggerOnKeyEvent_ = false;
388 event.intension = testcase.intension;
389 if (testcase.curFocusHub == 3) {
390 buttonFocusHub3->RequestFocusImmediately();
391 EXPECT_EQ(buttonFocusHub3->IsCurrentFocus(), true);
392 }
393 page->OnFocusEventScope(event);
394 auto currentFocusNode = focusManager->switchingFocus_;
395 auto nodeId = currentFocusNode->GetFrameId();
396 EXPECT_EQ(nodeId, testcase.expect);
397 parent->SetFocusScopeId("", true, true);
398 parent2->SetFocusScopeId("", true, true);
399 }
400 }
401 } // namespace OHOS::Ace::NG