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_tester_impl.h"
17
18 #include <algorithm>
19 #include <queue>
20
21 #include "base/geometry/ng/point_t.h"
22 #include "base/geometry/rect.h"
23 #include "base/memory/ace_type.h"
24 #include "base/utils/utils.h"
25 #include "core/common/ace_engine.h"
26 #include "core/common/container.h"
27 #include "core/components_ng/base/ui_node.h"
28 #include "core/pipeline_ng/pipeline_context.h"
29
30 namespace OHOS::Ace::ComponentTest {
FindComponentImpl(const ComponentTestMatcherImpl & matcher,ErrInfo & errInfo) const31 ComponentTestComponentImpl* ComponentTestTesterImpl::FindComponentImpl(
32 const ComponentTestMatcherImpl& matcher, ErrInfo& errInfo) const
33 {
34 errInfo = QueryRetMsg(RET_ERR_FAILED);
35 auto container = AceEngine::Get().GetContainer(ACE_INSTANCE_ID);
36 CHECK_NULL_RETURN(container, nullptr);
37 auto context = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
38 CHECK_NULL_RETURN(context, nullptr);
39 auto rootNode = context->GetRootElement();
40 CHECK_NULL_RETURN(rootNode, nullptr);
41 errInfo = QueryRetMsg(RET_OK);
42 std::queue<RefPtr<NG::UINode>> elements;
43 elements.push(rootNode);
44 while (!elements.empty()) {
45 auto current = elements.front();
46 elements.pop();
47 if (matcher.Match(current)) {
48 ComponentTestComponentImpl* componentTestComponentImpl = new ComponentTestComponentImpl();
49 componentTestComponentImpl->SetUiNode(current);
50 componentTestComponentImpl->SetEffective();
51 return componentTestComponentImpl;
52 }
53
54 const auto& children = current->GetChildren();
55 for (const auto& child : children) {
56 elements.push(child);
57 }
58 }
59 return nullptr;
60 }
61
FindComponentsImpl(const ComponentTestMatcherImpl & matcher,ErrInfo & errInfo) const62 std::unique_ptr<std::vector<ComponentTestComponentImpl*>> ComponentTestTesterImpl::FindComponentsImpl(
63 const ComponentTestMatcherImpl& matcher, ErrInfo& errInfo) const
64 {
65 auto testerElements = std::make_unique<std::vector<ComponentTestComponentImpl*>>();
66 auto container = AceEngine::Get().GetContainer(ACE_INSTANCE_ID);
67 errInfo = QueryRetMsg(RET_ERR_FAILED);
68 CHECK_NULL_RETURN(container, nullptr);
69 auto context = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
70 CHECK_NULL_RETURN(context, nullptr);
71 auto rootNode = context->GetRootElement();
72 CHECK_NULL_RETURN(rootNode, nullptr);
73 errInfo = QueryRetMsg(RET_OK);
74
75 std::queue<RefPtr<NG::UINode>> elements;
76 elements.push(rootNode);
77 RefPtr<NG::UINode> inspectorElement;
78 while (!elements.empty()) {
79 auto current = elements.front();
80 elements.pop();
81 if (matcher.Match(current)) {
82 ComponentTestComponentImpl* componentTestComponentImpl = new ComponentTestComponentImpl();
83 componentTestComponentImpl->SetUiNode(current);
84 componentTestComponentImpl->SetEffective();
85 testerElements->emplace_back(componentTestComponentImpl);
86 }
87
88 const auto& children = current->GetChildren();
89 for (const auto& child : children) {
90 elements.push(child);
91 }
92 }
93 return testerElements;
94 }
95
AssertComponentExistImpl(const ComponentTestMatcherImpl & matcher,ErrInfo & errInfo) const96 void ComponentTestTesterImpl::AssertComponentExistImpl(const ComponentTestMatcherImpl& matcher, ErrInfo& errInfo) const
97 {
98 ComponentTestComponentImpl* component = FindComponentImpl(matcher, errInfo);
99 if (component == nullptr) {
100 errInfo = QueryRetMsg(ErrCode::RET_ERR_ASSERTION_COMPONENT_EXIST);
101 return;
102 }
103 delete component;
104 }
105
ScrollUntilExistImpl(const ComponentTestMatcherImpl & matcher,ErrInfo & errInfo) const106 ComponentTestComponentImpl* ComponentTestTesterImpl::ScrollUntilExistImpl(
107 const ComponentTestMatcherImpl& matcher, ErrInfo& errInfo) const
108 {
109 errInfo = QueryRetMsg(ErrCode::RET_ERR_FAILED);
110 auto container = AceEngine::Get().GetContainer(ACE_INSTANCE_ID);
111 CHECK_NULL_RETURN(container, nullptr);
112 auto context = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
113 CHECK_NULL_RETURN(context, nullptr);
114 auto rootNode = context->GetRootElement();
115 CHECK_NULL_RETURN(rootNode, nullptr);
116
117 std::queue<RefPtr<NG::UINode>> elements;
118 RefPtr<NG::UINode> target = nullptr;
119 elements.push(rootNode);
120 auto scale = context->GetViewScale();
121 NG::RectF screenRect(0.0, 0.0, context->GetRootWidth() * scale, context->GetRootHeight() * scale);
122 while (!elements.empty()) {
123 auto current = elements.front();
124 elements.pop();
125 if (matcher.Match(current)) {
126 target = current;
127 break;
128 }
129
130 const auto& children = current->GetChildren();
131 for (const auto& child : children) {
132 elements.push(child);
133 }
134 }
135 if (target) {
136 const RefPtr<NG::FrameNode>& frameNode = AceType::DynamicCast<NG::FrameNode>(target);
137 NG::RectF rect = frameNode->GetTransformRectRelativeToWindow();
138 ScrollImpl(rect.GetX(), rect.GetY(), errInfo);
139 ComponentTestComponentImpl* componentTestComponentImpl = new ComponentTestComponentImpl();
140 componentTestComponentImpl->SetUiNode(target);
141 errInfo = QueryRetMsg(ErrCode::RET_OK);
142 return componentTestComponentImpl;
143 }
144 return nullptr;
145 }
146
TriggerKeyImpl(OHOS::MMI::KeyCode keyCode,ErrInfo & errInfo) const147 void ComponentTestTesterImpl::TriggerKeyImpl(OHOS::MMI::KeyCode keyCode, ErrInfo& errInfo) const
148 {
149 SingleKeyAction singleKeyAction(keyCode);
150 singleKeyAction.Send();
151 }
152
TriggerCombineKeysImpl(const std::vector<OHOS::MMI::KeyCode> & keyCodes,ErrInfo & errInfo) const153 void ComponentTestTesterImpl::TriggerCombineKeysImpl(
154 const std::vector<OHOS::MMI::KeyCode>& keyCodes, ErrInfo& errInfo) const
155 {
156 CombinedKeysAction combinedKeysAction(keyCodes);
157 combinedKeysAction.Send();
158 }
159
TapImpl(float x,float y,ErrInfo & errInfo) const160 void ComponentTestTesterImpl::TapImpl(float x, float y, ErrInfo& errInfo) const
161 {
162 GenericClick(x, y, TouchType::TAP);
163 }
164
DoubleTapImpl(float x,float y,ErrInfo & errInfo) const165 void ComponentTestTesterImpl::DoubleTapImpl(float x, float y, ErrInfo& errInfo) const
166 {
167 GenericClick(x, y, TouchType::DOUBLE_TAP);
168 }
169
PressImpl(float x,float y,ErrInfo & errInfo,uint32_t duration) const170 void ComponentTestTesterImpl::PressImpl(float x, float y, ErrInfo& errInfo, uint32_t duration) const
171 {
172 GenericClick(x, y, TouchType::PRESS, duration);
173 }
174
ScrollImpl(float deltaX,float deltaY,ErrInfo & errInfo) const175 void ComponentTestTesterImpl::ScrollImpl(float deltaX, float deltaY, ErrInfo& errInfo) const
176 {
177 ScrollAction scrollAction(deltaX, deltaY);
178 EventSequenceManager::GetInstance().Execute(&scrollAction);
179 }
180
DragImpl(float startX,float startY,float endX,float endY,uint32_t speed,ErrInfo & errInfo) const181 void ComponentTestTesterImpl::DragImpl(
182 float startX, float startY, float endX, float endY, uint32_t speed, ErrInfo& errInfo) const
183 {
184 NG::PointF startPonit(startX, startY);
185 NG::PointF endPonit(endX, endY);
186 MoveAction moveAction(startPonit, endPonit, TouchType::DRAG);
187 EventSequenceManager::GetInstance().Execute(&moveAction);
188 }
189
FlingImpl(const NG::PointF & from,const NG::PointF & to,uint32_t stepLen,uint32_t speed,ErrInfo & errInfo) const190 void ComponentTestTesterImpl::FlingImpl(
191 const NG::PointF& from, const NG::PointF& to, uint32_t stepLen, uint32_t speed, ErrInfo& errInfo) const
192 {
193 int32_t distanceX = to.GetX() - from.GetX();
194 int32_t distanceY = to.GetY() - from.GetY();
195 uint32_t distance = sqrt(distanceX * distanceX + distanceY * distanceY);
196 if (stepLen > 0 && stepLen <= distance) {
197 uint32_t steps = distance / stepLen;
198 if (speed < MIN_SPEED || speed > MAX_SPEED) {
199 LOGW("%{public}s", "The fling speed out of range");
200 speed = DEFAULT_SPEED;
201 }
202 MoveAction moveAction(from, to, TouchType::FLING, speed, steps);
203 EventSequenceManager::GetInstance().Execute(&moveAction);
204 errInfo = QueryRetMsg(ErrCode::RET_OK);
205 } else {
206 errInfo = QueryRetMsg(ErrCode::RET_ERROR_PARAM_INVALID);
207 }
208 }
209
FlingImpl(UiDirection direction,uint32_t speed,ErrInfo & errInfo) const210 void ComponentTestTesterImpl::FlingImpl(UiDirection direction, uint32_t speed, ErrInfo& errInfo) const
211 {
212 auto container = AceEngine::Get().GetContainer(ACE_INSTANCE_ID);
213 if (!container) {
214 errInfo = QueryRetMsg(ErrCode::RET_ERR_FAILED);
215 return;
216 }
217 auto context = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
218 if (!context) {
219 errInfo = QueryRetMsg(ErrCode::RET_ERR_FAILED);
220 return;
221 }
222 auto scale = context->GetViewScale();
223 auto rootHeight = context->GetRootHeight();
224 auto rootWidth = context->GetRootWidth();
225 NG::RectF screenRect(0.0, 0.0, rootWidth * scale, rootHeight * scale);
226 NG::PointF to;
227 NG::PointF from(screenRect.Width() * HALF, screenRect.Height() * HALF);
228 switch (direction) {
229 case UiDirection::TO_UP:
230 to.SetX(screenRect.Width() * HALF);
231 to.SetY(screenRect.Height() * HALF - screenRect.Height() * QUARTER);
232 break;
233 case UiDirection::TO_DOWN:
234 to.SetX(screenRect.Width() * HALF);
235 to.SetY(screenRect.Height() * HALF + screenRect.Width() * QUARTER);
236 break;
237 case UiDirection::TO_LEFT:
238 to.SetX(screenRect.Width() * HALF - screenRect.Width() * QUARTER);
239 to.SetY(screenRect.Height() * HALF);
240 break;
241 case UiDirection::TO_RIGHT:
242 to.SetX(screenRect.Width() * HALF + screenRect.Width() * QUARTER);
243 to.SetY(screenRect.Height() * HALF);
244 break;
245 default:
246 errInfo = QueryRetMsg(ErrCode::RET_ERROR_PARAM_INVALID);
247 return;
248 }
249 MoveAction moveAction(from, to, TouchType::FLING, speed, MIN_STEP_CONUT);
250 EventSequenceManager::GetInstance().Execute(&moveAction);
251 errInfo = QueryRetMsg(ErrCode::RET_OK);
252 }
253
GenericClick(float x,float y,const TouchType touchType,uint32_t duration) const254 void ComponentTestTesterImpl::GenericClick(float x, float y, const TouchType touchType, uint32_t duration) const
255 {
256 auto point = NG::PointF(x, y);
257 ClickAction clickAction(point, touchType, duration);
258 EventSequenceManager::GetInstance().Execute(&clickAction);
259 }
260
261 } // namespace OHOS::Ace::ComponentTest
262