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