Skip to content

Commit 8cc8af7

Browse files
feat: add textarea component (#399)
* chore: add textarea component and fix textbox wait_to_be_editable method * chore: pre-commit fixes * chore: compliance fix and ui tests added * chore: pre-commit fixes * chore: fix ui tests * ci: pin splunk/addonfactory-test-matrix-action to 1.10 --------- Co-authored-by: Artem Rys <rysartem@gmail.com>
1 parent 6f8a39d commit 8cc8af7

File tree

6 files changed

+183
-2
lines changed

6 files changed

+183
-2
lines changed

.github/workflows/build-test-release.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
steps:
2121
- uses: actions/checkout@v4
2222
- id: matrix
23-
uses: splunk/addonfactory-test-matrix-action@v1
23+
uses: splunk/addonfactory-test-matrix-action@v1.10
2424

2525
fossa-scan:
2626
continue-on-error: true
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#
2+
# Copyright 2023 Splunk Inc.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
import platform
17+
18+
from selenium.webdriver.common.keys import Keys
19+
20+
from ..base_component import Selector
21+
from .textbox import TextBox
22+
23+
os_base = platform.system()
24+
25+
26+
class TextArea(TextBox):
27+
"""
28+
Entity-Component: TextBox
29+
"""
30+
31+
def __init__(self, browser, container, encrypted=False):
32+
"""
33+
:param browser: The selenium webdriver
34+
:param container: The locator of the container where the control is located in.
35+
"""
36+
super().__init__(browser, container)
37+
self.elements.update(
38+
{
39+
"input": Selector(
40+
select=container.select + ' textarea[data-test="textbox"]'
41+
)
42+
}
43+
)
44+
45+
def get_value(self):
46+
"""
47+
get value from the textbox
48+
:return: Str The current value of the textbox
49+
"""
50+
return self.input.get_attribute("value")
51+
52+
def get_placeholder_value(self):
53+
"""
54+
get placeholder value from the textbox
55+
:return: Str Value of the placeholder
56+
"""
57+
return self.input.get_attribute("placeholder")
58+
59+
def get_textarea_height(self) -> int:
60+
"""
61+
Get the height of the displayed textarea.
62+
:return: Int Height of the textarea in pixels.
63+
"""
64+
return self.input.size["height"]
65+
66+
def append_value(self, value) -> None:
67+
"""
68+
Appends the specified 'value' to an textarea element
69+
"""
70+
self.input.send_keys(value)
71+
72+
def screenshot(self) -> str:
73+
"""
74+
Creates screenshot of current element
75+
:return: screenshot as base64
76+
"""
77+
return self.input.screenshot_as_base64
78+
79+
def scroll(self, direction: str, scroll_count: int) -> None:
80+
"""
81+
Scrolls the input element in the specified direction.
82+
"""
83+
valid_directions = ["UP", "DOWN"]
84+
if direction not in valid_directions:
85+
raise ValueError("Invalid direction. Use 'UP' or 'DOWN'.")
86+
key = Keys.ARROW_UP if direction == "UP" else Keys.ARROW_DOWN
87+
for _ in range(scroll_count):
88+
self.input.send_keys(key)

pytest_splunk_addon_ui_smartx/components/controls/textbox.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,6 @@ def wait_to_be_editable(self):
9595
"""
9696

9797
def _wait_for_field_to_be_editable(driver):
98-
return self.is_editable == True
98+
return self.is_editable()
9999

100100
self.wait_for(_wait_for_field_to_be_editable, msg="Field is uneditable")

tests/testdata/Splunk_TA_UCCExample/globalConfig.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,17 @@
709709
"help": "The maximum number of results returned by the query.",
710710
"required": false
711711
},
712+
{
713+
"type": "textarea",
714+
"label": "Example Textarea Field",
715+
"field": "example_textarea_field",
716+
"help": "Help message",
717+
"options": {
718+
"rowsMin": 3,
719+
"rowsMax": 15
720+
},
721+
"required": true
722+
},
712723
{
713724
"field": "example_help_link",
714725
"label": "",

tests/ui/Example_UccLib/input_page.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from pytest_splunk_addon_ui_smartx.components.controls.checkbox import Checkbox
88
from pytest_splunk_addon_ui_smartx.components.controls.learn_more import LearnMore
99
from pytest_splunk_addon_ui_smartx.components.controls.textbox import TextBox
10+
from pytest_splunk_addon_ui_smartx.components.controls.textarea import TextArea
1011
from pytest_splunk_addon_ui_smartx.components.controls.single_select import SingleSelect
1112
from pytest_splunk_addon_ui_smartx.components.controls.multi_select import MultiSelect
1213
from pytest_splunk_addon_ui_smartx.components.controls.message import Message
@@ -109,6 +110,12 @@ def __init__(self, browser, container):
109110
+ ' [data-test="control-group"][data-name="example_help_link"]'
110111
),
111112
)
113+
self.text_area = TextArea(
114+
browser,
115+
Selector(
116+
select=entity_container.select + ' [data-name="example_textarea_field"]'
117+
),
118+
)
112119
self.title = BaseComponent(browser, Selector(select=' [data-test="title"]'))
113120

114121

tests/ui/test_splunk_ta_example_addon_input_1.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ def add_input_one(ucc_smartx_rest_helper):
8787
"singleSelectTest": "two",
8888
"start_date": "2020-12-11T20:00:32.000z",
8989
"disabled": 0,
90+
"example_textarea_field": "line1\nline2",
9091
}
9192
yield input_page.backend_conf.post_stanza(url, kwargs)
9293

@@ -794,6 +795,7 @@ def test_example_input_one_add_frontend_validation(
794795
input_page.entity1.object.set_value("test_object")
795796
input_page.entity1.object_fields.set_value("test_field")
796797
input_page.entity1.query_start_date.set_value("2020-12-11T20:00:32.000z")
798+
input_page.entity1.text_area.set_value("line1\nline2")
797799
self.assert_util(input_page.entity1.save, True)
798800
input_page.table.wait_for_rows_to_appear(1)
799801
self.assert_util(
@@ -829,6 +831,7 @@ def test_example_input_one_add_backend_validation(
829831
input_page.entity1.object.set_value("test_object")
830832
input_page.entity1.object_fields.set_value("test_field")
831833
input_page.entity1.query_start_date.set_value("2020-12-11T20:00:32.000z")
834+
input_page.entity1.text_area.set_value("line1\nline2")
832835
self.assert_util(input_page.entity1.save, True)
833836
input_page.table.wait_for_rows_to_appear(1)
834837
value_to_test = {
@@ -844,6 +847,7 @@ def test_example_input_one_add_backend_validation(
844847
"singleSelectTest": "two",
845848
"start_date": "2020-12-11T20:00:32.000z",
846849
"disabled": 0,
850+
"example_textarea_field": "line1\nline2",
847851
}
848852
backend_stanza = input_page.backend_conf.get_stanza(
849853
"example_input_one://dummy_input"
@@ -889,6 +893,7 @@ def test_example_input_one_edit_frontend_validation(
889893
input_page.entity1.order_by.set_value("LastDate")
890894
input_page.entity1.limit.set_value("2000")
891895
input_page.entity1.query_start_date.set_value("2020-20-20T20:20:20.000z")
896+
input_page.entity1.text_area.set_value("line3\nline4")
892897
self.assert_util(input_page.entity1.save, True)
893898
input_page.table.wait_for_rows_to_appear(1)
894899
self.assert_util(
@@ -926,6 +931,7 @@ def test_example_input_one_edit_backend_validation(
926931
input_page.entity1.order_by.set_value("LastDate")
927932
input_page.entity1.limit.set_value("2000")
928933
input_page.entity1.query_start_date.set_value("2020-20-20T20:20:20.000z")
934+
input_page.entity1.text_area.set_value("line3\nline4")
929935
self.assert_util(input_page.entity1.save, True)
930936
input_page.table.wait_for_rows_to_appear(1)
931937
value_to_test = {
@@ -942,6 +948,7 @@ def test_example_input_one_edit_backend_validation(
942948
"singleSelectTest": "four",
943949
"start_date": "2020-20-20T20:20:20.000z",
944950
"disabled": 0,
951+
"example_textarea_field": "line3\nline4",
945952
}
946953
backend_stanza = input_page.backend_conf.get_stanza(
947954
"example_input_one://dummy_input_one"
@@ -974,6 +981,7 @@ def test_example_input_one_clone_default_values(
974981
input_page.entity1.query_start_date.get_value, "2020-12-11T20:00:32.000z"
975982
)
976983
self.assert_util(input_page.entity1.limit.get_value, "1000")
984+
self.assert_util(input_page.entity1.text_area.get_value, "line1\nline2")
977985

978986
@pytest.mark.execute_enterprise_cloud_true
979987
@pytest.mark.forwarder
@@ -990,6 +998,7 @@ def test_example_input_one_clone_frontend_validation(
990998
input_page.entity1.name.set_value("dummy_input_one_Clone_Test")
991999
input_page.entity1.interval.set_value("180")
9921000
input_page.entity1.limit.set_value("500")
1001+
input_page.entity1.text_area.set_value("line1\nline2")
9931002
self.assert_util(input_page.entity1.save, True)
9941003
input_page.table.wait_for_rows_to_appear(2)
9951004
self.assert_util(
@@ -1019,6 +1028,7 @@ def test_example_input_one_clone_backend_validation(
10191028
input_page.entity1.name.set_value("dummy_input_one_Clone_Test")
10201029
input_page.entity1.interval.set_value("180")
10211030
input_page.entity1.limit.set_value("500")
1031+
input_page.entity1.text_area.set_value("line3\nline4")
10221032
self.assert_util(input_page.entity1.save, True)
10231033
input_page.table.wait_for_rows_to_appear(2)
10241034
value_to_test = {
@@ -1035,6 +1045,7 @@ def test_example_input_one_clone_backend_validation(
10351045
"singleSelectTest": "two",
10361046
"start_date": "2020-12-11T20:00:32.000z",
10371047
"disabled": 0,
1048+
"example_textarea_field": "line3\nline4",
10381049
}
10391050
backend_stanza = input_page.backend_conf.get_stanza(
10401051
"example_input_one://dummy_input_one_Clone_Test"
@@ -1276,3 +1287,67 @@ def test_example_input_one_delete_valid_prompt_message(
12761287
self.assert_util(
12771288
prompt_message, 'Are you sure you want to delete "{}" ?'.format(input_name)
12781289
)
1290+
1291+
@pytest.mark.execute_enterprise_cloud_true
1292+
@pytest.mark.forwarder
1293+
@pytest.mark.input
1294+
def test_inputs_textarea_height(
1295+
self, ucc_smartx_selenium_helper, ucc_smartx_rest_helper, add_input_one
1296+
):
1297+
"""
1298+
Verifies that textarea height values
1299+
"""
1300+
input_page = InputPage(ucc_smartx_selenium_helper, ucc_smartx_rest_helper)
1301+
input_page.table.edit_row("dummy_input_one")
1302+
min_textarea_height = 71
1303+
max_textarea_height = 311
1304+
long_input = ""
1305+
self.assert_util(
1306+
min_textarea_height, input_page.entity1.text_area.get_textarea_height
1307+
)
1308+
for i in range(1, 50):
1309+
long_input += f"{str(i)}\n"
1310+
input_page.entity1.text_area.append_value(long_input)
1311+
self.assert_util(
1312+
max_textarea_height, input_page.entity1.text_area.get_textarea_height
1313+
)
1314+
1315+
@pytest.mark.execute_enterprise_cloud_true
1316+
@pytest.mark.forwarder
1317+
@pytest.mark.input
1318+
def test_inputs_textarea_big_input(
1319+
self, ucc_smartx_selenium_helper, ucc_smartx_rest_helper, add_input_one
1320+
):
1321+
"""
1322+
Verifies that textarea can handle big inputs
1323+
"""
1324+
input_page = InputPage(ucc_smartx_selenium_helper, ucc_smartx_rest_helper)
1325+
input_page.table.edit_row("dummy_input_one")
1326+
big_input = ""
1327+
for i in range(1, 1000):
1328+
big_input += f"{str(i)}\n"
1329+
input_page.entity1.text_area.set_value(big_input)
1330+
self.assert_util(big_input, input_page.entity1.text_area.get_value())
1331+
self.assert_util(input_page.entity1.save, True)
1332+
input_page.table.edit_row("dummy_input_one")
1333+
self.assert_util(big_input.strip(), input_page.entity1.text_area.get_value())
1334+
1335+
@pytest.mark.execute_enterprise_cloud_true
1336+
@pytest.mark.forwarder
1337+
@pytest.mark.input
1338+
def test_inputs_textarea_scroll(
1339+
self, ucc_smartx_selenium_helper, ucc_smartx_rest_helper, add_input_one
1340+
):
1341+
"""
1342+
Verifies that textarea height values
1343+
"""
1344+
input_page = InputPage(ucc_smartx_selenium_helper, ucc_smartx_rest_helper)
1345+
input_page.table.edit_row("dummy_input_one")
1346+
long_input = ""
1347+
screnshot_before = input_page.entity1.text_area.screenshot()
1348+
for i in range(1, 50):
1349+
long_input += f"{str(i)}\n"
1350+
input_page.entity1.text_area.append_value(long_input)
1351+
input_page.entity1.text_area.scroll("UP", 40)
1352+
screenshot_after = input_page.entity1.text_area.screenshot()
1353+
self.assert_util(screnshot_before, screenshot_after, operator="!=")

0 commit comments

Comments
 (0)