• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "js_component_test_component.h"
17 
18 #include "component_test/core/component_test_component_impl.h"
19 #include "interfaces/napi/kits/utils/napi_utils.h"
20 
21 #include "base/log/log.h"
22 #include "base/utils/utils.h"
23 
24 namespace OHOS::Ace::Napi {
25 namespace {
26 constexpr char TAP[] = "tap";
27 constexpr char DOUBLE_TAP[] = "doubleTap";
28 constexpr char PRESS[] = "press";
29 constexpr char PINCH_OUT[] = "pinchOut";
30 constexpr char PINCH_IN[] = "pinchIn";
31 constexpr char INPUT_TEXT[] = "inputText";
32 constexpr char CLEAR_TEXT[] = "clearText";
33 constexpr char SCROLL_TO_TOP[] = "scrollToTop";
34 constexpr char SCROLL_TO_BOTTOM[] = "scrollToBottom";
35 constexpr char GET_ID[] = "getId";
36 constexpr char GET_TEXT[] = "getText";
37 constexpr char GET_TYPE[] = "getType";
38 constexpr char IS_CLICKABLE[] = "isClickable";
39 constexpr char IS_LONGPRESSABLE[] = "isLongPressable";
40 constexpr char IS_SCROLLABLE[] = "isScrollable";
41 constexpr char IS_ENABLED[] = "isEnabled";
42 constexpr char IS_FOCUSED[] = "isFocused";
43 constexpr char IS_SELECTED[] = "isSelected";
44 constexpr char IS_CHECKED[] = "isChecked";
45 constexpr char IS_CHECKABLE[] = "isCheckable";
46 constexpr char GET_INSPECTORINFO[] = "getInspectorInfo";
47 constexpr char GET_INSPECTORTREE[] = "getInspectorTree";
48 constexpr char GET_CHILDCOUNT[] = "getChildCount";
49 constexpr char GET_BOUNDS[] = "getBounds";
50 } // namespace
51 
52 thread_local napi_ref ComponentTestComponent::constructorRef_ = nullptr;
53 const napi_property_descriptor ComponentTestComponent::componentDesc_[] = {
54     DECLARE_NAPI_FUNCTION(TAP, ComponentTestComponent::JSTap),
55     DECLARE_NAPI_FUNCTION(DOUBLE_TAP, ComponentTestComponent::JSDoubleTap),
56     DECLARE_NAPI_FUNCTION(PRESS, ComponentTestComponent::JSPress),
57     DECLARE_NAPI_FUNCTION(PINCH_OUT, ComponentTestComponent::JSPinchOut),
58     DECLARE_NAPI_FUNCTION(PINCH_IN, ComponentTestComponent::JSPinchIn),
59     DECLARE_NAPI_FUNCTION(INPUT_TEXT, ComponentTestComponent::JSInputText),
60     DECLARE_NAPI_FUNCTION(CLEAR_TEXT, ComponentTestComponent::JSClearText),
61     DECLARE_NAPI_FUNCTION(SCROLL_TO_TOP, ComponentTestComponent::JSScrollToTop),
62     DECLARE_NAPI_FUNCTION(SCROLL_TO_BOTTOM, ComponentTestComponent::JSScrollToBottom),
63     DECLARE_NAPI_FUNCTION(GET_ID, ComponentTestComponent::JSGetId),
64     DECLARE_NAPI_FUNCTION(GET_TEXT, ComponentTestComponent::JSGetText),
65     DECLARE_NAPI_FUNCTION(GET_TYPE, ComponentTestComponent::JSGetType),
66     DECLARE_NAPI_FUNCTION_WITH_DATA(IS_CLICKABLE, ComponentTestComponent::GenericBoolCallback, (void*)IS_CLICKABLE),
67     DECLARE_NAPI_FUNCTION_WITH_DATA(
68         IS_LONGPRESSABLE, ComponentTestComponent::GenericBoolCallback, (void*)IS_LONGPRESSABLE),
69     DECLARE_NAPI_FUNCTION_WITH_DATA(IS_SCROLLABLE, ComponentTestComponent::GenericBoolCallback, (void*)IS_SCROLLABLE),
70     DECLARE_NAPI_FUNCTION_WITH_DATA(IS_ENABLED, ComponentTestComponent::GenericBoolCallback, (void*)IS_ENABLED),
71     DECLARE_NAPI_FUNCTION_WITH_DATA(IS_FOCUSED, ComponentTestComponent::GenericBoolCallback, (void*)IS_FOCUSED),
72     DECLARE_NAPI_FUNCTION_WITH_DATA(IS_SELECTED, ComponentTestComponent::GenericBoolCallback, (void*)IS_SELECTED),
73     DECLARE_NAPI_FUNCTION_WITH_DATA(IS_CHECKED, ComponentTestComponent::GenericBoolCallback, (void*)IS_CHECKED),
74     DECLARE_NAPI_FUNCTION_WITH_DATA(IS_CHECKABLE, ComponentTestComponent::GenericBoolCallback, (void*)IS_CHECKABLE),
75     DECLARE_NAPI_FUNCTION(GET_INSPECTORINFO, ComponentTestComponent::JSGetInspectorInfo),
76     DECLARE_NAPI_FUNCTION(GET_INSPECTORTREE, ComponentTestComponent::JSGetInspectorTree),
77     DECLARE_NAPI_FUNCTION(GET_CHILDCOUNT, ComponentTestComponent::JSGetChildCount),
78     DECLARE_NAPI_FUNCTION(GET_BOUNDS, ComponentTestComponent::JSGetBounds),
79 };
80 
DefineComponentTestComponent(napi_env env,napi_value exports)81 napi_status ComponentTestComponent::DefineComponentTestComponent(napi_env env, napi_value exports)
82 {
83     napi_value constructor = nullptr;
84     NAPI_CALL_BASE(env,
85         napi_define_class(env, COMPONENT_NAME, NAPI_AUTO_LENGTH, Constructor, nullptr,
86             sizeof(componentDesc_) / sizeof(napi_property_descriptor), componentDesc_, &constructor),
87         NAPI_ERR);
88     NAPI_CALL_BASE(env, napi_set_named_property(env, exports, COMPONENT_NAME, constructor), NAPI_ERR);
89     NAPI_CALL_BASE(env, napi_create_reference(env, constructor, 1, &constructorRef_), NAPI_ERR);
90     return napi_ok;
91 }
92 
Constructor(napi_env env,napi_callback_info info)93 napi_value ComponentTestComponent::Constructor(napi_env env, napi_callback_info info)
94 {
95     napi_value thisVar = nullptr;
96     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
97     ComponentTest::ComponentTestComponentImpl* componentImpl =
98         new (std::nothrow) ComponentTest::ComponentTestComponentImpl();
99     COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, componentImpl != nullptr, ErrCode::RET_ERR_FAILED,
100         "Failed to create componentImpl.", NapiGetUndefined(env));
101     NAPI_CALL_BASE(env, napi_wrap(env, thisVar, componentImpl, Destructor, nullptr, nullptr), thisVar);
102     return thisVar;
103 }
104 
Destructor(napi_env env,void * data,void * hint)105 void ComponentTestComponent::Destructor(napi_env env, void* data, void* hint)
106 {
107     ComponentTest::ComponentTestComponentImpl* componentImpl =
108         reinterpret_cast<ComponentTest::ComponentTestComponentImpl*>(data);
109     CHECK_NULL_VOID(componentImpl);
110     if (constructorRef_ != nullptr) {
111         napi_delete_reference(env, constructorRef_);
112     }
113     delete componentImpl;
114     componentImpl = nullptr;
115 }
116 
JSTap(napi_env env,napi_callback_info info)117 napi_value ComponentTestComponent::JSTap(napi_env env, napi_callback_info info)
118 {
119     napi_value thisVar = nullptr;
120     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
121     ComponentTestAsyncCtx* asyncContext = CreateComponentAsyncContext(env, thisVar);
122     CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
123     napi_value promise = nullptr;
124     NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
125     ComponentTest::ComponentTestManagerProxy::PostJSTask(
126         [](void* data) {
127             ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
128             CHECK_NULL_VOID(asyncContext);
129             if (!asyncContext->componentImpl) {
130                 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
131                 return;
132             }
133             asyncContext->componentImpl->TapImpl(asyncContext->ret);
134             napi_get_null(asyncContext->env, &asyncContext->asyncResult);
135         },
136         AsyncCompleteWork, (void*)asyncContext);
137     return promise;
138 }
139 
JSDoubleTap(napi_env env,napi_callback_info info)140 napi_value ComponentTestComponent::JSDoubleTap(napi_env env, napi_callback_info info)
141 {
142     napi_value thisVar = nullptr;
143     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
144     ComponentTestAsyncCtx* asyncContext = CreateComponentAsyncContext(env, thisVar);
145     CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
146     napi_value promise = nullptr;
147     NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
148     ComponentTest::ComponentTestManagerProxy::PostJSTask(
149         [](void* data) {
150             ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
151             CHECK_NULL_VOID(asyncContext);
152             if (!asyncContext->componentImpl) {
153                 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
154                 return;
155             }
156             asyncContext->componentImpl->DoubleTapImpl(asyncContext->ret);
157             napi_get_null(asyncContext->env, &asyncContext->asyncResult);
158         },
159         AsyncCompleteWork, (void*)asyncContext);
160     return promise;
161 }
162 
JSPress(napi_env env,napi_callback_info info)163 napi_value ComponentTestComponent::JSPress(napi_env env, napi_callback_info info)
164 {
165     size_t argc = ARG_COUNT_ONE;
166     napi_value argv = nullptr;
167     napi_value thisVar = nullptr;
168     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, &thisVar, nullptr));
169     uint32_t delayMs = 0;
170     COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_ZERO || argc == ARG_COUNT_ONE, ErrCode::RET_ERROR_PARAM_INVALID);
171     if (argc == ARG_COUNT_ONE) {
172         COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, GetValueType(env, argv) == napi_number, ErrCode::RET_ERROR_PARAM_INVALID,
173             "Parameter is not of type number", NapiGetUndefined(env));
174         NAPI_CALL(env, napi_get_value_uint32(env, argv, &delayMs));
175     }
176     ComponentTestAsyncCtx* asyncContext = CreateComponentAsyncContext(env, thisVar);
177     CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
178     asyncContext->delayMs = delayMs;
179 
180     napi_value promise = nullptr;
181     NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
182     ComponentTest::ComponentTestManagerProxy::PostJSTask(
183         [](void* data) {
184             ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
185             CHECK_NULL_VOID(asyncContext);
186             if (!asyncContext->componentImpl) {
187                 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
188                 return;
189             }
190             asyncContext->componentImpl->PressImpl(asyncContext->ret, asyncContext->delayMs);
191             napi_get_null(asyncContext->env, &asyncContext->asyncResult);
192         },
193         AsyncCompleteWork, (void*)asyncContext);
194     return promise;
195 }
196 
JSPinchOut(napi_env env,napi_callback_info info)197 napi_value ComponentTestComponent::JSPinchOut(napi_env env, napi_callback_info info)
198 {
199     size_t argc = ARG_COUNT_ONE;
200     napi_value argv = nullptr;
201     napi_value thisVar = nullptr;
202     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, &thisVar, nullptr));
203     COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_ONE, ErrCode::RET_ERROR_PARAM_INVALID);
204     COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, GetValueType(env, argv) == napi_number, ErrCode::RET_ERROR_PARAM_INVALID,
205         "Parameter is not of type number", NapiGetUndefined(env));
206     double scale = 0;
207     NAPI_CALL(env, napi_get_value_double(env, argv, &scale));
208     ComponentTestAsyncCtx* asyncContext = CreateComponentAsyncContext(env, thisVar);
209     CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
210     asyncContext->scale = static_cast<float>(scale);
211 
212     napi_value promise = nullptr;
213     NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
214     ComponentTest::ComponentTestManagerProxy::PostJSTask(
215         [](void* data) {
216             ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
217             CHECK_NULL_VOID(asyncContext);
218             if (!asyncContext->componentImpl) {
219                 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
220                 return;
221             }
222             asyncContext->componentImpl->PinchOutImpl(asyncContext->scale, asyncContext->ret);
223             napi_get_null(asyncContext->env, &asyncContext->asyncResult);
224         },
225         AsyncCompleteWork, (void*)asyncContext);
226     return promise;
227 }
228 
JSPinchIn(napi_env env,napi_callback_info info)229 napi_value ComponentTestComponent::JSPinchIn(napi_env env, napi_callback_info info)
230 {
231     size_t argc = ARG_COUNT_ONE;
232     napi_value argv = nullptr;
233     napi_value thisVar = nullptr;
234     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, &thisVar, nullptr));
235     COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_ONE, ErrCode::RET_ERROR_PARAM_INVALID);
236     COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, GetValueType(env, argv) == napi_number, ErrCode::RET_ERROR_PARAM_INVALID,
237         "Parameter is not of type number", NapiGetUndefined(env));
238     double scale = 0;
239     NAPI_CALL(env, napi_get_value_double(env, argv, &scale));
240     ComponentTestAsyncCtx* asyncContext = CreateComponentAsyncContext(env, thisVar);
241     CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
242     asyncContext->scale = static_cast<float>(scale);
243 
244     napi_value promise = nullptr;
245     NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
246     ComponentTest::ComponentTestManagerProxy::PostJSTask(
247         [](void* data) {
248             ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
249             CHECK_NULL_VOID(asyncContext);
250             if (!asyncContext->componentImpl) {
251                 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
252                 return;
253             }
254             asyncContext->componentImpl->PinchInImpl(asyncContext->scale, asyncContext->ret);
255             napi_get_null(asyncContext->env, &asyncContext->asyncResult);
256         },
257         AsyncCompleteWork, (void*)asyncContext);
258     return promise;
259 }
260 
JSInputText(napi_env env,napi_callback_info info)261 napi_value ComponentTestComponent::JSInputText(napi_env env, napi_callback_info info)
262 {
263     size_t argc = ARG_COUNT_ONE;
264     napi_value argv = nullptr;
265     napi_value thisVar = nullptr;
266     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, &thisVar, nullptr));
267     COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_ONE, ErrCode::RET_ERROR_PARAM_INVALID);
268     std::string text;
269     std::string errMsg;
270     COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, CheckAndParseStr(env, argv, text, errMsg), ErrCode::RET_ERROR_PARAM_INVALID,
271         errMsg, NapiGetUndefined(env));
272     ComponentTestAsyncCtx* asyncContext = CreateComponentAsyncContext(env, thisVar);
273     CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
274     asyncContext->text = text;
275 
276     napi_value promise = nullptr;
277     NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
278     ComponentTest::ComponentTestManagerProxy::PostJSTask(
279         [](void* data) {
280             ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
281             CHECK_NULL_VOID(asyncContext);
282             if (!asyncContext->componentImpl) {
283                 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
284                 return;
285             }
286             asyncContext->componentImpl->InputTextImpl(asyncContext->text, asyncContext->ret);
287             napi_get_null(asyncContext->env, &asyncContext->asyncResult);
288         },
289         AsyncCompleteWork, (void*)asyncContext);
290     return promise;
291 }
292 
JSClearText(napi_env env,napi_callback_info info)293 napi_value ComponentTestComponent::JSClearText(napi_env env, napi_callback_info info)
294 {
295     napi_value thisVar = nullptr;
296     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
297     ComponentTestAsyncCtx* asyncContext = CreateComponentAsyncContext(env, thisVar);
298     CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
299 
300     napi_value promise = nullptr;
301     NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
302     ComponentTest::ComponentTestManagerProxy::PostJSTask(
303         [](void* data) {
304             ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
305             CHECK_NULL_VOID(asyncContext);
306             if (!asyncContext->componentImpl) {
307                 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
308                 return;
309             }
310             asyncContext->componentImpl->ClearTextImpl(asyncContext->ret);
311             napi_get_null(asyncContext->env, &asyncContext->asyncResult);
312         },
313         AsyncCompleteWork, (void*)asyncContext);
314     return promise;
315 }
316 
JSScrollToTop(napi_env env,napi_callback_info info)317 napi_value ComponentTestComponent::JSScrollToTop(napi_env env, napi_callback_info info)
318 {
319     size_t argc = ARG_COUNT_ONE;
320     napi_value argv = nullptr;
321     napi_value thisVar = nullptr;
322     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, &thisVar, nullptr));
323     COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_ZERO || argc == ARG_COUNT_ONE, ErrCode::RET_ERROR_PARAM_INVALID);
324     uint32_t speed = 0;
325     if (argc == ARG_COUNT_ONE) {
326         COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, GetValueType(env, argv) == napi_number, ErrCode::RET_ERROR_PARAM_INVALID,
327             "Parameter is not of type number", NapiGetUndefined(env));
328         NAPI_CALL(env, napi_get_value_uint32(env, argv, &speed));
329     }
330     ComponentTestAsyncCtx* asyncContext = CreateComponentAsyncContext(env, thisVar);
331     CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
332     asyncContext->speed = speed;
333 
334     napi_value promise = nullptr;
335     NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
336     ComponentTest::ComponentTestManagerProxy::PostJSTask(
337         [](void* data) {
338             ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
339             CHECK_NULL_VOID(asyncContext);
340             if (!asyncContext->componentImpl) {
341                 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
342                 return;
343             }
344             napi_get_null(asyncContext->env, &asyncContext->asyncResult);
345             asyncContext->componentImpl->ScrollToTopImplAsync(asyncContext->speed, [asyncContext](ErrInfo errInfo) {
346                 asyncContext->ret = errInfo;
347                 AsyncCompleteWork(asyncContext);
348             });
349         },
350         nullptr, (void*)asyncContext);
351     return promise;
352 }
353 
JSScrollToBottom(napi_env env,napi_callback_info info)354 napi_value ComponentTestComponent::JSScrollToBottom(napi_env env, napi_callback_info info)
355 {
356     size_t argc = ARG_COUNT_ONE;
357     napi_value argv = nullptr;
358     napi_value thisVar = nullptr;
359     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, &thisVar, nullptr));
360     COMPONENT_TEST_NAPI_ASSERT(env, argc == ARG_COUNT_ZERO || argc == ARG_COUNT_ONE, ErrCode::RET_ERROR_PARAM_INVALID);
361     uint32_t speed = 0;
362     if (argc == ARG_COUNT_ONE) {
363         COMPONENT_TEST_NAPI_ASSERT_CUSTOM(env, GetValueType(env, argv) == napi_number, ErrCode::RET_ERROR_PARAM_INVALID,
364             "Parameter is not of type number", NapiGetUndefined(env));
365         NAPI_CALL(env, napi_get_value_uint32(env, argv, &speed));
366     }
367     ComponentTestAsyncCtx* asyncContext = CreateComponentAsyncContext(env, thisVar);
368     CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
369     asyncContext->speed = speed;
370 
371     napi_value promise = nullptr;
372     NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
373     ComponentTest::ComponentTestManagerProxy::PostJSTask(
374         [](void* data) {
375             ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
376             CHECK_NULL_VOID(asyncContext);
377             if (!asyncContext->componentImpl) {
378                 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
379                 return;
380             }
381             napi_get_null(asyncContext->env, &asyncContext->asyncResult);
382             asyncContext->componentImpl->ScrollToBottomImplAsync(asyncContext->speed, [asyncContext](ErrInfo errInfo) {
383                 asyncContext->ret = errInfo;
384                 AsyncCompleteWork(asyncContext);
385             });
386         },
387         nullptr, (void*)asyncContext);
388     return promise;
389 }
390 
JSGetId(napi_env env,napi_callback_info info)391 napi_value ComponentTestComponent::JSGetId(napi_env env, napi_callback_info info)
392 {
393     napi_value thisVar = nullptr;
394     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
395     ComponentTestAsyncCtx* asyncContext = CreateComponentAsyncContext(env, thisVar);
396     CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
397 
398     napi_value promise = nullptr;
399     NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
400     ComponentTest::ComponentTestManagerProxy::PostJSTask(
401         [](void* data) {
402             ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
403             CHECK_NULL_VOID(asyncContext);
404             if (!asyncContext->componentImpl) {
405                 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
406                 return;
407             }
408             napi_create_string_utf8(asyncContext->env,
409                 asyncContext->componentImpl->GetIdImpl(asyncContext->ret).c_str(), NAPI_AUTO_LENGTH,
410                 &asyncContext->asyncResult);
411         },
412         AsyncCompleteWork, (void*)asyncContext);
413     return promise;
414 }
415 
JSGetText(napi_env env,napi_callback_info info)416 napi_value ComponentTestComponent::JSGetText(napi_env env, napi_callback_info info)
417 {
418     napi_value thisVar = nullptr;
419     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
420     ComponentTestAsyncCtx* asyncContext = CreateComponentAsyncContext(env, thisVar);
421     CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
422 
423     napi_value promise = nullptr;
424     NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
425     ComponentTest::ComponentTestManagerProxy::PostJSTask(
426         [](void* data) {
427             ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
428             CHECK_NULL_VOID(asyncContext);
429             if (!asyncContext->componentImpl) {
430                 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
431                 return;
432             }
433             napi_create_string_utf8(asyncContext->env,
434                 asyncContext->componentImpl->GetTextImpl(asyncContext->ret).c_str(), NAPI_AUTO_LENGTH,
435                 &asyncContext->asyncResult);
436         },
437         AsyncCompleteWork, (void*)asyncContext);
438     return promise;
439 }
440 
JSGetType(napi_env env,napi_callback_info info)441 napi_value ComponentTestComponent::JSGetType(napi_env env, napi_callback_info info)
442 {
443     napi_value thisVar = nullptr;
444     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
445     ComponentTestAsyncCtx* asyncContext = CreateComponentAsyncContext(env, thisVar);
446     CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
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->componentImpl) {
455                 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
456                 return;
457             }
458             napi_create_string_utf8(asyncContext->env,
459                 asyncContext->componentImpl->GetTypeImpl(asyncContext->ret).c_str(), NAPI_AUTO_LENGTH,
460                 &asyncContext->asyncResult);
461         },
462         AsyncCompleteWork, (void*)asyncContext);
463     return promise;
464 }
465 
GenericBoolCallback(napi_env env,napi_callback_info info)466 napi_value ComponentTestComponent::GenericBoolCallback(napi_env env, napi_callback_info info)
467 {
468     napi_value thisVar = nullptr;
469     void* data = nullptr;
470     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data));
471     const char* functionName = static_cast<const char*>(data);
472     ComponentTestAsyncCtx* asyncContext = CreateComponentAsyncContext(env, thisVar);
473     CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
474     asyncContext->functionName = functionName;
475 
476     napi_value promise = nullptr;
477     NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
478     ComponentTest::ComponentTestManagerProxy::PostJSTask(
479         [](void* data) {
480             ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
481             CHECK_NULL_VOID(asyncContext);
482             if (!asyncContext->componentImpl || !asyncContext->functionName) {
483                 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
484                 return;
485             }
486             if (std::strcmp(asyncContext->functionName, IS_CLICKABLE) == 0) {
487                 napi_get_boolean(asyncContext->env, asyncContext->componentImpl->IsClickableImpl(asyncContext->ret),
488                     &asyncContext->asyncResult);
489             } else if (std::strcmp(asyncContext->functionName, IS_LONGPRESSABLE) == 0) {
490                 napi_get_boolean(asyncContext->env, asyncContext->componentImpl->IsLongPressableImpl(asyncContext->ret),
491                     &asyncContext->asyncResult);
492             } else if (std::strcmp(asyncContext->functionName, IS_SCROLLABLE) == 0) {
493                 napi_get_boolean(asyncContext->env, asyncContext->componentImpl->IsScrollableImpl(asyncContext->ret),
494                     &asyncContext->asyncResult);
495             } else if (std::strcmp(asyncContext->functionName, IS_ENABLED) == 0) {
496                 napi_get_boolean(asyncContext->env, asyncContext->componentImpl->IsEnabledImpl(asyncContext->ret),
497                     &asyncContext->asyncResult);
498             } else if (std::strcmp(asyncContext->functionName, IS_FOCUSED) == 0) {
499                 napi_get_boolean(asyncContext->env, asyncContext->componentImpl->IsFocusedImpl(asyncContext->ret),
500                     &asyncContext->asyncResult);
501             } else if (std::strcmp(asyncContext->functionName, IS_SELECTED) == 0) {
502                 napi_get_boolean(asyncContext->env, asyncContext->componentImpl->IsSelectedImpl(asyncContext->ret),
503                     &asyncContext->asyncResult);
504             } else if (std::strcmp(asyncContext->functionName, IS_CHECKED) == 0) {
505                 napi_get_boolean(asyncContext->env, asyncContext->componentImpl->IsCheckedImpl(asyncContext->ret),
506                     &asyncContext->asyncResult);
507             } else if (std::strcmp(asyncContext->functionName, IS_CHECKABLE) == 0) {
508                 napi_get_boolean(asyncContext->env, asyncContext->componentImpl->IsCheckableImpl(asyncContext->ret),
509                     &asyncContext->asyncResult);
510             } else {
511                 LOGW("Unknown function %{public}s", asyncContext->functionName);
512             }
513         },
514         AsyncCompleteWork, (void*)asyncContext);
515     return promise;
516 }
517 
JSGetInspectorInfo(napi_env env,napi_callback_info info)518 napi_value ComponentTestComponent::JSGetInspectorInfo(napi_env env, napi_callback_info info)
519 {
520     napi_value thisVar = nullptr;
521     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
522     ComponentTestAsyncCtx* asyncContext = CreateComponentAsyncContext(env, thisVar);
523     CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
524     napi_value promise = nullptr;
525     NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
526     ComponentTest::ComponentTestManagerProxy::PostJSTask(
527         [](void* data) {
528             ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
529             CHECK_NULL_VOID(asyncContext);
530             if (!asyncContext->componentImpl) {
531                 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
532                 return;
533             }
534             napi_create_string_utf8(asyncContext->env,
535                 asyncContext->componentImpl->GetInspectorInfoImpl(asyncContext->ret).c_str(), NAPI_AUTO_LENGTH,
536                 &asyncContext->asyncResult);
537         },
538         AsyncCompleteWork, (void*)asyncContext);
539     return promise;
540 }
541 
JSGetInspectorTree(napi_env env,napi_callback_info info)542 napi_value ComponentTestComponent::JSGetInspectorTree(napi_env env, napi_callback_info info)
543 {
544     napi_value thisVar = nullptr;
545     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
546     ComponentTestAsyncCtx* asyncContext = CreateComponentAsyncContext(env, thisVar);
547     CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
548 
549     napi_value promise = nullptr;
550     NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
551     ComponentTest::ComponentTestManagerProxy::PostJSTask(
552         [](void* data) {
553             ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
554             CHECK_NULL_VOID(asyncContext);
555             if (!asyncContext->componentImpl) {
556                 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
557                 return;
558             }
559             napi_create_string_utf8(asyncContext->env,
560                 asyncContext->componentImpl->GetInspectorTreeImpl(asyncContext->ret).c_str(), NAPI_AUTO_LENGTH,
561                 &asyncContext->asyncResult);
562         },
563         AsyncCompleteWork, (void*)asyncContext);
564     return promise;
565 }
566 
JSGetChildCount(napi_env env,napi_callback_info info)567 napi_value ComponentTestComponent::JSGetChildCount(napi_env env, napi_callback_info info)
568 {
569     napi_value thisVar = nullptr;
570     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
571     ComponentTestAsyncCtx* asyncContext = CreateComponentAsyncContext(env, thisVar);
572     CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
573 
574     napi_value promise = nullptr;
575     NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
576     ComponentTest::ComponentTestManagerProxy::PostJSTask(
577         [](void* data) {
578             ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
579             CHECK_NULL_VOID(asyncContext);
580             if (!asyncContext->componentImpl) {
581                 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
582                 return;
583             }
584             napi_create_int32(asyncContext->env, asyncContext->componentImpl->GetChildCountImpl(asyncContext->ret),
585                 &asyncContext->asyncResult);
586         },
587         AsyncCompleteWork, (void*)asyncContext);
588     return promise;
589 }
590 
JSGetBounds(napi_env env,napi_callback_info info)591 napi_value ComponentTestComponent::JSGetBounds(napi_env env, napi_callback_info info)
592 {
593     napi_value thisVar = nullptr;
594     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
595     ComponentTestAsyncCtx* asyncContext = CreateComponentAsyncContext(env, thisVar);
596     CHECK_NULL_RETURN(asyncContext, NapiGetUndefined(env));
597 
598     napi_value promise = nullptr;
599     NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &promise));
600     ComponentTest::ComponentTestManagerProxy::PostJSTask(
601         [](void* data) {
602             ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
603             CHECK_NULL_VOID(asyncContext);
604             if (!asyncContext->componentImpl) {
605                 asyncContext->ret = QueryRetMsg(ErrCode::RET_ERR_FAILED);
606                 return;
607             }
608             napi_value tmp = nullptr;
609             napi_create_object(asyncContext->env, &asyncContext->asyncResult);
610             NG::RectF bounds = asyncContext->componentImpl->GetBoundsImpl(asyncContext->ret);
611             if (asyncContext->ret.errCode != ErrCode::RET_OK) {
612                 return;
613             }
614             napi_create_int32(asyncContext->env, bounds.Left(), &tmp);
615             napi_set_named_property(asyncContext->env, asyncContext->asyncResult, "left", tmp);
616             napi_create_int32(asyncContext->env, bounds.Right(), &tmp);
617             napi_set_named_property(asyncContext->env, asyncContext->asyncResult, "right", tmp);
618             napi_create_int32(asyncContext->env, bounds.Top(), &tmp);
619             napi_set_named_property(asyncContext->env, asyncContext->asyncResult, "top", tmp);
620             napi_create_int32(asyncContext->env, bounds.Bottom(), &tmp);
621             napi_set_named_property(asyncContext->env, asyncContext->asyncResult, "bottom", tmp);
622         },
623         AsyncCompleteWork, (void*)asyncContext);
624     return promise;
625 }
626 
CreateJsComponent(napi_env env,napi_value * result,ComponentTest::ComponentTestComponentImpl * componentImpl)627 void ComponentTestComponent::CreateJsComponent(
628     napi_env env, napi_value* result, ComponentTest::ComponentTestComponentImpl* componentImpl)
629 {
630     napi_create_object(env, result);
631     napi_define_properties(env, *result, sizeof(componentDesc_) / sizeof(napi_property_descriptor), componentDesc_);
632     napi_wrap(env, *result, componentImpl, ComponentTestComponent::Destructor, nullptr, nullptr);
633 }
634 
AsyncCompleteWork(void * data)635 void ComponentTestComponent::AsyncCompleteWork(void* data)
636 {
637     ComponentTestAsyncCtx* asyncContext = reinterpret_cast<ComponentTestAsyncCtx*>(data);
638     napi_handle_scope scope = nullptr;
639     napi_open_handle_scope(asyncContext->env, &scope);
640     if (asyncContext->ret.errCode != ErrCode::RET_OK) {
641         ComponentTest::ComponentTestManagerProxy::Record(
642             std::string(asyncContext->ret.message), "napi_reject_deferred", ComponentTest::Result::ERROR);
643         napi_throw(asyncContext->env, CreateBusinessError(asyncContext->env, asyncContext->ret));
644         napi_reject_deferred(asyncContext->env, asyncContext->deferred, asyncContext->asyncResult);
645     } else {
646         napi_resolve_deferred(asyncContext->env, asyncContext->deferred, asyncContext->asyncResult);
647     }
648     napi_close_handle_scope(asyncContext->env, scope);
649     delete asyncContext;
650     asyncContext = nullptr;
651 }
652 
CreateComponentAsyncContext(napi_env env,napi_value thisVar)653 ComponentTestAsyncCtx* CreateComponentAsyncContext(napi_env env, napi_value thisVar)
654 {
655     ComponentTestAsyncCtx* asyncContext = CreateAsyncContext(env);
656     if (asyncContext == nullptr) {
657         return nullptr;
658     }
659     ComponentTest::ComponentTestComponentImpl* componentImpl = nullptr;
660     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&componentImpl));
661     if (status != napi_ok || !componentImpl) {
662         LOGE("%{public}s", "Failed to get unwrap ComponentTestTesterImpl");
663         COMPONENT_TEST_NAPI_THROW(env, ErrCode::RET_ERR_FAILED);
664         return nullptr;
665     }
666     asyncContext->componentImpl = componentImpl;
667     return asyncContext;
668 }
669 } // namespace OHOS::Ace::Napi
670