Skip to content

test: Add tests for client error console and card kitchensink #1262

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Apr 4, 2024
Merged
190 changes: 152 additions & 38 deletions tests/playwright/controls.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,22 +351,54 @@ def expect_label(


class _WidthLocM:
"""
A mixin class representing the `loc`'s width.
This class provides methods to expect the width attribute of an element.
"""

def expect_width(
self: _InputBaseP,
value: AttrValue,
*,
timeout: Timeout = None,
) -> None:
"""
Expect the width attribute of an element to have a specific value.

Parameters
----------
value
The expected value of the width attribute.
timeout
The maximum time to wait for the expectation to be fulfilled.
Defaults to None.
"""
expect_attr(self.loc, "width", value=value, timeout=timeout)


class _WidthContainerM:
"""
A mixin class representing the container's width.
This class provides methods to expect the width attribute of an element's container.
"""

def expect_width(
self: _InputWithContainerP,
value: AttrValue,
*,
timeout: Timeout = None,
) -> None:
"""
Expect the width attribute of an element's container to have a specific value.

Parameters
----------
value
The expected value of the width attribute.
timeout
The maximum time to wait for the expectation to be fulfilled.
Defaults to None.
"""
expect_attr(self.loc_container, "width", value=value, timeout=timeout)


Expand Down Expand Up @@ -2676,7 +2708,7 @@ def close_full_screen(
"""
self._loc_close_button.click(timeout=timeout)

def expect_full_screen(
def expect_full_screen_open(
self: _CardFullScreenLayoutP, open: bool, *, timeout: Timeout = None
) -> None:
"""
Expand All @@ -2693,31 +2725,48 @@ def expect_full_screen(
int(open), timeout=timeout
)

def expect_full_screen_available(
self: _CardFullScreenLayoutP, available: bool, *, timeout: Timeout = None
) -> None:
"""
Expects the card to be available for full screen mode.

Parameters
----------
available
True if the value box is expected to be available for full screen mode, False otherwise.
timeout
The maximum time to wait for the expectation to pass. Defaults to None.
"""
playwright_expect(self._loc_fullscreen).to_have_count(
int(available), timeout=timeout
)


class ValueBox(
_WidthLocM,
_CardFullScreenM,
_InputWithContainer,
):
"""
ValueBox control for shiny.ui.value_box - https://shiny.posit.co/py/api/core/ui.value_box.html
ValueBox control for :func:`~shiny.ui.value_box`
"""

loc: Locator
"""
Locator for the value box's value
`Locator` for the value box's value
"""
loc_showcase: Locator
"""
Locator for the value box showcase
`Locator` for the value box showcase
"""
loc_title: Locator
"""
Locator for the value box title
`Locator` for the value box title
"""
loc_body: Locator
"""
Locator for the value box body
`Locator` for the value box body
"""

def __init__(self, page: Page, id: str) -> None:
Expand Down Expand Up @@ -2835,35 +2884,40 @@ def expect_body(
timeout=timeout,
)

def expect_full_screen_available(
self, available: bool, *, timeout: Timeout = None
) -> None:

class Card(_WidthLocM, _CardFooterM, _CardBodyM, _CardFullScreenM, _InputWithContainer):
"""
Card control for :func:`~shiny.ui.card`
"""

loc: Locator
"""
`Locator` for the card's value
"""
loc_title: Locator
"""
`Locator` for the card title
"""
loc_footer: Locator
"""
`Locator` for the card footer
"""
loc_body: Locator
"""
`Locator` for the card body
"""

def __init__(self, page: Page, id: str) -> None:
"""
Expects the value box to be available for full screen mode.
Initializes a new instance of the Card class.

Parameters
----------
available
True if the value box is expected to be available for full screen mode, False otherwise.
timeout
The maximum time to wait for the expectation to pass. Defaults to None.
page
The Playwright page object.
id
The ID of the card.
"""
playwright_expect(self._loc_fullscreen).to_have_count(
int(available), timeout=timeout
)


class Card(_WidthLocM, _CardFooterM, _CardBodyM, _CardFullScreenM, _InputWithContainer):
# *args: TagChild | TagAttrs | CardItem,
# full_screen: bool = False,
# height: CssUnit | None = None,
# max_height: CssUnit | None = None,
# min_height: CssUnit | None = None,
# fill: bool = True,
# class_: str | None = None,
# wrapper: WrapperCallable | MISSING_TYPE | None = MISSING,
# **kwargs: TagAttrValue
def __init__(self, page: Page, id: str) -> None:
super().__init__(
page,
id=id,
Expand All @@ -2886,14 +2940,25 @@ def __init__(self, page: Page, id: str) -> None:

def expect_header(
self,
text: PatternOrStr,
text: PatternOrStr | None,
*,
timeout: Timeout = None,
) -> None:
playwright_expect(self.loc_title).to_have_text(
text,
timeout=timeout,
)
"""
Expects the card header to have a specific text.

Parameters
----------
text
The expected text pattern or string
Note: None if the header is expected to not exist.
timeout
The maximum time to wait for the expectation to pass. Defaults to None.
"""
if text is None:
playwright_expect(self.loc_title).to_have_count(0, timeout=timeout)
else:
playwright_expect(self.loc_title).to_have_text(text, timeout=timeout)

# def expect_body(
# self,
Expand All @@ -2908,17 +2973,66 @@ def expect_header(
# timeout=timeout,
# )

def expect_footer(
self,
text: PatternOrStr | None,
*,
timeout: Timeout = None,
) -> None:
"""
Expects the card footer to have a specific text.

Parameters
----------
text
The expected text pattern or string
Note: None if the footer is expected to not exist.
timeout
The maximum time to wait for the expectation to pass. Defaults to None.
"""
if text is None:
playwright_expect(self.loc_footer).to_have_count(0, timeout=timeout)
else:
playwright_expect(self.loc_footer).to_have_text(text, timeout=timeout)

def expect_max_height(self, value: StyleValue, *, timeout: Timeout = None) -> None:
"""
Expects the card to have a specific maximum height.

Parameters
----------
value
The expected maximum height value.
timeout
The maximum time to wait for the expectation to pass. Defaults to None.
"""
expect_to_have_style(self.loc_container, "max-height", value, timeout=timeout)

def expect_min_height(self, value: StyleValue, *, timeout: Timeout = None) -> None:
"""
Expects the card to have a specific minimum height.

Parameters
----------
value
The expected minimum height value.
timeout
The maximum time to wait for the expectation to pass. Defaults to None.
"""
expect_to_have_style(self.loc_container, "min-height", value, timeout=timeout)

def expect_height(self, value: StyleValue, *, timeout: Timeout = None) -> None:
expect_to_have_style(self.loc_container, "height", value, timeout=timeout)

"""
Expects the card to have a specific height.

# Experimental below
Parameters
----------
value
The expected height value.
timeout
The maximum time to wait for the expectation to pass. Defaults to None.
"""
expect_to_have_style(self.loc_container, "height", value, timeout=timeout)


class Accordion(
Expand Down
11 changes: 11 additions & 0 deletions tests/playwright/deploys/shiny-client-console-error/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from shiny import reactive, render
from shiny.express import input, ui

ui.input_action_button("same_id", "Action")
ui.input_action_button("same_id", "Action")


@render.text()
@reactive.event(input.same_id)
def counter():
return f"{input.same_id()}"
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
git+https://github.com/posit-dev/py-htmltools.git#egg=htmltools

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"https://api.shinyapps.io": {
"server_url": "https://api.shinyapps.io",
"app_url": "https://testing-apps.shinyapps.io/shiny_client_console_error/",
"app_id": 11634266,
"app_guid": null,
"title": "shiny_client_console_error",
"app_mode": "python-shiny",
"app_store_version": 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from playwright.sync_api import Page, expect
from utils.deploy_utils import create_deploys_app_url_fixture, skip_if_not_chrome

app_url = create_deploys_app_url_fixture("shiny_client_console_error")


@skip_if_not_chrome
def test_shiny_client_console_error(page: Page, app_url: str) -> None:
page.goto(app_url)

assert page.locator("#same_id").count() == 2
shiny_error_message = page.locator("shiny-error-message")

# show the client error message only for local apps
if "127.0.0.1" in app_url:

expect(shiny_error_message).not_to_have_count(0)
expect(shiny_error_message).to_have_attribute(
"message", 'The following ID was repeated:\n- "same_id": 2 inputs'
)
expect(page.get_by_role("button", name="Dismiss all")).to_have_count(1)
expect(
page.get_by_role("button", name="Copy error to clipboard")
).to_have_count(1)

# for deployed apps to shinyapps.io or connect hide the client error message
else:
expect(shiny_error_message).to_have_count(0)
12 changes: 6 additions & 6 deletions tests/playwright/shiny/components/card-input/test_card-input.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,25 @@ def test_card_input(page: Page, app_path: str, sel_card: str, sel_vb: str) -> No
out_vb = OutputCode(page, "out_value_box")

# Open and close card full screen, check input value ------
card.expect_full_screen(False)
card.expect_full_screen_open(False)
out_card.expect_value("False")

card.open_full_screen()
card.expect_full_screen(True)
card.expect_full_screen_open(True)
out_card.expect_value("True")

card.close_full_screen()
card.expect_full_screen(False)
card.expect_full_screen_open(False)
out_card.expect_value("False")

# Open and close value box full screen, check input value ------
vb.expect_full_screen(False)
vb.expect_full_screen_open(False)
out_vb.expect_value("False")

vb.open_full_screen()
vb.expect_full_screen(True)
vb.expect_full_screen_open(True)
out_vb.expect_value("True")

vb.close_full_screen()
vb.expect_full_screen(False)
vb.expect_full_screen_open(False)
out_vb.expect_value("False")
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ def test_valuebox(page: Page, local_app: ShinyAppProc) -> None:
assert get_value_box_bg_color(value_box1) == "rgb(193, 0, 0)"
assert get_value_box_fg_color(value_box1) == "rgb(255, 255, 255)"
value_box1.expect_full_screen_available(True)
value_box1.expect_full_screen(False)
value_box1.expect_full_screen_open(False)
value_box1.open_full_screen()
value_box1.expect_full_screen(True)
value_box1.expect_full_screen_open(True)
value_box1.expect_body(["Inside the fullscreen"])
value_box1.close_full_screen()
value_box1.expect_full_screen(False)
value_box1.expect_full_screen_open(False)

value_box2 = ValueBox(page, "valuebox2")
value_box2.expect_height(None)
Expand Down
Loading