From ab727d31811daac44c56e041cf4625440bf0bf3f Mon Sep 17 00:00:00 2001 From: Carlos Diaz Date: Thu, 17 Feb 2022 11:12:59 -0600 Subject: [PATCH] test(textarea): add unit test (#3074) * test(textarea): Password mode * test(textarea): label style with one line enabled * test(textarea): Cursor click pos * chore(textarea): Move auto hide to helper * test(textarea): Placeholder text * test(textarea): Default properties values * test(textarea): Remove assert from one line test * tests(textarea): Remove unused variables * feat/textarea: Add and use is_valid_but_non_printable_char * chore/textarea: General cleanup * test(textarea): Accepted chars * Update src/widgets/lv_textarea.c * test(textarea): Assert text is empty after widget creation * test(textarea): Update test for label style with one line enabled * test(textarea): Add default text helper and use it * test(textarea): Ignore line break chars in one line mode * textarea: Check for line break chars sooner when adding char * textarea: Start refactor of insert_handler * textarea: Add comments to insert_handler Co-authored-by: Gabor Kiss-Vamosi --- src/widgets/lv_textarea.c | 297 +++++++++++++-------------- tests/src/test_cases/test_textarea.c | 107 ++++++++++ 2 files changed, 250 insertions(+), 154 deletions(-) create mode 100644 tests/src/test_cases/test_textarea.c diff --git a/src/widgets/lv_textarea.c b/src/widgets/lv_textarea.c index 0dff383d7..74cbf6d87 100644 --- a/src/widgets/lv_textarea.c +++ b/src/widgets/lv_textarea.c @@ -34,6 +34,7 @@ #endif #define LV_TEXTAREA_PWD_BULLET_UNICODE 0x2022 +#define IGNORE_KERNING '\0' /********************** * TYPEDEFS @@ -57,6 +58,8 @@ static void update_cursor_position_on_click(lv_event_t * e); static lv_res_t insert_handler(lv_obj_t * obj, const char * txt); static void draw_placeholder(lv_event_t * e); static void draw_cursor(lv_event_t * e); +static void auto_hide_characters(lv_obj_t * obj); +static inline bool is_valid_but_non_printable_char(const uint32_t letter); /********************** * STATIC VARIABLES @@ -100,13 +103,16 @@ void lv_textarea_add_char(lv_obj_t * obj, uint32_t c) lv_textarea_t * ta = (lv_textarea_t *)obj; - const char * letter_buf; + if(ta->one_line && (c == '\n' || c == '\r')) { + LV_LOG_INFO("Text area: line break ignored in one-line mode"); + return; + } uint32_t u32_buf[2]; u32_buf[0] = c; u32_buf[1] = 0; - letter_buf = (char *)&u32_buf; + const char * letter_buf = (char *)&u32_buf; #if LV_BIG_ENDIAN_SYSTEM if(c != 0) while(*letter_buf == 0) ++letter_buf; @@ -115,11 +121,6 @@ void lv_textarea_add_char(lv_obj_t * obj, uint32_t c) lv_res_t res = insert_handler(obj, letter_buf); if(res != LV_RES_OK) return; - if(ta->one_line && (c == '\n' || c == '\r')) { - LV_LOG_INFO("Text area: line break ignored in one-line mode"); - return; - } - uint32_t c_uni = _lv_txt_encoded_next((const char *)&c, NULL); if(char_is_accepted(obj, c_uni) == false) { @@ -127,7 +128,7 @@ void lv_textarea_add_char(lv_obj_t * obj, uint32_t c) return; } - if(ta->pwd_mode != 0) pwd_char_hider(obj); /*Make sure all the current text contains only '*'*/ + if(ta->pwd_mode) pwd_char_hider(obj); /*Make sure all the current text contains only '*'*/ /*If the textarea is empty, invalidate it to hide the placeholder*/ if(ta->placeholder_txt) { @@ -136,30 +137,19 @@ void lv_textarea_add_char(lv_obj_t * obj, uint32_t c) } lv_label_ins_text(ta->label, ta->cursor.pos, letter_buf); /*Insert the character*/ - lv_textarea_clear_selection(obj); /*Clear selection*/ + lv_textarea_clear_selection(obj); /*Clear selection*/ - if(ta->pwd_mode != 0) { - ta->pwd_tmp = lv_mem_realloc(ta->pwd_tmp, strlen(ta->pwd_tmp) + strlen(letter_buf) + 1); /*+2: the new char + \0*/ + if(ta->pwd_mode) { + /*+2: the new char + \0*/ + size_t realloc_size = strlen(ta->pwd_tmp) + strlen(letter_buf) + 1; + ta->pwd_tmp = lv_mem_realloc(ta->pwd_tmp, realloc_size); LV_ASSERT_MALLOC(ta->pwd_tmp); if(ta->pwd_tmp == NULL) return; _lv_txt_ins(ta->pwd_tmp, ta->cursor.pos, (const char *)letter_buf); /*Auto hide characters*/ - if(ta->pwd_show_time == 0) { - pwd_char_hider(obj); - } - else { - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, ta); - lv_anim_set_exec_cb(&a, pwd_char_hider_anim); - lv_anim_set_time(&a, ta->pwd_show_time); - lv_anim_set_values(&a, 0, 1); - lv_anim_set_path_cb(&a, lv_anim_path_step); - lv_anim_set_ready_cb(&a, pwd_char_hider_anim_ready); - lv_anim_start(&a); - } + auto_hide_characters(obj); } /*Move the cursor after the new character*/ @@ -175,7 +165,7 @@ void lv_textarea_add_text(lv_obj_t * obj, const char * txt) lv_textarea_t * ta = (lv_textarea_t *)obj; - if(ta->pwd_mode != 0) pwd_char_hider(obj); /*Make sure all the current text contains only '*'*/ + if(ta->pwd_mode) pwd_char_hider(obj); /*Make sure all the current text contains only '*'*/ /*Add the character one-by-one if not all characters are accepted or there is character limit.*/ if(lv_textarea_get_accepted_chars(obj) || lv_textarea_get_max_length(obj)) { @@ -200,28 +190,16 @@ void lv_textarea_add_text(lv_obj_t * obj, const char * txt) lv_label_ins_text(ta->label, ta->cursor.pos, txt); lv_textarea_clear_selection(obj); - if(ta->pwd_mode != 0) { - ta->pwd_tmp = lv_mem_realloc(ta->pwd_tmp, strlen(ta->pwd_tmp) + strlen(txt) + 1); + if(ta->pwd_mode) { + size_t realloc_size = strlen(ta->pwd_tmp) + strlen(txt) + 1; + ta->pwd_tmp = lv_mem_realloc(ta->pwd_tmp, realloc_size); LV_ASSERT_MALLOC(ta->pwd_tmp); if(ta->pwd_tmp == NULL) return; _lv_txt_ins(ta->pwd_tmp, ta->cursor.pos, txt); /*Auto hide characters*/ - if(ta->pwd_show_time == 0) { - pwd_char_hider(obj); - } - else { - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, ta); - lv_anim_set_exec_cb(&a, pwd_char_hider_anim); - lv_anim_set_time(&a, ta->pwd_show_time); - lv_anim_set_values(&a, 0, 1); - lv_anim_set_path_cb(&a, lv_anim_path_step); - lv_anim_set_ready_cb(&a, pwd_char_hider_anim_ready); - lv_anim_start(&a); - } + auto_hide_characters(obj); } /*Move the cursor after the new text*/ @@ -259,7 +237,7 @@ void lv_textarea_del_char(lv_obj_t * obj) if(txt[0] == '\0') lv_obj_invalidate(obj); } - if(ta->pwd_mode != 0) { + if(ta->pwd_mode) { _lv_txt_cut(ta->pwd_tmp, ta->cursor.pos - 1, 1); ta->pwd_tmp = lv_mem_realloc(ta->pwd_tmp, strlen(ta->pwd_tmp) + 1); @@ -301,7 +279,7 @@ void lv_textarea_set_text(lv_obj_t * obj, const char * txt) if(lv_textarea_get_accepted_chars(obj) || lv_textarea_get_max_length(obj)) { lv_label_set_text(ta->label, ""); lv_textarea_set_cursor_pos(obj, LV_TEXTAREA_CURSOR_LAST); - if(ta->pwd_mode != 0) { + if(ta->pwd_mode) { ta->pwd_tmp[0] = '\0'; /*Clear the password too*/ } uint32_t i = 0; @@ -321,27 +299,14 @@ void lv_textarea_set_text(lv_obj_t * obj, const char * txt) if(txt_act[0] == '\0') lv_obj_invalidate(obj); } - if(ta->pwd_mode != 0) { + if(ta->pwd_mode) { ta->pwd_tmp = lv_mem_realloc(ta->pwd_tmp, strlen(txt) + 1); LV_ASSERT_MALLOC(ta->pwd_tmp); if(ta->pwd_tmp == NULL) return; strcpy(ta->pwd_tmp, txt); /*Auto hide characters*/ - if(ta->pwd_show_time == 0) { - pwd_char_hider(obj); - } - else { - lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_var(&a, ta); - lv_anim_set_exec_cb(&a, pwd_char_hider_anim); - lv_anim_set_time(&a, ta->pwd_show_time); - lv_anim_set_values(&a, 0, 1); - lv_anim_set_path_cb(&a, lv_anim_path_step); - lv_anim_set_ready_cb(&a, pwd_char_hider_anim_ready); - lv_anim_start(&a); - } + auto_hide_characters(obj); } lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); @@ -355,29 +320,22 @@ void lv_textarea_set_placeholder_text(lv_obj_t * obj, const char * txt) lv_textarea_t * ta = (lv_textarea_t *)obj; size_t txt_len = strlen(txt); - - if(txt_len == 0) { - if(ta->placeholder_txt) { - lv_mem_free(ta->placeholder_txt); - ta->placeholder_txt = NULL; - } + if((txt_len == 0) && (ta->placeholder_txt)) { + lv_mem_free(ta->placeholder_txt); + ta->placeholder_txt = NULL; } else { - /*Allocate memory for the placeholder_txt text*/ - if(ta->placeholder_txt == NULL) { - ta->placeholder_txt = lv_mem_alloc(txt_len + 1); - } - else { - ta->placeholder_txt = lv_mem_realloc(ta->placeholder_txt, txt_len + 1); - - } + /*NOTE: Using special realloc behavior, malloc-like when data_p is NULL*/ + ta->placeholder_txt = lv_mem_realloc(ta->placeholder_txt, txt_len + 1); LV_ASSERT_MALLOC(ta->placeholder_txt); if(ta->placeholder_txt == NULL) { LV_LOG_ERROR("lv_textarea_set_placeholder_text: couldn't allocate memory for placeholder"); return; } + strcpy(ta->placeholder_txt, txt); + ta->placeholder_txt[txt_len] = '\0'; } lv_obj_invalidate(obj); @@ -440,7 +398,7 @@ void lv_textarea_set_cursor_click_pos(lv_obj_t * obj, bool en) LV_ASSERT_OBJ(obj, MY_CLASS); lv_textarea_t * ta = (lv_textarea_t *)obj; - ta->cursor.click_pos = en ? 1 : 0; + ta->cursor.click_pos = en ? 1U : 0U; } void lv_textarea_set_password_mode(lv_obj_t * obj, bool en) @@ -450,11 +408,12 @@ void lv_textarea_set_password_mode(lv_obj_t * obj, bool en) lv_textarea_t * ta = (lv_textarea_t *)obj; if(ta->pwd_mode == en) return; - ta->pwd_mode = en == false ? 0 : 1; + ta->pwd_mode = en ? 1U : 0U; /*Pwd mode is now enabled*/ - if(en != false) { - char * txt = lv_label_get_text(ta->label); + if(en) { + char * txt = lv_label_get_text(ta->label); size_t len = strlen(txt); + ta->pwd_tmp = lv_mem_alloc(len + 1); LV_ASSERT_MALLOC(ta->pwd_tmp); if(ta->pwd_tmp == NULL) return; @@ -483,21 +442,21 @@ void lv_textarea_set_one_line(lv_obj_t * obj, bool en) lv_textarea_t * ta = (lv_textarea_t *)obj; if(ta->one_line == en) return; - if(en) { - ta->one_line = 1; - lv_obj_set_width(ta->label, LV_SIZE_CONTENT); - lv_obj_set_style_min_width(ta->label, lv_pct(100), 0); + ta->one_line = en ? 1U : 0U; + lv_coord_t width = en ? LV_SIZE_CONTENT : lv_pct(100); + lv_coord_t min_width_value = en ? lv_pct(100) : 0; + lv_obj_set_width(ta->label, width); + lv_obj_set_style_min_width(ta->label, min_width_value, 0); + + if(en) { lv_obj_set_height(obj, LV_SIZE_CONTENT); - lv_obj_scroll_to(obj, 0, 0, LV_ANIM_OFF); } else { - ta->one_line = 0; - lv_obj_set_width(ta->label, lv_pct(100)); - lv_obj_set_style_min_width(ta->label, 0, 0); lv_obj_remove_local_style_prop(obj, LV_STYLE_HEIGHT, LV_PART_MAIN); - lv_obj_scroll_to(obj, 0, 0, LV_ANIM_OFF); } + + lv_obj_scroll_to(obj, 0, 0, LV_ANIM_OFF); } void lv_textarea_set_accepted_chars(lv_obj_t * obj, const char * list) @@ -628,7 +587,7 @@ bool lv_textarea_get_password_mode(const lv_obj_t * obj) LV_ASSERT_OBJ(obj, MY_CLASS); lv_textarea_t * ta = (lv_textarea_t *)obj; - return ta->pwd_mode == 0 ? false : true; + return ta->pwd_mode == 1U; } bool lv_textarea_get_one_line(const lv_obj_t * obj) @@ -636,7 +595,7 @@ bool lv_textarea_get_one_line(const lv_obj_t * obj) LV_ASSERT_OBJ(obj, MY_CLASS); lv_textarea_t * ta = (lv_textarea_t *)obj; - return ta->one_line == 0 ? false : true; + return ta->one_line == 1U; } const char * lv_textarea_get_accepted_chars(lv_obj_t * obj) @@ -922,7 +881,7 @@ static void cursor_blink_anim_cb(void * obj, int32_t show) { lv_textarea_t * ta = (lv_textarea_t *)obj; if(show != ta->cursor.show) { - ta->cursor.show = show == 0 ? 0 : 1; + ta->cursor.show = show ? 1U : 0U; lv_area_t area_tmp; lv_area_copy(&area_tmp, &ta->cursor.area); area_tmp.x1 += ta->label->coords.x1; @@ -963,33 +922,35 @@ static void pwd_char_hider_anim_ready(lv_anim_t * a) static void pwd_char_hider(lv_obj_t * obj) { lv_textarea_t * ta = (lv_textarea_t *)obj; - if(ta->pwd_mode != 0) { - char * txt = lv_label_get_text(ta->label); - int32_t enc_len = _lv_txt_get_encoded_length(txt); - if(enc_len == 0) return; - - /*If the textarea's font has "bullet" character use it else fallback to "*"*/ - const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - lv_font_glyph_dsc_t g; - bool has_bullet; - has_bullet = lv_font_get_glyph_dsc(font, &g, LV_TEXTAREA_PWD_BULLET_UNICODE, 0); - const char * bullet; - if(has_bullet) bullet = LV_SYMBOL_BULLET; - else bullet = "*"; - - size_t bullet_len = strlen(bullet); - char * txt_tmp = lv_mem_buf_get(enc_len * bullet_len + 1); - int32_t i; - for(i = 0; i < enc_len; i++) { - lv_memcpy(&txt_tmp[i * bullet_len], bullet, bullet_len); - } - - txt_tmp[i * bullet_len] = '\0'; - - lv_label_set_text(ta->label, txt_tmp); - lv_mem_buf_release(txt_tmp); - refr_cursor_area(obj); + if(ta->pwd_mode == 0) { + return; } + + /* When ta->label is empty we get 0 back */ + char * txt = lv_label_get_text(ta->label); + uint32_t enc_len = _lv_txt_get_encoded_length(txt); + if(enc_len == 0) return; + + /*If the textarea's font has "bullet" character use it else fallback to "*"*/ + lv_font_glyph_dsc_t g; + const char * bullet = "*"; + + const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); + if(lv_font_get_glyph_dsc(font, &g, LV_TEXTAREA_PWD_BULLET_UNICODE, 0)) bullet = LV_SYMBOL_BULLET; + + const size_t bullet_len = strlen(bullet); + char * txt_tmp = lv_mem_buf_get(enc_len * bullet_len + 1); + + uint32_t i; + for(i = 0; i < enc_len; i++) { + lv_memcpy(&txt_tmp[i * bullet_len], bullet, bullet_len); + } + txt_tmp[i * bullet_len] = '\0'; + + lv_label_set_text(ta->label, txt_tmp); + lv_mem_buf_release(txt_tmp); + + refr_cursor_area(obj); } /** @@ -1002,6 +963,9 @@ static bool char_is_accepted(lv_obj_t * obj, uint32_t c) { lv_textarea_t * ta = (lv_textarea_t *)obj; + /*If the accepted char list in not specified the accept the character*/ + if(ta->accepted_chars == NULL) return true; + /*If no restriction accept it*/ if((ta->accepted_chars == NULL || ta->accepted_chars[0] == '\0') && ta->max_length == 0) return true; @@ -1011,19 +975,15 @@ static bool char_is_accepted(lv_obj_t * obj, uint32_t c) } /*Accepted character?*/ - if(ta->accepted_chars) { - uint32_t i = 0; + /*We're sure ta->accepted_chars != NULL*/ + uint32_t i = 0; - while(ta->accepted_chars[i] != '\0') { - uint32_t a = _lv_txt_encoded_next(ta->accepted_chars, &i); - if(a == c) return true; /*Accepted*/ - } + while(ta->accepted_chars[i] != '\0') { + uint32_t a = _lv_txt_encoded_next(ta->accepted_chars, &i); + if(a == c) return true; /*Accepted*/ + } - return false; /*The character wasn't in the list*/ - } - else { - return true; /*If the accepted char list in not specified the accept the character*/ - } + return false; /*The character wasn't in the list*/ } static void start_cursor_blink(lv_obj_t * obj) @@ -1058,22 +1018,17 @@ static void refr_cursor_area(lv_obj_t * obj) uint32_t cur_pos = lv_textarea_get_cursor_pos(obj); const char * txt = lv_label_get_text(ta->label); - uint32_t byte_pos; - byte_pos = _lv_txt_encoded_get_byte_id(txt, cur_pos); - + uint32_t byte_pos = _lv_txt_encoded_get_byte_id(txt, cur_pos); uint32_t letter = _lv_txt_encoded_next(&txt[byte_pos], NULL); - lv_coord_t letter_h = lv_font_get_line_height(font); - + /* Letter height and width */ + const lv_coord_t letter_h = lv_font_get_line_height(font); /*Set letter_w (set not 0 on non printable but valid chars)*/ - lv_coord_t letter_w; - if(letter == '\0' || letter == '\n' || letter == '\r') { - letter_w = lv_font_get_glyph_width(font, ' ', '\0'); - } - else { - /*`letter_next` parameter is '\0' to ignore kerning*/ - letter_w = lv_font_get_glyph_width(font, letter, '\0'); + uint32_t letter_space = letter; + if(is_valid_but_non_printable_char(letter)) { + letter_space = ' '; } + lv_coord_t letter_w = lv_font_get_glyph_width(font, letter_space, IGNORE_KERNING); lv_point_t letter_pos; lv_label_get_letter_pos(ta->label, cur_pos, &letter_pos); @@ -1081,8 +1036,9 @@ static void refr_cursor_area(lv_obj_t * obj) lv_text_align_t align = lv_obj_calculate_style_text_align(ta->label, LV_PART_MAIN, lv_label_get_text(ta->label)); /*If the cursor is out of the text (most right) draw it to the next line*/ - if(letter_pos.x + ta->label->coords.x1 + letter_w > ta->label->coords.x2 && ta->one_line == 0 && - align != LV_TEXT_ALIGN_RIGHT) { + if(((letter_pos.x + ta->label->coords.x1) + letter_w > ta->label->coords.x2) && + (ta->one_line == 0 && align != LV_TEXT_ALIGN_RIGHT)) { + letter_pos.x = 0; letter_pos.y += letter_h + line_space; @@ -1091,12 +1047,11 @@ static void refr_cursor_area(lv_obj_t * obj) letter = _lv_txt_encoded_next(&txt[byte_pos], NULL); } - if(letter == '\0' || letter == '\n' || letter == '\r') { - letter_w = lv_font_get_glyph_width(font, ' ', '\0'); - } - else { - letter_w = lv_font_get_glyph_width(font, letter, '\0'); + uint32_t tmp = letter; + if(is_valid_but_non_printable_char(letter)) { + tmp = ' '; } + letter_w = lv_font_get_glyph_width(font, tmp, IGNORE_KERNING); } /*Save the byte position. It is required to draw `LV_CURSOR_BLOCK`*/ @@ -1139,7 +1094,6 @@ static void update_cursor_position_on_click(lv_event_t * e) lv_indev_t * click_source = lv_indev_get_act(); if(click_source == NULL) return; - lv_event_code_t code = lv_event_get_code(e); lv_obj_t * obj = lv_event_get_target(e); lv_textarea_t * ta = (lv_textarea_t *)obj; if(ta->cursor.click_pos == 0) return; @@ -1161,26 +1115,27 @@ static void update_cursor_position_on_click(lv_event_t * e) rel_pos.x = point_act.x - label_coords.x1; rel_pos.y = point_act.y - label_coords.y1; - lv_coord_t label_width = lv_obj_get_width(ta->label); + const lv_event_code_t code = lv_event_get_code(e); - uint16_t char_id_at_click; + lv_coord_t label_width = lv_obj_get_width(ta->label); + uint16_t char_id_at_click = 0; #if LV_LABEL_TEXT_SELECTION lv_label_t * label_data = (lv_label_t *)ta->label; - bool click_outside_label; + bool click_outside_label = false; /*Check if the click happened on the left side of the area outside the label*/ if(rel_pos.x < 0) { char_id_at_click = 0; - click_outside_label = true; + click_outside_label = true; } /*Check if the click happened on the right side of the area outside the label*/ else if(rel_pos.x >= label_width) { char_id_at_click = LV_TEXTAREA_CURSOR_LAST; - click_outside_label = true; + click_outside_label = true; } else { char_id_at_click = lv_label_get_letter_on(ta->label, &rel_pos); - click_outside_label = !lv_label_is_char_under_pos(ta->label, &rel_pos); + click_outside_label = !lv_label_is_char_under_pos(ta->label, &rel_pos); } if(ta->text_sel_en) { @@ -1250,13 +1205,18 @@ static void update_cursor_position_on_click(lv_event_t * e) #endif } +/* Returns LV_RES_OK when no operation were performed + * Returns LV_RES_INV when a user defined text was inserted */ static lv_res_t insert_handler(lv_obj_t * obj, const char * txt) { ta_insert_replace = NULL; lv_event_send(obj, LV_EVENT_INSERT, (char *)txt); - if(ta_insert_replace) { - if(ta_insert_replace[0] == '\0') return LV_RES_INV; /*Drop this text*/ + /* Drop txt if insert replace is set to '\0' */ + if(ta_insert_replace && ta_insert_replace[0] == '\0') + return LV_RES_INV; + + if(ta_insert_replace) { /*Add the replaced text directly it's different from the original*/ if(strcmp(ta_insert_replace, txt)) { lv_textarea_add_text(obj, ta_insert_replace); @@ -1338,4 +1298,33 @@ static void draw_cursor(lv_event_t * e) } } +static void auto_hide_characters(lv_obj_t * obj) +{ + lv_textarea_t * ta = (lv_textarea_t *) obj; + + if(ta->pwd_show_time == 0) { + pwd_char_hider(obj); + } + else { + lv_anim_t a; + lv_anim_init(&a); + lv_anim_set_var(&a, ta); + lv_anim_set_exec_cb(&a, pwd_char_hider_anim); + lv_anim_set_time(&a, ta->pwd_show_time); + lv_anim_set_values(&a, 0, 1); + lv_anim_set_path_cb(&a, lv_anim_path_step); + lv_anim_set_ready_cb(&a, pwd_char_hider_anim_ready); + lv_anim_start(&a); + } +} + +static inline bool is_valid_but_non_printable_char(const uint32_t letter) +{ + if(letter == '\0' || letter == '\n' || letter == '\r') { + return true; + } + + return false; +} + #endif diff --git a/tests/src/test_cases/test_textarea.c b/tests/src/test_cases/test_textarea.c new file mode 100644 index 000000000..99a14d819 --- /dev/null +++ b/tests/src/test_cases/test_textarea.c @@ -0,0 +1,107 @@ +#if LV_BUILD_TEST +#include "../lvgl.h" + +#include "unity/unity.h" + +static lv_obj_t * active_screen = NULL; +static lv_obj_t * textarea = NULL; + +static const char * textarea_default_text = ""; + +void setUp(void) +{ + active_screen = lv_scr_act(); + textarea = lv_textarea_create(active_screen); +} + +void tearDown(void) +{ + /* Function run after every test */ +} + +void test_textarea_should_have_valid_documented_defualt_values(void) +{ + TEST_ASSERT(lv_textarea_get_cursor_click_pos(textarea)); + TEST_ASSERT_EQUAL(0U, lv_textarea_get_one_line(textarea)); + /* No placeholder text should be set on widget creation */ + TEST_ASSERT_EQUAL_STRING(textarea_default_text, lv_textarea_get_placeholder_text(textarea)); + TEST_ASSERT_EQUAL_STRING(textarea_default_text, lv_textarea_get_text(textarea)); +} + +/* When in password mode the lv_textarea_get_text function returns + * the actual text, not the bullet characters. */ +void test_textarea_should_return_actual_text_when_password_mode_is_enabled(void) +{ + const char * text = "Hello LVGL!"; + + lv_textarea_add_text(textarea, text); + lv_textarea_set_password_mode(textarea, true); + + TEST_ASSERT_TRUE(lv_textarea_get_password_mode(textarea)); + TEST_ASSERT_EQUAL_STRING(text, lv_textarea_get_text(textarea)); +} + +void test_textarea_should_update_label_style_with_one_line_enabled(void) +{ + lv_textarea_t * txt_ptr = (lv_textarea_t *) textarea; + + lv_textarea_add_text(textarea, "Hi"); + lv_textarea_set_one_line(textarea, true); + + lv_coord_t left_padding = lv_obj_get_style_pad_left(txt_ptr->label, LV_PART_MAIN); + lv_coord_t right_padding = lv_obj_get_style_pad_right(txt_ptr->label, LV_PART_MAIN); + lv_coord_t line_width = lv_obj_get_width(txt_ptr->label); + lv_coord_t expected_size = left_padding + right_padding + line_width; + + TEST_ASSERT(lv_textarea_get_one_line(textarea)); + TEST_ASSERT_EQUAL_UINT16(expected_size, lv_obj_get_width(txt_ptr->label)); + TEST_ASSERT_EQUAL_UINT16(lv_pct(100), lv_obj_get_style_min_width(txt_ptr->label, LV_PART_MAIN)); +} + +void test_textarea_cursor_click_pos_field_update(void) +{ + lv_textarea_set_cursor_click_pos(textarea, false); + + TEST_ASSERT_FALSE(lv_textarea_get_cursor_click_pos(textarea)); +} + +void test_textarea_should_update_placeholder_text(void) +{ + const char * new_placeholder = "LVGL Rocks!!!!!"; + const char * text = "Hello LVGL!"; + + /* Allocating memory for placeholder text */ + lv_textarea_set_placeholder_text(textarea, text); + TEST_ASSERT_EQUAL_STRING(text, lv_textarea_get_placeholder_text(textarea)); + + /* Reallocating memory for the new placeholder text */ + lv_textarea_set_placeholder_text(textarea, new_placeholder); + TEST_ASSERT_EQUAL_STRING(new_placeholder, lv_textarea_get_placeholder_text(textarea)); + + /* Freeing allocated memory for placeholder text */ + lv_textarea_set_placeholder_text(textarea, ""); + TEST_ASSERT_EQUAL_STRING("", lv_textarea_get_placeholder_text(textarea)); +} + +void test_textarea_should_keep_only_accepted_chars(void) +{ + const char * accepted_list = "abcd"; + + lv_textarea_set_accepted_chars(textarea, accepted_list); + lv_textarea_set_text(textarea, "abcde"); + + TEST_ASSERT_EQUAL_STRING(accepted_list, lv_textarea_get_text(textarea)); +} + +void test_textarea_in_one_line_mode_should_ignore_line_break_characters(void) +{ + lv_textarea_set_one_line(textarea, true); + + lv_textarea_add_char(textarea, '\n'); + TEST_ASSERT_EQUAL_STRING(textarea_default_text, lv_textarea_get_text(textarea)); + + lv_textarea_add_char(textarea, '\r'); + TEST_ASSERT_EQUAL_STRING(textarea_default_text, lv_textarea_get_text(textarea)); +} + +#endif