diff --git a/e2e/conftest.py b/e2e/conftest.py index 12c2f99b2..4c03b863f 100644 --- a/e2e/conftest.py +++ b/e2e/conftest.py @@ -200,6 +200,13 @@ def create_doc_example_fixture(example_name: str, scope: str = "module"): ) +def x_create_doc_example_fixture(example_name: str, scope: str = "module"): + """Used to create app fixtures from apps in py-shiny/shiny/examples""" + return create_app_fixture( + here / "../shiny/experimental/api-examples" / example_name / "app.py", scope + ) + + @pytest.fixture(scope="module") def local_app(request: pytest.FixtureRequest) -> Generator[ShinyAppProc, None, None]: sa = run_shiny_app(PurePath(request.path).parent / "app.py", wait_for_start=False) diff --git a/e2e/controls.py b/e2e/controls.py index 4091bf4bf..f3cbd9d53 100644 --- a/e2e/controls.py +++ b/e2e/controls.py @@ -2336,3 +2336,38 @@ def expect_n_row( n, timeout=timeout, ) + + +class Sidebar( + _WidthLocM, + _InputWithContainer, +): + # *args: TagChild | TagAttrs, + # width: CssUnit = 250, + # position: Literal["left", "right"] = "left", + # open: Literal["desktop", "open", "closed", "always"] = "desktop", + # id: Optional[str] = None, + # title: TagChild | str = None, + # bg: Optional[str] = None, + # fg: Optional[str] = None, + # class_: Optional[str] = None, # TODO-future; Consider using `**kwargs` instead + # max_height_mobile: Optional[str | float] = None, + def __init__(self, page: Page, id: str) -> None: + super().__init__( + page, + id=id, + loc=f"> div#{id}", + loc_container="div.bslib-sidebar-layout", + ) + self.loc_handle = self.loc_container.locator("button.collapse-toggle") + + def expect_title(self, value: PatternOrStr, *, timeout: Timeout = None) -> None: + playwright_expect(self.loc).to_have_text(value, timeout=timeout) + + def expect_handle(self, exists: bool, *, timeout: Timeout = None) -> None: + playwright_expect(self.loc_handle).to_have_count(int(exists), timeout=timeout) + + def expect_open(self, open: bool, *, timeout: Timeout = None) -> None: + playwright_expect(self.loc_handle).to_have_attribute( + "aria-expanded", str(open).lower(), timeout=timeout + ) diff --git a/e2e/experimental/test_sidebar.py b/e2e/experimental/test_sidebar.py new file mode 100644 index 000000000..b2f8f9da0 --- /dev/null +++ b/e2e/experimental/test_sidebar.py @@ -0,0 +1,45 @@ +from conftest import ShinyAppProc, x_create_doc_example_fixture +from controls import OutputTextVerbatim, Sidebar +from playwright.sync_api import Page + +app = x_create_doc_example_fixture("sidebar") + + +def test_autoresize(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + left_sidebar = Sidebar(page, "sidebar_left") + output_txt_left = OutputTextVerbatim(page, "state_left") + left_sidebar.expect_title("Left sidebar content") + output_txt_left.expect_value("input.sidebar_left(): True") + left_sidebar.expect_handle(True) + left_sidebar.expect_open(True) + left_sidebar.loc_handle.click() + left_sidebar.expect_open(False) + output_txt_left.expect_value("input.sidebar_left(): False") + + right_sidebar = Sidebar(page, "sidebar_right") + output_txt_right = OutputTextVerbatim(page, "state_right") + right_sidebar.expect_title("Right sidebar content") + output_txt_right.expect_value("input.sidebar_right(): True") + right_sidebar.expect_handle(True) + right_sidebar.expect_open(True) + right_sidebar.loc_handle.click() + right_sidebar.expect_open(False) + output_txt_right.expect_value("input.sidebar_right(): False") + + closed_sidebar = Sidebar(page, "sidebar_closed") + output_txt_closed = OutputTextVerbatim(page, "state_closed") + output_txt_closed.expect_value("input.sidebar_closed(): False") + closed_sidebar.expect_handle(True) + closed_sidebar.expect_open(False) + closed_sidebar.loc_handle.click() + closed_sidebar.expect_title("Closed sidebar content") + closed_sidebar.expect_open(True) + output_txt_closed.expect_value("input.sidebar_closed(): True") + + always_sidebar = Sidebar(page, "sidebar_always") + output_txt_always = OutputTextVerbatim(page, "state_always") + always_sidebar.expect_title("Always sidebar content") + output_txt_always.expect_value("input.sidebar_always(): False") + always_sidebar.expect_handle(False)