• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 "component_test/core/component_test_component_impl.h"
17 
18 #include <string>
19 
20 #include "component_test/core/combination_isscrollable.h"
21 
22 #include "base/json/json_util.h"
23 #include "base/utils/utils.h"
24 #include "base/utils/utf_helper.h"
25 #include "core/common/ace_engine.h"
26 #include "core/components_ng/base/inspector_filter.h"
27 #include "core/components_ng/pattern/button/button_layout_property.h"
28 #include "core/components_ng/pattern/checkbox/checkbox_event_hub.h"
29 #include "core/components_ng/pattern/checkbox/checkbox_pattern.h"
30 #include "core/components_ng/pattern/checkboxgroup/checkboxgroup_pattern.h"
31 #include "core/components_ng/pattern/grid/grid_item_pattern.h"
32 #include "core/components_ng/pattern/list/list_item_pattern.h"
33 #include "core/components_ng/pattern/marquee/marquee_accessibility_property.h"
34 #include "core/components_ng/pattern/menu/menu_item/menu_item_pattern.h"
35 #include "core/components_ng/pattern/menu/menu_pattern.h"
36 #include "core/components_ng/pattern/picker/datepicker_pattern.h"
37 #include "core/components_ng/pattern/radio/radio_event_hub.h"
38 #include "core/components_ng/pattern/refresh/refresh_pattern.h"
39 #include "core/components_ng/pattern/scroll/scroll_pattern.h"
40 #include "core/components_ng/pattern/scroll_bar/scroll_bar_pattern.h"
41 #include "core/components_ng/pattern/search/search_pattern.h"
42 #include "core/components_ng/pattern/slider/slider_accessibility_property.h"
43 #include "core/components_ng/pattern/slider/slider_pattern.h"
44 #include "core/components_ng/pattern/text/span_node.h"
45 #include "core/components_ng/pattern/text/text_base.h"
46 #include "core/components_ng/pattern/text/text_layout_property.h"
47 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
48 #include "core/components_ng/pattern/time_picker/timepicker_column_pattern.h"
49 #include "core/components_ng/pattern/web/web_accessibility_property.h"
50 
51 namespace OHOS::Ace::ComponentTest {
52 namespace {
53 constexpr char INSPECTOR_TYPE[] = "$type";
54 constexpr char INSPECTOR_ID[] = "$ID";
55 constexpr char INSPECTOR_RECT[] = "$rect";
56 constexpr char INSPECTOR_ATTRS[] = "$attrs";
57 constexpr char INSPECTOR_WIDTH[] = "width";
58 constexpr char INSPECTOR_HEIGHT[] = "height";
59 constexpr char INSPECTOR_RESOLUTION[] = "$resolution";
60 constexpr char INSPECTOR_CHILDREN[] = "$children";
61 constexpr char INSPECTOR_DEBUGLINE[] = "$debugLine";
62 constexpr char INSPECTOR_VIEW_ID[] = "$viewID";
63 constexpr char INSPECTOR_COMPONENT_TYPE[] = "type";
64 NG::RectF deviceRect;
65 } // namespace
66 
TapImpl(ErrInfo & errInfo) const67 void ComponentTestComponentImpl::TapImpl(ErrInfo& errInfo) const
68 {
69     if (!GenericClick(TouchType::TAP)) {
70         errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
71     }
72 }
73 
DoubleTapImpl(ErrInfo & errInfo) const74 void ComponentTestComponentImpl::DoubleTapImpl(ErrInfo& errInfo) const
75 {
76     if (!GenericClick(TouchType::DOUBLE_TAP)) {
77         errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
78     }
79 }
80 
PressImpl(ErrInfo & errInfo,uint32_t duration) const81 void ComponentTestComponentImpl::PressImpl(ErrInfo& errInfo, uint32_t duration) const
82 {
83     if (!GenericClick(TouchType::PRESS, duration)) {
84         errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
85     }
86 }
87 
PinchOutImpl(float scale,ErrInfo & errInfo) const88 void ComponentTestComponentImpl::PinchOutImpl(float scale, ErrInfo& errInfo) const
89 {
90     auto container = AceEngine::Get().GetContainer(ACE_INSTANCE_ID);
91     CHECK_NULL_VOID(container);
92     auto context = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
93     CHECK_NULL_VOID(context);
94     CHECK_NULL_VOID(uiNode_);
95     auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode_);
96     CHECK_NULL_VOID(frameNode);
97     NG::RectF rect = frameNode->GetTransformRectRelativeToWindow();
98     auto viewScale = context->GetViewScale();
99     float widthScale = context->GetRootWidth() * viewScale / rect.Width();
100     float heightScale = context->GetRootHeight() * viewScale / rect.Height();
101     float originalScale = (widthScale < heightScale) ? widthScale : heightScale;
102     if (scale < 1) {
103         return;
104     } else if (scale > originalScale) {
105         scale = originalScale;
106     }
107     PinchAction pinchAction(rect, scale);
108     EventSequenceManager::GetInstance().Execute(&pinchAction);
109 }
110 
PinchInImpl(float scale,ErrInfo & errInfo) const111 void ComponentTestComponentImpl::PinchInImpl(float scale, ErrInfo& errInfo) const
112 {
113     const RefPtr<NG::FrameNode>& frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode_);
114     CHECK_NULL_VOID(uiNode_);
115     CHECK_NULL_VOID(frameNode);
116     NG::RectF rectBound = frameNode->GetTransformRectRelativeToWindow();
117     if (scale > 1 && scale < 0) {
118         return;
119     }
120     PinchAction pinchAction(rectBound, scale);
121     EventSequenceManager::GetInstance().Execute(&pinchAction);
122 }
123 
InputTextImpl(std::string text,ErrInfo & errInfo) const124 void ComponentTestComponentImpl::InputTextImpl(std::string text, ErrInfo& errInfo) const
125 {
126     const RefPtr<NG::FrameNode>& frameNode = GetFrameNode();
127     if (!frameNode) {
128         errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_NOT_SUPPORTED);
129         return;
130     }
131     const RefPtr<NG::Pattern>& pattern = frameNode->GetPattern();
132     if (!pattern) {
133         errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
134         return;
135     }
136     std::string currentText = GetTextImpl(errInfo);
137     SingleKeyAction singleKeyAction(text, currentText);
138     singleKeyAction.Send();
139     return;
140 }
141 
ClearTextImpl(ErrInfo & errInfo) const142 void ComponentTestComponentImpl::ClearTextImpl(ErrInfo& errInfo) const
143 {
144     const RefPtr<NG::FrameNode>& frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode_);
145     if (!frameNode) {
146         errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
147         return;
148     }
149     std::vector<OHOS::MMI::KeyCode> keyCodes;
150     std::string buff = GetTextImpl(errInfo);
151     keyCodes.push_back(OHOS::MMI::KeyCode::KEY_DPAD_DOWN);
152     for (auto i : buff) {
153         if (i == '\n') {
154             keyCodes.push_back(OHOS::MMI::KeyCode::KEY_DPAD_DOWN);
155         }
156     }
157     keyCodes.push_back(OHOS::MMI::KeyCode::KEY_DPAD_DOWN);
158     keyCodes.push_back(OHOS::MMI::KeyCode::KEY_MOVE_END);
159     for (size_t i = 0; i < buff.size(); i++) {
160         keyCodes.push_back(OHOS::MMI::KeyCode::KEY_FORWARD_DEL);
161     }
162     SingleKeyAction singleKeyAction(keyCodes);
163     singleKeyAction.Send();
164     return;
165 }
166 
GetEndpointChildFrameNode(RefPtr<NG::UINode> parentNode,bool first)167 RefPtr<NG::FrameNode> GetEndpointChildFrameNode(RefPtr<NG::UINode> parentNode, bool first)
168 {
169     auto node = parentNode;
170     while (node && !node->IsAtomicNode()) {
171         node = first ? node->GetFirstChild() : node->GetLastChild();
172         if (AceType::InstanceOf<NG::FrameNode>(node)) {
173             break;
174         }
175     }
176     return AceType::DynamicCast<NG::FrameNode>(node);
177 }
178 
ScrollToBorderAsync(uint32_t speed,bool toTop,std::function<void (ErrInfo errInfo)> && callback) const179 void ComponentTestComponentImpl::ScrollToBorderAsync(
180     uint32_t speed, bool toTop, std::function<void(ErrInfo errInfo)>&& callback) const
181 {
182     const RefPtr<NG::FrameNode>& frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode_);
183     if (!frameNode) {
184         callback(QueryRetMsg(ErrCode::RET_ERR_COMPONENT_NOT_SUPPORTED));
185         return;
186     }
187     const RefPtr<NG::FrameNode>& endFrameNode = GetEndpointChildFrameNode(uiNode_, toTop);
188     if (!endFrameNode) {
189         callback(QueryRetMsg(ErrCode::RET_ERR_COMPONENT_NOT_SUPPORTED));
190         return;
191     }
192     NG::RectF parentRect = frameNode->GetRectWithRender();
193     NG::RectF endFrameRect = endFrameNode->GetTransformRectRelativeToWindow();
194     float endY = toTop ? endFrameRect.GetY() : endFrameRect.GetY() + endFrameRect.Height();
195     NG::PointF bottomPoint(parentRect.Center().GetX(), parentRect.Bottom());
196     NG::PointF topPoint(parentRect.Center().GetX(), parentRect.Top());
197     if (toTop) {
198         if (LessOrEqual(parentRect.GetY(), endY) && GreatNotEqual(parentRect.GetY() + parentRect.Height(), endY)) {
199             callback({ ErrCode::RET_OK, "" });
200             return;
201         }
202         MoveAction moveAction(topPoint, bottomPoint, TouchType::DRAG, speed);
203         EventSequenceManager::GetInstance().Execute(&moveAction);
204     } else {
205         if (GreatOrEqual(parentRect.GetY() + parentRect.Height(), endY) && LessNotEqual(parentRect.GetY(), endY)) {
206             callback({ ErrCode::RET_OK, "" });
207             return;
208         }
209         MoveAction moveAction(bottomPoint, topPoint, TouchType::DRAG, speed);
210         EventSequenceManager::GetInstance().Execute(&moveAction);
211     }
212     ComponentTestManagerProxy::PostJSTask(
213         [this, speed, toTop, passedCallback = std::move(callback)](void* data) {
214             ScrollToBorderAsync(speed, toTop, [passedCallback](ErrInfo errInfo) { passedCallback(errInfo); });
215         },
216         nullptr);
217     return;
218 }
219 
ScrollToTopImplAsync(uint32_t speed,std::function<void (ErrInfo errInfo)> && callback) const220 void ComponentTestComponentImpl::ScrollToTopImplAsync(
221     uint32_t speed, std::function<void(ErrInfo errInfo)>&& callback) const
222 {
223     ScrollToBorderAsync(speed, true, std::move(callback));
224 }
225 
ScrollToBottomImplAsync(uint32_t speed,std::function<void (ErrInfo errInfo)> && callback) const226 void ComponentTestComponentImpl::ScrollToBottomImplAsync(
227     uint32_t speed, std::function<void(ErrInfo errInfo)>&& callback) const
228 {
229     ScrollToBorderAsync(speed, false, std::move(callback));
230 }
231 
GetIdImpl(ErrInfo & errInfo) const232 std::string ComponentTestComponentImpl::GetIdImpl(ErrInfo& errInfo) const
233 {
234     if (uiNode_) {
235         const RefPtr<NG::FrameNode>& frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode_);
236         if (frameNode) {
237             return frameNode->GetInspectorId().value_or("");
238         }
239     }
240     errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
241     return "";
242 }
243 
GetTextByPattern(const RefPtr<NG::FrameNode> & frameNode,std::string & text)244 bool GetTextByPattern(const RefPtr<NG::FrameNode>& frameNode, std::string& text)
245 {
246     const RefPtr<NG::Pattern>& pattern = frameNode->GetPattern();
247     CHECK_NULL_RETURN(pattern, false);
248     if (AceType::InstanceOf<NG::TextFieldPattern>(pattern)) {
249         auto textFieldPattern = AceType::DynamicCast<NG::TextFieldPattern>(pattern);
250         CHECK_NULL_RETURN(textFieldPattern, false);
251         text = textFieldPattern->GetTextValue();
252         return true;
253     } else if (AceType::InstanceOf<NG::SearchPattern>(pattern)) {
254         auto searchPattern = AceType::DynamicCast<NG::SearchPattern>(pattern);
255         if (searchPattern) {
256             auto textFieldFrameNode = AceType::DynamicCast<NG::FrameNode>(frameNode->GetChildAtIndex(0));
257             auto textFieldPattern = textFieldFrameNode->GetPattern<NG::TextFieldPattern>();
258             CHECK_NULL_RETURN(textFieldPattern, false);
259             text = textFieldPattern->GetTextValue();
260             return true;
261         }
262     }
263     return false;
264 }
GetTextByEventHub(const RefPtr<NG::FrameNode> & frameNode,std::string & text)265 bool GetTextByEventHub(const RefPtr<NG::FrameNode>& frameNode, std::string& text)
266 {
267     const RefPtr<NG::EventHub>& eventHub = frameNode->GetOrCreateEventHub<NG::EventHub>();
268     CHECK_NULL_RETURN(eventHub, false);
269     if (AceType::InstanceOf<NG::CheckBoxEventHub>(eventHub)) {
270         auto checkBoxEventHub = AceType::DynamicCast<NG::CheckBoxEventHub>(eventHub);
271         if (checkBoxEventHub) {
272             text = checkBoxEventHub->GetName();
273             return true;
274         }
275     } else if (AceType::InstanceOf<NG::RadioEventHub>(eventHub)) {
276         auto radioEventHub = AceType::DynamicCast<NG::RadioEventHub>(eventHub);
277         if (radioEventHub) {
278             text = radioEventHub->GetValue();
279             return true;
280         }
281     }
282     return false;
283 }
GetTextByAccessibilityProperty(const RefPtr<NG::FrameNode> & frameNode,std::string & text)284 bool GetTextByAccessibilityProperty(const RefPtr<NG::FrameNode>& frameNode, std::string& text)
285 {
286     const RefPtr<NG::AccessibilityProperty>& accessibilityProperty =
287         frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
288     CHECK_NULL_RETURN(accessibilityProperty, false);
289     if (AceType::InstanceOf<NG::AccessibilityProperty>(accessibilityProperty)) {
290         if (accessibilityProperty) {
291             text = accessibilityProperty->GetText();
292             return true;
293         }
294     }
295     return false;
296 }
GetTextByLayoutProperty(const RefPtr<NG::FrameNode> & frameNode,std::string & text)297 bool GetTextByLayoutProperty(const RefPtr<NG::FrameNode>& frameNode, std::string& text)
298 {
299     const RefPtr<NG::LayoutProperty>& layoutProperty = frameNode->GetLayoutProperty<NG::LayoutProperty>();
300     CHECK_NULL_RETURN(layoutProperty, false);
301     if (AceType::InstanceOf<NG::ButtonLayoutProperty>(layoutProperty)) {
302         auto buttonLayoutProperty = AceType::DynamicCast<NG::ButtonLayoutProperty>(layoutProperty);
303         if (buttonLayoutProperty) {
304             text = buttonLayoutProperty->GetLabelValue();
305             return true;
306         }
307     } else if (AceType::InstanceOf<NG::TextLayoutProperty>(layoutProperty)) {
308         auto textLayoutProperty = AceType::DynamicCast<NG::TextLayoutProperty>(layoutProperty);
309         if (textLayoutProperty) {
310             text = UtfUtils::Str16ToStr8(textLayoutProperty->GetContent().value());
311             return true;
312         }
313     }
314     return false;
315 }
GetTextImpl(ErrInfo & errInfo) const316 std::string ComponentTestComponentImpl::GetTextImpl(ErrInfo& errInfo) const
317 {
318     const RefPtr<NG::FrameNode>& frameNode = GetFrameNode();
319     if (!frameNode) {
320         errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_NOT_SUPPORTED);
321         return "";
322     }
323     std::string buff;
324     if (OHOS::Ace::ComponentTest::GetTextByPattern(frameNode, buff)) {
325         return buff;
326     } else if (OHOS::Ace::ComponentTest::GetTextByEventHub(frameNode, buff)) {
327         return buff;
328     } else if (OHOS::Ace::ComponentTest::GetTextByAccessibilityProperty(frameNode, buff)) {
329         return buff;
330     } else if (OHOS::Ace::ComponentTest::GetTextByLayoutProperty(frameNode, buff)) {
331         return buff;
332     } else {
333         return "";
334     }
335 }
336 
GetTypeImpl(ErrInfo & errInfo) const337 std::string ComponentTestComponentImpl::GetTypeImpl(ErrInfo& errInfo) const
338 {
339     if (uiNode_) {
340         const RefPtr<NG::FrameNode>& frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode_);
341         if (frameNode) {
342             return frameNode->GetTag();
343         }
344     }
345     errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
346     return "";
347 }
348 
IsClickableImpl(ErrInfo & errInfo) const349 bool ComponentTestComponentImpl::IsClickableImpl(ErrInfo& errInfo) const
350 {
351     const RefPtr<NG::FrameNode>& frameNode = GetFrameNode();
352     if (!frameNode) {
353         errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
354         return false;
355     }
356     auto gesture = frameNode->GetOrCreateGestureEventHub();
357     return gesture && gesture->IsClickable();
358 }
359 
IsLongPressableImpl(ErrInfo & errInfo) const360 bool ComponentTestComponentImpl::IsLongPressableImpl(ErrInfo& errInfo) const
361 {
362     const RefPtr<NG::FrameNode>& frameNode = GetFrameNode();
363     if (!frameNode) {
364         errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
365         return false;
366     }
367     auto gesture = frameNode->GetOrCreateGestureEventHub();
368     return gesture && gesture->GetLongPressRecognizer();
369 }
370 
IsScrollableByPattern(const RefPtr<NG::FrameNode> & frameNode)371 bool IsScrollableByPattern(const RefPtr<NG::FrameNode>& frameNode)
372 {
373     const RefPtr<NG::Pattern>& pattern = frameNode->GetPattern();
374     if (AceType::InstanceOf<OHOS::Ace::NG::ScrollablePattern>(pattern)) {
375         auto scrollablePattern = AceType::DynamicCast<OHOS::Ace::NG::ScrollablePattern>(pattern);
376         return scrollablePattern->IsScrollable();
377     } else if (AceType::InstanceOf<OHOS::Ace::NG::ScrollBarPattern>(pattern)) {
378         auto scrollBarPattern = frameNode->GetPattern<OHOS::Ace::NG::ScrollBarPattern>();
379         CHECK_NULL_RETURN(scrollBarPattern, false);
380         if (scrollBarPattern->GetAxis() != Axis::NONE && Positive(scrollBarPattern->GetControlDistance())) {
381             return true;
382         }
383         return false;
384     } else if (AceType::InstanceOf<OHOS::Ace::NG::RefreshPattern>(pattern)) {
385         auto refreshPattern = frameNode->GetPattern<OHOS::Ace::NG::RefreshPattern>();
386         CHECK_NULL_RETURN(refreshPattern, false);
387         return !refreshPattern->IsRefreshing();
388     } else if (AceType::InstanceOf<OHOS::Ace::NG::MenuPattern>(pattern)) {
389         auto firstChild = AceType::DynamicCast<NG::FrameNode>(frameNode->GetChildAtIndex(0));
390         if (firstChild && firstChild->GetTag() == V2::SCROLL_ETS_TAG) {
391             auto scrollPattern = firstChild->GetPattern<OHOS::Ace::NG::ScrollPattern>();
392             CHECK_NULL_RETURN(scrollPattern, false);
393             if (scrollPattern->IsScrollable() && !NearZero(scrollPattern->GetScrollableDistance())) {
394                 return true;
395             }
396         }
397     }
398     return false;
399 }
400 
IsScrollableImpl(ErrInfo & errInfo) const401 bool ComponentTestComponentImpl::IsScrollableImpl(ErrInfo& errInfo) const
402 {
403     const RefPtr<NG::FrameNode> frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode_);
404     if (!frameNode) {
405         errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
406         return false;
407     }
408     const RefPtr<NG::Pattern>& pattern = frameNode->GetPattern();
409     if (!pattern) {
410         errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
411         return false;
412     }
413     OHOS::Ace::CombinationIsScrollable combinationIsscrollable(frameNode);
414     if (combinationIsscrollable.IsComponentExist()) {
415         return combinationIsscrollable.IsComponentScrollable();
416     }
417     if (IsScrollableByPattern(frameNode)) {
418         return true;
419     }
420     if (AceType::InstanceOf<OHOS::Ace::NG::DatePickerPattern>(pattern)) {
421         auto datePickerPattern = AceType::DynamicCast<OHOS::Ace::NG::DatePickerPattern>(pattern);
422         CHECK_NULL_RETURN(datePickerPattern, false);
423         auto options = datePickerPattern->GetOptions();
424         auto it = options.find(frameNode);
425         uint32_t ret = 0;
426         if (it != options.end()) {
427             ret = it->second.size();
428         }
429         return ret > 1;
430     } else if (AceType::InstanceOf<OHOS::Ace::NG::TimePickerColumnPattern>(pattern)) {
431         auto timePickerPattern = AceType::DynamicCast<OHOS::Ace::NG::TimePickerColumnPattern>(pattern);
432         CHECK_NULL_RETURN(timePickerPattern, 0);
433         auto options = timePickerPattern->GetOptions();
434         CHECK_NULL_RETURN(options.find(frameNode) != options.end(), false);
435         return (options[frameNode] > 1) ? true : false;
436     } else if (AceType::InstanceOf<OHOS::Ace::NG::SliderPattern>(pattern)) {
437         const RefPtr<NG::SliderAccessibilityProperty>& sliderAccessibilityProperty =
438             frameNode->GetAccessibilityProperty<NG::SliderAccessibilityProperty>();
439         return sliderAccessibilityProperty->IsScrollable();
440     } else {
441         return false;
442     }
443 }
444 
IsEnabledImpl(ErrInfo & errInfo) const445 bool ComponentTestComponentImpl::IsEnabledImpl(ErrInfo& errInfo) const
446 {
447     const RefPtr<NG::FrameNode>& frameNode = GetFrameNode();
448     if (!frameNode) {
449         errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
450         return false;
451     }
452     auto eventHub = frameNode->GetOrCreateEventHub<NG::EventHub>();
453     return eventHub && eventHub->IsEnabled();
454 }
455 
IsFocusedImpl(ErrInfo & errInfo) const456 bool ComponentTestComponentImpl::IsFocusedImpl(ErrInfo& errInfo) const
457 {
458     const RefPtr<NG::FrameNode>& frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode_);
459     if (!frameNode) {
460         errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
461         return false;
462     }
463     auto focusHub = frameNode->GetFocusHub();
464     if (!focusHub) {
465         errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
466         return false;
467     }
468     return focusHub->IsDefaultFocus() && focusHub->IsFocusable();
469 }
470 
IsSelectedImpl(ErrInfo & errInfo) const471 bool ComponentTestComponentImpl::IsSelectedImpl(ErrInfo& errInfo) const
472 {
473     const RefPtr<NG::FrameNode>& frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode_);
474     if (!frameNode) {
475         errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
476         return false;
477     }
478     const RefPtr<NG::Pattern>& pattern = frameNode->GetPattern();
479     if (!pattern) {
480         errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
481         return false;
482     }
483     if (AceType::InstanceOf<NG::ListItemPattern>(pattern)) {
484         auto listItemPattern = AceType::DynamicCast<NG::ListItemPattern>(pattern);
485         if (listItemPattern) {
486             return listItemPattern->IsSelected();
487         }
488     } else if (AceType::InstanceOf<NG::GridItemPattern>(pattern)) {
489         auto gridItemPattern = AceType::DynamicCast<NG::GridItemPattern>(pattern);
490         if (gridItemPattern) {
491             return gridItemPattern->IsSelected();
492         }
493     } else if (AceType::InstanceOf<NG::TextBase>(pattern)) {
494         auto textBase = AceType::DynamicCast<NG::TextBase>(pattern);
495         if (textBase) {
496             return textBase->IsSelected();
497         }
498     } else if (AceType::InstanceOf<NG::MenuItemPattern>(pattern)) {
499         auto menuItemPattern = AceType::DynamicCast<NG::MenuItemPattern>(pattern);
500         if (menuItemPattern) {
501             return menuItemPattern->IsSelected();
502         }
503     }
504     return false;
505 }
506 
IsCheckedImpl(ErrInfo & errInfo) const507 bool ComponentTestComponentImpl::IsCheckedImpl(ErrInfo& errInfo) const
508 {
509     const RefPtr<NG::FrameNode>& frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode_);
510     if (!frameNode) {
511         errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
512         return false;
513     }
514     const RefPtr<NG::AccessibilityProperty>& accessibilityProperty =
515         frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
516     if (accessibilityProperty) {
517         return accessibilityProperty->IsChecked();
518     } else {
519         return false;
520     }
521 }
522 
IsCheckableImpl(ErrInfo & errInfo) const523 bool ComponentTestComponentImpl::IsCheckableImpl(ErrInfo& errInfo) const
524 {
525     const RefPtr<NG::FrameNode>& frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode_);
526     if (!frameNode) {
527         errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
528         return false;
529     }
530     const RefPtr<NG::AccessibilityProperty>& accessibilityProperty =
531         frameNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
532     if (accessibilityProperty) {
533         return accessibilityProperty->IsCheckable();
534     } else {
535         return false;
536     }
537 }
538 
GetInspectorInfoImpl(ErrInfo & errInfo) const539 std::string ComponentTestComponentImpl::GetInspectorInfoImpl(ErrInfo& errInfo) const
540 {
541     CHECK_NULL_RETURN(uiNode_, "");
542     auto jsonNode = JsonUtil::Create(true);
543     jsonNode->Put(INSPECTOR_TYPE, uiNode_->GetTag().c_str());
544     jsonNode->Put(INSPECTOR_ID, uiNode_->GetInspectorId().value_or("").c_str());
545     auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode_);
546     if (frameNode) {
547         auto rect = frameNode->GetTransformRectRelativeToWindow();
548         jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
549     }
550     auto jsonAttrs = JsonUtil::Create(true);
551     std::string debugLine = uiNode_->GetDebugLine();
552     jsonNode->Put(INSPECTOR_DEBUGLINE, debugLine.c_str());
553     NG::InspectorFilter filter;
554     uiNode_->ToJsonValue(jsonAttrs, filter);
555     jsonNode->Put(INSPECTOR_ATTRS, jsonAttrs);
556     return jsonNode->ToString();
557 }
558 
GetInspectorTreeImpl(ErrInfo & errInfo) const559 std::string ComponentTestComponentImpl::GetInspectorTreeImpl(ErrInfo& errInfo) const
560 {
561     if (uiNode_) {
562         auto container = AceEngine::Get().GetContainer(ACE_INSTANCE_ID);
563         auto context = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
564         auto jsonNode = JsonUtil::Create(true);
565         GetContextInfo(context, jsonNode);
566         std::vector<RefPtr<NG::UINode>> children;
567         for (const auto& item : uiNode_->GetChildren()) {
568             GetFrameNodeChildren(item, children, uiNode_->GetPageId());
569         }
570         return GetChildrenInspectorInfo(children, uiNode_->GetPageId(), std::move(jsonNode));
571     }
572     errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
573     return "";
574 }
575 
GetChildCountImpl(ErrInfo & errInfo) const576 int32_t ComponentTestComponentImpl::GetChildCountImpl(ErrInfo& errInfo) const
577 {
578     return uiNode_->TotalChildCount();
579 }
580 
GetBoundsImpl(ErrInfo & errInfo) const581 NG::RectF ComponentTestComponentImpl::GetBoundsImpl(ErrInfo& errInfo) const
582 {
583     if (uiNode_) {
584         const RefPtr<NG::FrameNode>& frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode_);
585         if (frameNode) {
586             return frameNode->GetTransformRectRelativeToWindow();
587         }
588     }
589     errInfo = QueryRetMsg(ErrCode::RET_ERR_COMPONENT_INVISIBLE_OR_DESTROYED);
590     return NG::RectF { 0, 0, 0, 0 };
591 }
592 
SetUiNode(const RefPtr<NG::UINode> uiNode)593 void ComponentTestComponentImpl::SetUiNode(const RefPtr<NG::UINode> uiNode)
594 {
595     uiNode_ = uiNode;
596 }
597 
SetEffective()598 void ComponentTestComponentImpl::SetEffective()
599 {
600     auto container = AceEngine::Get().GetContainer(ACE_INSTANCE_ID);
601     CHECK_NULL_VOID(container);
602     auto context = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
603     CHECK_NULL_VOID(context);
604     auto scale = context->GetViewScale();
605     NG::RectF screenRect(0, 0, context->GetRootWidth() * scale, context->GetRootHeight() * scale);
606     CHECK_NULL_VOID(uiNode_);
607     const RefPtr<NG::FrameNode>& frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode_);
608     if (frameNode) {
609         NG::RectF rect = frameNode->GetTransformRectRelativeToWindow();
610         effective_ = screenRect.IntersectRectT(rect);
611     } else {
612         effective_ = NG::RectF();
613     }
614 }
615 
GetContextInfo(const RefPtr<NG::PipelineContext> & context,std::unique_ptr<JsonValue> & jsonRoot) const616 void ComponentTestComponentImpl::GetContextInfo(
617     const RefPtr<NG::PipelineContext>& context, std::unique_ptr<JsonValue>& jsonRoot) const
618 {
619     auto scale = context->GetViewScale();
620     auto rootHeight = context->GetRootHeight();
621     auto rootWidth = context->GetRootWidth();
622     deviceRect.SetRect(0, 0, rootWidth * scale, rootHeight * scale);
623     jsonRoot->Put(INSPECTOR_WIDTH, std::to_string(rootWidth * scale).c_str());
624     jsonRoot->Put(INSPECTOR_HEIGHT, std::to_string(rootHeight * scale).c_str());
625     jsonRoot->Put(INSPECTOR_RESOLUTION, std::to_string(PipelineBase::GetCurrentDensity()).c_str());
626 }
627 
GetFrameNodeChildren(const RefPtr<NG::UINode> & uiNode,std::vector<RefPtr<NG::UINode>> & children,int32_t pageId) const628 void ComponentTestComponentImpl::GetFrameNodeChildren(
629     const RefPtr<NG::UINode>& uiNode, std::vector<RefPtr<NG::UINode>>& children, int32_t pageId) const
630 {
631     if (AceType::InstanceOf<NG::FrameNode>(uiNode) || AceType::InstanceOf<NG::SpanNode>(uiNode)) {
632         if (uiNode->GetTag() == "stage") {
633         } else if (uiNode->GetTag() == "page") {
634             if (uiNode->GetPageId() != pageId) {
635                 return;
636             }
637         } else {
638             auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
639             auto spanNode = AceType::DynamicCast<NG::SpanNode>(uiNode);
640             if ((frameNode && !frameNode->IsInternal()) || spanNode) {
641                 children.emplace_back(uiNode);
642                 return;
643             }
644         }
645     }
646     for (const auto& frameChild : uiNode->GetChildren()) {
647         GetFrameNodeChildren(frameChild, children, pageId);
648     }
649 }
650 
GetChildrenInspectorInfo(std::vector<RefPtr<NG::UINode>> children,int32_t pageId,std::unique_ptr<JsonValue> jsonNode) const651 std::string ComponentTestComponentImpl::GetChildrenInspectorInfo(
652     std::vector<RefPtr<NG::UINode>> children, int32_t pageId, std::unique_ptr<JsonValue> jsonNode) const
653 {
654     auto jsonNodeArray = JsonUtil::CreateArray(true);
655     for (auto& uiNode : children) {
656         GetInspectorChildren(uiNode, jsonNodeArray, pageId);
657     }
658     if (jsonNodeArray->GetArraySize()) {
659         jsonNode->PutRef(INSPECTOR_CHILDREN, std::move(jsonNodeArray));
660     }
661 
662     return jsonNode->ToString();
663 }
664 
NodeRectToString(RefPtr<NG::FrameNode> node)665 std::string NodeRectToString(RefPtr<NG::FrameNode> node)
666 {
667     NG::RectF rect;
668     bool isActive = node->IsActive();
669     if (isActive) {
670         rect = node->GetTransformRectRelativeToWindow();
671     }
672     rect = rect.Constrain(deviceRect);
673     if (rect.IsEmpty()) {
674         rect.SetRect(0, 0, 0, 0);
675     }
676     return std::to_string(rect.Left())
677         .append(",")
678         .append(std::to_string(rect.Top()))
679         .append(",")
680         .append(std::to_string(rect.Width()))
681         .append(",")
682         .append(std::to_string(rect.Height()));
683 }
684 
GetInspectorChildren(const RefPtr<NG::UINode> & parent,std::unique_ptr<JsonValue> & jsonNodeArray,int pageId) const685 void ComponentTestComponentImpl::GetInspectorChildren(
686     const RefPtr<NG::UINode>& parent, std::unique_ptr<JsonValue>& jsonNodeArray, int pageId) const
687 {
688     // Span is a special case in Inspector since span inherits from UINode
689     if (AceType::InstanceOf<NG::SpanNode>(parent)) {
690         GetSpanInspector(parent, jsonNodeArray, pageId);
691         return;
692     }
693     auto jsonNode = JsonUtil::Create(true);
694     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
695     jsonNode->Put(INSPECTOR_ID, parent->GetInspectorId().value_or("").c_str());
696     if (parent->GetTag() == "__Common__") {
697         jsonNode->Put(INSPECTOR_COMPONENT_TYPE, "custom");
698     } else {
699         jsonNode->Put(INSPECTOR_COMPONENT_TYPE, "build-in");
700     }
701     auto node = AceType::DynamicCast<NG::FrameNode>(parent);
702     if (node) {
703         std::string strRec = NodeRectToString(node);
704         jsonNode->Put(INSPECTOR_RECT, strRec.c_str());
705         jsonNode->Put(INSPECTOR_DEBUGLINE, node->GetDebugLine().c_str());
706         jsonNode->Put(INSPECTOR_VIEW_ID, node->GetViewId().c_str());
707         auto jsonObject = JsonUtil::Create(true);
708         parent->ToJsonValue(jsonObject, NG::InspectorFilter());
709         jsonNode->Put(INSPECTOR_ATTRS, jsonObject);
710     }
711 
712     std::vector<RefPtr<NG::UINode>> children;
713     for (const auto& item : parent->GetChildren()) {
714         GetFrameNodeChildren(item, children, pageId);
715     }
716     if (node != nullptr) {
717         auto overlayNode = node->GetOverlayNode();
718         if (overlayNode != nullptr) {
719             GetFrameNodeChildren(overlayNode, children, pageId);
720         }
721     }
722     auto jsonChildrenArray = JsonUtil::CreateArray(true);
723     for (auto uiNode : children) {
724         GetInspectorChildren(uiNode, jsonChildrenArray, pageId);
725     }
726     if (jsonChildrenArray->GetArraySize()) {
727         jsonNode->Put(INSPECTOR_CHILDREN, jsonChildrenArray);
728     }
729     jsonNodeArray->PutRef(std::move(jsonNode));
730 }
731 
GetSpanInspector(const RefPtr<NG::UINode> & parent,std::unique_ptr<JsonValue> & jsonNodeArray,int pageId) const732 void ComponentTestComponentImpl::GetSpanInspector(
733     const RefPtr<NG::UINode>& parent, std::unique_ptr<JsonValue>& jsonNodeArray, int pageId) const
734 {
735     // span rect follows parent text size
736     auto spanParentNode = parent->GetParent();
737     while (spanParentNode != nullptr) {
738         if (AceType::InstanceOf<NG::FrameNode>(spanParentNode)) {
739             break;
740         }
741         spanParentNode = spanParentNode->GetParent();
742     }
743     CHECK_NULL_VOID(spanParentNode);
744     auto node = AceType::DynamicCast<NG::FrameNode>(spanParentNode);
745     auto jsonNode = JsonUtil::Create(true);
746     auto jsonObject = JsonUtil::Create(true);
747     NG::InspectorFilter filter;
748     parent->ToJsonValue(jsonObject, filter);
749     jsonNode->Put(INSPECTOR_ATTRS, jsonObject);
750     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
751     jsonNode->Put(INSPECTOR_ID, parent->GetInspectorId().value_or("").c_str());
752     std::string strRec = NodeRectToString(node);
753     jsonNode->Put(INSPECTOR_RECT, strRec.c_str());
754     jsonNode->Put(INSPECTOR_DEBUGLINE, parent->GetDebugLine().c_str());
755     jsonNode->Put(INSPECTOR_VIEW_ID, parent->GetViewId().c_str());
756     jsonNodeArray->PutRef(std::move(jsonNode));
757 }
758 
GenericClick(const TouchType touchType,uint32_t duration) const759 bool ComponentTestComponentImpl::GenericClick(const TouchType touchType, uint32_t duration) const
760 {
761     CHECK_NULL_RETURN(uiNode_, false);
762     NG::OffsetF center = effective_.Center();
763     NG::PointF point(center.GetX(), center.GetY());
764     ClickAction clickAction(point, touchType, duration);
765     EventSequenceManager::GetInstance().Execute(&clickAction);
766     return true;
767 }
768 
GetFrameNode() const769 RefPtr<NG::FrameNode> ComponentTestComponentImpl::GetFrameNode() const
770 {
771     CHECK_NULL_RETURN(uiNode_, nullptr);
772     const RefPtr<NG::FrameNode>& frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode_);
773     CHECK_NULL_RETURN(frameNode, nullptr);
774     return frameNode;
775 }
776 
777 } // namespace OHOS::Ace::ComponentTest
778