1 /*
2 * Copyright (c) 2021 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 "percent_tdd_test.h"
17
18 #include "ace_log.h"
19 #include "component.h"
20 #include "component_utils.h"
21 #include "js_app_context.h"
22 #include "js_app_environment.h"
23 #include "js_fwk_common.h"
24 #include "number_parser.h"
25
26 namespace OHOS {
27 namespace ACELite {
28 const char * const PercentTddTest::ATTR_STATIC_STYLE_NAME = "staticStyle";
29 const char * const PercentTddTest::STYLE_WIDTH_NAME = "width";
30 const char * const PercentTddTest::STYLE_HEIGHT_NAME = "height";
31 const char * const PercentTddTest::STYLE_TOP_NAME = "top";
32 const char * const PercentTddTest::STYLE_LEFT_NAME = "left";
33 const char * const PercentTddTest::STYLE_MARGINTOP_NAME = "marginTop";
34 const char * const PercentTddTest::STYLE_MARGINLEFT_NAME = "marginLeft";
35 const char * const PercentTddTest::STYLE_MARGINRIGHT_NAME = "marginRight";
36 const char * const PercentTddTest::STYLE_MARGINBOTTOM_NAME = "marginBottom";
37 const char * const PercentTddTest::FUNC_CREATE_ELEMENT = "_c";
SetUp()38 void PercentTddTest::SetUp()
39 {
40 JsAppEnvironment *env = JsAppEnvironment::GetInstance();
41 if (env == nullptr) {
42 // should never happen
43 return;
44 }
45 env->InitJsFramework();
46 }
47
TearDown()48 void PercentTddTest::TearDown()
49 {
50 JsAppEnvironment *env = JsAppEnvironment::GetInstance();
51 JsAppContext *context = JsAppContext::GetInstance();
52 if (env == nullptr || context == nullptr) {
53 // should never happen
54 return;
55 }
56 context->ReleaseStyles();
57 env->Cleanup();
58 }
59
PrepareOptions(JSValue & options,JSValue & staticStyle) const60 void PercentTddTest::PrepareOptions(JSValue &options, JSValue &staticStyle) const
61 {
62 // prepare component options
63 options = JSObject::Create();
64 staticStyle = JSObject::Create();
65 JSObject::Set(options, ATTR_STATIC_STYLE_NAME, staticStyle);
66 }
67
SetStyleWithValue(JSValue target,const char * key,const char * value) const68 void PercentTddTest::SetStyleWithValue(JSValue target, const char *key, const char *value) const
69 {
70 if ((JSUndefined::Is(target)) || (key == nullptr) || (value == nullptr)) {
71 return;
72 }
73 JSValue propValue = JSString::Create(value);
74 JSObject::Set(target, key, propValue);
75 ReleaseJerryValue(propValue, VA_ARG_END_FLAG);
76 }
77
ConfigStylesWithRect(JSValue staticStyle,const char * widthValue,const char * heightValue) const78 void PercentTddTest::ConfigStylesWithRect(JSValue staticStyle, const char *widthValue, const char *heightValue) const
79 {
80 SetStyleWithValue(staticStyle, STYLE_WIDTH_NAME, widthValue);
81 SetStyleWithValue(staticStyle, STYLE_HEIGHT_NAME, heightValue);
82 }
83
ConfigStylesWithPosition(JSValue staticStyle,const char * topValue,const char * leftValue) const84 void PercentTddTest::ConfigStylesWithPosition(JSValue staticStyle, const char *topValue, const char *leftValue) const
85 {
86 SetStyleWithValue(staticStyle, STYLE_TOP_NAME, topValue);
87 SetStyleWithValue(staticStyle, STYLE_LEFT_NAME, leftValue);
88 }
89
ConfigStylesWithMargin(JSValue staticStyle,const char * marginValue) const90 void PercentTddTest::ConfigStylesWithMargin(JSValue staticStyle, const char *marginValue) const
91 {
92 ConfigStylesWithMargins(staticStyle, marginValue, marginValue, marginValue, marginValue);
93 }
94
ConfigStylesWithMargins(JSValue staticStyle,const char * marginTopValue,const char * marginLeftValue,const char * marginRightValue,const char * marginBottomValue) const95 void PercentTddTest::ConfigStylesWithMargins(JSValue staticStyle,
96 const char *marginTopValue,
97 const char *marginLeftValue,
98 const char *marginRightValue,
99 const char *marginBottomValue) const
100 {
101 SetStyleWithValue(staticStyle, STYLE_MARGINTOP_NAME, marginTopValue);
102 SetStyleWithValue(staticStyle, STYLE_MARGINLEFT_NAME, marginLeftValue);
103 SetStyleWithValue(staticStyle, STYLE_MARGINRIGHT_NAME, marginRightValue);
104 SetStyleWithValue(staticStyle, STYLE_MARGINBOTTOM_NAME, marginBottomValue);
105 }
106
DumpJSObjectJson(JSValue value) const107 void PercentTddTest::DumpJSObjectJson(JSValue value) const
108 {
109 if (JSUndefined::Is(value)) {
110 return;
111 }
112 char *jsonStr = MallocStringOf(jerry_json_stringify(value));
113 HILOG_DEBUG(HILOG_MODULE_ACE, "JSObject: %{public}s", jsonStr);
114 ACE_FREE(jsonStr);
115 }
116
BuildViewTree(JSValue element,int16_t parentWidth,int16_t parentHeight) const117 Component *PercentTddTest::BuildViewTree(JSValue element, int16_t parentWidth, int16_t parentHeight) const
118 {
119 if (JSUndefined::Is(element)) {
120 return nullptr;
121 }
122
123 Component *component = ComponentUtils::GetComponentFromBindingObject(element);
124 if (component != nullptr) {
125 ConstrainedParameter parentParameter = {parentWidth, parentHeight};
126 Component::BuildViewTree(component, nullptr, parentParameter);
127 }
128 return component;
129 }
130
VerifyDimension(JSValue element,uint16_t keyID,int16_t targetPX) const131 void PercentTddTest::VerifyDimension(JSValue element, uint16_t keyID, int16_t targetPX) const
132 {
133 EXPECT_FALSE(JSUndefined::Is(element));
134 Component *component = ComponentUtils::GetComponentFromBindingObject(element);
135 EXPECT_FALSE(component == nullptr);
136 if (component == nullptr) {
137 HILOG_ERROR(HILOG_MODULE_ACE, "can not fetch component from element");
138 return;
139 }
140 Dimension dimension = component->GetDimension(keyID);
141 EXPECT_EQ(dimension.type, DimensionType::TYPE_PIXEL);
142 EXPECT_EQ(dimension.value.pixel, targetPX);
143 }
144
145 /**
146 * @tc.name: AceliteFrameworkPercentParse001
147 * @tc.desc: Verify the percent converting process
148 */
149 HWTEST_F(PercentTddTest, PercentParse001, TestSize.Level1)
150 {
151 uint16_t strLength = 5;
152 float percentValue = 0;
153 /**
154 * @tc.steps: step1. pass nullptr for parsing
155 */
156 bool result = NumberParser::ParsePercentValue(nullptr, strLength, percentValue);
157 /**
158 * @tc.steps: step2. check if parse failed
159 */
160 EXPECT_FALSE(result);
161 }
162
163 /**
164 * @tc.name: AceliteFrameworkPercentParse002
165 * @tc.desc: Verify the percent converting process
166 */
167 HWTEST_F(PercentTddTest, PercentParse002, TestSize.Level1)
168 {
169 uint16_t strLength = 1;
170 const char *strBuffer = "100%";
171 float percentValue = 0;
172 /**
173 * @tc.steps: step1. give the length small than the min length
174 */
175 bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
176 /**
177 * @tc.steps: step2. check if parse failed
178 */
179 EXPECT_FALSE(result);
180 }
181
182 /**
183 * @tc.name: AceliteFrameworkPercentParse003
184 * @tc.desc: Verify the percent converting process
185 */
186 HWTEST_F(PercentTddTest, PercentParse003, TestSize.Level1)
187 {
188 uint16_t strLength = 4;
189 const char *strBuffer = "100%";
190 float percentValue = 0;
191 /**
192 * @tc.steps: step1. give the corrent string and length
193 */
194 bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
195 EXPECT_TRUE(result);
196 float correctValue = 100;
197 /**
198 * @tc.steps: step2. check if parse successfully
199 */
200 EXPECT_EQ(percentValue, correctValue);
201 }
202
203 /**
204 * @tc.name: AceliteFrameworkPercentParse004
205 * @tc.desc: Verify the percent converting process
206 */
207 HWTEST_F(PercentTddTest, PercentParse004, TestSize.Level1)
208 {
209 uint16_t strLength = 7;
210 /**
211 * @tc.steps: step1. give one string not in digit format
212 */
213 const char *strBuffer = "abcdef%";
214 float percentValue = 0;
215 bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
216 /**
217 * @tc.steps: step2. check if parse failed
218 */
219 EXPECT_FALSE(result);
220 }
221
222 /**
223 * @tc.name: AceliteFrameworkPercentParse005
224 * @tc.desc: Verify the percent converting process
225 */
226 HWTEST_F(PercentTddTest, PercentParse005, TestSize.Level1)
227 {
228 uint16_t strLength = 20;
229 /**
230 * @tc.steps: step1. give one string which is too long
231 */
232 const char *strBuffer = "1567890123343433434%";
233 float percentValue = 0;
234 bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
235 /**
236 * @tc.steps: step2. check if parse failed
237 */
238 EXPECT_FALSE(result);
239 }
240
241 /**
242 * @tc.name: AceliteFrameworkPercentParse006
243 * @tc.desc: Verify the percent converting process
244 */
245 HWTEST_F(PercentTddTest, PercentParse006, TestSize.Level1)
246 {
247 uint16_t strLength = 4;
248 /**
249 * @tc.steps: step1. give one string which includes no-digit charater
250 */
251 const char *strBuffer = "50a%";
252 float percentValue = 0;
253 bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
254 /**
255 * @tc.steps: step2. check if parse failed
256 */
257 EXPECT_FALSE(result);
258 }
259
260 /**
261 * @tc.name: AceliteFrameworkPercentParse007
262 * @tc.desc: Verify the percent converting process
263 */
264 HWTEST_F(PercentTddTest, PercentParse007, TestSize.Level1)
265 {
266 uint16_t strLength = 4;
267 /**
268 * @tc.steps: step1. give one negative number
269 */
270 const char *strBuffer = "-40%";
271 float percentValue = 0;
272 bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
273 /**
274 * @tc.steps: step2. check if parse successfully and the result is negative number
275 */
276 EXPECT_TRUE(result);
277 float correctValue = -40;
278 EXPECT_EQ(percentValue, correctValue);
279 }
280
281 /**
282 * @tc.name: AceliteFrameworkPercentParse008
283 * @tc.desc: Verify the percent converting process
284 */
285 HWTEST_F(PercentTddTest, PercentParse008, TestSize.Level1)
286 {
287 uint16_t strLength = 6;
288 /**
289 * @tc.steps: step1. give one string which is not number and not including %
290 */
291 const char *strBuffer = "abcdef";
292 float percentValue = 0;
293 bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
294 /**
295 * @tc.steps: step2. check if parse failed
296 */
297 EXPECT_FALSE(result);
298 }
299
300 /**
301 * @tc.name: AceliteFrameworkPercentParse009
302 * @tc.desc: Verify the percent converting process
303 */
304 HWTEST_F(PercentTddTest, PercentParse009, TestSize.Level1)
305 {
306 uint16_t strLength = 100;
307 /**
308 * @tc.steps: step1. give one string which is not number and including %
309 */
310 const char *strBuffer = "abcdef%";
311 float percentValue = 0;
312 bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
313 /**
314 * @tc.steps: step2. check if parse failed
315 */
316 EXPECT_FALSE(result);
317 }
318
319 /**
320 * @tc.name: AceliteFrameworkPercentParse010
321 * @tc.desc: Verify the percent converting process
322 */
323 HWTEST_F(PercentTddTest, PercentParse010, TestSize.Level1)
324 {
325 /**
326 * @tc.steps: step1. give one string which is bigger than float range
327 */
328 const char *strBuffer = "123456789012345%";
329 uint16_t strLength = 16;
330 float percentValue = 0;
331 bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
332 EXPECT_TRUE(result);
333 /**
334 * @tc.steps: step2. check the value is correct
335 */
336 float correctValue = static_cast<float>(123456789012345);
337 EXPECT_EQ(percentValue, correctValue);
338 }
339
340 /**
341 * @tc.name: AceliteFrameworkPercentParse011
342 * @tc.desc: Verify the percent converting process
343 */
344 HWTEST_F(PercentTddTest, PercentParse011, TestSize.Level1)
345 {
346 float percentValue = 0;
347 uint16_t strLength = 16;
348 /**
349 * @tc.steps: step1. give one very small value
350 */
351 const char *strBuffer = "-12345678901234%";
352 bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
353 EXPECT_TRUE(result);
354 /**
355 * @tc.steps: step2. check the value is correct
356 */
357 float correctValue = static_cast<float>(-12345678901234);
358 EXPECT_EQ(percentValue, correctValue);
359 }
360
361 /**
362 * @tc.name: AceliteFrameworkPercentSupport001
363 * @tc.desc: Verify the percent processing on div.
364 */
365 HWTEST_F(PercentTddTest, PercentSupport001, TestSize.Level1)
366 {
367 TDD_CASE_BEGIN();
368 /**
369 * @tc.steps: step1. prepare child component
370 */
371 JSValue textTag = JSString::Create("text");
372 JSValue textOption;
373 JSValue textStaticStyle;
374 PrepareOptions(textOption, textStaticStyle);
375 ConfigStylesWithRect(textStaticStyle, "50%", "50%");
376 JSValue textArgs[ARG_LENGTH_2] = {textTag, textOption};
377 JSValue textEl = JSGlobal::Call(FUNC_CREATE_ELEMENT, textArgs, ARG_LENGTH_2);
378 /**
379 * @tc.steps: step2. prepare parent component
380 */
381 JSValue divTag = JSString::Create("div");
382 JSValue divOption;
383 JSValue divStaticStyle;
384 PrepareOptions(divOption, divStaticStyle);
385 ConfigStylesWithRect(divStaticStyle, "100%", "100%");
386 JSValue divChildren = JSArray::Create(0);
387 JSArray::Push(divChildren, textEl);
388 JSValue divArgs[ARG_LENGTH_3] = {divTag, divOption, divChildren};
389 JSValue divEl = JSGlobal::Call(FUNC_CREATE_ELEMENT, divArgs, ARG_LENGTH_3);
390 /**
391 * @tc.steps: step3. trigger render and build
392 */
393 const int16_t screenWidth = 454;
394 const int16_t screenHeight = 454;
395 Component *divComponent = BuildViewTree(divEl, screenWidth, screenHeight);
396 /**
397 * @tc.steps: step4. verify
398 */
399 VerifyDimension(divEl, K_WIDTH, screenWidth);
400 const int16_t halfNum = 2;
401 VerifyDimension(textEl, K_HEIGHT, (screenHeight / halfNum));
402 /**
403 * @tc.steps: step5. release resource
404 */
405 ComponentUtils::ReleaseComponents(divComponent);
406 ReleaseJerryValue(textTag, textStaticStyle, textOption, textEl, VA_ARG_END_FLAG);
407 ReleaseJerryValue(divTag, divStaticStyle, divOption, divEl, divChildren, VA_ARG_END_FLAG);
408 TDD_CASE_END();
409 }
410
411 /**
412 * @tc.name: AceliteFrameworkPercentSupport002
413 * @tc.desc: Verify the percent processing on component.
414 */
415 HWTEST_F(PercentTddTest, PercentSupport002, TestSize.Level0)
416 {
417 TDD_CASE_BEGIN();
418 /**
419 * @tc.steps: step1. prepare child component
420 */
421 JSValue textTag = JSString::Create("text");
422 JSValue textOption;
423 JSValue textStaticStyle;
424 PrepareOptions(textOption, textStaticStyle);
425 ConfigStylesWithPosition(textStaticStyle, "10%", "10%");
426 JSValue textArgs[ARG_LENGTH_2] = {textTag, textOption};
427 JSValue textEl = JSGlobal::Call(FUNC_CREATE_ELEMENT, textArgs, ARG_LENGTH_2);
428 /**
429 * @tc.steps: step2. prepare parent component
430 */
431 JSValue stackTag = JSString::Create("stack");
432 JSValue stackOption;
433 JSValue stackStaticStyle;
434 PrepareOptions(stackOption, stackStaticStyle);
435 ConfigStylesWithRect(stackStaticStyle, "50%", "50%");
436 JSValue stackChildren = JSArray::Create(0);
437 JSArray::Push(stackChildren, textEl);
438 JSValue stackArgs[ARG_LENGTH_3] = {stackTag, stackOption, stackChildren};
439 JSValue stackEl = JSGlobal::Call(FUNC_CREATE_ELEMENT, stackArgs, ARG_LENGTH_3);
440 /**
441 * @tc.steps: step3. trigger render and build
442 */
443 const int16_t screenWidth = 1024;
444 const int16_t screenHeight = 768;
445 Component *stackComponent = BuildViewTree(stackEl, screenWidth, screenHeight);
446 /**
447 * @tc.steps: step4. verify
448 */
449 const int16_t halfNum = 2;
450 const int16_t marginPercentNum = 10;
451 VerifyDimension(stackEl, K_WIDTH, (screenWidth / halfNum));
452 VerifyDimension(textEl, K_TOP, ((screenHeight / halfNum) / marginPercentNum));
453 /**
454 * @tc.steps: step5. release resource
455 */
456 ComponentUtils::ReleaseComponents(stackComponent);
457 ReleaseJerryValue(textTag, textStaticStyle, textOption, textEl, VA_ARG_END_FLAG);
458 ReleaseJerryValue(stackTag, stackStaticStyle, stackOption, stackEl, stackChildren, VA_ARG_END_FLAG);
459 TDD_CASE_END();
460 }
461
462 /**
463 * @tc.name: AceliteFrameworkPercentSupport003
464 * @tc.desc: Verify the percent processing on component.
465 */
466 HWTEST_F(PercentTddTest, PercentSupport003, TestSize.Level0)
467 {
468 TDD_CASE_BEGIN();
469 /**
470 * @tc.steps: step1. prepare child component
471 */
472 JSValue labelTag = JSString::Create("text");
473 JSValue labelOption;
474 JSValue labelStaticStyle;
475 PrepareOptions(labelOption, labelStaticStyle);
476 ConfigStylesWithMargins(labelStaticStyle, "10%", "10%", "10%", "10%");
477 JSValue labelArgs[ARG_LENGTH_2] = {labelTag, labelOption};
478 JSValue textEl = JSGlobal::Call(FUNC_CREATE_ELEMENT, labelArgs, ARG_LENGTH_2);
479 /**
480 * @tc.steps: step2. prepare parent component
481 */
482 JSValue containerTag = JSString::Create("div");
483 JSValue containerOption;
484 JSValue containerStaticStyle;
485 PrepareOptions(containerOption, containerStaticStyle);
486 ConfigStylesWithRect(containerStaticStyle, "100%", "100%");
487 JSValue containerChildren = JSArray::Create(0);
488 JSArray::Push(containerChildren, textEl);
489 JSValue containerArgs[ARG_LENGTH_3] = {containerTag, containerOption, containerChildren};
490 JSValue containerEl = JSGlobal::Call(FUNC_CREATE_ELEMENT, containerArgs, ARG_LENGTH_3);
491 /**
492 * @tc.steps: step3. trigger render and build
493 */
494 const int16_t screenWidth = 600;
495 const int16_t screenHeight = 800;
496 Component *containerComponent = BuildViewTree(containerEl, screenWidth, screenHeight);
497 /**
498 * @tc.steps: step4. verify
499 */
500 const int16_t marginPercent = 10;
501 VerifyDimension(textEl, K_MARGIN_TOP, (screenHeight / marginPercent));
502 /**
503 * @tc.steps: step5. release resource
504 */
505 ComponentUtils::ReleaseComponents(containerComponent);
506 ReleaseJerryValue(labelTag, labelStaticStyle, labelOption, textEl, VA_ARG_END_FLAG);
507 ReleaseJerryValue(containerTag, containerStaticStyle, containerOption, containerEl, containerChildren,
508 VA_ARG_END_FLAG);
509 TDD_CASE_END();
510 }
511
512 /**
513 * used for debugging TDD implementation on simulator
514 */
RunTests()515 void PercentTddTest::RunTests()
516 {
517 #ifndef TDD_ASSERTIONS
518 PercentParse001();
519 PercentParse002();
520 PercentParse003();
521 PercentParse004();
522 PercentParse005();
523 PercentParse006();
524 PercentParse007();
525 PercentParse008();
526 PercentParse009();
527 PercentParse010();
528 PercentParse011();
529 PercentSupport001();
530 PercentSupport002();
531 PercentSupport003();
532 #endif // TDD_ASSERTIONS
533 }
534 } // namespace ACELite
535 } // namespace OHOS
536