Skip to content

Commit 68a01d0

Browse files
fix(playwright): Add playwright workaround within Accordion's .expect_open() and .expect_panels() (#1165)
Co-authored-by: Barret Schloerke <[email protected]>
1 parent f0cc575 commit 68a01d0

File tree

5 files changed

+50
-25
lines changed

5 files changed

+50
-25
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7878

7979
* Fixed output controller `OutputDataFrame` in `shiny.playwright.controller` to correctly assert the number of rows in `.expect_nrow()` as the total number of virtual rows, not the number of currently displaying rows. (#1719)
8080

81-
* Fixed issue where `@render.download` did not respect the module namespacing. (Thanks, @nsiicm0) (#1732)
81+
* Fixed issue where `@render.download` did not respect the module namespacing. (Thanks, @nsiicm0!) (#1732)
82+
83+
* Added workaround in `Accordion` in `shiny.playwright.controller` where `.expect_open()` and `.expect_panels()` would hang while resolving a playwright locator. (Thanks, @joesho112358!) (#1165)
8284

8385
## [1.1.0] - 2024-09-03
8486

shiny/playwright/controller/_accordion.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ def expect_open(
255255
arr=value,
256256
key="data-value",
257257
timeout=timeout,
258+
alt_verify=True,
258259
)
259260

260261
def expect_panels(
@@ -281,6 +282,7 @@ def expect_panels(
281282
arr=value,
282283
key="data-value",
283284
timeout=timeout,
285+
alt_verify=True,
284286
)
285287

286288
def set(

shiny/playwright/controller/_expect.py

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ def expect_locator_values_in_list(
146146
is_checked: bool | MISSING_TYPE = MISSING,
147147
timeout: Timeout = None,
148148
key: str = "value",
149+
alt_verify: bool = False,
149150
) -> None:
150151
"""
151152
Expect the locator to contain the values in the list.
@@ -171,6 +172,11 @@ def expect_locator_values_in_list(
171172
The timeout for the expectation. Defaults to `None`.
172173
key
173174
The key. Defaults to `"value"`.
175+
alt_verify
176+
Determines if multiple expectations should be performed.
177+
Defaults to `False`, a single (and very complicated) locator is asserted.
178+
`True` will perform multiple assertions, which have the possibility of being invalid.
179+
Use in playwright bug situations only.
174180
"""
175181
# Make sure the locator has exactly `arr` values
176182

@@ -195,6 +201,28 @@ def expect_locator_values_in_list(
195201
return
196202
loc_container_orig = loc_container
197203

204+
def perform_multiple_assertions():
205+
# Expecting container to exist (count = 1)
206+
playwright_expect(loc_container_orig).to_have_count(1, timeout=timeout)
207+
208+
# Expecting the container to contain {len(arr)} items
209+
playwright_expect(loc_container_orig.locator(loc_item)).to_have_count(
210+
len(arr), timeout=timeout
211+
)
212+
213+
for item, i in zip(arr, range(len(arr))):
214+
# Expecting item `{i}` to be `{item}`
215+
playwright_expect(
216+
loc_container_orig.locator(loc_item).nth(i)
217+
).to_have_attribute(key, item, timeout=timeout)
218+
return
219+
220+
if alt_verify:
221+
# Accordion has issues where the single locator assertion waits forever within playwright.
222+
# Perform multiple assertions until playwright fixes bug.
223+
perform_multiple_assertions()
224+
return
225+
198226
# Find all items in set
199227
for item, i in zip(arr, range(len(arr))):
200228
# Get all elements of type
@@ -220,21 +248,8 @@ def expect_locator_values_in_list(
220248
try:
221249
playwright_expect(loc_inputs).to_have_count(len(arr), timeout=timeout)
222250
except AssertionError as e:
223-
# Debug expections
224-
225-
# Expecting container to exist (count = 1)
226-
playwright_expect(loc_container_orig).to_have_count(1, timeout=timeout)
227-
228-
# Expecting the container to contain {len(arr)} items
229-
playwright_expect(loc_container_orig.locator(loc_item)).to_have_count(
230-
len(arr), timeout=timeout
231-
)
232-
233-
for item, i in zip(arr, range(len(arr))):
234-
# Expecting item `{i}` to be `{item}`
235-
playwright_expect(
236-
loc_container_orig.locator(loc_item).nth(i)
237-
).to_have_attribute(key, item, timeout=timeout)
251+
# Debug expectations
252+
perform_multiple_assertions()
238253

239254
# Could not find the reason why. Raising the original error.
240255
raise e

shiny/render/_data_frame_utils/_tbl_data.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from __future__ import annotations
22

3-
from typing import Any, List, TypedDict, cast
3+
from typing import TYPE_CHECKING, Any, List, TypedDict, cast
44

55
import narwhals.stable.v1 as nw
66
import orjson
@@ -33,6 +33,9 @@
3333
"subset_frame",
3434
)
3535

36+
if TYPE_CHECKING:
37+
import pandas as pd
38+
3639
########################################################################################
3740
# Narwhals
3841
#
@@ -81,15 +84,20 @@ def as_data_frame(
8184
except TypeError as e:
8285
try:
8386
compatible_data = compatible_to_pandas(data)
84-
return nw.from_native(compatible_data, eager_only=True)
87+
ret: DataFrame[pd.DataFrame] = nw.from_native(
88+
compatible_data, eager_only=True
89+
)
90+
# Cast internal data as `IntoDataFrameT` type.
91+
# A warning has already been given to the user, so this is tolerable.
92+
return cast(DataFrame[IntoDataFrameT], ret)
8593
except TypeError:
8694
# Couldn't convert to pandas, so raise the original error
8795
raise e
8896

8997

9098
def compatible_to_pandas(
91-
data: IntoDataFrameT,
92-
) -> IntoDataFrameT:
99+
data: IntoDataFrame,
100+
) -> pd.DataFrame:
93101
"""
94102
Convert data to pandas, if possible.
95103
@@ -108,6 +116,7 @@ def compatible_to_pandas(
108116
stacklevel=3,
109117
)
110118
return data.to_pandas()
119+
# pyright: ignore[reportReturnType]
111120

112121
raise TypeError(f"Unsupported data type: {type(data)}")
113122

tests/playwright/shiny/components/accordion/test_accordion.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,6 @@ def test_accordion(page: Page, local_app: ShinyAppProc) -> None:
7979
"input.acc(): ('updated_section_a', 'Section C', 'Section D')"
8080
)
8181

82-
# TODO-karan-future; Remove return when test is able to pass. Currently it hangs indefinitely and no notification as to why.
83-
return
84-
8582
toggle_efg_button.click()
8683
acc.expect_panels(
8784
[
@@ -92,7 +89,7 @@ def test_accordion(page: Page, local_app: ShinyAppProc) -> None:
9289
"Section E",
9390
"Section F",
9491
"Section G",
95-
]
92+
],
9693
)
9794
acc.expect_open(
9895
[
@@ -102,7 +99,7 @@ def test_accordion(page: Page, local_app: ShinyAppProc) -> None:
10299
"Section E",
103100
"Section F",
104101
"Section G",
105-
]
102+
],
106103
)
107104
# Should be uncommented once https://github.com/rstudio/bslib/issues/565 is fixed
108105
# output_txt_verbatim.expect_value(

0 commit comments

Comments
 (0)