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 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 "js_component_test_tester.h"
17
18 #include <string>
19
20 #include "component_test/component_test_proxy.h"
21 #include "component_test/core/component_test_component_impl.h"
22 #include "component_test/core/component_test_matcher_impl.h"
23 #include "component_test/core/component_test_tester_impl.h"
24 #include "interfaces/napi/kits/utils/napi_utils.h"
25 #include "js_component_test_component.h"
26 #include "js_component_test_matcher.h"
27
28 #include "base/log/log.h"
29 #include "base/utils/utils.h"
30
31 namespace OHOS::Ace::Napi {
32 namespace {
33 const int8_t COMBINE_KEY_MAX_COUNT = 10;
34
CheckAndParsePoint(napi_env env,napi_value arg,NG::PointF & point,std::string & errMsg)35 bool CheckAndParsePoint(napi_env env, napi_value arg, NG::PointF& point, std::string& errMsg)
36 {
37 bool pointX = false;
38 bool ponitY = false;
39 napi_value nx = nullptr;
40 napi_value ny = nullptr;
41 int32_t x = 0;
42 int32_t y = 0;
43 if (GetValueType(env, arg) != napi_object) {
44 errMsg = "Parameter from is not of type object";
45 return false;
46 }
47 napi_has_named_property(env, arg, "x", &pointX);
48 if (!pointX) {
49 errMsg = "The input parameter does not exist at x";
50 return false;
51 }
52 napi_get_named_property(env, arg, "x", &nx);
53 if (GetValueType(env, nx) != napi_number) {
54 errMsg = "Parameter x is not of type number";
55 return false;
56 }
57 napi_get_value_int32(env, nx, &x);
58
59 napi_has_named_property(env, arg, "y", &ponitY);
60 if (!ponitY) {
61 errMsg = "The input parameter does not exist at y";
62 return false;
63 }
64 napi_get_named_property(env, arg, "y", &ny);
65 if (GetValueType(env, ny) != napi_number) {
66 errMsg = "Parameter y is not of type number";
67 return false;
68 }
69 napi_get_value_int32(env, ny, &y);
70
71 point.SetX(x);
72 point.SetY(y);
73 return true;
74 }
75 } // namespace
76
77 thread_local napi_ref ComponentTestTester::constructorRef_ = nullptr;
78
DefineComponentTestTester(napi_env env,napi_value exports)79 napi_status ComponentTestTester::DefineComponentTestTester(napi_env env, napi_value exports)
80 {
81 napi_value constructor = nullptr;
82
83 napi_property_descriptor desc[] = {
84 DECLARE_NAPI_STATIC_FUNCTION("create", JSCreate),
85 DECLARE_NAPI_FUNCTION("pump", JSPump),
86 DECLARE_NAPI_FUNCTION("findComponent", JSFindComponent),
87 DECLARE_NAPI_FUNCTION("findComponents", JSFindComponents),
88 DECLARE_NAPI_FUNCTION("assertComponentExist", JSAssertComponentExist),
89 DECLARE_NAPI_FUNCTION("scrollUntilExist", JSScrollUntilExist),
90 DECLARE_NAPI_FUNCTION("triggerkey", JSTriggerkey),
91 DECLARE_NAPI_FUNCTION("triggerCombineKeys", JSTriggerCombineKeys),
92 DECLARE_NAPI_FUNCTION("tap", JSTap),
93 DECLARE_NAPI_FUNCTION("doubleTap", JSDoubleTap),
94 DECLARE_NAPI_FUNCTION("press", JSPress),
95 DECLARE_NAPI_FUNCTION("scroll", JSScroll),
96 DECLARE_NAPI_FUNCTION("drag", JSDrag),
97 DECLARE_NAPI_FUNCTION("fling", JSFling),
98 };
99 NAPI_CALL_BASE(env,
100 napi_define_class(env, TESTER_NAME, NAPI_AUTO_LENGTH, Constructor, nullptr,
101 sizeof(desc) / sizeof(napi_property_descriptor), desc, &constructor),
102 NAPI_ERR);
103 NAPI_CALL_BASE(env, napi_set_named_property(env, exports, TESTER_NAME, constructor), NAPI_ERR);
104 NAPI_CALL_BASE(env, napi_create_reference(env, constructor, 1, &constructorRef_), NAPI_ERR);
105
106 return napi_ok;
107 }
108
Constructor(napi_env env,napi_callback_info info)109 napi_value ComponentTestTester::Constructor(napi_env env, napi_callback_info info)
110 {
111 napi_value thisVar = nullptr;
112 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
113 ComponentTest::ComponentTestTesterImpl* testerImpl = new (std::nothrow) ComponentTest::ComponentTestTesterImpl();
114 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(
115 env, testerImpl != nullptr, ErrCode::RET_ERR_FAILED, "Failed to create testerImpl.", NapiGetUndefined(env));
116 NAPI_CALL_BASE(env, napi_wrap(env, thisVar, testerImpl, Destructor, nullptr, nullptr), thisVar);
117 return thisVar;
118 }
119
Destructor(napi_env env,void * data,void * hint)120 void ComponentTestTester::Destructor(napi_env env, void* data, void* hint)
121 {
122 ComponentTest::ComponentTestTesterImpl* testerImpl =
123 reinterpret_cast<ComponentTest::ComponentTestTesterImpl*>(data);
124 CHECK_NULL_VOID(testerImpl);
125 if (constructorRef_ != nullptr) {
126 napi_delete_reference(env, constructorRef_);
127 }
128 delete testerImpl;
129 testerImpl = nullptr;
130 }
131
JSCreate(napi_env env,napi_callback_info info)132 napi_value ComponentTestTester::JSCreate(napi_env env, napi_callback_info info)
133 {
134 CHECK_COMPONENT_TEST_ENABLED();
135 napi_value constructor = nullptr;
136 napi_value thisVar = nullptr;
137 NAPI_CALL(env, napi_get_reference_value(env, constructorRef_, &constructor));
138 NAPI_CALL(env, napi_new_instance(env, constructor, 0, nullptr, &thisVar));
139 COMPONENT_TEST_NAPI_ASSERT(env, thisVar != nullptr, ErrCode::RET_ERR_FAILED);
140 return thisVar;
141 }
142
JSPump(napi_env env,napi_callback_info info)143 napi_value ComponentTestTester::JSPump(napi_env env, napi_callback_info info)
144 {
145 size_t argc = ARG_COUNT_ONE;
146 napi_value argv = nullptr;
147 napi_value thisVar = nullptr;
148 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, &thisVar, nullptr));
149 COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_ZERO || argc == ARG_COUNT_ONE, ErrCode::RET_ERROR_PARAM_INVALID);
150
151 uint32_t delayMs = 0;
152 std::string errMsg;
153 if (argc == ARG_COUNT_ONE) {
154 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseUInt32(env, argv, delayMs, errMsg),
155 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, NapiGetUndefined(env));
156 }
157 ComponentTestAsyncCtx* asyncContext = CreateTesterAsyncContext(env, thisVar);
158 CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
159
160 napi_value promise = nullptr;
161 NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
162 ComponentTest::ComponentTestManagerProxy::ClaimLongOperation();
163 AceEngine::Get()
164 .GetContainer(ACE_INSTANCE_ID)
165 ->GetTaskExecutor()
166 ->PostDelayedTask([asyncContext]() mutable {
167 ComponentTest::ComponentTestManagerProxy::LongOperationComplete();
168 napi_get_null(asyncContext->env, &asyncContext->asyncResult);
169 napi_resolve_deferred(asyncContext->env, asyncContext->deferred, asyncContext->asyncResult);
170 delete asyncContext;
171 asyncContext = nullptr;
172 },
173 TaskExecutor::TaskType::JS, delayMs, {});
174 return promise;
175 }
176
JSFindComponent(napi_env env,napi_callback_info info)177 napi_value ComponentTestTester::JSFindComponent(napi_env env, napi_callback_info info)
178 {
179 size_t argc = ARG_COUNT_ONE;
180 napi_value argv = nullptr;
181 napi_value thisVar = nullptr;
182 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, &thisVar, nullptr));
183 COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_ONE, ErrCode::RET_ERROR_PARAM_INVALID);
184 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, GetValueType(env, argv) == napi_object, ErrCode::RET_ERROR_PARAM_INVALID,
185 "Parameter is not of type object", NapiGetUndefined(env));
186 ComponentTestAsyncCtx* asyncContext = CreateTesterAsyncContext(env, thisVar);
187 CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
188 asyncContext->matcherImpl = GetMatcher(env, argv);
189 CHECK_NULL_RETURN(asyncContext->matcherImpl, NapiGetUndefined(env));
190
191 napi_value promise = nullptr;
192 NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
193 ComponentTest::ComponentTestManagerProxy::PostJSTask(
194 [](void* data) {
195 ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
196 CHECK_NULL_VOID(asyncContext);
197 if (!asyncContext->testerImpl || !asyncContext->matcherImpl) {
198 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
199 return;
200 }
201 ComponentTest::ComponentTestComponentImpl* componentImpl =
202 asyncContext->testerImpl->FindComponentImpl(*(asyncContext->matcherImpl), asyncContext->ret);
203 if (!componentImpl) {
204 LOGW("%{public}s", "Cannot find target component.");
205 napi_get_null(asyncContext->env, &asyncContext->asyncResult);
206 return;
207 }
208 ComponentTestComponent::CreateJsComponent(asyncContext->env, &asyncContext->asyncResult, componentImpl);
209 },
210 AsyncCompleteWork, (void*)asyncContext);
211 return promise;
212 }
213
JSFindComponents(napi_env env,napi_callback_info info)214 napi_value ComponentTestTester::JSFindComponents(napi_env env, napi_callback_info info)
215 {
216 size_t argc = ARG_COUNT_ONE;
217 napi_value argv = nullptr;
218 napi_value thisVar = nullptr;
219 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, &thisVar, nullptr));
220 COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_ONE, ErrCode::RET_ERROR_PARAM_INVALID);
221 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, GetValueType(env, argv) == napi_object, ErrCode::RET_ERROR_PARAM_INVALID,
222 "Parameter is not of type object", NapiGetUndefined(env));
223 ComponentTestAsyncCtx* asyncContext = CreateTesterAsyncContext(env, thisVar);
224 CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
225 asyncContext->matcherImpl = GetMatcher(env, argv);
226 CHECK_NULL_RETURN(asyncContext->matcherImpl, NapiGetUndefined(env));
227
228 napi_value promise = nullptr;
229 NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
230 ComponentTest::ComponentTestManagerProxy::PostJSTask(
231 [](void* data) {
232 ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
233 CHECK_NULL_VOID(asyncContext);
234 if (!asyncContext->matcherImpl || !asyncContext->testerImpl) {
235 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
236 return;
237 }
238 std::unique_ptr<std::vector<ComponentTest::ComponentTestComponentImpl*>> componentImpls =
239 asyncContext->testerImpl->FindComponentsImpl(*(asyncContext->matcherImpl), asyncContext->ret);
240 if (!componentImpls) {
241 LOGE("Cannot find target components.");
242 napi_get_null(asyncContext->env, &asyncContext->asyncResult);
243 return;
244 }
245 napi_create_array(asyncContext->env, &(asyncContext->asyncResult));
246 int32_t index = 0;
247 for (const auto componentImpl : *componentImpls) {
248 napi_handle_scope scope;
249 napi_open_handle_scope(asyncContext->env, &scope);
250 if (scope == nullptr) {
251 return;
252 }
253 napi_value instance = nullptr;
254 ComponentTestComponent::CreateJsComponent(asyncContext->env, &instance, componentImpl);
255 napi_set_element(asyncContext->env, asyncContext->asyncResult, index++, instance);
256 napi_close_handle_scope(asyncContext->env, scope);
257 }
258 },
259 AsyncCompleteWork, (void*)asyncContext);
260 return promise;
261 }
262
JSAssertComponentExist(napi_env env,napi_callback_info info)263 napi_value ComponentTestTester::JSAssertComponentExist(napi_env env, napi_callback_info info)
264 {
265 size_t argc = ARG_COUNT_ONE;
266 napi_value argv = nullptr;
267 napi_value thisVar = nullptr;
268 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, &thisVar, nullptr));
269 COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_ONE, ErrCode::RET_ERROR_PARAM_INVALID);
270 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, GetValueType(env, argv) == napi_object, ErrCode::RET_ERROR_PARAM_INVALID,
271 "Parameter is not of type object", NapiGetUndefined(env));
272 ComponentTestAsyncCtx* asyncContext = CreateTesterAsyncContext(env, thisVar);
273 CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
274 asyncContext->matcherImpl = GetMatcher(env, argv);
275 CHECK_NULL_RETURN(asyncContext->matcherImpl, NapiGetUndefined(env));
276
277 napi_value promise = nullptr;
278 NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
279 ComponentTest::ComponentTestManagerProxy::PostJSTask(
280 [](void* data) {
281 ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
282 CHECK_NULL_VOID(asyncContext);
283 if (!asyncContext->testerImpl || !asyncContext->matcherImpl) {
284 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
285 return;
286 }
287 asyncContext->testerImpl->AssertComponentExistImpl(*(asyncContext->matcherImpl), asyncContext->ret);
288 napi_get_null(asyncContext->env, &asyncContext->asyncResult);
289 },
290 [](void* data) {
291 ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
292 napi_handle_scope scope = nullptr;
293 napi_open_handle_scope(asyncContext->env, &scope);
294 if (asyncContext->ret.errCode != ErrCode::RET_OK) {
295 napi_value err = CreateBusinessError(asyncContext->env, asyncContext->ret);
296 ComponentTest::ComponentTestManagerProxy::Record(
297 "assert component exist FAIL", "js_assert", ComponentTest::Result::FAIL);
298 napi_throw(asyncContext->env, err);
299 } else {
300 ComponentTest::ComponentTestManagerProxy::Record(
301 "assert component exist PASS", "js_assert", ComponentTest::Result::PASS);
302 napi_resolve_deferred(asyncContext->env, asyncContext->deferred, asyncContext->asyncResult);
303 }
304 napi_close_handle_scope(asyncContext->env, scope);
305 delete asyncContext;
306 asyncContext = nullptr;
307 },
308 (void*)asyncContext);
309 return promise;
310 }
311
PostScrollUntilExist(ComponentTestAsyncCtx * asyncContext)312 void PostScrollUntilExist(ComponentTestAsyncCtx* asyncContext)
313 {
314 ComponentTest::ComponentTestManagerProxy::PostJSTask(
315 [](void* data) {
316 ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
317 CHECK_NULL_VOID(asyncContext);
318 if (!asyncContext->matcherImpl || !asyncContext->testerImpl) {
319 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
320 return;
321 }
322 ComponentTest::ComponentTestComponentImpl* componentImpl =
323 asyncContext->testerImpl->ScrollUntilExistImpl(*(asyncContext->matcherImpl), asyncContext->ret);
324
325 if (!componentImpl) {
326 LOGE("%{public}s", "Cannot find target component.");
327 return;
328 }
329 asyncContext->componentImpl = componentImpl;
330 },
331 [](void* data) {
332 ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
333 CHECK_NULL_VOID(asyncContext);
334 if (!asyncContext->componentImpl) {
335 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
336 return;
337 }
338 asyncContext->componentImpl->SetEffective();
339 ComponentTestComponent::CreateJsComponent(
340 asyncContext->env, &asyncContext->asyncResult, asyncContext->componentImpl);
341 napi_handle_scope scope = nullptr;
342 napi_open_handle_scope(asyncContext->env, &scope);
343
344 if (asyncContext->ret.errCode != ErrCode::RET_OK) {
345 ComponentTest::ComponentTestManagerProxy::Record(
346 std::string(asyncContext->ret.message), "napi_reject_deferred", ComponentTest::Result::ERROR);
347 napi_reject_deferred(asyncContext->env, asyncContext->deferred,
348 CreateBusinessError(asyncContext->env, asyncContext->ret));
349 } else {
350 napi_resolve_deferred(asyncContext->env, asyncContext->deferred, asyncContext->asyncResult);
351 }
352 napi_close_handle_scope(asyncContext->env, scope);
353 delete asyncContext;
354 asyncContext = nullptr;
355 },
356 (void*)asyncContext);
357 }
358
JSScrollUntilExist(napi_env env,napi_callback_info info)359 napi_value ComponentTestTester::JSScrollUntilExist(napi_env env, napi_callback_info info)
360 {
361 size_t argc = ARG_COUNT_ONE;
362 napi_value argv = nullptr;
363 napi_value thisVar = nullptr;
364 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, &thisVar, nullptr));
365 COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_ONE, ErrCode::RET_ERROR_PARAM_INVALID);
366 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, GetValueType(env, argv) == napi_object, ErrCode::RET_ERROR_PARAM_INVALID,
367 "Parameter is not of type object", NapiGetUndefined(env));
368 ComponentTestAsyncCtx* asyncContext = CreateTesterAsyncContext(env, thisVar);
369 CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
370 asyncContext->matcherImpl = GetMatcher(env, argv);
371 CHECK_NULL_RETURN(asyncContext->matcherImpl, NapiGetUndefined(env));
372
373 napi_value promise = nullptr;
374 NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
375 PostScrollUntilExist(asyncContext);
376 return promise;
377 }
378
JSTriggerkey(napi_env env,napi_callback_info info)379 napi_value ComponentTestTester::JSTriggerkey(napi_env env, napi_callback_info info)
380 {
381 size_t argc = ARG_COUNT_ONE;
382 napi_value argv = nullptr;
383 napi_value thisVar = nullptr;
384 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, &thisVar, nullptr));
385 COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_ONE, ErrCode::RET_ERROR_PARAM_INVALID);
386
387 uint32_t keycode = 0;
388 std::string errMsg;
389 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseUInt32(env, argv, keycode, errMsg),
390 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, NapiGetUndefined(env));
391 ComponentTestAsyncCtx* asyncContext = CreateTesterAsyncContext(env, thisVar);
392 CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
393 asyncContext->keyCode = static_cast<OHOS::MMI::KeyCode>(keycode);
394
395 napi_value promise = nullptr;
396 NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
397 ComponentTest::ComponentTestManagerProxy::PostJSTask(
398 [](void* data) {
399 ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
400 CHECK_NULL_VOID(asyncContext);
401 if (!asyncContext->testerImpl) {
402 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
403 return;
404 }
405 asyncContext->testerImpl->TriggerKeyImpl(asyncContext->keyCode, asyncContext->ret);
406 napi_get_null(asyncContext->env, &asyncContext->asyncResult);
407 },
408 AsyncCompleteWork, (void*)asyncContext);
409 return promise;
410 }
411
JSTriggerCombineKeys(napi_env env,napi_callback_info info)412 napi_value ComponentTestTester::JSTriggerCombineKeys(napi_env env, napi_callback_info info)
413 {
414 size_t argc = ARG_COUNT_ONE;
415 napi_value argv = nullptr;
416 napi_value thisVar = nullptr;
417 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, &thisVar, nullptr));
418 COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_ONE, ErrCode::RET_ERROR_PARAM_INVALID);
419 bool result = false;
420 NAPI_CALL(env, napi_is_array(env, argv, &result));
421 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(
422 env, result, ErrCode::RET_ERROR_PARAM_INVALID, "The type of argv is not array!", NapiGetUndefined(env));
423 uint32_t length = 0;
424 uint32_t keyCode = 0;
425 std::vector<OHOS::MMI::KeyCode> keyCodes;
426 NAPI_CALL(env, napi_get_array_length(env, argv, &length));
427 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, length > 0 && length <= COMBINE_KEY_MAX_COUNT,
428 ErrCode::RET_ERROR_PARAM_INVALID, "The number of combination keys cannot exceed 10.", NapiGetUndefined(env));
429 std::string errMsg;
430 for (uint32_t i = 0; i < length; ++i) {
431 napi_handle_scope scope;
432 napi_open_handle_scope(env, &scope);
433 if (scope == nullptr) {
434 return NapiGetUndefined(env);
435 }
436 napi_value element;
437 napi_get_element(env, argv, i, &element);
438
439 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseUInt32(env, element, keyCode, errMsg),
440 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, NapiGetUndefined(env));
441 keyCodes.emplace_back(static_cast<OHOS::MMI::KeyCode>(keyCode));
442 napi_close_handle_scope(env, scope);
443 }
444 ComponentTestAsyncCtx* asyncContext = CreateTesterAsyncContext(env, thisVar);
445 CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
446 asyncContext->keyCodes = std::move(keyCodes);
447
448 napi_value promise = nullptr;
449 NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
450 ComponentTest::ComponentTestManagerProxy::PostJSTask(
451 [](void* data) {
452 ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
453 CHECK_NULL_VOID(asyncContext);
454 if (!asyncContext->testerImpl) {
455 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
456 return;
457 }
458 asyncContext->testerImpl->TriggerCombineKeysImpl(asyncContext->keyCodes, asyncContext->ret);
459 napi_get_null(asyncContext->env, &asyncContext->asyncResult);
460 },
461 AsyncCompleteWork, (void*)asyncContext);
462 return promise;
463 }
464
JSTap(napi_env env,napi_callback_info info)465 napi_value ComponentTestTester::JSTap(napi_env env, napi_callback_info info)
466 {
467 size_t argc = ARG_COUNT_TWO;
468 napi_value argv[ARG_COUNT_TWO] = { nullptr };
469 napi_value thisVar = nullptr;
470 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
471 COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_TWO, ErrCode::RET_ERROR_PARAM_INVALID);
472
473 uint32_t x = 0;
474 uint32_t y = 0;
475 std::string errMsg;
476 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseUInt32(env, argv[ARG_COUNT_ZERO], x, errMsg),
477 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, NapiGetUndefined(env));
478 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseUInt32(env, argv[ARG_COUNT_ONE], y, errMsg),
479 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, NapiGetUndefined(env));
480 ComponentTestAsyncCtx* asyncContext = CreateTesterAsyncContext(env, thisVar);
481 CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
482 asyncContext->x = x;
483 asyncContext->y = y;
484
485 napi_value promise = nullptr;
486 NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
487 ComponentTest::ComponentTestManagerProxy::PostJSTask(
488 [](void* data) {
489 ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
490 CHECK_NULL_VOID(asyncContext);
491 if (!asyncContext->testerImpl) {
492 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
493 return;
494 }
495 asyncContext->testerImpl->TapImpl(asyncContext->x, asyncContext->y, asyncContext->ret);
496 napi_get_null(asyncContext->env, &asyncContext->asyncResult);
497 },
498 AsyncCompleteWork, (void*)asyncContext);
499 return promise;
500 }
501
JSDoubleTap(napi_env env,napi_callback_info info)502 napi_value ComponentTestTester::JSDoubleTap(napi_env env, napi_callback_info info)
503 {
504 size_t argc = ARG_COUNT_TWO;
505 napi_value argv[ARG_COUNT_TWO] = { nullptr };
506 napi_value thisVar = nullptr;
507 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
508 COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_TWO, ErrCode::RET_ERROR_PARAM_INVALID);
509
510 uint32_t x = 0;
511 uint32_t y = 0;
512 std::string errMsg = "";
513 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseUInt32(env, argv[ARG_COUNT_ZERO], x, errMsg),
514 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, NapiGetUndefined(env));
515 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseUInt32(env, argv[ARG_COUNT_ONE], y, errMsg),
516 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, NapiGetUndefined(env));
517 ComponentTestAsyncCtx* asyncContext = CreateTesterAsyncContext(env, thisVar);
518 CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
519 asyncContext->x = x;
520 asyncContext->y = y;
521
522 napi_value promise = nullptr;
523 NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
524 ComponentTest::ComponentTestManagerProxy::PostJSTask(
525 [](void* data) {
526 ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
527 CHECK_NULL_VOID(asyncContext);
528 if (!asyncContext->testerImpl) {
529 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
530 return;
531 }
532 asyncContext->testerImpl->DoubleTapImpl(asyncContext->x, asyncContext->y, asyncContext->ret);
533 napi_get_null(asyncContext->env, &asyncContext->asyncResult);
534 },
535 AsyncCompleteWork, (void*)asyncContext);
536 return promise;
537 }
538
JSPress(napi_env env,napi_callback_info info)539 napi_value ComponentTestTester::JSPress(napi_env env, napi_callback_info info)
540 {
541 size_t argc = ARG_COUNT_THREE;
542 napi_value argv[ARG_COUNT_THREE] = { nullptr };
543 napi_value thisVar = nullptr;
544 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
545 COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_TWO || argc == ARG_COUNT_THREE, ErrCode::RET_ERROR_PARAM_INVALID);
546
547 uint32_t x = 0;
548 uint32_t y = 0;
549 std::string errMsg;
550 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseUInt32(env, argv[ARG_COUNT_ZERO], x, errMsg),
551 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, NapiGetUndefined(env));
552 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseUInt32(env, argv[ARG_COUNT_ONE], y, errMsg),
553 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, NapiGetUndefined(env));
554 uint32_t duration = 0;
555 if (argc == ARG_COUNT_THREE) {
556 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseUInt32(env, argv[ARG_COUNT_TWO], duration, errMsg),
557 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, NapiGetUndefined(env));
558 }
559 ComponentTestAsyncCtx* asyncContext = CreateTesterAsyncContext(env, thisVar);
560 CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
561 asyncContext->x = x;
562 asyncContext->y = y;
563 asyncContext->duration = duration;
564
565 napi_value promise = nullptr;
566 NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
567 ComponentTest::ComponentTestManagerProxy::PostJSTask(
568 [](void* data) {
569 ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
570 CHECK_NULL_VOID(asyncContext);
571 if (!asyncContext->testerImpl) {
572 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
573 return;
574 }
575 asyncContext->testerImpl->PressImpl(
576 asyncContext->x, asyncContext->y, asyncContext->ret, asyncContext->duration);
577 napi_get_null(asyncContext->env, &asyncContext->asyncResult);
578 },
579 AsyncCompleteWork, (void*)asyncContext);
580 return promise;
581 }
582
JSScroll(napi_env env,napi_callback_info info)583 napi_value ComponentTestTester::JSScroll(napi_env env, napi_callback_info info)
584 {
585 size_t argc = ARG_COUNT_TWO;
586 napi_value argv[ARG_COUNT_TWO] = { nullptr };
587 napi_value thisVar = nullptr;
588 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
589 COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_TWO, ErrCode::RET_ERROR_PARAM_INVALID);
590
591 int32_t deltaX = 0;
592 int32_t deltaY = 0;
593 std::string errMsg;
594 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseInt32(env, argv[ARG_COUNT_ZERO], deltaX, errMsg),
595 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, NapiGetUndefined(env));
596 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseInt32(env, argv[ARG_COUNT_ONE], deltaY, errMsg),
597 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, NapiGetUndefined(env));
598 ComponentTestAsyncCtx* asyncContext = CreateTesterAsyncContext(env, thisVar);
599 CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
600 asyncContext->deltaX = deltaX;
601 asyncContext->deltaY = deltaY;
602
603 napi_value promise = nullptr;
604 NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
605 ComponentTest::ComponentTestManagerProxy::PostJSTask(
606 [](void* data) {
607 ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
608 CHECK_NULL_VOID(asyncContext);
609 if (!asyncContext->testerImpl) {
610 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
611 return;
612 }
613 asyncContext->testerImpl->ScrollImpl(asyncContext->deltaX, asyncContext->deltaY, asyncContext->ret);
614 napi_get_null(asyncContext->env, &asyncContext->asyncResult);
615 },
616 AsyncCompleteWork, (void*)asyncContext);
617 return promise;
618 }
619
JSDrag(napi_env env,napi_callback_info info)620 napi_value ComponentTestTester::JSDrag(napi_env env, napi_callback_info info)
621 {
622 size_t argc = ARG_COUNT_FIVE;
623 napi_value argv[ARG_COUNT_FIVE] = { nullptr };
624 napi_value thisVar = nullptr;
625 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
626 COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_FOUR || argc == ARG_COUNT_FIVE, ErrCode::RET_ERROR_PARAM_INVALID);
627 ComponentTestAsyncCtx* asyncContext = CreateTesterAsyncContext(env, thisVar);
628 CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
629 std::string errMsg;
630 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseUInt32(env, argv[ARG_COUNT_ZERO], asyncContext->x, errMsg),
631 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, NapiGetUndefined(env));
632 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseUInt32(env, argv[ARG_COUNT_ONE], asyncContext->y, errMsg),
633 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, NapiGetUndefined(env));
634 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseUInt32(env, argv[ARG_COUNT_TWO], asyncContext->endx, errMsg),
635 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, NapiGetUndefined(env));
636 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseUInt32(env, argv[ARG_COUNT_THREE], asyncContext->endy, errMsg),
637 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, NapiGetUndefined(env));
638 if (argc == ARG_COUNT_FIVE) {
639 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env,
640 CheckAndParseUInt32(env, argv[ARG_COUNT_THREE], asyncContext->speed, errMsg),
641 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, NapiGetUndefined(env));
642 }
643
644 napi_value promise = nullptr;
645 NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
646 ComponentTest::ComponentTestManagerProxy::PostJSTask(
647 [](void* data) {
648 ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
649 CHECK_NULL_VOID(asyncContext);
650 if (!asyncContext->testerImpl) {
651 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
652 return;
653 }
654 asyncContext->testerImpl->DragImpl(asyncContext->x, asyncContext->y, asyncContext->endx, asyncContext->endy,
655 asyncContext->speed, asyncContext->ret);
656 napi_get_null(asyncContext->env, &asyncContext->asyncResult);
657 },
658 AsyncCompleteWork, (void*)asyncContext);
659 return promise;
660 }
661
FlingPoint(napi_env env,napi_value argv[],ComponentTestAsyncCtx * asyncContext)662 bool FlingPoint(napi_env env, napi_value argv[], ComponentTestAsyncCtx* asyncContext)
663 {
664 NG::PointF from;
665 NG::PointF to;
666 uint32_t speed = 0;
667 uint32_t stepLen = 0;
668 std::string errMsg;
669 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParsePoint(env, argv[ARG_COUNT_ZERO], from, errMsg),
670 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, false);
671 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(
672 env, CheckAndParsePoint(env, argv[ARG_COUNT_ONE], to, errMsg), ErrCode::RET_ERROR_PARAM_INVALID, errMsg, false);
673 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseUInt32(env, argv[ARG_COUNT_TWO], stepLen, errMsg),
674 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, false);
675 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseUInt32(env, argv[ARG_COUNT_THREE], speed, errMsg),
676 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, false);
677 const int32_t distanceX = to.GetX() - from.GetX();
678 const int32_t distanceY = to.GetY() - from.GetY();
679 const uint32_t distance = sqrt(distanceX * distanceX + distanceY * distanceY);
680 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, stepLen > 0 && stepLen <= distance, ErrCode::RET_ERROR_PARAM_INVALID,
681 "The stepLen is out of range", false);
682 asyncContext->flingP = true;
683 asyncContext->speed = speed;
684 asyncContext->from = from;
685 asyncContext->to = to;
686 asyncContext->stepLen = stepLen;
687 return true;
688 }
689
FlingDirection(napi_env env,napi_value argv[],ComponentTestAsyncCtx * asyncContext)690 bool FlingDirection(napi_env env, napi_value argv[], ComponentTestAsyncCtx* asyncContext)
691 {
692 uint32_t direction = 0;
693 uint32_t speed = 0;
694 std::string errMsg;
695 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseUInt32(env, argv[ARG_COUNT_ZERO], direction, errMsg),
696 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, false);
697 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseUInt32(env, argv[ARG_COUNT_ONE], speed, errMsg),
698 ErrCode::RET_ERROR_PARAM_INVALID, errMsg, false);
699 COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env,
700 direction >= ComponentTest::UiDirection::TO_LEFT && direction <= ComponentTest::UiDirection::TO_DOWN,
701 ErrCode::RET_ERROR_PARAM_INVALID, "Direction can choose from 0,1,2,3 (left, right, up, down)", false);
702 asyncContext->flingP = false;
703 asyncContext->speed = speed;
704 asyncContext->direction = static_cast<ComponentTest::UiDirection>(direction);
705 return true;
706 }
707
JSFling(napi_env env,napi_callback_info info)708 napi_value ComponentTestTester::JSFling(napi_env env, napi_callback_info info)
709 {
710 size_t argc = ARG_COUNT_FOUR;
711 napi_value argv[ARG_COUNT_FOUR] = { nullptr };
712 napi_value thisVar = nullptr;
713 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
714 COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_TWO || argc == ARG_COUNT_FOUR, ErrCode::RET_ERROR_PARAM_INVALID);
715 ComponentTestAsyncCtx* asyncContext = CreateTesterAsyncContext(env, thisVar);
716 CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
717 if (argc == ARG_COUNT_TWO) {
718 CHECK_EQUAL_RETURN(FlingDirection(env, argv, asyncContext), false, NapiGetUndefined(env));
719 }
720 if (argc == ARG_COUNT_FOUR) {
721 CHECK_EQUAL_RETURN(FlingPoint(env, argv, asyncContext), false, NapiGetUndefined(env));
722 }
723 napi_value promise = nullptr;
724 NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
725 ComponentTest::ComponentTestManagerProxy::PostJSTask(
726 [](void* data) {
727 ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
728 CHECK_NULL_VOID(asyncContext);
729 if (!asyncContext->testerImpl) {
730 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
731 return;
732 }
733 if (asyncContext->flingP) {
734 asyncContext->testerImpl->FlingImpl(asyncContext->from, asyncContext->to, asyncContext->stepLen,
735 asyncContext->speed, asyncContext->ret);
736 } else {
737 asyncContext->testerImpl->FlingImpl(asyncContext->direction, asyncContext->speed, asyncContext->ret);
738 }
739 napi_get_null(asyncContext->env, &asyncContext->asyncResult);
740 },
741 AsyncCompleteWork, (void*)asyncContext);
742 return promise;
743 }
744
AsyncCompleteWork(void * data)745 void ComponentTestTester::AsyncCompleteWork(void* data)
746 {
747 ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
748 napi_handle_scope scope = nullptr;
749 napi_open_handle_scope(asyncContext->env, &scope);
750
751 if (asyncContext->ret.errCode != ErrCode::RET_OK) {
752 ComponentTest::ComponentTestManagerProxy::Record(
753 "assert component exist FAIL", "js_assert", ComponentTest::Result::FAIL);
754 napi_reject_deferred(
755 asyncContext->env, asyncContext->deferred, CreateBusinessError(asyncContext->env, asyncContext->ret));
756 } else {
757 napi_resolve_deferred(asyncContext->env, asyncContext->deferred, asyncContext->asyncResult);
758 }
759 napi_close_handle_scope(asyncContext->env, scope);
760 delete asyncContext;
761 asyncContext = nullptr;
762 }
763
CreateTesterAsyncContext(napi_env env,napi_value thisVar)764 ComponentTestAsyncCtx* CreateTesterAsyncContext(napi_env env, napi_value thisVar)
765 {
766 ComponentTestAsyncCtx* asyncContext = CreateAsyncContext(env);
767 if (asyncContext == nullptr) {
768 return nullptr;
769 }
770 ComponentTest::ComponentTestTesterImpl* testerImpl = nullptr;
771 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&testerImpl));
772 if (status != napi_ok || !testerImpl) {
773 LOGE("%{public}s", "Failed to get unwrap ComponentTestTesterImpl");
774 COMPONENT_TEST_NAPI_THROW(env, ErrCode::RET_ERR_FAILED);
775 return nullptr;
776 }
777 asyncContext->testerImpl = testerImpl;
778 return asyncContext;
779 }
780 } // namespace OHOS::Ace::Napi
781