• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "gtest/gtest.h"
17 #define private public
18 #define protected public
19 #include "test/mock/core/common/mock_container.h"
20 #include "test/mock/core/common/mock_theme_manager.h"
21 #include "test/mock/core/pipeline/mock_pipeline_context.h"
22 
23 #include "base/memory/referenced.h"
24 #include "core/components/common/properties/color.h"
25 #include "core/components/theme/app_theme.h"
26 #include "core/components_ng/base/frame_node.h"
27 #include "core/components_ng/event/event_hub.h"
28 #include "core/components_ng/event/focus_event_handler.h"
29 #include "core/components_ng/event/focus_hub.h"
30 #include "core/components_ng/pattern/button/button_pattern.h"
31 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
32 #include "core/components_ng/pattern/stage/page_pattern.h"
33 namespace OHOS::Ace::NG {
34 namespace {
35 const int32_t VERSION_TWELVE = 12;
36 const int32_t VERSION_EIGHTEEN = 18;
37 } // namespace
38 
39 class FocusEventHandlerTestNg : public testing::Test {
40 public:
41     static void SetUpTestSuite();
42     static void TearDownTestSuite();
43     void SetUp() override;
44     void TearDown() override;
45 };
46 } // namespace OHOS::Ace::NG
47 
48 using namespace testing;
49 using namespace testing::ext;
50 
51 namespace OHOS::Ace::NG {
SetUpTestSuite()52 void FocusEventHandlerTestNg::SetUpTestSuite()
53 {
54     MockPipelineContext::SetUp();
55     MockContainer::SetUp(MockPipelineContext::GetCurrent());
56 }
57 
TearDownTestSuite()58 void FocusEventHandlerTestNg::TearDownTestSuite()
59 {
60     MockPipelineContext::TearDown();
61     MockContainer::TearDown();
62 }
63 
SetUp()64 void FocusEventHandlerTestNg::SetUp() {}
65 
TearDown()66 void FocusEventHandlerTestNg::TearDown()
67 {
68     auto context = MockPipelineContext::GetCurrent();
69     ASSERT_NE(context, nullptr);
70     ASSERT_NE(context->rootNode_, nullptr);
71     context->rootNode_->children_.clear();
72 }
73 
74 struct KeyEventClickTestCase {
75     bool focusActive;
76     bool needFocusHandleClick;
77     FocusIntension intension;
78     bool isTabStop;
79     bool expect;
80 };
81 
82 const vector<KeyEventClickTestCase> HandleKeyEventClickOnVersion12TestCase {
83     { false, false, FocusIntension::SELECT, false, false },
84     { true, false, FocusIntension::SELECT, false, false },
85     { false, true, FocusIntension::SELECT, false, true },
86     { true, true, FocusIntension::SELECT, false, true },
87     { false, false, FocusIntension::SPACE, false, false },
88     { true, false, FocusIntension::SPACE, false, false },
89     { false, true, FocusIntension::SPACE, false, true },
90     { true, true, FocusIntension::SPACE, false, true },
91     { false, false, FocusIntension::SELECT, true, false },
92     { true, false, FocusIntension::SELECT, true, false },
93     { false, true, FocusIntension::SELECT, true, false },
94     { true, true, FocusIntension::SELECT, true, false },
95     { false, false, FocusIntension::SPACE, true, false },
96     { true, false, FocusIntension::SPACE, true, false },
97     { false, true, FocusIntension::SPACE, true, true },
98     { true, true, FocusIntension::SPACE, true, true },
99 };
100 
101 const vector<KeyEventClickTestCase> HandleKeyEventClickOnVersion18TestCase {
102     { false, false, FocusIntension::SELECT, false, false },
103     { true, false, FocusIntension::SELECT, false, false },
104     { false, true, FocusIntension::SELECT, false, false },
105     { true, true, FocusIntension::SELECT, false, true },
106     { false, false, FocusIntension::SPACE, false, false },
107     { true, false, FocusIntension::SPACE, false, false },
108     { false, true, FocusIntension::SPACE, false, false },
109     { true, true, FocusIntension::SPACE, false, true },
110     { false, false, FocusIntension::SELECT, true, false },
111     { true, false, FocusIntension::SELECT, true, false },
112     { false, true, FocusIntension::SELECT, true, false },
113     { true, true, FocusIntension::SELECT, true, false },
114     { false, false, FocusIntension::SPACE, true, false },
115     { true, false, FocusIntension::SPACE, true, false },
116     { false, true, FocusIntension::SPACE, true, false },
117     { true, true, FocusIntension::SPACE, true, true },
118 };
119 
CreateTestTreeWithDefaultFocus()120 RefPtr<FrameNode> CreateTestTreeWithDefaultFocus()
121 {
122     auto context = MockPipelineContext::GetCurrent();
123     auto focusManager = context->GetOrCreateFocusManager();
124     auto pagePattern = AceType::MakeRefPtr<PagePattern>(AceType::MakeRefPtr<PageInfo>());
125     auto pageNode = FrameNode::CreateFrameNode(V2::PAGE_ETS_TAG, 1, pagePattern);
126     pageNode->onMainTree_ = true;
127     auto pageFocusHub = pageNode->GetOrCreateFocusHub();
128     context->rootNode_->AddChild(pageNode);
129     auto columnPattern = AceType::MakeRefPtr<LinearLayoutPattern>(true);
130     auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, 2, columnPattern);
131     columnNode->onMainTree_ = true;
132     auto columnFocusHub = columnNode->GetOrCreateFocusHub();
133     auto buttonPattern = AceType::MakeRefPtr<ButtonPattern>();
134     auto buttonNode = FrameNode::CreateFrameNode(V2::BUTTON_ETS_TAG, 3, buttonPattern);
135     buttonNode->onMainTree_ = true;
136     auto buttonFocusHub = buttonNode->GetOrCreateFocusHub();
137     pageNode->AddChild(columnNode);
138     columnNode->AddChild(buttonNode);
139     pagePattern->FocusViewShow();
140     context->FlushFocusView();
141     pagePattern->TriggerFocusMove();
142     EXPECT_EQ(buttonFocusHub->IsCurrentFocus(), true);
143     return buttonNode;
144 }
145 
ClearRootChild()146 void ClearRootChild()
147 {
148     auto context = MockPipelineContext::GetCurrent();
149     ASSERT_NE(context, nullptr);
150     ASSERT_NE(context->rootNode_, nullptr);
151     context->rootNode_->children_.clear();
152 }
153 
154 /**
155  * @tc.name: GetFocusIntension001
156  * @tc.desc: Create SetStyle.
157  * @tc.type: FUNC
158  */
159 HWTEST_F(FocusEventHandlerTestNg, GetFocusIntensionTest001, TestSize.Level1)
160 {
161     KeyEvent event;
162     event.action = KeyAction::DOWN;
163     event.isPreIme = false;
164     event.code = KeyCode::KEY_NUMPAD_ENTER;
165     event.pressedCodes = { KeyCode::KEY_NUMPAD_ENTER };
166     auto expectIntension = FocusEvent::GetFocusIntension(event);
167     EXPECT_EQ(expectIntension, FocusIntension::SELECT);
168     event.code = KeyCode::KEY_SPACE;
169     event.pressedCodes = { KeyCode::KEY_SPACE };
170     expectIntension = FocusEvent::GetFocusIntension(event);
171     EXPECT_EQ(expectIntension, FocusIntension::SPACE);
172 }
173 
174 /**
175  * @tc.name: GetFocusIntensionFromKey001
176  * @tc.desc: Create SetStyle.
177  * @tc.type: FUNC
178  */
179 HWTEST_F(FocusEventHandlerTestNg, GetFocusIntensionFromKeyTest001, TestSize.Level1)
180 {
181     KeyIntention keyIntention;
182     keyIntention = KeyIntention::INTENTION_SELECT;
183     auto expectIntension = FocusEvent::GetFocusIntensionFromKey(keyIntention);
184     EXPECT_EQ(expectIntension, FocusIntension::SELECT);
185     keyIntention = KeyIntention::INTENTION_ESCAPE;
186     expectIntension = FocusEvent::GetFocusIntensionFromKey(keyIntention);
187     EXPECT_EQ(expectIntension, FocusIntension::ESC);
188     keyIntention = KeyIntention::INTENTION_HOME;
189     expectIntension = FocusEvent::GetFocusIntensionFromKey(keyIntention);
190     EXPECT_EQ(expectIntension, FocusIntension::HOME);
191     keyIntention = KeyIntention::INTENTION_UNKNOWN;
192     expectIntension = FocusEvent::GetFocusIntensionFromKey(keyIntention);
193     EXPECT_EQ(expectIntension, FocusIntension::NONE);
194 }
195 
196 /**
197  * @tc.name: HandleKeyEventRedispatchTest001
198  * @tc.desc: Create SetStyle.
199  * @tc.type: FUNC
200  */
201 HWTEST_F(FocusEventHandlerTestNg, HandleKeyEventRedispatchTest001, TestSize.Level1)
202 {
203     /**
204      * @tc.steps: step1. Test HandleKeyEvent Redispatch false
205      * expected: return false
206      */
207     auto context = MockPipelineContext::GetCurrent();
208     ASSERT_NE(context, nullptr);
209     auto buttonNode = CreateTestTreeWithDefaultFocus();
210     EXPECT_NE(buttonNode, nullptr);
211     auto buttonFocusHub = buttonNode->GetOrCreateFocusHub();
212     EXPECT_NE(buttonFocusHub, nullptr);
213     KeyEvent event;
214     event.isRedispatch = true;
215     FocusIntension intension = FocusIntension::NONE;
216     auto result = buttonFocusHub->HandleKeyEvent(event, intension);
217     EXPECT_EQ(result, false);
218 }
219 
220 /**
221  * @tc.name: HandleKeyEventMetaKeyTest001
222  * @tc.desc: Create SetStyle.
223  * @tc.type: FUNC
224  */
225 HWTEST_F(FocusEventHandlerTestNg, HandleKeyEventMetaKeyTest001, TestSize.Level1)
226 {
227     /**
228      * @tc.steps: step1. Test HandleKeyEventMetaKey with KeyCode::KEY_0
229      * expected: PreIme consume and metaKey is 0;
230      */
231     auto context = MockPipelineContext::GetCurrent();
232     auto focusManager = context->GetOrCreateFocusManager();
233     ASSERT_NE(context, nullptr);
234     KeyEvent event;
235     event.isRedispatch = false;
236     event.isPreIme = true;
237     event.code = KeyCode::KEY_0;
238     event.pressedCodes = { KeyCode::KEY_0 };
239     FocusIntension intension = FocusIntension::NONE;
240     auto metaKey = 0;
__anon546ba6f20202(KeyEventInfo& event) 241     auto onKeyEventCallback = [&metaKey](KeyEventInfo& event) {
242         if (event.GetMetaKey() == 1) {
243             metaKey = 1;
244         }
245         event.SetStopPropagation(true);
246         return true;
247     };
248     auto buttonNode = CreateTestTreeWithDefaultFocus();
249     EXPECT_NE(buttonNode, nullptr);
250     auto buttonFocusHub = buttonNode->GetOrCreateFocusHub();
251     EXPECT_NE(buttonFocusHub, nullptr);
252     buttonFocusHub->SetOnKeyPreIme(std::move(onKeyEventCallback));
253     auto result = buttonFocusHub->HandleKeyEvent(event, intension);
254     EXPECT_EQ(result, true);
255     EXPECT_EQ(metaKey, 0);
256 
257     /**
258      * @tc.steps: step2. Test HandleKeyEventMetaKey with KeyCode::KEY_META_LEFT
259      * expected: PreIme consume and metaKey is 1;
260      */
261     event.code = KeyCode::KEY_META_LEFT;
262     event.pressedCodes = { KeyCode::KEY_META_LEFT };
263     auto result2 = buttonFocusHub->HandleKeyEvent(event, intension);
264     EXPECT_EQ(result2, true);
265     EXPECT_EQ(metaKey, 1);
266 
267     /**
268      * @tc.steps: step3. Test HandleKeyEventMetaKey with KeyCode::KEY_META_RIGHT
269      * expected: PreIme consume and metaKey is 1;
270      */
271     metaKey = 0;
272     event.code = KeyCode::KEY_META_RIGHT;
273     event.pressedCodes = { KeyCode::KEY_META_RIGHT };
274     auto result3 = buttonFocusHub->HandleKeyEvent(event, intension);
275     EXPECT_EQ(result3, true);
276     EXPECT_EQ(metaKey, 1);
277 }
278 
279 /**
280  * @tc.name: HandleKeyEventOnClickTest001
281  * @tc.desc: Create SetStyle.
282  * @tc.type: FUNC
283  */
284 HWTEST_F(FocusEventHandlerTestNg, HandleKeyEventOnClickTest001, TestSize.Level1)
285 {
286     /**
287      * @tc.steps: step1. Set APITargetVersion 12
288      * expected: ret is equal to expect;
289      */
290     KeyEvent event;
291     event.isRedispatch = false;
292     event.isPreIme = false;
293     for (auto& testcase : HandleKeyEventClickOnVersion12TestCase) {
294         auto context = MockPipelineContext::GetCurrent();
295         ASSERT_NE(context, nullptr);
296         auto buttonNode = CreateTestTreeWithDefaultFocus();
297         EXPECT_NE(buttonNode, nullptr);
298         auto buttonFocusHub = buttonNode->GetOrCreateFocusHub();
299         EXPECT_NE(buttonFocusHub, nullptr);
300         MockContainer::Current()->SetApiTargetVersion(VERSION_TWELVE);
301         FocusIntension intension = testcase.intension;
302         buttonFocusHub->ClearOnClickCallback();
303         if (testcase.needFocusHandleClick) {
__anon546ba6f20302(GestureEvent& info) 304             auto onClickEventCallback = [](GestureEvent& info) { return true; };
305             buttonFocusHub->SetOnClickCallback(std::move(onClickEventCallback));
306         }
307         auto focusManager = context->GetOrCreateFocusManager();
308         focusManager->isFocusActive_ = testcase.focusActive;
309         auto themeManager = AceType::MakeRefPtr<MockThemeManager>();
310         context->SetThemeManager(themeManager);
311         EXPECT_CALL(*themeManager, GetTheme(_)).WillRepeatedly(Return(AceType::MakeRefPtr<AppTheme>()));
312         auto appTheme = context->GetTheme<AppTheme>();
313         appTheme->focusActiveByTab_ = testcase.needFocusHandleClick;
314         buttonFocusHub->tabStop_ = testcase.isTabStop;
315         auto result = buttonFocusHub->HandleKeyEvent(event, intension);
316         EXPECT_EQ(result, testcase.expect);
317     }
318 }
319 
320 /**
321  * @tc.name: HandleKeyEventOnClickTest002
322  * @tc.desc: Create SetStyle.
323  * @tc.type: FUNC
324  */
325 HWTEST_F(FocusEventHandlerTestNg, HandleKeyEventOnClickTest002, TestSize.Level1)
326 {
327     /**
328      * @tc.steps: step1. Set APITargetVersion 18
329      * expected: ret is equal to expect;
330      */
331     KeyEvent event;
332     event.isRedispatch = false;
333     event.isPreIme = false;
334     for (auto& testcase : HandleKeyEventClickOnVersion18TestCase) {
335         auto context = MockPipelineContext::GetCurrent();
336         ASSERT_NE(context, nullptr);
337         auto buttonNode = CreateTestTreeWithDefaultFocus();
338         EXPECT_NE(buttonNode, nullptr);
339         auto buttonFocusHub = buttonNode->GetOrCreateFocusHub();
340         EXPECT_NE(buttonFocusHub, nullptr);
341         MockContainer::Current()->SetApiTargetVersion(VERSION_EIGHTEEN);
342         FocusIntension intension = testcase.intension;
343         buttonFocusHub->ClearOnClickCallback();
344         if (testcase.needFocusHandleClick) {
__anon546ba6f20402(GestureEvent& info) 345             auto onClickEventCallback = [](GestureEvent& info) { return true; };
346             buttonFocusHub->SetOnClickCallback(std::move(onClickEventCallback));
347         }
348         auto focusManager = context->GetOrCreateFocusManager();
349         focusManager->isFocusActive_ = testcase.focusActive;
350         auto themeManager = AceType::MakeRefPtr<MockThemeManager>();
351         context->SetThemeManager(themeManager);
352         EXPECT_CALL(*themeManager, GetTheme(_)).WillRepeatedly(Return(AceType::MakeRefPtr<AppTheme>()));
353         auto appTheme = context->GetTheme<AppTheme>();
354         appTheme->focusActiveByTab_ = testcase.needFocusHandleClick;
355         buttonFocusHub->tabStop_ = testcase.isTabStop;
356         auto result = buttonFocusHub->HandleKeyEvent(event, intension);
357         EXPECT_EQ(result, testcase.expect);
358     }
359 }
360 
361 /**
362  * @tc.name: HandleCrownEventTest001
363  * @tc.desc: Create SetStyle.
364  * @tc.type: FUNC
365  */
366 HWTEST_F(FocusEventHandlerTestNg, HandleCrownEventTest001, TestSize.Level1)
367 {
368     /**
369      * @tc.steps: step1. Set CrownEventInternal
370      * expected: ret is equal to expect;
371      */
372     CrownEvent event;
373     FocusEvent focusEvent(static_cast<const NonPointerEvent&>(event));
374     auto consume = false;
__anon546ba6f20502(const CrownEvent&) 375     auto onCrownEventCallbackInternal = [&consume](const CrownEvent&) {
376         consume = true;
377         return true;
378     };
379     auto buttonNode = CreateTestTreeWithDefaultFocus();
380     EXPECT_NE(buttonNode, nullptr);
381     auto buttonFocusHub = buttonNode->GetOrCreateFocusHub();
382     EXPECT_NE(buttonFocusHub, nullptr);
383     buttonFocusHub->SetOnCrownEventInternal(std::move(onCrownEventCallbackInternal));
384     auto result = buttonFocusHub->OnFocusEventNode(focusEvent);
385     EXPECT_EQ(consume, result);
386 
387     /**
388      * @tc.steps: step2. Set CrownEventUser
389      * expected: ret is equal to expect;
390      */
391     consume = false;
392     auto consume2 = false;
__anon546ba6f20602(CrownEventInfo& crownInfo) 393     auto onCrownEventCallbackUser = [&consume2](CrownEventInfo& crownInfo) {
394         crownInfo.SetStopPropagation(true);
395         consume2 = true;
396         return true;
397     };
398     buttonFocusHub->SetOnCrownCallback(std::move(onCrownEventCallbackUser));
399     result = buttonFocusHub->OnFocusEventNode(focusEvent);
400     EXPECT_EQ(consume, false);
401     EXPECT_EQ(consume2, result);
402 }
403 
404 /**
405  * @tc.name: OnKeyPreIme001
406  * @tc.desc: Test the function OnKeyPreIme.
407  * @tc.type: FUNC
408  */
409 HWTEST_F(FocusEventHandlerTestNg, OnKeyPreIme001, TestSize.Level1)
410 {
411     /**
412      * @tc.steps1: create frameNode.
413      */
414     auto frameNode = FrameNode::CreateFrameNode(V2::DYNAMIC_COMPONENT_ETS_TAG, -1, AceType::MakeRefPtr<Pattern>());
415 
416     /**
417      * @tc.steps2: create eventHub and focusHub.
418      */
419     RefPtr<EventHub> eventHub = AceType::MakeRefPtr<EventHub>();
420     eventHub->AttachHost(frameNode);
421     auto focusHub = AceType::MakeRefPtr<FocusHub>(AceType::WeakClaim(AceType::RawPtr(eventHub)));
422     KeyEvent keyEvent;
423     keyEvent.action = KeyAction::UP;
424     keyEvent.code = KeyCode::KEY_SPACE;
425 
426     /**
427      * @tc.steps3: call the function OnKeyEvent with FocusType::NODE.
428      * @tc.expected: The return value of OnKeyEvent is true.
429      */
430     focusHub->SetFocusType(FocusType::NODE);
431     focusHub->currentFocus_ = true;
432     focusHub->SetIsNodeNeedKey(true);
433 
434     bool isExecute = false;
__anon546ba6f20702(const KeyEvent& event) 435     auto onKeyEvent = [&isExecute](const KeyEvent& event) mutable -> bool {
436         isExecute = true;
437         return true;
438     };
439     focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
440     KeyEventInfo info(keyEvent);
441     focusHub->OnKeyPreIme(info, keyEvent);
442     EXPECT_TRUE(isExecute);
443 }
444 
445 
446 /**
447  * @tc.name: HandleCrownEventTest001
448  * @tc.desc: test OnClick function.
449  * @tc.type: FUNC
450  */
451 HWTEST_F(FocusEventHandlerTestNg, FocusEventHubOnClickTest001, TestSize.Level1)
452 {
453     /**
454      * @tc.steps: step1. Set onClickCallback
455      * expected: ret is equal to expect;
456      */
457     KeyEvent event;
458     auto consume = false;
__anon546ba6f20802(const GestureEvent&) 459     auto onClickCallback = [&consume](const GestureEvent&) {
460         consume = true;
461     };
462     auto buttonNode = CreateTestTreeWithDefaultFocus();
463     EXPECT_NE(buttonNode, nullptr);
464     auto buttonFocusHub = buttonNode->GetOrCreateFocusHub();
465     EXPECT_NE(buttonFocusHub, nullptr);
466     buttonFocusHub->SetOnClickCallback(std::move(onClickCallback));
467     buttonFocusHub->OnClick(event);
468     EXPECT_EQ(consume, true);
469 }
470 } // namespace OHOS::Ace::NG
471