forked from streamlit/streamlit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathst_multiselect_test.py
248 lines (199 loc) · 8.95 KB
/
st_multiselect_test.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2024)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from playwright.sync_api import Page, expect
from e2e_playwright.conftest import ImageCompareFunction, wait_for_app_run
from e2e_playwright.shared.app_utils import (
check_top_level_class,
click_checkbox,
expect_help_tooltip,
get_element_by_key,
)
def select_for_kth_multiselect(
page: Page, option_text: str, k: int, close_after_selecting: bool
) -> None:
"""Select an option from a multiselect widget.
Parameters
----------
page : Page
The playwright page to use.
option_text : str
The text of the option to select.
k : int
The index of the multiselect widget to select from.
close_after_selecting : bool
Whether to close the dropdown after selecting the option.
"""
multiselect_elem = page.get_by_test_id("stMultiSelect").nth(k)
multiselect_elem.locator("input").click()
page.locator("li").filter(has_text=option_text).first.click()
if close_after_selecting:
page.keyboard.press("Escape")
wait_for_app_run(page)
def del_from_kth_multiselect(page: Page, option_text: str, k: int):
"""Delete an option from a multiselect widget.
Parameters
----------
page : Page
The playwright page to use.
option_text : str
The text of the option to delete.
k : int
The index of the multiselect widget to delete from.
"""
multiselect_elem = page.get_by_test_id("stMultiSelect").nth(k)
multiselect_elem.locator(
f'span[data-baseweb="tag"] span[title="{option_text}"] + span[role="presentation"]'
).first.click()
def test_multiselect_on_load(themed_app: Page, assert_snapshot: ImageCompareFunction):
"""Should show widgets correctly when loaded."""
multiselect_elements = themed_app.get_by_test_id("stMultiSelect")
expect(multiselect_elements).to_have_count(12)
for idx, el in enumerate(multiselect_elements.all()):
assert_snapshot(el, name="st_multiselect-" + str(idx))
def test_help_tooltip_works(app: Page):
element_with_help = app.get_by_test_id("stMultiSelect").nth(0)
expect_help_tooltip(app, element_with_help, "Help text")
def test_multiselect_initial_value(app: Page):
"""Should show the correct initial values."""
text_elements = app.get_by_test_id("stText")
expect(text_elements).to_have_count(13)
expected = [
"value 1: []",
"value 2: []",
"value 3: []",
"value 4: ['tea', 'water']",
"value 5: []",
"value 6: []",
"value 7: []",
"value 8: []",
"value 9: []",
"value 10: []",
"value 11: []",
"multiselect changed: False",
"value 12: ['A long option']",
]
for text_element, expected_text in zip(text_elements.all(), expected):
expect(text_element).to_have_text(expected_text, use_inner_text=True)
def test_multiselect_clear_all(app: Page):
"""Should clear all options when clicking clear all."""
select_for_kth_multiselect(app, "Female", 1, True)
app.locator('.stMultiSelect [role="button"][aria-label="Clear all"]').first.click()
expect(app.get_by_test_id("stText").nth(1)).to_have_text("value 2: []")
def test_multiselect_show_values_in_dropdown(
app: Page, assert_snapshot: ImageCompareFunction
):
"""Screenshot test to check that values are shown in dropdown."""
multiselect_elem = app.get_by_test_id("stMultiSelect").nth(0)
multiselect_elem.locator("input").click()
wait_for_app_run(app)
dropdown_elements = app.locator("li")
expect(dropdown_elements).to_have_count(2)
assert_snapshot(dropdown_elements.nth(0), name="st_multiselect-dropdown_0")
assert_snapshot(dropdown_elements.nth(1), name="st_multiselect-dropdown_1")
def test_multiselect_long_values_in_dropdown(
app: Page, assert_snapshot: ImageCompareFunction
):
"""Should show long values correctly (with ellipses) in the dropdown menu."""
multiselect_elem = app.get_by_test_id("stMultiSelect").nth(4)
multiselect_elem.locator("input").click()
wait_for_app_run(app)
dropdown_elems = app.locator("li").all()
for idx, el in enumerate(dropdown_elems):
assert_snapshot(el, name="st_multiselect-dropdown_long_label_" + str(idx))
def test_multiselect_long_values_in_narrow_column(
app: Page, assert_snapshot: ImageCompareFunction
):
"""Should show long values correctly (with ellipses) when in narrow column widths."""
multiselect_elem = app.get_by_test_id("stMultiSelect").nth(11)
wait_for_app_run(app)
# Wait for list items to be loaded in
app.locator("li").all()
assert_snapshot(multiselect_elem, name="st_multiselect-dropdown_narrow_column")
def test_multiselect_register_callback(app: Page):
"""Should call the callback when an option is selected."""
app.get_by_test_id("stMultiSelect").nth(10).locator("input").click()
app.locator("li").first.click()
expect(app.get_by_test_id("stText").nth(10)).to_have_text("value 11: ['male']")
expect(app.get_by_test_id("stText").nth(11)).to_have_text(
"multiselect changed: True"
)
def test_multiselect_max_selections_form(app: Page):
"""Should apply max selections when used in form."""
select_for_kth_multiselect(app, "male", 8, False)
expect(app.locator("li")).to_have_text(
"You can only select up to 1 option. Remove an option first.",
use_inner_text=True,
)
def test_multiselect_max_selections_1(app: Page):
"""Should show the correct text when maxSelections is reached and closing after selecting."""
select_for_kth_multiselect(app, "male", 9, True)
app.get_by_test_id("stMultiSelect").nth(9).click()
expect(app.locator("li")).to_have_text(
"You can only select up to 1 option. Remove an option first.",
use_inner_text=True,
)
def test_multiselect_max_selections_2(app: Page):
"""Should show the correct text when maxSelections is reached and not closing after selecting."""
select_for_kth_multiselect(app, "male", 9, False)
expect(app.locator("li")).to_have_text(
"You can only select up to 1 option. Remove an option first.",
use_inner_text=True,
)
def test_multiselect_valid_options(app: Page):
"""Should allow selections when there are valid options."""
expect(app.get_by_test_id("stMultiSelect").first).to_have_text(
"multiselect 1\n\nPlease select", use_inner_text=True
)
def test_multiselect_no_valid_options(app: Page):
"""Should show that their are no options."""
expect(app.get_by_test_id("stMultiSelect").nth(2)).to_have_text(
"multiselect 3\n\nNo options to select.", use_inner_text=True
)
def test_multiselect_single_selection(app: Page, assert_snapshot: ImageCompareFunction):
"""Should allow selections."""
select_for_kth_multiselect(app, "Female", 1, True)
expect(app.get_by_test_id("stMultiSelect").locator("span").nth(1)).to_have_text(
"Female", use_inner_text=True
)
assert_snapshot(
app.get_by_test_id("stMultiSelect").nth(1), name="st_multiselect-selection"
)
expect(app.get_by_test_id("stText").nth(1)).to_have_text(
"value 2: ['female']", use_inner_text=True
)
def test_multiselect_deselect_option(app: Page):
"""Should deselect an option when deselecting it."""
select_for_kth_multiselect(app, "Female", 1, True)
select_for_kth_multiselect(app, "Male", 1, True)
del_from_kth_multiselect(app, "Female", 1)
expect(app.get_by_test_id("stText").nth(1)).to_have_text("value 2: ['male']")
def test_multiselect_option_over_max_selections(app: Page):
"""Should show an error when more than max_selections got selected."""
click_checkbox(app, "set_multiselect_9")
expect(app.get_by_test_id("stException")).to_contain_text(
"Multiselect has 2 options selected but max_selections is set to 1"
)
def test_multiselect_double_selection(app: Page):
"""Should allow multiple selections."""
select_for_kth_multiselect(app, "Female", 1, True)
select_for_kth_multiselect(app, "Male", 1, True)
expect(app.get_by_test_id("stText").nth(1)).to_have_text(
"value 2: ['female', 'male']"
)
def test_check_top_level_class(app: Page):
"""Check that the top level class is correctly set."""
check_top_level_class(app, "stMultiSelect")
def test_custom_css_class_via_key(app: Page):
"""Test that the element can have a custom css class via the key argument."""
expect(get_element_by_key(app, "multiselect 9")).to_be_visible()