• 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 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