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