From 2b5c77b225198bb703b58b9f5c49319d572872c1 Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Tue, 1 Oct 2024 10:35:00 -0700 Subject: [PATCH 1/8] Add kitchensink tests for accordion --- shiny/playwright/controller/_accordion.py | 57 +++++++++++++++++-- .../shiny/inputs/accordion_kitchensink/app.py | 50 ++++++++++++++++ .../test_accordion_kitchensink.py | 41 +++++++++++++ 3 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 tests/playwright/shiny/inputs/accordion_kitchensink/app.py create mode 100644 tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py diff --git a/shiny/playwright/controller/_accordion.py b/shiny/playwright/controller/_accordion.py index 890b03bde..039ecdab7 100644 --- a/shiny/playwright/controller/_accordion.py +++ b/shiny/playwright/controller/_accordion.py @@ -98,18 +98,18 @@ def expect_body(self, value: PatternOrStr, *, timeout: Timeout = None) -> None: """ playwright_expect(self.loc_body).to_have_text(value, timeout=timeout) - def expect_icon(self, value: PatternOrStr, *, timeout: Timeout = None) -> None: + def expect_icon(self, value: bool, *, timeout: Timeout = None) -> None: """ - Expects the accordion panel icon to have the specified text. + Expects the accordion panel icon to exist or not. Parameters ---------- value - The expected text pattern or string. + `True` if the icon is expected to exist, `False` otherwise. timeout The maximum time to wait for the icon to appear. Defaults to `None`. """ - playwright_expect(self.loc_icon).to_have_text(value, timeout=timeout) + playwright_expect(self.loc_icon).to_have_count(int(value), timeout=timeout) def expect_open(self, value: bool, *, timeout: Timeout = None) -> None: """ @@ -307,6 +307,55 @@ def set( ) self.accordion_panel(elem_value).set(elem_value in open, timeout=timeout) + def expect_class( + self, + class_name: str, + has_class: bool, + *, + timeout: Timeout = None, + ) -> None: + """ + Expects the accordion to have the specified class. + + Parameters + ---------- + class_name + The class name to expect. + has_class + `True` if the class is expected + timeout + The maximum time to wait for the class to appear. Defaults to `None`. + """ + _expect_class_to_have_value( + self.loc_container, + class_name, + has_class=has_class, + timeout=timeout, + ) + + def expect_multiple( + self, + value: bool, + *, + timeout: Timeout = None, + ) -> None: + """ + Expects the accordion to be multiple or not. + + Parameters + ---------- + value + `True` if the accordion is expected to be multiple, `False` otherwise. + timeout + The maximum time to wait for the expectation to pass. Defaults to `None`. + """ + _expect_class_to_have_value( + self.loc_container, + "autoclose", + has_class=not value, + timeout=timeout, + ) + def accordion_panel( self, data_value: str, diff --git a/tests/playwright/shiny/inputs/accordion_kitchensink/app.py b/tests/playwright/shiny/inputs/accordion_kitchensink/app.py new file mode 100644 index 000000000..b29552deb --- /dev/null +++ b/tests/playwright/shiny/inputs/accordion_kitchensink/app.py @@ -0,0 +1,50 @@ +from faicons import icon_svg + +from shiny import App, ui + +app_ui = ui.page_fluid( + ui.h1("Accordion Kitchensink"), + ui.accordion( + ui.accordion_panel( + "Panel 1", + ui.p("This is the content of Panel 1"), + value="panel1", + ), + ui.accordion_panel( + "Panel 2", + ui.p("This is the content of Panel 2"), + icon=icon_svg("trash-arrow-up"), + value="panel2", + ), + id="accordion_1", + width="600px", + height="300px", + multiple=False, + class_="bg-light", + ), + ui.accordion( + ui.accordion_panel( + "Panel 3", + ui.p("This is the content of Panel 3"), + value="panel3", + ), + ui.accordion_panel( + "Panel 4", + ui.p("This is the content of Panel 4"), + value="panel4", + ), + id="accordion_2", + multiple=True, + ), +) + + +def server( + input, + output, + session, # pyright: ignore[reportUnknownParameterType, reportMissingParameterType] +): + pass + + +app = App(app_ui, server) # pyright: ignore[reportUnknownArgumentType] diff --git a/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py b/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py new file mode 100644 index 000000000..2cc9ef217 --- /dev/null +++ b/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py @@ -0,0 +1,41 @@ +from playwright.sync_api import Page + +from shiny.playwright import controller +from shiny.run import ShinyAppProc + + +def test_accordion_kitchensink(page: Page, local_app: ShinyAppProc) -> None: + page.goto(local_app.url) + + accordion1 = controller.Accordion(page, "accordion_1") + accordion1.expect_width("600px") + accordion1.expect_height("300px") + accordion1.expect_class("bg-light", True) + accordion1.expect_multiple(False) + accordion1_panel1 = accordion1.accordion_panel("panel1") + accordion1_panel1.expect_open(True) + accordion1_panel1.expect_label("Panel 1") + # accordion1_panel1.expect_icon(False) # not sure why this is not working + + accordion1_panel2 = accordion1.accordion_panel("panel2") + accordion1_panel2.expect_open(False) + accordion1_panel2.expect_label("Panel 2") + accordion1_panel2.expect_icon(True) + accordion1_panel2.set(True) + accordion1_panel2.expect_open(True) + accordion1_panel1.expect_open(False) + + accordion2 = controller.Accordion(page, "accordion_2") + accordion2.expect_width(None) + accordion2.expect_height(None) + accordion2.expect_class("bg-light", False) + accordion2.expect_multiple(True) + + accordion2_panel3 = accordion2.accordion_panel("panel3") + accordion2_panel3.expect_open(True) + + accordion2_panel4 = accordion2.accordion_panel("panel4") + accordion2_panel4.expect_open(False) + accordion2_panel4.set(True) + accordion2_panel4.expect_open(True) + accordion2_panel3.expect_open(True) From 42205e83934519d707ca35bf387b2b3d416cdb32 Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Tue, 1 Oct 2024 10:55:21 -0700 Subject: [PATCH 2/8] Update test_accordion.py --- tests/playwright/shiny/components/accordion/test_accordion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/playwright/shiny/components/accordion/test_accordion.py b/tests/playwright/shiny/components/accordion/test_accordion.py index adb038d03..174e18d7a 100644 --- a/tests/playwright/shiny/components/accordion/test_accordion.py +++ b/tests/playwright/shiny/components/accordion/test_accordion.py @@ -66,7 +66,7 @@ def test_accordion(page: Page, local_app: ShinyAppProc) -> None: toggle_updates_button.click() acc_panel_updated_A.expect_label("Updated title") acc_panel_updated_A.expect_body("Updated body") - acc_panel_updated_A.expect_icon("Look! An icon! -->") + acc_panel_updated_A.expect_icon(True) acc.expect_panels(["updated_section_a", "Section B", "Section C", "Section D"]) # workaround - toggle it twice Section A From 153182e916986b429046c7ea791fa644cb7e56f0 Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Tue, 1 Oct 2024 11:06:52 -0700 Subject: [PATCH 3/8] add pyright ignore --- tests/playwright/shiny/inputs/accordion_kitchensink/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/playwright/shiny/inputs/accordion_kitchensink/app.py b/tests/playwright/shiny/inputs/accordion_kitchensink/app.py index b29552deb..a9bf290e0 100644 --- a/tests/playwright/shiny/inputs/accordion_kitchensink/app.py +++ b/tests/playwright/shiny/inputs/accordion_kitchensink/app.py @@ -40,8 +40,8 @@ def server( - input, - output, + input, # pyright: ignore[reportUnknownParameterType, reportMissingParameterType] + output, # pyright: ignore[reportUnknownParameterType, reportMissingParameterType] session, # pyright: ignore[reportUnknownParameterType, reportMissingParameterType] ): pass From 978f8b285fff1e5885f504f1870013ee0e82aead Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 1 Oct 2024 16:40:12 -0400 Subject: [PATCH 4/8] Rename value to exists. Fix unexpected test behavior --- shiny/playwright/controller/_accordion.py | 10 +++++++--- .../test_accordion_kitchensink.py | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/shiny/playwright/controller/_accordion.py b/shiny/playwright/controller/_accordion.py index 039ecdab7..60e0478eb 100644 --- a/shiny/playwright/controller/_accordion.py +++ b/shiny/playwright/controller/_accordion.py @@ -98,18 +98,22 @@ def expect_body(self, value: PatternOrStr, *, timeout: Timeout = None) -> None: """ playwright_expect(self.loc_body).to_have_text(value, timeout=timeout) - def expect_icon(self, value: bool, *, timeout: Timeout = None) -> None: + def expect_icon(self, exists: bool, *, timeout: Timeout = None) -> None: """ Expects the accordion panel icon to exist or not. Parameters ---------- - value + exists `True` if the icon is expected to exist, `False` otherwise. timeout The maximum time to wait for the icon to appear. Defaults to `None`. """ - playwright_expect(self.loc_icon).to_have_count(int(value), timeout=timeout) + icon_child_loc = self.loc_icon.locator("> *") + if exists: + playwright_expect(icon_child_loc).not_to_have_count(0, timeout=timeout) + else: + playwright_expect(icon_child_loc).to_have_count(0, timeout=timeout) def expect_open(self, value: bool, *, timeout: Timeout = None) -> None: """ diff --git a/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py b/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py index 2cc9ef217..5e95c2735 100644 --- a/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py +++ b/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py @@ -15,7 +15,7 @@ def test_accordion_kitchensink(page: Page, local_app: ShinyAppProc) -> None: accordion1_panel1 = accordion1.accordion_panel("panel1") accordion1_panel1.expect_open(True) accordion1_panel1.expect_label("Panel 1") - # accordion1_panel1.expect_icon(False) # not sure why this is not working + accordion1_panel1.expect_icon(False) # not sure why this is not working accordion1_panel2 = accordion1.accordion_panel("panel2") accordion1_panel2.expect_open(False) From c9a77d0190c2e7a7c586392bdcd62e6859b60f55 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 1 Oct 2024 16:46:06 -0400 Subject: [PATCH 5/8] Apply suggestions from code review --- .../shiny/inputs/accordion_kitchensink/app.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tests/playwright/shiny/inputs/accordion_kitchensink/app.py b/tests/playwright/shiny/inputs/accordion_kitchensink/app.py index a9bf290e0..b3305509b 100644 --- a/tests/playwright/shiny/inputs/accordion_kitchensink/app.py +++ b/tests/playwright/shiny/inputs/accordion_kitchensink/app.py @@ -1,6 +1,6 @@ from faicons import icon_svg -from shiny import App, ui +from shiny import App, Inputs, ui app_ui = ui.page_fluid( ui.h1("Accordion Kitchensink"), @@ -39,12 +39,8 @@ ) -def server( - input, # pyright: ignore[reportUnknownParameterType, reportMissingParameterType] - output, # pyright: ignore[reportUnknownParameterType, reportMissingParameterType] - session, # pyright: ignore[reportUnknownParameterType, reportMissingParameterType] -): +def server(input: Inputs): pass -app = App(app_ui, server) # pyright: ignore[reportUnknownArgumentType] +app = App(app_ui, server) From aa8640d7bbe2e51d9220f188e05dc8deb891427f Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Tue, 1 Oct 2024 17:04:47 -0700 Subject: [PATCH 6/8] Add CHANGELOG --- CHANGELOG.md | 4 ++++ shiny/playwright/controller/_accordion.py | 2 +- .../accordion_kitchensink/test_accordion_kitchensink.py | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0850651f1..66a4482c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * `.expect_layout()` for Navset controllers in `shiny.playwright.controllers` is now renamed to `.expect_fluid()` and requires a `bool` value. To keep behavior the same, use `.expect_fluid(True)` (#1668) +* `.expect_icon()` for Accordion controllers in `shiny.playwright.controllers` now requires a `bool` value instead of a `str`. (#1710) + ### New features ### Other changes @@ -27,6 +29,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Small improvements to the default pulse busy indicator to better blend with any background. It's also now slightly smaller by default.(#1707) +* Added `.expect_class()` and `.expect_multiple()` for `Accordion` in `shiny.playwright.controllers` (#1710) + ### Bug fixes * A few fixes for `ui.Chat()`, including: diff --git a/shiny/playwright/controller/_accordion.py b/shiny/playwright/controller/_accordion.py index 60e0478eb..bb661d942 100644 --- a/shiny/playwright/controller/_accordion.py +++ b/shiny/playwright/controller/_accordion.py @@ -314,8 +314,8 @@ def set( def expect_class( self, class_name: str, - has_class: bool, *, + has_class: bool = True, timeout: Timeout = None, ) -> None: """ diff --git a/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py b/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py index 5e95c2735..ff3953462 100644 --- a/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py +++ b/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py @@ -10,7 +10,7 @@ def test_accordion_kitchensink(page: Page, local_app: ShinyAppProc) -> None: accordion1 = controller.Accordion(page, "accordion_1") accordion1.expect_width("600px") accordion1.expect_height("300px") - accordion1.expect_class("bg-light", True) + accordion1.expect_class("bg-light", has_class=True) accordion1.expect_multiple(False) accordion1_panel1 = accordion1.accordion_panel("panel1") accordion1_panel1.expect_open(True) @@ -28,7 +28,7 @@ def test_accordion_kitchensink(page: Page, local_app: ShinyAppProc) -> None: accordion2 = controller.Accordion(page, "accordion_2") accordion2.expect_width(None) accordion2.expect_height(None) - accordion2.expect_class("bg-light", False) + accordion2.expect_class("bg-light", has_class=False) accordion2.expect_multiple(True) accordion2_panel3 = accordion2.accordion_panel("panel3") From 6665cf3448a909446635256118db07ce3f04aa75 Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Tue, 1 Oct 2024 17:07:44 -0700 Subject: [PATCH 7/8] remove comment --- .../inputs/accordion_kitchensink/test_accordion_kitchensink.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py b/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py index ff3953462..76e4e4bd6 100644 --- a/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py +++ b/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py @@ -15,7 +15,7 @@ def test_accordion_kitchensink(page: Page, local_app: ShinyAppProc) -> None: accordion1_panel1 = accordion1.accordion_panel("panel1") accordion1_panel1.expect_open(True) accordion1_panel1.expect_label("Panel 1") - accordion1_panel1.expect_icon(False) # not sure why this is not working + accordion1_panel1.expect_icon(False) accordion1_panel2 = accordion1.accordion_panel("panel2") accordion1_panel2.expect_open(False) From 60424912121eeeffe13f1b720a63ecd97985583d Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Fri, 4 Oct 2024 14:42:02 -0400 Subject: [PATCH 8/8] Remove `expect_class(*, has_class=)` parameter --- shiny/playwright/controller/_accordion.py | 5 +---- .../accordion_kitchensink/test_accordion_kitchensink.py | 3 +-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/shiny/playwright/controller/_accordion.py b/shiny/playwright/controller/_accordion.py index 969b3780a..1e541d479 100644 --- a/shiny/playwright/controller/_accordion.py +++ b/shiny/playwright/controller/_accordion.py @@ -321,7 +321,6 @@ def expect_class( self, class_name: str, *, - has_class: bool = True, timeout: Timeout = None, ) -> None: """ @@ -331,15 +330,13 @@ def expect_class( ---------- class_name The class name to expect. - has_class - `True` if the class is expected timeout The maximum time to wait for the class to appear. Defaults to `None`. """ _expect_class_to_have_value( self.loc_container, class_name, - has_class=has_class, + has_class=True, timeout=timeout, ) diff --git a/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py b/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py index 76e4e4bd6..9cbe5a8f4 100644 --- a/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py +++ b/tests/playwright/shiny/inputs/accordion_kitchensink/test_accordion_kitchensink.py @@ -10,7 +10,7 @@ def test_accordion_kitchensink(page: Page, local_app: ShinyAppProc) -> None: accordion1 = controller.Accordion(page, "accordion_1") accordion1.expect_width("600px") accordion1.expect_height("300px") - accordion1.expect_class("bg-light", has_class=True) + accordion1.expect_class("bg-light") accordion1.expect_multiple(False) accordion1_panel1 = accordion1.accordion_panel("panel1") accordion1_panel1.expect_open(True) @@ -28,7 +28,6 @@ def test_accordion_kitchensink(page: Page, local_app: ShinyAppProc) -> None: accordion2 = controller.Accordion(page, "accordion_2") accordion2.expect_width(None) accordion2.expect_height(None) - accordion2.expect_class("bg-light", has_class=False) accordion2.expect_multiple(True) accordion2_panel3 = accordion2.accordion_panel("panel3")