From 19a888da06c65f9561e6f3421dadd7f4d1d6688d Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Tue, 4 Mar 2025 21:27:12 -0800 Subject: [PATCH 01/23] Add tests along with core & express apps --- shiny/playwright/controller/_base.py | 8 +- shiny/playwright/controller/_input_buttons.py | 2 +- .../accordion_panel/app-core.py | 65 ++++++++ .../accordion_panel/app-express.py | 47 ++++++ .../test_accordion_panel_core_express.py | 58 +++++++ .../card/app-core.py | 46 ++++++ .../card/app-express.py | 40 +++++ .../card/test_card_core_express.py | 29 ++++ .../card_footer/app-core.py | 53 ++++++ .../card_footer/app-express.py | 36 +++++ .../test_card_footer_core_express.py | 45 ++++++ .../input_action_button/app-core.py | 58 +++++++ .../input_action_button/app-express.py | 49 ++++++ .../test_input_action_button_core_express.py | 43 +++++ .../input_action_link/app-core.py | 62 +++++++ .../input_action_link/app-express.py | 44 +++++ .../test_input_action_link_core_express.py | 43 +++++ .../input_checkbox/app-core.py | 40 +++++ .../input_checkbox/app-express.py | 29 ++++ .../test_input_checkbox_core_express.py | 36 +++++ .../input_checkbox_group/app-core.py | 39 +++++ .../input_checkbox_group/app-express.py | 33 ++++ .../test_input_checkbox_group_core_express.py | 34 ++++ .../input_dark_mode/app-core.py | 41 +++++ .../input_dark_mode/app-express.py | 29 ++++ .../test_input_dark_mode_core_express.py | 17 ++ .../input_date/app-core.py | 121 ++++++++++++++ .../input_date/app-express.py | 94 +++++++++++ .../test_input_date_core_express.py | 77 +++++++++ .../input_date_range/app-core.py | 75 +++++++++ .../input_date_range/app-express.py | 65 ++++++++ .../test_input_date_range_core_express.py | 48 ++++++ .../input_file/app-core.py | 79 +++++++++ .../input_file/app-express.py | 67 ++++++++ .../test_input_file_core_express.py | 55 +++++++ .../input_numeric/app-core.py | 62 +++++++ .../input_numeric/app-express.py | 44 +++++ .../test_input_numeric_core_express.py | 56 +++++++ .../input_password/app-core.py | 46 ++++++ .../input_password/app-express.py | 33 ++++ .../test_input_password_core_express.py | 31 ++++ .../input_radio_buttons/app-core.py | 40 +++++ .../input_radio_buttons/app-express.py | 34 ++++ .../test_input_radio_buttons_core_express.py | 33 ++++ .../input_select/app-core.py | 112 +++++++++++++ .../input_select/app-express.py | 99 ++++++++++++ .../test_input_select_core_express.py | 71 ++++++++ .../input_slider/app-core.py | 151 ++++++++++++++++++ .../input_slider/app-express.py | 121 ++++++++++++++ .../test_input_slider_core_express.py | 101 ++++++++++++ .../input_switch/app-core.py | 35 ++++ .../input_switch/app-express.py | 24 +++ .../test_input_switch_core_express.py | 35 ++++ .../input_task_button/app-core.py | 50 ++++++ .../input_task_button/app-express.py | 43 +++++ .../test_input_task_button_core_express.py | 34 ++++ .../input_text/app-core.py | 34 ++++ .../input_text/app-express.py | 28 ++++ .../test_input_text_core_express.py | 31 ++++ .../input_text_area/app-core.py | 39 +++++ .../input_text_area/app-express.py | 35 ++++ .../test_input_text_area_core_express.py | 38 +++++ 62 files changed, 3164 insertions(+), 3 deletions(-) create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/test_accordion_panel_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/card/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/card/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/card/test_card_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/test_card_footer_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/test_input_action_button_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/test_input_action_link_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/test_input_checkbox_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/test_input_checkbox_group_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/test_input_dark_mode_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_date/test_input_date_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/test_input_date_range_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_file/test_input_file_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/test_input_numeric_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_password/test_input_password_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/test_input_radio_buttons_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_select/test_input_select_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/test_input_switch_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/test_input_task_button_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_text/test_input_text_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/test_input_text_area_core_express.py diff --git a/shiny/playwright/controller/_base.py b/shiny/playwright/controller/_base.py index bd4433ab7..acde32d97 100644 --- a/shiny/playwright/controller/_base.py +++ b/shiny/playwright/controller/_base.py @@ -123,8 +123,12 @@ def set_text( def _expect_multiple(loc: Locator, multiple: bool, timeout: Timeout = None) -> None: - value = "True" if multiple else None - _expect_style_to_have_value(loc, "multiple", value, timeout=timeout) + _expect_attribute_to_have_value( + loc, + "multiple", + value="multiple" if multiple else None, + timeout=timeout, + ) ###################################################### diff --git a/shiny/playwright/controller/_input_buttons.py b/shiny/playwright/controller/_input_buttons.py index 37433a80a..287053185 100644 --- a/shiny/playwright/controller/_input_buttons.py +++ b/shiny/playwright/controller/_input_buttons.py @@ -101,7 +101,7 @@ def click(self, *, timeout: Timeout = None): timeout The maximum time to wait for the input dark mode to be clicked. Defaults to `None`. """ - self.loc.click(timeout=timeout) + self.loc.locator("button").click(timeout=timeout) return self def expect_mode(self, value: str, *, timeout: Timeout = None): diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-core.py new file mode 100644 index 000000000..d59c64751 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-core.py @@ -0,0 +1,65 @@ +from shiny import App, reactive, render, ui + +# Define the UI +app_ui = ui.page_fillable( + # Add Font Awesome CSS in the head section + ui.tags.head( + ui.tags.link( + rel="stylesheet", + href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css", + ) + ), + # Card containing accordion + ui.card( + ui.accordion( + # Basic Panel + ui.accordion_panel( + "Basic Panel", + ui.markdown("This is a basic panel with just a title parameter"), + ), + # Panel with title and value + ui.accordion_panel( + "Panel with Value", + ui.markdown("This panel has both a title and a value parameter"), + value="panel2", + ), + # Panel with title, value, and icon + ui.accordion_panel( + "Panel with Icon", + ui.markdown("This panel includes an icon parameter using Font Awesome"), + value="panel3", + icon=ui.tags.i( + class_="fa-solid fa-shield-halved", style="font-size: 1rem;" + ), + ), + # Panel with title, value, icon, and custom attributes + ui.accordion_panel( + "Panel with Custom Attributes", + ui.markdown( + "This panel demonstrates custom attributes (class and style)" + ), + value="panel4", + icon=ui.tags.i(class_="fa-solid fa-star", style="font-size: 1rem;"), + class_="custom-panel", + style="background-color: #f8f9fa;", + ), + id="acc", + open=True, + multiple=True, + ), + ), + # Output for selected panel + ui.output_text("selected_panel"), +) + + +# Define the server +def server(input, output, session): + @output + @render.text + def selected_panel(): + return f"Currently selected panel: {input.acc()}" + + +# Create the app +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-express.py new file mode 100644 index 000000000..1002c599f --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-express.py @@ -0,0 +1,47 @@ +from shiny import reactive +from shiny.express import input, ui, render + +# Add Font Awesome CSS in the head section first +ui.head_content( + ui.HTML( + '' + ) +) + +ui.page_opts(fillable=True) + +with ui.card(): + with ui.accordion(id="acc", open=True, multiple=True): + # Panel with just title + with ui.accordion_panel("Basic Panel"): + ui.markdown("This is a basic panel with just a title parameter") + + # Panel with title and value + with ui.accordion_panel("Panel with Value", value="panel2"): + ui.markdown("This panel has both a title and a value parameter") + + # Panel with title, value, and icon + with ui.accordion_panel( + "Panel with Icon", + value="panel3", + icon=ui.tags.i( + class_="fa-solid fa-shield-halved", style="font-size: 1rem;" + ), + ): + ui.markdown("This panel includes an icon parameter using Font Awesome") + + # Panel with title, value, icon, and custom attributes + with ui.accordion_panel( + "Panel with Custom Attributes", + value="panel4", + icon=ui.tags.i(class_="fa-solid fa-star", style="font-size: 1rem;"), + class_="custom-panel", + style="background-color: #f8f9fa;", + ): + ui.markdown("This panel demonstrates custom attributes (class and style)") + + +# Show which panel is currently selected +@render.text +def selected_panel(): + return f"Currently selected panel: {input.acc()}" diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/test_accordion_panel_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/test_accordion_panel_core_express.py new file mode 100644 index 000000000..b9dad3534 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/test_accordion_panel_core_express.py @@ -0,0 +1,58 @@ +from playwright.sync_api import Page + +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + +def test_accordion_demo(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Test accordion with ID "acc" + accordion = controller.Accordion(page, "acc") + + # Test that multiple panels can be open + accordion.expect_multiple(True) + + # Test that accordion is initially open + panel1 = accordion.accordion_panel("Basic Panel") + panel2 = accordion.accordion_panel("panel2") + panel3 = accordion.accordion_panel("panel3") + panel4 = accordion.accordion_panel("panel4") + + # Test initial state + panel1.expect_open(True) + panel2.expect_open(True) + panel3.expect_open(True) + panel4.expect_open(True) + + # Test panel labels + panel1.expect_label("Basic Panel") + panel2.expect_label("Panel with Value") + panel3.expect_label("Panel with Icon") + panel4.expect_label("Panel with Custom Attributes") + + # Test panel content + panel1.expect_body("This is a basic panel with just a title parameter") + panel2.expect_body("This panel has both a title and a value parameter") + panel3.expect_body("This panel includes an icon parameter using Font Awesome") + panel4.expect_body("This panel demonstrates custom attributes (class and style)") + + # Test icons (presence/absence) + panel1.expect_icon(False) # First panel has no icon + panel2.expect_icon(False) # Second panel has no icon + panel3.expect_icon(True) # Third panel has an icon + panel4.expect_icon(True) # Fourth panel has an icon + + # Test closing and opening panels + panel1.set(False) + panel1.expect_open(False) + panel1.set(True) + panel1.expect_open(True) + + # Test output text that shows selected panel + selected_text = controller.OutputText(page, "selected_panel") + selected_text.expect_value( + "Currently selected panel: ('Basic Panel', 'panel2', 'panel3', 'panel4')" + ) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-core.py new file mode 100644 index 000000000..9bc7d15e9 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-core.py @@ -0,0 +1,46 @@ +from shiny import App, reactive, render, ui + +# Define the UI +app_ui = ui.page_fillable( + # Card with all possible parameters + ui.card( + ui.card_header("Card Demo", "This demonstrates all card parameters"), + ui.markdown( + """ + This is the main content of the card. + The card has various parameters set including: + + * full_screen=True - allows expanding to full screen + * height='300px' - sets fixed height + * fill=True - allows card to grow/shrink + * class_='my-4' - adds custom CSS classes + """ + ), + ui.card_footer("Card Footer", class_="text-muted"), + id="demo_card", + full_screen=True, # Allow card to be expanded to full screen + height="300px", # Set card height + fill=True, # Allow card to grow/shrink to fit container + class_="my-4", # Add custom CSS classes + ), + # Another card showing dynamic content + ui.card( + ui.card_header("Dynamic Content Demo"), + ui.output_text("dynamic_content"), + id="dynamic_card", + full_screen=True, + height="200px", + class_="mt-4", + ), +) + + +# Define the server +def server(input, output, session): + @render.text + def dynamic_content(): + return "This card shows how to include dynamic content using render functions" + + +# Create the app +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-express.py new file mode 100644 index 000000000..51fdfcb22 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-express.py @@ -0,0 +1,40 @@ +from shiny import reactive +from shiny.express import input, ui, render + +# Set page options +ui.page_opts(fillable=True) + +# Card with all possible parameters +with ui.card( + id="demo_card", + full_screen=True, # Allow card to be expanded to full screen + height="300px", # Set card height + fill=True, # Allow card to grow/shrink to fit container + class_="my-4", # Add custom CSS classes +): + # Card header + ui.card_header("Card Demo", "This demonstrates all card parameters") + + # Card body content + ui.markdown( + """ + This is the main content of the card. + The card has various parameters set including: + + * full_screen=True - allows expanding to full screen + * height='300px' - sets fixed height + * fill=True - allows card to grow/shrink + * class_='my-4' - adds custom CSS classes + """ + ) + + # Card footer + ui.card_footer("Card Footer", class_="text-muted") + +# Another card showing dynamic content +with ui.card(id="dynamic_card", full_screen=True, height="200px", class_="mt-4"): + ui.card_header("Dynamic Content Demo") + + @render.text + def dynamic_content(): + return "This card shows how to include dynamic content using render functions" diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card/test_card_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/card/test_card_core_express.py new file mode 100644 index 000000000..fd03d85cf --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/card/test_card_core_express.py @@ -0,0 +1,29 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.run import ShinyAppProc +from shiny.pytest import create_app_fixture + + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_cards(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + # Test demo_card + demo_card = controller.Card(page, "demo_card") + demo_card.expect_header("Card DemoThis demonstrates all card parameters") + demo_card.expect_height("300px") + demo_card.expect_footer("Card Footer") + demo_card.expect_full_screen_available(True) + + # Test dynamic_card + dynamic_card = controller.Card(page, "dynamic_card") + dynamic_card.expect_header("Dynamic Content Demo") + dynamic_card.expect_height("200px") + dynamic_card.expect_full_screen_available(True) + + # Test dynamic content in dynamic_card + dynamic_content = controller.OutputText(page, "dynamic_content") + dynamic_content.expect_value( + "This card shows how to include dynamic content using render functions" + ) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-core.py new file mode 100644 index 000000000..839769862 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-core.py @@ -0,0 +1,53 @@ +from shiny import App, render, reactive, ui + +app_ui = ui.page_fillable( + # First card with basic footer + ui.card( + ui.card_header("Basic Card with Header"), + "This is a basic card with header and footer", + ui.card_footer("Footer content", class_="bg-light"), + full_screen=True, + height="300px", + id="card1", + ), + # Second card with complex footer + ui.card( + ui.card_header("Card with Complex Footer"), + "This card shows different types of content in footer", + ui.card_footer( + ui.HTML("Bold text"), + ui.tags.span(" | ", style="margin: 0 10px;"), + ui.tags.em("Emphasized text"), + ui.tags.span(" | ", style="margin: 0 10px;"), + ui.tags.span("Regular text", style="color: green;"), + ), + full_screen=True, + height="600px", + id="card2", + ), + # Third card with interactive footer + ui.card( + ui.card_header("Card with Interactive Footer"), + "This card has interactive elements in its footer", + ui.card_footer( + ui.input_action_button("btn", "Click Me", class_="btn-primary"), + ui.output_text("click_count"), + class_="d-flex justify-content-between align-items-center", + ), + full_screen=True, + height="400px", + id="card3", + ), +) + + +def server(input, output, session): + @output + @render.text + def click_count(): + if not input.btn(): + return "No clicks yet" + return f"Clicked {input.btn()} times" + + +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-express.py new file mode 100644 index 000000000..752eec5cf --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-express.py @@ -0,0 +1,36 @@ +from shiny.express import input, ui, render + +# Set page options including title +ui.page_opts(title="Card Footer Demo", fillable=True) + +# Create a card with footer to demonstrate basic parameters +with ui.card(full_screen=True, height="300px", id="card1"): + ui.card_header("Basic Card with Header") + "This is a basic card with header and footer" + ui.card_footer("Footer content", class_="bg-light") + +# Create another card to show different content types in footer +with ui.card(full_screen=True, height="600px", id="card2"): + ui.card_header("Card with Complex Footer") + "This card shows different types of content in footer" + + with ui.card_footer(): + ui.HTML("Bold text") + ui.tags.span(" | ", style="margin: 0 10px;") + ui.tags.em("Emphasized text") + ui.tags.span(" | ", style="margin: 0 10px;") + ui.tags.span("Regular text", style="color: green;") + +# Add a third card with interactive elements in footer +with ui.card(full_screen=True, height="400px", id="card3"): + ui.card_header("Card with Interactive Footer") + "This card has interactive elements in its footer" + + with ui.card_footer(class_="d-flex justify-content-between align-items-center"): + ui.input_action_button("btn", "Click Me", class_="btn-primary") + + @render.text + def click_count(): + if not input.btn(): + return "No clicks yet" + return f"Clicked {input.btn()} times" diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/test_card_footer_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/test_card_footer_core_express.py new file mode 100644 index 000000000..950705545 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/test_card_footer_core_express.py @@ -0,0 +1,45 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.run import ShinyAppProc +from shiny.pytest import create_app_fixture + +app = create_app_fixture(["app-core.py", "app-express.py"]) + +def test_cards_with_footer(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Test card1 + card1 = controller.Card(page, "card1") + card1.expect_header("Basic Card with Header") + card1.expect_height("300px") + card1.expect_footer("Footer content") + card1.expect_full_screen_available(True) + + # Test card2 + card2 = controller.Card(page, "card2") + card2.expect_header("Card with Complex Footer") + card2.expect_height("600px") + card2.expect_footer("Bold text | Emphasized text | Regular text") + card2.expect_full_screen_available(True) + + # Test card3 + card3 = controller.Card(page, "card3") + card3.expect_header("Card with Interactive Footer") + card3.expect_height("400px") + card3.expect_full_screen_available(True) + + # Test the button and its interaction + btn = controller.InputActionButton(page, "btn") + btn.expect_label("Click Me") + + # Test initial state + output_text = controller.OutputText(page, "click_count") + output_text.expect_value("No clicks yet") + + # Test after clicking + btn.click() + output_text.expect_value("Clicked 1 times") + + # Test multiple clicks + btn.click() + output_text.expect_value("Clicked 2 times") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-core.py new file mode 100644 index 000000000..a65d3b3cc --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-core.py @@ -0,0 +1,58 @@ +from shiny import App, reactive, render, ui + +# Create the UI +app_ui = ui.page_fluid( + # Add Font Awesome CSS in the head + ui.tags.head( + ui.tags.link( + rel="stylesheet", + href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css", + ) + ), + # Main layout + ui.layout_column_wrap( + ui.card( + ui.card_header("Action Button Examples"), + # Basic button with width parameter + ui.input_action_button(id="btn1", label="Basic Button", width="200px"), + ui.br(), # Add spacing + # Button with icon and disabled state + ui.input_action_button( + id="btn2", + label="Disabled Button with Icon", + icon=ui.tags.i(class_="fa-solid fa-shield-halved"), + disabled=True, + ), + ui.br(), # Add spacing + # Button with custom class and style attributes + ui.input_action_button( + id="btn3", + label="Styled Button", + class_="btn-success", + style="margin-top: 20px;", + ), + ), + # Card for displaying results + ui.card( + ui.card_header("Click Counts"), + ui.output_text("click_counts"), + ), + width="100%", + ), +) + + +# Define the server +def server(input, output, session): + @output + @render.text + def click_counts(): + return ( + f"Button 1 clicks: {input.btn1() or 0}\n" + f"Button 2 clicks: {input.btn2() or 0}\n" + f"Button 3 clicks: {input.btn3() or 0}" + ) + + +# Create and return the app +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-express.py new file mode 100644 index 000000000..7136b540d --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-express.py @@ -0,0 +1,49 @@ +from shiny import reactive +from shiny.express import input, ui, render + +# Add Font Awesome CSS for icons - this needs to be before any UI elements +ui.head_content( + ui.HTML( + '' + ) +) + +# Create a layout with some spacing +with ui.layout_column_wrap(width="100%"): + with ui.card(): + ui.card_header("Action Button Examples") + + # Basic button with width parameter + ui.input_action_button(id="btn1", label="Basic Button", width="200px") + + ui.br() # Add some spacing + + # Button with icon and disabled state + ui.input_action_button( + id="btn2", + label="Disabled Button with Icon", + icon=ui.tags.i(class_="fa-solid fa-shield-halved"), + disabled=True, + ) + + ui.br() # Add some spacing + + # Button with custom class and style attributes + ui.input_action_button( + id="btn3", + label="Styled Button", + class_="btn-success", + style="margin-top: 20px;", + ) + + # Create another card for displaying results + with ui.card(): + ui.card_header("Click Counts") + + @render.text + def click_counts(): + return ( + f"Button 1 clicks: {input.btn1() or 0}\n" + f"Button 2 clicks: {input.btn2() or 0}\n" + f"Button 3 clicks: {input.btn3() or 0}" + ) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/test_input_action_button_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/test_input_action_button_core_express.py new file mode 100644 index 000000000..daea1ba7f --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/test_input_action_button_core_express.py @@ -0,0 +1,43 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_action_buttons(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Test basic button (btn1) + btn1 = controller.InputActionButton(page, "btn1") + btn1.expect_label("Basic Button") + btn1.expect_width("200px") + + # Test button with icon (btn2) + btn2 = controller.InputActionButton(page, "btn2") + btn2.expect_label("Disabled Button with Icon") + + # Test styled button (btn3) + btn3 = controller.InputActionButton(page, "btn3") + btn3.expect_label("Styled Button") + + # Test initial click counts + click_counts = controller.OutputText(page, "click_counts") + click_counts.expect_value( + "Button 1 clicks: 0\nButton 2 clicks: 0\nButton 3 clicks: 0" + ) + + # Test clicking btn1 and verify count updates + btn1.click() + click_counts.expect_value( + "Button 1 clicks: 1\nButton 2 clicks: 0\nButton 3 clicks: 0" + ) + + # Test clicking btn3 and verify count updates + btn3.click() + click_counts.expect_value( + "Button 1 clicks: 1\nButton 2 clicks: 0\nButton 3 clicks: 1" + ) + + # btn2 is disabled, so we don't test clicking it diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-core.py new file mode 100644 index 000000000..e27f33c27 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-core.py @@ -0,0 +1,62 @@ +from shiny import App, reactive, render, ui + +# Define the UI +app_ui = ui.page_fillable( + # Add Font Awesome CSS in the head section + ui.tags.head( + ui.tags.link( + rel="stylesheet", + href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css", + ) + ), + # Create layout with columns + ui.layout_column_wrap( + # First card + ui.card( + ui.card_header("Action Link Demo"), + # Create an action link with an icon + ui.input_action_link( + id="demo_link", + label="Click Me!", + icon=ui.tags.i(class_="fa-solid fa-shield-halved"), + ), + ui.output_text("link_clicks"), + full_screen=True, + height="300px", + id="card1", + ), + # Second card + ui.card( + ui.card_header("Click History"), + ui.output_text("click_history"), + full_screen=True, + height="300px", + id="card2", + ), + width=1 / 2, + ), +) + + +# Define the server +def server(input, output, session): + @output + @render.text + def link_clicks(): + count = input.demo_link() or 0 + return f"The link has been clicked {count} times" + + @output + @render.text + def click_history(): + count = input.demo_link() or 0 + if count == 0: + return "No clicks yet!" + elif count == 1: + return "First click recorded!" + else: + return f"You've clicked {count} times. Keep going!" + + +# Create and return the app +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-express.py new file mode 100644 index 000000000..a3e293bfb --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-express.py @@ -0,0 +1,44 @@ +from shiny import reactive +from shiny.express import input, render, ui + +# Add Font Awesome CSS in the head section +ui.head_content( + ui.HTML( + '' + ) +) + +# Set page title +ui.page_opts(fillable=True) + +with ui.layout_column_wrap(width=1 / 2): + # Create a card to hold the action link + with ui.card(full_screen=True, height="300px", id="card1"): + ui.card_header("Action Link Demo") + + # Create an action link with an icon + ui.input_action_link( + id="demo_link", + label="Click Me!", + icon=ui.tags.i(class_="fa-solid fa-shield-halved"), + ) + + # Display the click count + @render.text + def link_clicks(): + count = input.demo_link() or 0 + return f"The link has been clicked {count} times" + + # Create another card to show reactive behavior + with ui.card(full_screen=True, height="300px", id="card2"): + ui.card_header("Click History") + + @render.text + def click_history(): + count = input.demo_link() or 0 + if count == 0: + return "No clicks yet!" + elif count == 1: + return "First click recorded!" + else: + return f"You've clicked {count} times. Keep going!" diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/test_input_action_link_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/test_input_action_link_core_express.py new file mode 100644 index 000000000..e5742a243 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/test_input_action_link_core_express.py @@ -0,0 +1,43 @@ +from playwright.sync_api import Page, expect +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_action_link_demo(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Test first card + card1 = controller.Card(page, "card1") + card1.expect_header("Action Link Demo") + card1.expect_height("300px") + card1.expect_full_screen_available(True) + + # Test second card + card2 = controller.Card(page, "card2") + card2.expect_header("Click History") + card2.expect_height("300px") + card2.expect_full_screen_available(True) + + # Test action link + demo_link = controller.InputActionLink(page, "demo_link") + demo_link.expect_label("Click Me!") + + # Test initial states of outputs + output_text = controller.OutputText(page, "link_clicks") + output_text.expect_value("The link has been clicked 0 times") + + history_text = controller.OutputText(page, "click_history") + history_text.expect_value("No clicks yet!") + + # Test interaction - first click + demo_link.click() + output_text.expect_value("The link has been clicked 1 times") + history_text.expect_value("First click recorded!") + + # Test interaction - second click + demo_link.click() + output_text.expect_value("The link has been clicked 2 times") + history_text.expect_value("You've clicked 2 times. Keep going!") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-core.py new file mode 100644 index 000000000..46df2b9ea --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-core.py @@ -0,0 +1,40 @@ +from shiny import App, reactive, render, ui + +# Define the UI +app_ui = ui.page_fluid( + # Card containing all elements + ui.card( + ui.card_header("Checkbox Demo"), + # Basic checkbox with default value (False) + ui.input_checkbox(id="basic", label="Basic checkbox"), + # Checkbox with initial value set to True + ui.input_checkbox( + id="preset_value", label="Checkbox with preset value", value=True + ), + # Checkbox with custom width + ui.input_checkbox( + id="custom_width", + label="Checkbox with custom width (300px)", + value=False, + width="300px", + ), + # Output UI for checkbox values + ui.output_ui("checkbox_values"), + ) +) + + +# Define the server +def server(input, output, session): + @output + @render.ui + def checkbox_values(): + return ui.tags.div( + ui.tags.p(f"Basic checkbox value: {input.basic()}"), + ui.tags.p(f"Preset value checkbox: {input.preset_value()}"), + ui.tags.p(f"Custom width checkbox: {input.custom_width()}"), + ) + + +# Create the app +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-express.py new file mode 100644 index 000000000..c3ebbfd10 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-express.py @@ -0,0 +1,29 @@ +from shiny import reactive +from shiny.express import input, ui, render + + +with ui.card(): + ui.card_header("Checkbox Demo") + + # Basic checkbox with default value (False) + ui.input_checkbox(id="basic", label="Basic checkbox") + + # Checkbox with initial value set to True + ui.input_checkbox(id="preset_value", label="Checkbox with preset value", value=True) + + # Checkbox with custom width + ui.input_checkbox( + id="custom_width", + label="Checkbox with custom width (300px)", + value=False, + width="300px", + ) + + # Display the values of all checkboxes + @render.ui + def checkbox_values(): + return ui.tags.div( + ui.tags.p(f"Basic checkbox value: {input.basic()}"), + ui.tags.p(f"Preset value checkbox: {input.preset_value()}"), + ui.tags.p(f"Custom width checkbox: {input.custom_width()}"), + ) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/test_input_checkbox_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/test_input_checkbox_core_express.py new file mode 100644 index 000000000..c04f988b1 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/test_input_checkbox_core_express.py @@ -0,0 +1,36 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_checkbox_demo(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Test basic checkbox + basic_checkbox = controller.InputCheckbox(page, "basic") + basic_checkbox.expect_label("Basic checkbox") + basic_checkbox.expect_checked(False) # Default value should be False + + # Test checkbox with preset value + preset_checkbox = controller.InputCheckbox(page, "preset_value") + preset_checkbox.expect_label("Checkbox with preset value") + preset_checkbox.expect_checked(True) # Should be initially True + + # Test checkbox with custom width + custom_width_checkbox = controller.InputCheckbox(page, "custom_width") + custom_width_checkbox.expect_label("Checkbox with custom width (300px)") + custom_width_checkbox.expect_checked(False) # Should be initially False + custom_width_checkbox.expect_width("300px") + + # Test interactivity by changing values + basic_checkbox.set(True) + basic_checkbox.expect_checked(True) + + preset_checkbox.set(False) + preset_checkbox.expect_checked(False) + + custom_width_checkbox.set(True) + custom_width_checkbox.expect_checked(True) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-core.py new file mode 100644 index 000000000..f572a55ab --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-core.py @@ -0,0 +1,39 @@ +from shiny import App, reactive, render, ui + +# Create sample choices with HTML formatting for demonstration +choices = { + "red": ui.span("Red", style="color: #FF0000;"), + "green": ui.span("Green", style="color: #00AA00;"), + "blue": ui.span("Blue", style="color: #0000AA;"), +} + +app_ui = ui.page_fluid( + ui.card( + ui.card_header("Color Selection Demo"), + # Using input_checkbox_group with all its parameters + ui.input_checkbox_group( + id="colors", # Required: unique identifier + label="Choose colors", # Required: label text + choices=choices, # Required: choices as dict with HTML formatting + selected=["red", "blue"], # Optional: pre-selected values + inline=True, # Optional: display choices inline + width="300px", # Optional: CSS width + ), + # Add some spacing + ui.hr(), + # Output for selected values + ui.output_text("selected_colors"), + ) +) + + +def server(input, output, session): + @output + @render.text + def selected_colors(): + if input.colors(): + return f"You selected: {', '.join(input.colors())}" + return "No colors selected" + + +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-express.py new file mode 100644 index 000000000..3470d0dbb --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-express.py @@ -0,0 +1,33 @@ +from shiny import reactive +from shiny.express import input, render, ui + + +# Create sample choices with HTML formatting for demonstration +choices = { + "red": ui.span("Red", style="color: #FF0000;"), + "green": ui.span("Green", style="color: #00AA00;"), + "blue": ui.span("Blue", style="color: #0000AA;"), +} + +with ui.card(): + ui.card_header("Color Selection Demo") + + # Using input_checkbox_group with all its parameters + ui.input_checkbox_group( + id="colors", # Required: unique identifier + label="Choose colors", # Required: label text + choices=choices, # Required: choices as dict with HTML formatting + selected=["red", "blue"], # Optional: pre-selected values + inline=True, # Optional: display choices inline + width="300px", # Optional: CSS width + ) + + # Add some spacing + ui.hr() + + # Simple output to show selected values + @render.text + def selected_colors(): + if input.colors(): + return f"You selected: {', '.join(input.colors())}" + return "No colors selected" diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/test_input_checkbox_group_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/test_input_checkbox_group_core_express.py new file mode 100644 index 000000000..fe9392e86 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/test_input_checkbox_group_core_express.py @@ -0,0 +1,34 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_checkbox_group_demo(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Get the checkbox group controller + colors = controller.InputCheckboxGroup(page, "colors") + selected_output = controller.OutputText(page, "selected_colors") + + # Test initial state + colors.expect_label("Choose colors") + colors.expect_choices(["red", "green", "blue"]) + colors.expect_selected(["red", "blue"]) # Check pre-selected values + colors.expect_inline(True) + colors.expect_width("300px") + selected_output.expect_value("You selected: red, blue") + + # Test selecting different combinations + colors.set(["green"]) + selected_output.expect_value("You selected: green") + + # Test selecting multiple values + colors.set(["red", "green", "blue"]) + selected_output.expect_value("You selected: red, green, blue") + + # Test deselecting all values + colors.set([]) + selected_output.expect_value("No colors selected") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-core.py new file mode 100644 index 000000000..1c3bd5707 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-core.py @@ -0,0 +1,41 @@ +from shiny import App, reactive, render, ui + +# Define the UI +app_ui = ui.page_fillable( + # Add Font Awesome CSS in head + ui.tags.head( + ui.tags.link( + rel="stylesheet", + href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css", + ) + ), + # Create layout with sidebar + ui.layout_sidebar( + # Sidebar contents + ui.sidebar( + ui.input_dark_mode(id="mode", mode="light"), + ), + # Main panel contents + ui.card( + ui.card_header("Dark Mode Example"), + ui.output_text("current_mode"), + ui.p("This is a demonstration of dark mode functionality."), + ui.div( + ui.tags.i(class_="fa-solid fa-moon", style="font-size: 2rem;"), + ui.span(" Dark Mode Toggle Example", class_="ms-2"), + class_="mt-3", + ), + ), + ), +) + + +# Define the server +def server(input, output, session): + @render.text + def current_mode(): + return f"Current mode: {input.mode()}" + + +# Create the app +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-express.py new file mode 100644 index 000000000..a9fdd2006 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-express.py @@ -0,0 +1,29 @@ +from shiny import reactive +from shiny.express import input, ui, render + +# Add Font Awesome CSS +ui.head_content( + ui.HTML( + '' + ) +) + +# Set page options +ui.page_opts(fillable=True) + +with ui.layout_sidebar(): + with ui.sidebar(): + ui.input_dark_mode(id="mode", mode="light") + + with ui.card(): + ui.card_header("Dark Mode Example") + + @render.text + def current_mode(): + return f"Current mode: {input.mode()}" + + ui.p("This is a demonstration of dark mode functionality.") + + with ui.div(class_="mt-3"): + ui.tags.i(class_="fa-solid fa-moon", style="font-size: 2rem;") + ui.span(" Dark Mode Toggle Example", class_="ms-2") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/test_input_dark_mode_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/test_input_dark_mode_core_express.py new file mode 100644 index 000000000..b1449a707 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/test_input_dark_mode_core_express.py @@ -0,0 +1,17 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_dark_mode_demo(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Test dark mode input + dark_mode = controller.InputDarkMode(page, "mode") + dark_mode.expect_mode("light") # Default mode is light + dark_mode.click() # Toggle dark mode + dark_mode.expect_mode("dark") + dark_mode.expect_page_mode("dark") # Check if page mode is updated diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-core.py new file mode 100644 index 000000000..992cc3dd4 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-core.py @@ -0,0 +1,121 @@ +from datetime import date +from shiny import App, reactive, render, ui + +app_ui = ui.page_fluid( + ui.layout_column_wrap( + ui.div( + ui.input_date("date1", "Default date input:", value="2024-01-01"), + ui.output_text("selected_date1"), + ), + ui.div( + ui.input_date( + "date2", + "Date input with min/max:", + value=date(2024, 1, 1), + min="2024-01-01", + max="2024-12-31", + ), + ui.output_text("selected_date2"), + ), + ui.div( + ui.input_date( + "date3", + "Custom format (mm/dd/yy):", + value="2024-01-01", + format="mm/dd/yy", + ), + ui.output_text("selected_date3"), + ), + ui.div( + ui.input_date( + "date4", "Start in decade view:", value="2024-01-01", startview="decade" + ), + ui.output_text("selected_date4"), + ), + ui.div( + ui.input_date( + "date5", "Week starts on Monday:", value="2024-01-01", weekstart=1 + ), + ui.output_text("selected_date5"), + ), + ui.div( + ui.input_date( + "date6", "German language:", value="2024-01-01", language="de" + ), + ui.output_text("selected_date6"), + ), + ui.div( + ui.input_date("date7", "Custom width:", value="2024-01-01", width="400px"), + ui.output_text("selected_date7"), + ), + ui.div( + ui.input_date( + "date8", "Autoclose disabled:", value="2024-01-01", autoclose=False + ), + ui.output_text("selected_date8"), + ), + ui.div( + ui.input_date( + "date9", + "Specific dates disabled:", + value="2024-01-01", + datesdisabled=["2024-01-15", "2024-01-16", "2024-01-17"], + ), + ui.output_text("selected_date9"), + ), + ui.div( + ui.input_date( + "date10", + "Weekends disabled:", + value="2024-01-01", + daysofweekdisabled=[0, 6], # 0 = Sunday, 6 = Saturday + ), + ui.output_text("selected_date10"), + ), + ) +) + + +def server(input, output, session): + @render.text + def selected_date1(): + return f"Selected date: {input.date1()}" + + @render.text + def selected_date2(): + return f"Selected date: {input.date2()}" + + @render.text + def selected_date3(): + return f"Selected date: {input.date3()}" + + @render.text + def selected_date4(): + return f"Selected date: {input.date4()}" + + @render.text + def selected_date5(): + return f"Selected date: {input.date5()}" + + @render.text + def selected_date6(): + return f"Selected date: {input.date6()}" + + @render.text + def selected_date7(): + return f"Selected date: {input.date7()}" + + @render.text + def selected_date8(): + return f"Selected date: {input.date8()}" + + @render.text + def selected_date9(): + return f"Selected date: {input.date9()}" + + @render.text + def selected_date10(): + return f"Selected date: {input.date10()}" + + +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-express.py new file mode 100644 index 000000000..9be4f0aa0 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-express.py @@ -0,0 +1,94 @@ +from datetime import date +from shiny import reactive +from shiny.express import input, ui, render + +with ui.layout_column_wrap(): + # Basic date input + ui.input_date("date1", "Default date input:", value="2024-01-01") + + @render.text + def selected_date1(): + return f"Selected date: {input.date1()}" + + # Date input with min and max dates + ui.input_date( + "date2", + "Date input with min/max:", + value=date(2024, 1, 1), + min="2024-01-01", + max="2024-12-31", + ) + + @render.text + def selected_date2(): + return f"Selected date: {input.date2()}" + + # Date input with custom format + ui.input_date( + "date3", "Custom format (mm/dd/yy):", value="2024-01-01", format="mm/dd/yy" + ) + + @render.text + def selected_date3(): + return f"Selected date: {input.date3()}" + + # Date input with decade view + ui.input_date( + "date4", "Start in decade view:", value="2024-01-01", startview="decade" + ) + + @render.text + def selected_date4(): + return f"Selected date: {input.date4()}" + + # Date input with week starting on Monday + ui.input_date("date5", "Week starts on Monday:", value="2024-01-01", weekstart=1) + + @render.text + def selected_date5(): + return f"Selected date: {input.date5()}" + + # Date input with German language + ui.input_date("date6", "German language:", value="2024-01-01", language="de") + + @render.text + def selected_date6(): + return f"Selected date: {input.date6()}" + + # Date input with custom width + ui.input_date("date7", "Custom width:", value="2024-01-01", width="400px") + + @render.text + def selected_date7(): + return f"Selected date: {input.date7()}" + + # Date input with autoclose disabled + ui.input_date("date8", "Autoclose disabled:", value="2024-01-01", autoclose=False) + + @render.text + def selected_date8(): + return f"Selected date: {input.date8()}" + + # Date input with specific dates disabled + ui.input_date( + "date9", + "Specific dates disabled:", + value="2024-01-01", + datesdisabled=["2024-01-15", "2024-01-16", "2024-01-17"], + ) + + @render.text + def selected_date9(): + return f"Selected date: {input.date9()}" + + # Date input with specific days of week disabled + ui.input_date( + "date10", + "Weekends disabled:", + value="2024-01-01", + daysofweekdisabled=[0, 6], # 0 = Sunday, 6 = Saturday + ) + + @render.text + def selected_date10(): + return f"Selected date: {input.date10()}" diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/test_input_date_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/test_input_date_core_express.py new file mode 100644 index 000000000..7a7487f70 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/test_input_date_core_express.py @@ -0,0 +1,77 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_date_inputs(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Test basic date input + date1 = controller.InputDate(page, "date1") + date1.expect_label("Default date input:") + date1.expect_value("2024-01-01") + + # Test date input with min/max range + date2 = controller.InputDate(page, "date2") + date2.expect_label("Date input with min/max:") + date2.expect_value("2024-01-01") + date2.expect_min_date("2024-01-01") + date2.expect_max_date("2024-12-31") + + # Test date input with custom format + date3 = controller.InputDate(page, "date3") + date3.expect_label("Custom format (mm/dd/yy):") + date3.expect_format("mm/dd/yy") + date3.expect_value("01/01/24") + + # Test date input with decade view + date4 = controller.InputDate(page, "date4") + date4.expect_label("Start in decade view:") + date4.expect_value("2024-01-01") + date4.expect_startview("decade") + + # Test date input with Monday start + date5 = controller.InputDate(page, "date5") + date5.expect_label("Week starts on Monday:") + date5.expect_value("2024-01-01") + date5.expect_weekstart("1") + + # Test date input with German language + date6 = controller.InputDate(page, "date6") + date6.expect_label("German language:") + date6.expect_value("2024-01-01") + date6.expect_language("de") + + # Test date input with custom width + date7 = controller.InputDate(page, "date7") + date7.expect_label("Custom width:") + date7.expect_value("2024-01-01") + date7.expect_width("400px") + + # Test date input without autoclose + date8 = controller.InputDate(page, "date8") + date8.expect_label("Autoclose disabled:") + date8.expect_value("2024-01-01") + date8.expect_autoclose("false") + + # Test date input with disabled dates + date9 = controller.InputDate(page, "date9") + date9.expect_label("Specific dates disabled:") + date9.expect_value("2024-01-01") + date9.expect_datesdisabled(["2024-01-15", "2024-01-16", "2024-01-17"]) + + # Test date input with disabled days of week + date10 = controller.InputDate(page, "date10") + date10.expect_label("Weekends disabled:") + date10.expect_value("2024-01-01") + date10.expect_daysofweekdisabled([0, 6]) + + # Test setting new values + date1.set("2024-02-01") + date1.expect_value("2024-02-01") + + date2.set("2024-06-15") + date2.expect_value("2024-06-15") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-core.py new file mode 100644 index 000000000..0140ee066 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-core.py @@ -0,0 +1,75 @@ +from datetime import date +from shiny import App, reactive, render, ui + +# Define the UI +app_ui = ui.page_fluid( + # Add descriptive text + ui.h2("Date Range Input Example"), + ui.markdown( + """ + This example demonstrates a date range input with various customization options: + - Custom date format (mm/dd/yyyy) + - Restricted date range (2020-2025) + - Week starting on Monday + - Custom separator + """ + ), + # Layout wrapper + ui.layout_column_wrap( + # Date range input with all parameters + ui.input_date_range( + id="date_range", + label="Select Date Range", + start=date(2023, 1, 1), # Initial start date + end=date(2023, 12, 31), # Initial end date + min=date(2020, 1, 1), # Minimum allowed date + max=date(2025, 12, 31), # Maximum allowed date + format="mm/dd/yyyy", # Display format + startview="decade", # Initial view when opened + weekstart=1, # Week starts on Monday (0=Sunday, 1=Monday) + language="en", # Language for month/day names + separator=" → ", # Custom separator between dates + width="100%", # Width of the input + autoclose=True, # Close the calendar when a date is selected + ), + # Card to display selected range + ui.card( + ui.card_header("Selected Date Range"), + ui.output_text("selected_range"), + ), + ), + # Additional date info output + ui.output_ui("date_info"), +) + + +# Define the server +def server(input, output, session): + @render.text + def selected_range(): + date_range = input.date_range() + if date_range is None: + return "No dates selected" + + start, end = date_range + return f"Start date: {start}\nEnd date: {end}" + + @render.ui + def date_info(): + date_range = input.date_range() + if date_range is None: + return ui.p("Please select a date range", class_="text-muted") + + start, end = date_range + days = (end - start).days + + return ui.div( + ui.p(f"Number of days selected: {days}"), + ui.p(f"Start day of week: {start.strftime('%A')}"), + ui.p(f"End day of week: {end.strftime('%A')}"), + class_="mt-3", + ) + + +# Create and return the app +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-express.py new file mode 100644 index 000000000..f270e713a --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-express.py @@ -0,0 +1,65 @@ +from datetime import date +from shiny import reactive +from shiny.express import input, ui, render + + +# Add some descriptive text +ui.h2("Date Range Input Example") +ui.markdown( + """ +This example demonstrates a date range input with various customization options: +- Custom date format (mm/dd/yyyy) +- Restricted date range (2020-2025) +- Week starting on Monday +- Custom separator +""" +) + +with ui.layout_column_wrap(): + # Create a date range input with all possible parameters + ui.input_date_range( + id="date_range", + label="Select Date Range", + start=date(2023, 1, 1), # Initial start date + end=date(2023, 12, 31), # Initial end date + min=date(2020, 1, 1), # Minimum allowed date + max=date(2025, 12, 31), # Maximum allowed date + format="mm/dd/yyyy", # Display format + startview="decade", # Initial view when opened + weekstart=1, # Week starts on Monday (0=Sunday, 1=Monday) + language="en", # Language for month/day names + separator=" → ", # Custom separator between dates + width="100%", # Width of the input + autoclose=True, # Close the calendar when a date is selected + ) + + # Add a card to display the selected range + with ui.card(): + ui.card_header("Selected Date Range") + + @render.text + def selected_range(): + date_range = input.date_range() + if date_range is None: + return "No dates selected" + + start, end = date_range + return f"Start date: {start}\nEnd date: {end}" + + +# Add some additional information about the selection +@render.ui +def date_info(): + date_range = input.date_range() + if date_range is None: + return ui.p("Please select a date range", class_="text-muted") + + start, end = date_range + days = (end - start).days + + return ui.div( + ui.p(f"Number of days selected: {days}"), + ui.p(f"Start day of week: {start.strftime('%A')}"), + ui.p(f"End day of week: {end.strftime('%A')}"), + class_="mt-3", + ) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/test_input_date_range_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/test_input_date_range_core_express.py new file mode 100644 index 000000000..746d3f788 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/test_input_date_range_core_express.py @@ -0,0 +1,48 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_date_range_input(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Initialize the date range input controller + date_range = controller.InputDateRange(page, "date_range") + + # Test selected_range output + selected_range = controller.OutputText(page, "selected_range") + selected_range.expect_value("Start date: 2023-01-01\nEnd date: 2023-12-31") + + # Test initial properties + date_range.expect_label("Select Date Range") + date_range.expect_value(("01/01/2023", "12/31/2023")) # Test initial values + date_range.expect_min_date("2020-01-01") # Test minimum date + date_range.expect_max_date("2025-12-31") # Test maximum date + date_range.expect_format("mm/dd/yyyy") # Test date format + date_range.expect_startview("decade") # Test start view + date_range.expect_weekstart("1") # Test week start (Monday) + date_range.expect_language("en") # Test language setting + date_range.expect_separator(" → ") # Test separator + date_range.expect_width("100%") # Test width + date_range.expect_autoclose("true") # Test autoclose + + # Test setting new values + date_range.set(("2023-06-01", "2023-06-30")) + date_range.expect_value(("2023-06-01", "2023-06-30")) + + # Test setting only start date + date_range.set(("2023-07-01", None)) + date_range.expect_value(("2023-07-01", "2023-06-30")) + + # Test setting only end date + date_range.set((None, "2023-07-31")) + date_range.expect_value(("2023-07-01", "2023-07-31")) + + # Test setting dates at the boundaries + date_range.set(("2020-01-01", "2025-12-31")) # Min and max dates + date_range.expect_value(("2020-01-01", "2025-12-31")) + + diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py new file mode 100644 index 000000000..4714bcc34 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py @@ -0,0 +1,79 @@ +import pandas as pd +from shiny import App, reactive, render, ui +from shiny.types import FileInfo + +# Define the UI +app_ui = ui.page_fillable( + # Main card containing file input and table + ui.card( + ui.card_header("File Upload Demo"), + # File input with all possible parameters + ui.input_file( + id="file1", + label="Upload File", + multiple=True, + accept=[".csv", ".txt", "text/plain", "application/pdf", "image/*"], + button_label="Choose Files...", + placeholder="Multiple files can be selected", + width="400px", + capture="user", + ), + # Output for the data grid + ui.output_data_frame("file_table"), + # Instructions card + ui.card( + ui.markdown( + """ + ### Instructions: + 1. Click 'Choose Files...' to select one or more files + 2. Supported file types: CSV, TXT, PDF, and images + 3. File information will appear in the table below + 4. Use filters to search through uploaded files + """ + ) + ), + ) +) + + +# Define the server +def server(input, output, session): + # Reactive calculation for parsing files + @reactive.calc + def parse_files(): + files: list[FileInfo] | None = input.file1() + if not files: + return pd.DataFrame() + + # Create a DataFrame with file information + file_info = [] + for file in files: + file_info.append( + { + "Name": file["name"], + "Size (bytes)": file["size"], + "Type": file["type"], + } + ) + return pd.DataFrame(file_info) + + # Render the data grid + @output + @render.data_frame + def file_table(): + df = parse_files() + if df.empty: + return render.DataGrid( + pd.DataFrame(columns=["Name", "Size (bytes)", "Type"]), + height="300px", + width="100%", + filters=True, + selection_mode="row", + ) + return render.DataGrid( + df, height="300px", width="100%", filters=True, selection_mode="row" + ) + + +# Create and return the app +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py new file mode 100644 index 000000000..4279891e2 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py @@ -0,0 +1,67 @@ +import pandas as pd +from shiny import reactive +from shiny.express import input, render, ui +from shiny.types import FileInfo + +# Set page options +ui.page_opts(title="File Input Demo", fillable=True) + +with ui.card(): + ui.card_header("File Upload Demo") + + # File input with all possible parameters + ui.input_file( + id="file1", + label="Upload File", + multiple=True, + accept=[".csv", ".txt", "text/plain", "application/pdf", "image/*"], + button_label="Choose Files...", + placeholder="Multiple files can be selected", + width="400px", + capture="user", + ) + + @reactive.calc + def parse_files(): + files: list[FileInfo] | None = input.file1() + if not files: + return pd.DataFrame() + + # Create a DataFrame with file information + file_info = [] + for file in files: + file_info.append( + { + "Name": file["name"], + "Size (bytes)": file["size"], + "Type": file["type"], + } + ) + return pd.DataFrame(file_info) + + @render.data_frame + def file_table(): + df = parse_files() + if df.empty: + return render.DataGrid( + pd.DataFrame(columns=["Name", "Size (bytes)", "Type"]), + height="300px", + width="100%", + filters=True, + selection_mode="row", + ) + return render.DataGrid( + df, height="300px", width="100%", filters=True, selection_mode="row" + ) + + # Add some instructions + with ui.card(): + ui.markdown( + """ + ### Instructions: + 1. Click 'Choose Files...' to select one or more files + 2. Supported file types: CSV, TXT, PDF, and images + 3. File information will appear in the table below + 4. Use filters to search through uploaded files + """ + ) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/test_input_file_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/test_input_file_core_express.py new file mode 100644 index 000000000..710951f0d --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/test_input_file_core_express.py @@ -0,0 +1,55 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_file_input_demo(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Test file input component + file_input = controller.InputFile(page, "file1") + + # Test initial state + file_input.expect_label("Upload File") + file_input.expect_multiple(True) + file_input.expect_accept( + [".csv", ".txt", "text/plain", "application/pdf", "image/*"] + ) + file_input.expect_button_label("Choose Files...") + file_input.expect_width("400px") + file_input.expect_capture("user") + + # Test data frame output initial state + file_table = controller.OutputDataFrame(page, "file_table") + file_table.expect_column_labels(["Name", "Size (bytes)", "Type"]) + file_table.expect_nrow(0) + file_table.expect_ncol(3) + + # Note: The file content is a CSV with a header and some data + # Simulate uploading a CSV file + file_info: FilePayload = { + "name": "users.csv", + "mimeType": "text/csv", + "buffer": b",user_id,name,email\n1,Alice,alice@example.com\n2,\"Bob, Los Angeles\", bob\n", + } + + file_input.set(file_info) + file_input.expect_complete() + + # After upload, check if table is updated + file_table.expect_nrow(1) # Should show one row for the uploaded file + file_table.expect_ncol(3) # Should still have 3 columns + + # simulate uploading multiple files + file_info2 = file_info.copy() + file_info2["name"] = "users2.csv" + file_info2["buffer"] = b",user_id,name,email\n3,Charlie,charlie@example.com\n4,Dave,dave@example.com\n" + file_input.set([file_info, file_info2]) + file_input.expect_complete() + + # After uploading multiple files, check if table is updated + file_table.expect_nrow(2) # Should show two rows for the uploaded files + file_table.expect_ncol(3) # Should still have 3 columns diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-core.py new file mode 100644 index 000000000..c91208cec --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-core.py @@ -0,0 +1,62 @@ +from shiny import App, reactive, render, ui + +app_ui = ui.page_fluid( + ui.layout_column_wrap( + ui.card( + ui.card_header("Basic Numeric Input"), + ui.input_numeric(id="basic", label="Basic numeric input", value=10), + ui.output_text("basic_value"), + ), + ui.card( + ui.card_header("With Min/Max"), + ui.input_numeric( + id="with_min_max", + label="With min and max values", + value=5, + min=0, + max=10, + ), + ui.output_text("minmax_value"), + ), + ui.card( + ui.card_header("With Step Size"), + ui.input_numeric( + id="with_step", label="With step size", value=0, min=0, max=100, step=5 + ), + ui.output_text("step_value"), + ), + ui.card( + ui.card_header("With Custom Width"), + ui.input_numeric( + id="with_width", label="With custom width", value=42, width="200px" + ), + ui.output_text("width_value"), + ), + width=1 / 2, + ) +) + + +def server(input, output, session): + @output + @render.text + def basic_value(): + return f"Current value: {input.basic()}" + + @output + @render.text + def minmax_value(): + return f"Current value: {input.with_min_max()}" + + @output + @render.text + def step_value(): + return f"Current value: {input.with_step()}" + + @output + @render.text + def width_value(): + return f"Current value: {input.with_width()}" + + +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-express.py new file mode 100644 index 000000000..add71fbde --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-express.py @@ -0,0 +1,44 @@ +from shiny import reactive +from shiny.express import input, ui, render + +# Set page title +ui.page_opts(full_width=True) + +with ui.layout_column_wrap(width=1 / 2): + with ui.card(): + ui.card_header("Basic Numeric Input") + ui.input_numeric(id="basic", label="Basic numeric input", value=10) + + @render.text + def basic_value(): + return f"Current value: {input.basic()}" + + with ui.card(): + ui.card_header("With Min/Max") + ui.input_numeric( + id="with_min_max", label="With min and max values", value=5, min=0, max=10 + ) + + @render.text + def minmax_value(): + return f"Current value: {input.with_min_max()}" + + with ui.card(): + ui.card_header("With Step Size") + ui.input_numeric( + id="with_step", label="With step size", value=0, min=0, max=100, step=5 + ) + + @render.text + def step_value(): + return f"Current value: {input.with_step()}" + + with ui.card(): + ui.card_header("With Custom Width") + ui.input_numeric( + id="with_width", label="With custom width", value=42, width="200px" + ) + + @render.text + def width_value(): + return f"Current value: {input.with_width()}" diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/test_input_numeric_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/test_input_numeric_core_express.py new file mode 100644 index 000000000..1116c9fb3 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/test_input_numeric_core_express.py @@ -0,0 +1,56 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_numeric_inputs(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Test basic numeric input + basic = controller.InputNumeric(page, "basic") + basic_output = controller.OutputText(page, "basic_value") + + basic.expect_label("Basic numeric input") + basic.expect_value("10") + basic_output.expect_value("Current value: 10") + + + # Test with new value + basic.set("20") + basic_output.expect_value("Current value: 20") + + # Test numeric input with min/max + with_min_max = controller.InputNumeric(page, "with_min_max") + minmax_output = controller.OutputText(page, "minmax_value") + + with_min_max.expect_label("With min and max values") + with_min_max.expect_value("5") + with_min_max.expect_min("0") + with_min_max.expect_max("10") + minmax_output.expect_value("Current value: 5") + + # Test with step size + with_step = controller.InputNumeric(page, "with_step") + step_output = controller.OutputText(page, "step_value") + + with_step.expect_label("With step size") + with_step.expect_value("0") + with_step.expect_min("0") + with_step.expect_max("100") + with_step.expect_step("5") + step_output.expect_value("Current value: 0") + + # Test with custom width + with_width = controller.InputNumeric(page, "with_width") + width_output = controller.OutputText(page, "width_value") + + with_width.expect_label("With custom width") + with_width.expect_value("42") + with_width.expect_width("200px") + width_output.expect_value("Current value: 42") + + # Test all values output + all_values_output = controller.OutputText(page, "all_values") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-core.py new file mode 100644 index 000000000..d5e541e2d --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-core.py @@ -0,0 +1,46 @@ +from shiny import App, reactive, render, ui + +# Define the UI +app_ui = ui.page_fluid( + # Card container + ui.card( + ui.card_header("Password Input Example"), + # Create password input + ui.input_password( + id="pwd", + label="Enter Password", + value="default123", + width="300px", + placeholder="Type your password here", + ), + # Output for password length + ui.output_text("password_length"), + # Output for masked password + ui.output_text("password_masked"), + ) +) + + +# Define the server +def server(input, output, session): + # Show current input length + @output + @render.text + def password_length(): + pwd = input.pwd() + if not pwd: + return "No password entered" + return f"Password length: {len(pwd)} characters" + + # Show masked password + @output + @render.text + def password_masked(): + pwd = input.pwd() + if not pwd: + return "" + return f"Masked password: {'*' * len(pwd)}" + + +# Create and return the app +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-express.py new file mode 100644 index 000000000..07b7bcbe8 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-express.py @@ -0,0 +1,33 @@ +from shiny import reactive +from shiny.express import input, ui, render + +# Set page title +ui.page_opts(full_width=True) + +with ui.card(): + ui.card_header("Password Input Example") + + # Create password input + ui.input_password( + id="pwd", + label="Enter Password", + value="default123", + width="300px", + placeholder="Type your password here", + ) + + # Show current input length + @render.text + def password_length(): + pwd = input.pwd() + if not pwd: + return "No password entered" + return f"Password length: {len(pwd)} characters" + + # Show masked password + @render.text + def password_masked(): + pwd = input.pwd() + if not pwd: + return "" + return f"Masked password: {'*' * len(pwd)}" diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/test_input_password_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/test_input_password_core_express.py new file mode 100644 index 000000000..903b747a5 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/test_input_password_core_express.py @@ -0,0 +1,31 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_password_input(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Test password input + pwd = controller.InputPassword(page, "pwd") + pwd.expect_label("Enter Password") + pwd.expect_value("default123") + pwd.expect_width("300px") + pwd.expect_placeholder("Type your password here") + + # Test password length output + pwd_length = controller.OutputText(page, "password_length") + pwd_length.expect_value("Password length: 10 characters") + + # Test masked password output + pwd_masked = controller.OutputText(page, "password_masked") + pwd_masked.expect_value("Masked password: **********") + + # Test setting new password + pwd.set("newpass12") + pwd.expect_value("newpass12") + pwd_length.expect_value("Password length: 9 characters") + pwd_masked.expect_value("Masked password: *********") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-core.py new file mode 100644 index 000000000..f2d264082 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-core.py @@ -0,0 +1,40 @@ +from shiny import App, reactive, render, ui + +# Create sample choices with HTML content +choices = { + "choice1": ui.span("Choice 1", style="color: red;"), + "choice2": ui.span("Choice 2", style="color: blue;"), + "choice3": ui.span("Choice 3", style="color: green;"), +} + +# Define the UI +app_ui = ui.page_fluid( + ui.card( + ui.card_header("Radio Buttons Example"), + # Create radio buttons with all possible parameters + ui.input_radio_buttons( + id="radio_demo", # Required: unique identifier + label="Demo Radio Group", # Required: label text + choices=choices, # Required: choices as dict with HTML content + selected="choice1", # Optional: initial selected value + inline=True, # Optional: display buttons inline + width="300px", # Optional: CSS width + ), + # Add some spacing + ui.br(), + # Output for displaying selection + ui.output_text("selection"), + ) +) + + +# Define the server +def server(input, output, session): + @output + @render.text + def selection(): + return f"You selected: {input.radio_demo()}" + + +# Create and return the app +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-express.py new file mode 100644 index 000000000..dc21dfe31 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-express.py @@ -0,0 +1,34 @@ +from shiny import reactive +from shiny.express import input, render, ui + +# Set page title +ui.page_opts(full_width=True) + +# Create sample choices with HTML content +choices = { + "choice1": ui.span("Choice 1", style="color: red;"), + "choice2": ui.span("Choice 2", style="color: blue;"), + "choice3": ui.span("Choice 3", style="color: green;"), +} + +# Create a card to contain the radio buttons and output +with ui.card(): + ui.card_header("Radio Buttons Example") + + # Create radio buttons with all possible parameters + ui.input_radio_buttons( + id="radio_demo", # Required: unique identifier + label="Demo Radio Group", # Required: label text + choices=choices, # Required: choices as dict with HTML content + selected="choice1", # Optional: initial selected value + inline=True, # Optional: display buttons inline + width="300px", # Optional: CSS width + ) + + # Add some spacing + ui.br() + + # Display the current selection + @render.text + def selection(): + return f"You selected: {input.radio_demo()}" diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/test_input_radio_buttons_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/test_input_radio_buttons_core_express.py new file mode 100644 index 000000000..b57371fc5 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/test_input_radio_buttons_core_express.py @@ -0,0 +1,33 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_radio_buttons_demo(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Test radio buttons input + radio_buttons = controller.InputRadioButtons(page, "radio_demo") + selection_output = controller.OutputText(page, "selection") + + # Test initial state + radio_buttons.expect_label("Demo Radio Group") + radio_buttons.expect_choices(["choice1", "choice2", "choice3"]) + radio_buttons.expect_selected("choice1") # Test default selection + radio_buttons.expect_inline(True) + radio_buttons.expect_width("300px") + selection_output.expect_value("You selected: choice1") + + # Test changing selections + radio_buttons.set("choice2") + selection_output.expect_value("You selected: choice2") + + radio_buttons.set("choice3") + selection_output.expect_value("You selected: choice3") + + # Test going back to first choice + radio_buttons.set("choice1") + selection_output.expect_value("You selected: choice1") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-core.py new file mode 100644 index 000000000..fd308d6ef --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-core.py @@ -0,0 +1,112 @@ +from shiny import App, reactive, render, ui + +# Sample data for different types of choices +simple_choices = ["A", "B", "C", "D"] +dict_choices = {"a": "Option A", "b": "Option B", "c": "Option C"} +grouped_choices = { + "Group 1": {"g1a": "Group 1 - A", "g1b": "Group 1 - B"}, + "Group 2": {"g2a": "Group 2 - A", "g2b": "Group 2 - B"}, +} + +app_ui = ui.page_fillable( + ui.layout_column_wrap( + # Basic select with simple choices + ui.card( + ui.card_header("Basic Select"), + ui.input_select( + id="select1", + label="Basic select (simple list)", + choices=simple_choices, + selected="A", + ), + ui.output_text("selected_value1"), + ), + # Select with dictionary choices + ui.card( + ui.card_header("Dictionary Choices"), + ui.input_select( + id="select2", + label="Select with dictionary choices", + choices=dict_choices, + selected="a", + ), + ui.output_text("selected_value2"), + ), + # Select with grouped choices + ui.card( + ui.card_header("Grouped Choices"), + ui.input_select( + id="select3", + label="Select with grouped choices", + choices=grouped_choices, + selected="g1a", + ), + ui.output_text("selected_value3"), + ), + # Multiple select + ui.card( + ui.card_header("Multiple Select"), + ui.input_select( + id="select4", + label="Multiple select", + choices=simple_choices, + selected=["A", "B"], + multiple=True, + ), + ui.output_text("selected_value4"), + ), + # Select with custom width + ui.card( + ui.card_header("Custom Width"), + ui.input_select( + id="select5", + label="Select with custom width", + choices=simple_choices, + width="200px", + ), + ui.output_text("selected_value5"), + ), + # Select with size parameter + ui.card( + ui.card_header("Box Style"), + ui.input_select( + id="select6", + label="Select with size parameter", + choices=simple_choices, + size="4", # Shows 4 items at once + ), + ui.output_text("selected_value6"), + ), + width="400px", + ), +) + + +def server(input, output, session): + + @render.text + def selected_value1(): + return f"Selected: {input.select1()}" + + @render.text + def selected_value2(): + return f"Selected: {input.select2()}" + + @render.text + def selected_value3(): + return f"Selected: {input.select3()}" + + @render.text + def selected_value4(): + return f"Selected: {input.select4()}" + + @render.text + def selected_value5(): + return f"Selected: {input.select5()}" + + @render.text + def selected_value6(): + return f"Selected: {input.select6()}" + + +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-express.py new file mode 100644 index 000000000..d209df06f --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-express.py @@ -0,0 +1,99 @@ +from shiny import reactive +from shiny.express import input, ui, render + +# Sample data for different types of choices +simple_choices = ["A", "B", "C", "D"] +dict_choices = {"a": "Option A", "b": "Option B", "c": "Option C"} +grouped_choices = { + "Group 1": {"g1a": "Group 1 - A", "g1b": "Group 1 - B"}, + "Group 2": {"g2a": "Group 2 - A", "g2b": "Group 2 - B"}, +} + +# Page options +ui.page_opts(fillable=True) + +with ui.layout_column_wrap(width="400px"): + # Basic select with simple choices + with ui.card(): + ui.card_header("Basic Select") + ui.input_select( + id="select1", + label="Basic select (simple list)", + choices=simple_choices, + selected="A", + ) + + @render.text + def selected_value1(): + return f"Selected: {input.select1()}" + + # Select with dictionary choices + with ui.card(): + ui.card_header("Dictionary Choices") + ui.input_select( + id="select2", + label="Select with dictionary choices", + choices=dict_choices, + selected="a", + ) + + @render.text + def selected_value2(): + return f"Selected: {input.select2()}" + + # Select with grouped choices + with ui.card(): + ui.card_header("Grouped Choices") + ui.input_select( + id="select3", + label="Select with grouped choices", + choices=grouped_choices, + selected="g1a", + ) + + @render.text + def selected_value3(): + return f"Selected: {input.select3()}" + + # Multiple select + with ui.card(): + ui.card_header("Multiple Select") + ui.input_select( + id="select4", + label="Multiple select", + choices=simple_choices, + selected=["A", "B"], + multiple=True, + ) + + @render.text + def selected_value4(): + return f"Selected: {input.select4()}" + + # Select with custom width + with ui.card(): + ui.card_header("Custom Width") + ui.input_select( + id="select5", + label="Select with custom width", + choices=simple_choices, + width="200px", + ) + + @render.text + def selected_value5(): + return f"Selected: {input.select5()}" + + # Select with size parameter + with ui.card(): + ui.card_header("Box Style") + ui.input_select( + id="select6", + label="Select with size parameter", + choices=simple_choices, + size="4", # Shows 4 items at once + ) + + @render.text + def selected_value6(): + return f"Selected: {input.select6()}" diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/test_input_select_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/test_input_select_core_express.py new file mode 100644 index 000000000..4b07406d7 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/test_input_select_core_express.py @@ -0,0 +1,71 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_input_select_demo(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Test basic select with simple choices + select1 = controller.InputSelect(page, "select1") + select1.expect_label("Basic select (simple list)") + select1.expect_choices(["A", "B", "C", "D"]) + select1.expect_selected("A") # Test initial selection + select1.expect_multiple(False) + select1_value = controller.OutputText(page, "selected_value1") + select1_value.expect_value("Selected: A") + + # Test select with dictionary choices + select2 = controller.InputSelect(page, "select2") + select2.expect_label("Select with dictionary choices") + select2.expect_choices(["a", "b", "c"]) + select2.expect_choice_labels(["Option A", "Option B", "Option C"]) + select2.expect_selected("a") # Test initial selection + select2.expect_multiple(False) + select2_value = controller.OutputText(page, "selected_value2") + select2_value.expect_value("Selected: a") + + # Test select with grouped choices + select3 = controller.InputSelect(page, "select3") + select3.expect_label("Select with grouped choices") + select3.expect_choices(["g1a", "g1b", "g2a", "g2b"]) + select3.expect_choice_labels( + ["Group 1 - A", "Group 1 - B", "Group 2 - A", "Group 2 - B"] + ) + select3.expect_choice_groups(["Group 1", "Group 2"]) + select3.expect_selected("g1a") # Test initial selection + select3.expect_multiple(False) + select3_value = controller.OutputText(page, "selected_value3") + select3_value.expect_value("Selected: g1a") + + # Test multiple select + select4 = controller.InputSelect(page, "select4") + select4.expect_label("Multiple select") + select4.expect_choices(["A", "B", "C", "D"]) + select4.expect_selected(["A", "B"]) # Test initial multiple selection + select4.expect_multiple(True) + select4_value = controller.OutputText(page, "selected_value4") + select4_value.expect_value("Selected: ('A', 'B')") + + # Test select with custom width + select5 = controller.InputSelect(page, "select5") + select5.expect_label("Select with custom width") + select5.expect_choices(["A", "B", "C", "D"]) + select5.expect_width("200px") + select5.expect_multiple(False) + select5_value = controller.OutputText(page, "selected_value5") + select5_value.expect_value("Selected: A") + + + # Test select with size parameter + select6 = controller.InputSelect(page, "select6") + select6.expect_label("Select with size parameter") + select6.expect_choices(["A", "B", "C", "D"]) + select6.expect_size("4") + select6.expect_multiple(False) + select6_value = controller.OutputText(page, "selected_value6") + select6_value.expect_value("Selected: A") + diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py new file mode 100644 index 000000000..55f8b3b15 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py @@ -0,0 +1,151 @@ +from datetime import date, datetime +from shiny import App, reactive, render, ui + +app_ui = ui.page_fluid( + ui.panel_title("Slider Parameters Demo"), + ui.layout_column_wrap( + # Numeric Slider - basic parameters + ui.card( + ui.card_header("Basic Numeric Slider"), + ui.input_slider("slider1", "Min, max, value", min=0, max=100, value=50), + ui.output_text("value1"), + ), + # Numeric Slider with step + ui.card( + ui.card_header("Step Parameter"), + ui.input_slider( + "slider2", "Step size = 10", min=0, max=100, value=50, step=10 + ), + ui.output_text("value2"), + ), + # Range Slider + ui.card( + ui.card_header("Range Slider"), + ui.input_slider( + "slider3", "Select a range", min=0, max=100, value=(30, 70) + ), + ui.output_text("value3"), + ), + # Date Slider + ui.card( + ui.card_header("Date Slider"), + ui.input_slider( + "slider4", + "Select a date", + min=date(2023, 1, 1), + max=date(2023, 12, 31), + value=date(2023, 6, 15), + ), + ui.output_text("value4"), + ), + # Animated Slider + ui.card( + ui.card_header("Animated Slider"), + ui.input_slider( + "slider5", "With animation", min=0, max=100, value=50, animate=True + ), + ui.output_text("value5"), + ), + # Slider with custom formatting + ui.card( + ui.card_header("Custom Formatting"), + ui.input_slider( + "slider6", + "With prefix and suffix", + min=0, + max=100, + value=50, + pre="$", + post="%", + sep=",", + ), + ui.output_text("value6"), + ), + # Slider with ticks + ui.card( + ui.card_header("Ticks Display"), + ui.input_slider( + "slider7", "With tick marks", min=0, max=100, value=50, ticks=True + ), + ui.output_text("value7"), + ), + # Date Range Slider with drag_range + ui.card( + ui.card_header("Date Range"), + ui.input_slider( + "slider9", + "Draggable range", + min=date(2023, 1, 1), + max=date(2023, 12, 31), + value=(date(2023, 3, 1), date(2023, 9, 30)), + drag_range=True, + ), + ui.output_text("value9"), + ), + # Datetime slider + ui.card( + ui.card_header("Datetime Slider"), + ui.input_slider( + "slider10", + "With time format", + min=datetime(2023, 1, 1, 0, 0), + max=datetime(2023, 12, 31, 23, 59), + value=datetime(2023, 6, 15, 12, 30), + time_format="%Y-%m-%d %H:%M", + timezone="+0000", + ), + ui.output_text("value10"), + ), + width="400px", + ), +) + + +def server(input, output, session): + @render.text + @reactive.event(input.slider1) + def value1(): + return f"Value: {input.slider1()}" + + @render.text + @reactive.event(input.slider2) + def value2(): + return f"Value: {input.slider2()}" + + @render.text + @reactive.event(input.slider3) + def value3(): + return f"Value: {input.slider3()}" + + @render.text + @reactive.event(input.slider4) + def value4(): + return f"Value: {input.slider4()}" + + @render.text + @reactive.event(input.slider5) + def value5(): + return f"Value: {input.slider5()}" + + @render.text + @reactive.event(input.slider6) + def value6(): + return f"Value: {input.slider6()}" + + @render.text + @reactive.event(input.slider7) + def value7(): + return f"Value: {input.slider7()}" + + @render.text + @reactive.event(input.slider9) + def value9(): + return f"Value: {input.slider9()}" + + @render.text + @reactive.event(input.slider10) + def value10(): + return f"Value: {input.slider10()}" + + +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py new file mode 100644 index 000000000..67f181d66 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py @@ -0,0 +1,121 @@ +from datetime import date, datetime +from shiny import reactive +from shiny.express import input, ui, render + +ui.page_opts(title="Slider Parameters Demo", full_width=True) + +with ui.layout_column_wrap(width="400px"): + # Numeric Slider - basic parameters + with ui.card(): + ui.card_header("Basic Numeric Slider") + ui.input_slider("slider1", "Min, max, value", min=0, max=100, value=50) + + @render.text + def value1(): + return f"Value: {input.slider1()}" + + # Numeric Slider with step + with ui.card(): + ui.card_header("Step Parameter") + ui.input_slider("slider2", "Step size = 10", min=0, max=100, value=50, step=10) + + @render.text + def value2(): + return f"Value: {input.slider2()}" + + # Range Slider + with ui.card(): + ui.card_header("Range Slider") + ui.input_slider("slider3", "Select a range", min=0, max=100, value=(30, 70)) + + @render.text + def value3(): + return f"Value: {input.slider3()}" + + # Date Slider + with ui.card(): + ui.card_header("Date Slider") + ui.input_slider( + "slider4", + "Select a date", + min=date(2023, 1, 1), + max=date(2023, 12, 31), + value=date(2023, 6, 15), + ) + + @render.text + def value4(): + return f"Value: {input.slider4()}" + + # Animated Slider + with ui.card(): + ui.card_header("Animated Slider") + ui.input_slider( + "slider5", "With animation", min=0, max=100, value=50, animate=True + ) + + @render.text + def value5(): + return f"Value: {input.slider5()}" + + # Slider with custom formatting + with ui.card(): + ui.card_header("Custom Formatting") + ui.input_slider( + "slider6", + "With prefix and suffix", + min=0, + max=100, + value=50, + pre="$", + post="%", + sep=",", + ) + + @render.text + def value6(): + return f"Value: {input.slider6()}" + + # Slider with ticks + with ui.card(): + ui.card_header("Ticks Display") + ui.input_slider( + "slider7", "With tick marks", min=0, max=100, value=50, ticks=True + ) + + @render.text + def value7(): + return f"Value: {input.slider7()}" + + # Date Range Slider with drag_range + with ui.card(): + ui.card_header("Date Range") + ui.input_slider( + "slider9", + "Draggable range", + min=date(2023, 1, 1), + max=date(2023, 12, 31), + value=(date(2023, 3, 1), date(2023, 9, 30)), + drag_range=True, + ) + + @render.text + def value9(): + return f"Value: {input.slider9()}" + + # Datetime slider + with ui.card(): + ui.card_header("Datetime Slider") + ui.input_slider( + "slider10", + "With time format", + min=datetime(2023, 1, 1, 0, 0), + max=datetime(2023, 12, 31, 23, 59), + value=datetime(2023, 6, 15, 12, 30), + time_format="%Y-%m-%d %H:%M", + timezone="+0000", + ) + + @render.text + def value10(): + return f"Value: {input.slider10()}" diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py new file mode 100644 index 000000000..2c728aeb7 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py @@ -0,0 +1,101 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc +from datetime import date, datetime + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Test basic numeric slider + slider1 = controller.InputSlider(page, "slider1") + value1 = controller.OutputText(page, "value1") + value1.expect_value("Value: 50") + slider1.expect_label("Min, max, value") + slider1.expect_min("0") + slider1.expect_max("100") + slider1.expect_value("50") + + + # Test slider with step + slider2 = controller.InputSlider(page, "slider2") + value2 = controller.OutputText(page, "value2") + value2.expect_value("Value: 50") + slider2.expect_label("Step size = 10") + slider2.expect_min("0") + slider2.expect_max("100") + slider2.expect_value("50") + slider2.expect_step("10") + + # Test range slider + slider3 = controller.InputSliderRange(page, "slider3") + value3 = controller.OutputText(page, "value3") + value3.expect_value("Value: (30, 70)") + slider3.expect_label("Select a range") + slider3.expect_min("0") + slider3.expect_max("100") + slider3.expect_value(("30", "70")) + + # Test date slider + slider4 = controller.InputSlider(page, "slider4") + value4 = controller.OutputText(page, "value4") + value4.expect_value("Value: 2023-06-15") + slider4.expect_label("Select a date") + slider4.expect_min("1672560000000.0") # 2023-01-01 + slider4.expect_max("1704009600000.0") # 2023-12-31 + slider4.expect_value("2023-06-15") + + # Test animated slider + slider5 = controller.InputSlider(page, "slider5") + value5 = controller.OutputText(page, "value5") + value5.expect_value("Value: 50") + slider5.expect_label("With animation") + slider5.expect_min("0") + slider5.expect_max("100") + slider5.expect_value("50") + + # Test formatted slider + slider6 = controller.InputSlider(page, "slider6") + value6 = controller.OutputText(page, "value6") + value6.expect_value("Value: 50") + slider6.expect_label("With prefix and suffix") + slider6.expect_min("0") + slider6.expect_max("100") + slider6.expect_value("$50%") + slider6.expect_pre("$") + slider6.expect_post("%") + slider6.expect_sep(",") + + # Test slider with ticks + slider7 = controller.InputSlider(page, "slider7") + value7 = controller.OutputText(page, "value7") + value7.expect_value("Value: 50") + slider7.expect_label("With tick marks") + slider7.expect_min("0") + slider7.expect_max("100") + slider7.expect_value("50") + slider7.expect_ticks("true") + + # Test date range slider + slider9 = controller.InputSliderRange(page, "slider9") + value9 = controller.OutputText(page, "value9") + value9.expect_value("Value: (datetime.date(2023, 3, 1), datetime.date(2023, 9, 30))") + slider9.expect_label("Draggable range") + slider9.expect_min("1672560000000.0") # 2023-01-01 + slider9.expect_max("1704009600000.0") # 2023-12-31 + slider9.expect_value(("2023-03-01", "2023-09-30")) + slider9.expect_drag_range("true") + + # Test datetime slider + slider10 = controller.InputSlider(page, "slider10") + value10 = controller.OutputText(page, "value10") + value10.expect_value("Value: 2023-06-15 19:30:00") + slider10.expect_label("With time format") + slider10.expect_min("1672560000000.0") # 2023-01-01 00:00 + slider10.expect_max("1704095940000.0") # 2023-12-31 23:59 + slider10.expect_value("2023-06-15 19:30") + slider10.expect_time_format("%Y-%m-%d %H:%M") + slider10.expect_timezone("+0000") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-core.py new file mode 100644 index 000000000..1e3375d11 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-core.py @@ -0,0 +1,35 @@ +from shiny import App, reactive, render, ui + +# Define the UI +app_ui = ui.page_fluid( + # Create a card to contain the switches + ui.card( + ui.card_header("Switch Demo"), + # Basic switch with default parameters + ui.input_switch( + id="switch1", label="Basic switch (default params)", value=False + ), + # Switch with custom width + ui.input_switch( + id="switch2", label="Switch with custom width", value=True, width="300px" + ), + # Output for switch states + ui.output_text("switch_states"), + full_screen=True, + height="300px", + id="card1", + ) +) + + +# Define the server +def server(input, output, session): + @render.text + def switch_states(): + return ( + f"Switch 1 state: {input.switch1()}\n" f"Switch 2 state: {input.switch2()}" + ) + + +# Create the app +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-express.py new file mode 100644 index 000000000..8ec1f43bb --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-express.py @@ -0,0 +1,24 @@ +from shiny import reactive +from shiny.express import input, render, ui + +# Set page title +ui.page_opts(full_width=True) + +# Create a card to contain the switches +with ui.card(full_screen=True, height="300px", id="card1"): + ui.card_header("Switch Demo") + + # Basic switch with default parameters + ui.input_switch(id="switch1", label="Basic switch (default params)", value=False) + + # Switch with custom width + ui.input_switch( + id="switch2", label="Switch with custom width", value=True, width="300px" + ) + + # Display switch states + @render.text + def switch_states(): + return ( + f"Switch 1 state: {input.switch1()}\n" f"Switch 2 state: {input.switch2()}" + ) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/test_input_switch_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/test_input_switch_core_express.py new file mode 100644 index 000000000..056bf70d8 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/test_input_switch_core_express.py @@ -0,0 +1,35 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_switch_demo(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Test card1 + card1 = controller.Card(page, "card1") + card1.expect_header("Switch Demo") + card1.expect_height("300px") + card1.expect_full_screen_available(True) + + # Test switch1 + switch1 = controller.InputSwitch(page, "switch1") + switch1.expect_label("Basic switch (default params)") + switch1.expect_checked(False) # Test initial value + + # Toggle switch1 and verify + switch1.set(True) + switch1.expect_checked(True) + + # Test switch2 + switch2 = controller.InputSwitch(page, "switch2") + switch2.expect_label("Switch with custom width") + switch2.expect_checked(True) # Test initial value + switch2.expect_width("300px") + + # Toggle switch2 and verify + switch2.set(False) + switch2.expect_checked(False) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-core.py new file mode 100644 index 000000000..c99e646bb --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-core.py @@ -0,0 +1,50 @@ +from shiny import App, reactive, render, ui + +# Define the UI +app_ui = ui.page_fillable( + # Add Font Awesome CSS in the head section + ui.tags.head( + ui.tags.link( + rel="stylesheet", + href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css", + ) + ), + # Create a card to contain our task button and status + ui.card( + ui.card_header("Task Button Demo"), + # Define the task button + ui.input_task_button( + id="task_btn", + label="Run Task", + icon=ui.tags.i(class_="fa-solid fa-play"), + label_busy="Processing...", + icon_busy=ui.tags.i(class_="fa-solid fa-spinner fa-spin"), + class_="btn-primary m-3", + ), + ui.output_text("task_status"), + height="300px", + ), +) + + +# Define the server +def server(input, output, session): + @output + @render.text + def task_status(): + count = input.task_btn() + if count == 0: + return "Task hasn't started yet" + return f"Task has been run {count} times" + + @reactive.effect + @reactive.event(input.task_btn) + def handle_task(): + import time + + # Simulate a long-running task + time.sleep(2) + + +# Create and return the app +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-express.py new file mode 100644 index 000000000..eea64648b --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-express.py @@ -0,0 +1,43 @@ +from shiny import reactive +from shiny.express import input, ui, render + +# Page options for basic styling +ui.page_opts(fillable=True) + +# Add Font Awesome CSS in the head section +ui.head_content( + ui.HTML( + '' + ) +) + +# Create a card to contain our task button and status +with ui.card(height="300px"): + ui.card_header("Task Button Demo") + + # Define the task button + ui.input_task_button( + id="task_btn", + label="Run Task", + icon=ui.tags.i(class_="fa-solid fa-play"), + label_busy="Processing...", + icon_busy=ui.tags.i(class_="fa-solid fa-spinner fa-spin"), + class_="btn-primary m-3", + ) + + @render.text + def task_status(): + count = input.task_btn() + if count == 0: + return "Task hasn't started yet" + return f"Task has been run {count} times" + + +# Effect to handle the task +@reactive.effect +@reactive.event(input.task_btn) +def handle_task(): + import time + + # Simulate a long-running task + time.sleep(2) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/test_input_task_button_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/test_input_task_button_core_express.py new file mode 100644 index 000000000..7cc47b1a9 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/test_input_task_button_core_express.py @@ -0,0 +1,34 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_task_button_demo(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Get the task button controller + task_btn = controller.InputTaskButton(page, "task_btn") + task_status = controller.OutputText(page, "task_status") + + # Test initial state + task_btn.expect_label("Run Task") + task_btn.expect_label_busy("Processing...") + task_btn.expect_state("ready") + task_status.expect_value("Task hasn't started yet") + + # Click the button and test busy state + task_btn.click() + task_btn.expect_state("busy") + + # After task completes, verify new state and status + task_btn.expect_state("ready", timeout=3000) # Allow time for the 2-second sleep + task_status.expect_value("Task has been run 1 times") + + # Test a second click + task_btn.click() + task_btn.expect_state("busy") + task_btn.expect_state("ready", timeout=3000) + task_status.expect_value("Task has been run 2 times") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-core.py new file mode 100644 index 000000000..e97045f12 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-core.py @@ -0,0 +1,34 @@ +from shiny import App, reactive, render, ui + +# Define the UI +app_ui = ui.page_fillable( + # Create a card to contain the input and output + ui.card( + ui.card_header("Text Input Example"), + # Create text input with all possible parameters + ui.input_text( + id="demo_text", # Required: unique identifier + label="Demo Text Input", # Required: label text + value="Initial value", # Optional: starting value + width="300px", # Optional: CSS width + placeholder="Enter text here", # Optional: hint text + autocomplete="off", # Optional: browser autocomplete behavior + spellcheck="true", # Optional: browser spellcheck behavior + ), + # Add some spacing + ui.hr(), + # Output area for the current value + ui.output_text("current_value"), + ) +) + + +# Define the server function +def server(input, output, session): + @render.text + def current_value(): + return f"Current value: {input.demo_text()}" + + +# Create and return the app object +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-express.py new file mode 100644 index 000000000..fc7c14b15 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-express.py @@ -0,0 +1,28 @@ +from shiny import reactive +from shiny.express import input, ui, render + +# Set page options for a clean layout +ui.page_opts(fillable=True) + +# Create a card to contain the input and output +with ui.card(): + ui.card_header("Text Input Example") + + # Create text input with all possible parameters + ui.input_text( + id="demo_text", # Required: unique identifier + label="Demo Text Input", # Required: label text + value="Initial value", # Optional: starting value + width="300px", # Optional: CSS width + placeholder="Enter text here", # Optional: hint text + autocomplete="off", # Optional: browser autocomplete behavior + spellcheck="true", # Optional: browser spellcheck behavior + ) + + # Add some spacing + ui.hr() + + # Display area for the current value + @render.text + def current_value(): + return f"Current value: {input.demo_text()}" diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/test_input_text_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/test_input_text_core_express.py new file mode 100644 index 000000000..d277839c4 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/test_input_text_core_express.py @@ -0,0 +1,31 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_text_input_demo(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Test text input + text_input = controller.InputText(page, "demo_text") + text_output = controller.OutputText(page, "current_value") + + # Test initial state + text_input.expect_label("Demo Text Input") + text_input.expect_value("Initial value") + text_input.expect_width("300px") + text_input.expect_placeholder("Enter text here") + text_input.expect_autocomplete("off") + text_input.expect_spellcheck("true") + text_output.expect_value("Current value: Initial value") + + # Test setting new value + text_input.set("New test value") + text_output.expect_value("Current value: New test value") + + # Test empty value + text_input.set("") + text_output.expect_value("Current value: ") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-core.py new file mode 100644 index 000000000..70ba252bb --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-core.py @@ -0,0 +1,39 @@ +from shiny import App, reactive, render, ui + +# Define the UI +app_ui = ui.page_fluid( + # Page title is set in the page_fluid + ui.tags.head(ui.tags.title("Text Area Demo")), + # Create a text area with all possible parameters + ui.input_text_area( + id="text_input", + label="Enter your text:", + value="This is some default text.\nIt has multiple lines.\nYou can edit it!", + width="500px", + height="200px", + cols=50, + rows=8, + placeholder="Type something here...", + resize="both", + autoresize=True, + spellcheck="true", + ), + # Add some spacing + ui.br(), + ui.br(), + # Add a header for the output + ui.h4("Output:"), + # Add the output text area + ui.output_text("show_text"), +) + + +# Define the server +def server(input, output, session): + @render.text + def show_text(): + return f"You entered:\n{input.text_input()}" + + +# Create the app +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-express.py new file mode 100644 index 000000000..5b3e1ae21 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-express.py @@ -0,0 +1,35 @@ +from shiny import reactive +from shiny.express import input, render, ui + +ui.page_opts(full_width=True) + +ui.tags.head( + ui.tags.title("Text Area Demo"), +) +# Create a text area with all possible parameters +ui.input_text_area( + id="text_input", + label="Enter your text:", + value="This is some default text.\nIt has multiple lines.\nYou can edit it!", + width="500px", + height="200px", + cols=50, + rows=8, + placeholder="Type something here...", + resize="both", + autoresize=True, + spellcheck="true", +) + +# Add some spacing +ui.br() +ui.br() + +# Add a header for the output +ui.h4("Output:") + + +# Display the input value in a pre-formatted text block +@render.text +def show_text(): + return f"You entered:\n{input.text_input()}" diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/test_input_text_area_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/test_input_text_area_core_express.py new file mode 100644 index 000000000..abfa50d8e --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/test_input_text_area_core_express.py @@ -0,0 +1,38 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_text_area_demo(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Get the text area controller + text_area = controller.InputTextArea(page, "text_input") + + # Test initial state + text_area.expect_label("Enter your text:") + text_area.expect_value( + "This is some default text.\nIt has multiple lines.\nYou can edit it!" + ) + text_area.expect_width("500px") + text_area.expect_height("192px") # 8 rows * 24px per row instead of 200px + text_area.expect_cols("50") + text_area.expect_rows("8") + text_area.expect_placeholder("Type something here...") + text_area.expect_resize("both") + text_area.expect_autoresize(True) + text_area.expect_spellcheck("true") + + # Test output text controller + output_text = controller.OutputText(page, "show_text") + output_text.expect_value( + "You entered:\nThis is some default text.\nIt has multiple lines.\nYou can edit it!" + ) + + # Test setting new value + new_text = "This is new text\nWith new lines" + text_area.set(new_text) + output_text.expect_value(f"You entered:\n{new_text}") From 59eb59404db447d435c63915c07bfe050f7930b7 Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Wed, 5 Mar 2025 14:53:18 -0800 Subject: [PATCH 02/23] Add more tests --- .../update_tooltip/app-core.py | 92 ++++++++++++++++++ .../update_tooltip/app-express.py | 95 +++++++++++++++++++ .../test_update_tooltip_core_express.py | 51 ++++++++++ .../value_box/app-core.py | 80 ++++++++++++++++ .../value_box/app-express.py | 74 +++++++++++++++ .../value_box/test_value_box_core_express.py | 41 ++++++++ 6 files changed, 433 insertions(+) create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/test_update_tooltip_core_express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/value_box/test_value_box_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/app-core.py new file mode 100644 index 000000000..3f2eece04 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/app-core.py @@ -0,0 +1,92 @@ +from shiny import App, reactive, ui + +# Define the UI +app_ui = ui.page_fillable( + # Add Font Awesome for icons + ui.tags.head( + ui.tags.link( + rel="stylesheet", + href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css", + ), + ), + # Create a container card + ui.card( + ui.card_header("Tooltip Demo"), + # Control buttons in a row + ui.layout_column_wrap( + ui.input_action_button( + "btn_show", + "Show tooltip", + class_="btn btn-info", + icon=ui.tags.i(class_="fa-solid fa-eye"), + ), + ui.input_action_button( + "btn_close", + "Close tooltip", + class_="btn btn-warning", + icon=ui.tags.i(class_="fa-solid fa-eye-slash"), + ), + ui.input_action_button( + "btn_update", + "Update tooltip", + class_="btn btn-success", + icon=ui.tags.i(class_="fa-solid fa-sync"), + ), + width=1 / 3, + ), + ui.hr(), + # Center the tooltip button + ui.div( + ui.tooltip( + ui.input_action_button( + "btn_w_tooltip", + "Hover over me!", + class_="btn btn-primary btn-lg", + icon=ui.tags.i(class_="fa-solid fa-info-circle"), + ), + "Initial tooltip message - try the buttons above!", + id="tooltip_id", + placement="right", + ), + class_="d-flex justify-content-center align-items-center", + style="height: 200px;", + ), + ), +) + + +# Define the server +def server(input, output, session): + # Effect to show tooltip + @reactive.effect + @reactive.event(input.btn_show) + def _(): + ui.update_tooltip("tooltip_id", show=True) + + # Effect to close tooltip + @reactive.effect + @reactive.event(input.btn_close) + def _(): + ui.update_tooltip("tooltip_id", show=False) + + # Effect to update tooltip content and show it + @reactive.effect + @reactive.event(input.btn_update) + def _(): + # Create dynamic content based on number of clicks + count = input.btn_update() + content = f"Tooltip updated {count} time{'s' if count > 1 else ''}!" + # Update tooltip with new content and show it + ui.update_tooltip("tooltip_id", content, show=True) + + # Show notification when button with tooltip is clicked + @reactive.effect + @reactive.event(input.btn_w_tooltip) + def _(): + ui.notification_show( + "Button clicked!", duration=2, type="message", close_button=True + ) + + +# Create and return the app +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/app-express.py new file mode 100644 index 000000000..8cbaec0d3 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/app-express.py @@ -0,0 +1,95 @@ +from shiny import reactive +from shiny.express import input, render, ui + +# Page options +ui.page_opts( + title="Update Tooltip Demo", + fillable=True, + # Add Font Awesome for icons +) + +# Add Font Awesome CSS in the head section first +ui.head_content( + ui.tags.link( + rel="stylesheet", + href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css", + ) +) + +# Create a container card for better organization +with ui.card(): + ui.card_header("Tooltip Demo") + + # Control buttons in a row + with ui.layout_column_wrap(width=1 / 3): + ui.input_action_button( + "btn_show", + "Show tooltip", + class_="btn btn-info", + icon=ui.tags.i(class_="fa-solid fa-eye"), + ) + + ui.input_action_button( + "btn_close", + "Close tooltip", + class_="btn btn-warning", + icon=ui.tags.i(class_="fa-solid fa-eye-slash"), + ) + + ui.input_action_button( + "btn_update", + "Update tooltip", + class_="btn btn-success", + icon=ui.tags.i(class_="fa-solid fa-sync"), + ) + + # Spacer + ui.hr() + + # Center the tooltip button + with ui.div( + class_="d-flex justify-content-center align-items-center", + style="height: 200px;", + ): + with ui.tooltip(id="tooltip_id", placement="right"): + ui.input_action_button( + "btn_w_tooltip", + "Hover over me!", + class_="btn btn-primary btn-lg", + icon=ui.tags.i(class_="fa-solid fa-info-circle"), + ) + "Initial tooltip message - try the buttons above!" + + +# Effect to show tooltip +@reactive.effect +@reactive.event(input.btn_show) +def _(): + ui.update_tooltip("tooltip_id", show=True) + + +# Effect to close tooltip +@reactive.effect +@reactive.event(input.btn_close) +def _(): + ui.update_tooltip("tooltip_id", show=False) + + +# Effect to update tooltip content and show it +@reactive.effect +@reactive.event(input.btn_update) +def _(): + # Create dynamic content based on number of clicks + count = input.btn_update() + content = f"Tooltip updated {count} time{'s' if count > 1 else ''}!" + # Update tooltip with new content and show it + ui.update_tooltip("tooltip_id", content, show=True) + + +# Show notification when button with tooltip is clicked +@reactive.effect +@reactive.event(input.btn_w_tooltip) +def _(): + ui.notification_show( + "Button clicked!", duration=2, type="message", close_button=True + ) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/test_update_tooltip_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/test_update_tooltip_core_express.py new file mode 100644 index 000000000..9967bbf70 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/test_update_tooltip_core_express.py @@ -0,0 +1,51 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + +def test_tooltip_demo(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Get tooltip controller + tooltip = controller.Tooltip(page, "tooltip_id") + + # Get button controllers + show_btn = controller.InputActionButton(page, "btn_show") + close_btn = controller.InputActionButton(page, "btn_close") + update_btn = controller.InputActionButton(page, "btn_update") + tooltip_btn = controller.InputActionButton(page, "btn_w_tooltip") + + # Test initial button labels + show_btn.expect_label("Show tooltip") + close_btn.expect_label("Close tooltip") + update_btn.expect_label("Update tooltip") + tooltip_btn.expect_label("Hover over me!") + + # Test initial tooltip state and content + tooltip.expect_active(False) + show_btn.click() + tooltip.expect_body("Initial tooltip message - try the buttons above!") + tooltip.expect_placement("right") + + # Test showing tooltip + tooltip.expect_active(True) + + # Test closing tooltip + close_btn.click() + tooltip.expect_active(False) + + # Test updating tooltip content + update_btn.click() + tooltip.expect_active(True) + tooltip.expect_body("Tooltip updated 1 time!") + + close_btn.click() + tooltip.expect_active(False) + + # Click update button again and verify content changes + update_btn.click() + tooltip.expect_active(True) + tooltip.expect_body("Tooltip updated 2 times!") + diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-core.py new file mode 100644 index 000000000..3286146ca --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-core.py @@ -0,0 +1,80 @@ +from shiny import App, ui + +# Create a custom icon for the showcase using Font Awesome +icon = ui.tags.i(class_="fa-solid fa-chart-simple", style="font-size: 2rem;") + +app_ui = ui.page_fillable( + # Add Font Awesome CSS to the app + ui.head_content( + ui.HTML( + '' + ) + ), + ui.layout_column_wrap( + # 1. Basic value box with left-center showcase layout (default) + ui.value_box( + "Revenue", + "$5.2M", + "Up 12% from last month", + id="left_center_value_box", + showcase=icon, + theme="primary", + height="200px", + ), + # 2. Value box with top-right showcase layout + ui.value_box( + "Active Users", + "2.4K", + "Daily active users", + id="top_right_value_box", + showcase=icon, + showcase_layout="top right", + theme="bg-gradient-purple-red", + height="200px", + ), + # 3. Value box with bottom showcase layout + ui.value_box( + "Conversion Rate", + "3.8%", + "Increased by 0.5%", + id="bottom_value_box", + showcase=icon, + showcase_layout="bottom", + theme="text-success", + height="200px", + ), + # 4. Value box with full screen capability and custom theme + ui.value_box( + "Total Sales", + "8,742", + "Year to date performance", + id="full_screen_value_box", + showcase=icon, + full_screen=True, + theme="bg-gradient-orange-red", + height="600px", + min_height="150px", + max_height="300px", + fill=True, + ), + # 5. Value box with custom background color using class_ + ui.value_box( + "Pending Orders", + "156", + "Requires attention", + id="custom_bg_value_box", + showcase=icon, + theme=None, + height="200px", + class_="bg-warning text-dark", + ), + width="400px", + ), +) + + +def server(input, output, session): + pass + + +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py new file mode 100644 index 000000000..0b3325378 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py @@ -0,0 +1,74 @@ +from shiny import reactive +from shiny.express import input, ui, render + +ui.page_opts(fillable=True) + +# Create a custom icon for the showcase using Font Awesome +icon = ui.tags.i(class_="fa-solid fa-chart-simple", style="font-size: 2rem;") + +# Add Font Awesome CSS to the app +ui.head_content( + ui.HTML( + '' + ) +) + +with ui.layout_column_wrap(width="400px"): + # 1. Basic value box with left-center showcase layout (default) + with ui.value_box( + id="left_center_value_box", showcase=icon, theme="primary", height="200px" + ): + "Revenue" + "$5.2M" + "Up 12% from last month" + + # 2. Value box with top-right showcase layout + with ui.value_box( + id="top_right_value_box", + showcase=icon, + showcase_layout="top right", + theme="bg-gradient-purple-red", + height="200px", + ): + "Active Users" + "2.4K" + "Daily active users" + + # 3. Value box with bottom showcase layout + with ui.value_box( + id="bottom_value_box", + showcase=icon, + showcase_layout="bottom", + theme="text-success", + height="200px", + ): + "Conversion Rate" + "3.8%" + "Increased by 0.5%" + + # 4. Value box with full screen capability and custom theme + with ui.value_box( + id="full_screen_value_box", + showcase=icon, + full_screen=True, + theme="bg-gradient-orange-red", + height="600px", + min_height="150px", + max_height="300px", + fill=True, + ): + "Total Sales" + "8,742" + "Year to date performance" + + # 5. Value box with custom background color using class_ + with ui.value_box( + id="custom_bg_value_box", + showcase=icon, + theme=None, + height="200px", + class_="bg-warning text-dark", + ): + "Pending Orders" + "156" + "Requires attention" diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/test_value_box_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/test_value_box_core_express.py new file mode 100644 index 000000000..7622c6e26 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/test_value_box_core_express.py @@ -0,0 +1,41 @@ +from playwright.sync_api import Page +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_value_boxes(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Test left-center value box + left_center_box = controller.ValueBox(page, "left_center_value_box") + left_center_box.expect_title("Revenue") + left_center_box.expect_value("$5.2M") + left_center_box.expect_height("200px") + + # Test top-right value box + top_right_box = controller.ValueBox(page, "top_right_value_box") + top_right_box.expect_title("Active Users") + top_right_box.expect_value("2.4K") + top_right_box.expect_height("200px") + + # Test bottom value box + bottom_box = controller.ValueBox(page, "bottom_value_box") + bottom_box.expect_title("Conversion Rate") + bottom_box.expect_value("3.8%") + bottom_box.expect_height("200px") + + # Test full screen value box + full_screen_box = controller.ValueBox(page, "full_screen_value_box") + full_screen_box.expect_title("Total Sales") + full_screen_box.expect_value("8,742") + full_screen_box.expect_height("600px") + full_screen_box.expect_full_screen_available(True) + + # Test custom background value box + custom_bg_box = controller.ValueBox(page, "custom_bg_value_box") + custom_bg_box.expect_title("Pending Orders") + custom_bg_box.expect_value("156") + custom_bg_box.expect_height("200px") From 48568d105f1b09aad150ec7062cc78157ee90da0 Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Wed, 5 Mar 2025 14:54:24 -0800 Subject: [PATCH 03/23] linting issues --- .../test_accordion_panel_core_express.py | 1 + .../test_card_footer_core_express.py | 1 + .../test_input_date_range_core_express.py | 2 -- .../input_file/test_input_file_core_express.py | 6 ++++-- .../test_input_numeric_core_express.py | 1 - .../test_input_select_core_express.py | 2 -- .../test_input_slider_core_express.py | 17 +++++++++-------- .../test_input_text_area_core_express.py | 2 +- .../test_update_tooltip_core_express.py | 2 +- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/test_accordion_panel_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/test_accordion_panel_core_express.py index b9dad3534..30d34eba9 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/test_accordion_panel_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/test_accordion_panel_core_express.py @@ -6,6 +6,7 @@ app = create_app_fixture(["app-core.py", "app-express.py"]) + def test_accordion_demo(page: Page, app: ShinyAppProc) -> None: page.goto(app.url) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/test_card_footer_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/test_card_footer_core_express.py index 950705545..8f8002606 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/test_card_footer_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/test_card_footer_core_express.py @@ -5,6 +5,7 @@ app = create_app_fixture(["app-core.py", "app-express.py"]) + def test_cards_with_footer(page: Page, app: ShinyAppProc) -> None: page.goto(app.url) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/test_input_date_range_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/test_input_date_range_core_express.py index 746d3f788..7d922a970 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/test_input_date_range_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/test_input_date_range_core_express.py @@ -44,5 +44,3 @@ def test_date_range_input(page: Page, app: ShinyAppProc) -> None: # Test setting dates at the boundaries date_range.set(("2020-01-01", "2025-12-31")) # Min and max dates date_range.expect_value(("2020-01-01", "2025-12-31")) - - diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/test_input_file_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/test_input_file_core_express.py index 710951f0d..9ac6786e6 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/test_input_file_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/test_input_file_core_express.py @@ -33,7 +33,7 @@ def test_file_input_demo(page: Page, app: ShinyAppProc) -> None: file_info: FilePayload = { "name": "users.csv", "mimeType": "text/csv", - "buffer": b",user_id,name,email\n1,Alice,alice@example.com\n2,\"Bob, Los Angeles\", bob\n", + "buffer": b',user_id,name,email\n1,Alice,alice@example.com\n2,"Bob, Los Angeles", bob\n', } file_input.set(file_info) @@ -46,7 +46,9 @@ def test_file_input_demo(page: Page, app: ShinyAppProc) -> None: # simulate uploading multiple files file_info2 = file_info.copy() file_info2["name"] = "users2.csv" - file_info2["buffer"] = b",user_id,name,email\n3,Charlie,charlie@example.com\n4,Dave,dave@example.com\n" + file_info2["buffer"] = ( + b",user_id,name,email\n3,Charlie,charlie@example.com\n4,Dave,dave@example.com\n" + ) file_input.set([file_info, file_info2]) file_input.expect_complete() diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/test_input_numeric_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/test_input_numeric_core_express.py index 1116c9fb3..cac3d42c0 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/test_input_numeric_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/test_input_numeric_core_express.py @@ -17,7 +17,6 @@ def test_numeric_inputs(page: Page, app: ShinyAppProc) -> None: basic.expect_value("10") basic_output.expect_value("Current value: 10") - # Test with new value basic.set("20") basic_output.expect_value("Current value: 20") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/test_input_select_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/test_input_select_core_express.py index 4b07406d7..6c0ae9078 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/test_input_select_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/test_input_select_core_express.py @@ -59,7 +59,6 @@ def test_input_select_demo(page: Page, app: ShinyAppProc) -> None: select5_value = controller.OutputText(page, "selected_value5") select5_value.expect_value("Selected: A") - # Test select with size parameter select6 = controller.InputSelect(page, "select6") select6.expect_label("Select with size parameter") @@ -68,4 +67,3 @@ def test_input_select_demo(page: Page, app: ShinyAppProc) -> None: select6.expect_multiple(False) select6_value = controller.OutputText(page, "selected_value6") select6_value.expect_value("Selected: A") - diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py index 2c728aeb7..d7d810ba8 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py @@ -19,7 +19,6 @@ def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: slider1.expect_max("100") slider1.expect_value("50") - # Test slider with step slider2 = controller.InputSlider(page, "slider2") value2 = controller.OutputText(page, "value2") @@ -44,8 +43,8 @@ def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: value4 = controller.OutputText(page, "value4") value4.expect_value("Value: 2023-06-15") slider4.expect_label("Select a date") - slider4.expect_min("1672560000000.0") # 2023-01-01 - slider4.expect_max("1704009600000.0") # 2023-12-31 + slider4.expect_min("1672560000000.0") # 2023-01-01 + slider4.expect_max("1704009600000.0") # 2023-12-31 slider4.expect_value("2023-06-15") # Test animated slider @@ -82,10 +81,12 @@ def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: # Test date range slider slider9 = controller.InputSliderRange(page, "slider9") value9 = controller.OutputText(page, "value9") - value9.expect_value("Value: (datetime.date(2023, 3, 1), datetime.date(2023, 9, 30))") + value9.expect_value( + "Value: (datetime.date(2023, 3, 1), datetime.date(2023, 9, 30))" + ) slider9.expect_label("Draggable range") - slider9.expect_min("1672560000000.0") # 2023-01-01 - slider9.expect_max("1704009600000.0") # 2023-12-31 + slider9.expect_min("1672560000000.0") # 2023-01-01 + slider9.expect_max("1704009600000.0") # 2023-12-31 slider9.expect_value(("2023-03-01", "2023-09-30")) slider9.expect_drag_range("true") @@ -94,8 +95,8 @@ def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: value10 = controller.OutputText(page, "value10") value10.expect_value("Value: 2023-06-15 19:30:00") slider10.expect_label("With time format") - slider10.expect_min("1672560000000.0") # 2023-01-01 00:00 - slider10.expect_max("1704095940000.0") # 2023-12-31 23:59 + slider10.expect_min("1672560000000.0") # 2023-01-01 00:00 + slider10.expect_max("1704095940000.0") # 2023-12-31 23:59 slider10.expect_value("2023-06-15 19:30") slider10.expect_time_format("%Y-%m-%d %H:%M") slider10.expect_timezone("+0000") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/test_input_text_area_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/test_input_text_area_core_express.py index abfa50d8e..e20ecce9d 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/test_input_text_area_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/test_input_text_area_core_express.py @@ -18,7 +18,7 @@ def test_text_area_demo(page: Page, app: ShinyAppProc) -> None: "This is some default text.\nIt has multiple lines.\nYou can edit it!" ) text_area.expect_width("500px") - text_area.expect_height("192px") # 8 rows * 24px per row instead of 200px + text_area.expect_height("192px") # 8 rows * 24px per row instead of 200px text_area.expect_cols("50") text_area.expect_rows("8") text_area.expect_placeholder("Type something here...") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/test_update_tooltip_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/test_update_tooltip_core_express.py index 9967bbf70..cf6948fd8 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/test_update_tooltip_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/test_update_tooltip_core_express.py @@ -5,6 +5,7 @@ app = create_app_fixture(["app-core.py", "app-express.py"]) + def test_tooltip_demo(page: Page, app: ShinyAppProc) -> None: page.goto(app.url) @@ -48,4 +49,3 @@ def test_tooltip_demo(page: Page, app: ShinyAppProc) -> None: update_btn.click() tooltip.expect_active(True) tooltip.expect_body("Tooltip updated 2 times!") - From 1388794303dc407dd9a7dc069e3f9e7c85c3397a Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 6 Mar 2025 16:59:01 +0000 Subject: [PATCH 04/23] fixing imports --- .../accordion_panel/app-express.py | 2 +- .../shiny/tests_for_ai_generated_apps/card/app-express.py | 2 +- .../card/test_card_core_express.py | 4 ++-- .../shiny/tests_for_ai_generated_apps/card_footer/app-core.py | 2 +- .../tests_for_ai_generated_apps/card_footer/app-express.py | 2 +- .../card_footer/test_card_footer_core_express.py | 3 ++- .../input_action_button/app-express.py | 2 +- .../test_input_action_button_core_express.py | 1 + .../input_action_link/test_input_action_link_core_express.py | 1 + .../tests_for_ai_generated_apps/input_checkbox/app-express.py | 3 +-- .../input_checkbox/test_input_checkbox_core_express.py | 1 + .../input_checkbox_group/app-express.py | 1 - .../test_input_checkbox_group_core_express.py | 1 + .../input_dark_mode/app-express.py | 2 +- .../input_dark_mode/test_input_dark_mode_core_express.py | 1 + .../shiny/tests_for_ai_generated_apps/input_date/app-core.py | 1 + .../tests_for_ai_generated_apps/input_date/app-express.py | 3 ++- .../input_date/test_input_date_core_express.py | 1 + .../tests_for_ai_generated_apps/input_date_range/app-core.py | 1 + .../input_date_range/app-express.py | 4 ++-- .../input_date_range/test_input_date_range_core_express.py | 1 + .../shiny/tests_for_ai_generated_apps/input_file/app-core.py | 1 + .../tests_for_ai_generated_apps/input_file/app-express.py | 1 + .../input_file/test_input_file_core_express.py | 1 + .../tests_for_ai_generated_apps/input_numeric/app-express.py | 2 +- .../input_numeric/test_input_numeric_core_express.py | 1 + .../tests_for_ai_generated_apps/input_password/app-express.py | 2 +- .../input_password/test_input_password_core_express.py | 1 + .../test_input_radio_buttons_core_express.py | 1 + .../tests_for_ai_generated_apps/input_select/app-express.py | 2 +- .../input_select/test_input_select_core_express.py | 1 + .../tests_for_ai_generated_apps/input_slider/app-core.py | 1 + .../tests_for_ai_generated_apps/input_slider/app-express.py | 3 ++- .../input_slider/test_input_slider_core_express.py | 4 +++- .../input_switch/test_input_switch_core_express.py | 1 + .../input_task_button/app-express.py | 2 +- .../input_task_button/test_input_task_button_core_express.py | 1 + .../tests_for_ai_generated_apps/input_text/app-express.py | 2 +- .../input_text/test_input_text_core_express.py | 1 + .../input_text_area/test_input_text_area_core_express.py | 1 + .../update_tooltip/test_update_tooltip_core_express.py | 1 + .../tests_for_ai_generated_apps/value_box/app-express.py | 2 +- .../value_box/test_value_box_core_express.py | 1 + 43 files changed, 49 insertions(+), 23 deletions(-) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-express.py index 1002c599f..df6138eef 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-express.py @@ -1,5 +1,5 @@ from shiny import reactive -from shiny.express import input, ui, render +from shiny.express import input, render, ui # Add Font Awesome CSS in the head section first ui.head_content( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-express.py index 51fdfcb22..1e1c92375 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-express.py @@ -1,5 +1,5 @@ from shiny import reactive -from shiny.express import input, ui, render +from shiny.express import input, render, ui # Set page options ui.page_opts(fillable=True) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card/test_card_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/card/test_card_core_express.py index fd03d85cf..7dad28078 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/card/test_card_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/card/test_card_core_express.py @@ -1,8 +1,8 @@ from playwright.sync_api import Page + from shiny.playwright import controller -from shiny.run import ShinyAppProc from shiny.pytest import create_app_fixture - +from shiny.run import ShinyAppProc app = create_app_fixture(["app-core.py", "app-express.py"]) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-core.py index 839769862..e14763beb 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-core.py @@ -1,4 +1,4 @@ -from shiny import App, render, reactive, ui +from shiny import App, reactive, render, ui app_ui = ui.page_fillable( # First card with basic footer diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-express.py index 752eec5cf..22761bafc 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-express.py @@ -1,4 +1,4 @@ -from shiny.express import input, ui, render +from shiny.express import input, render, ui # Set page options including title ui.page_opts(title="Card Footer Demo", fillable=True) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/test_card_footer_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/test_card_footer_core_express.py index 8f8002606..211000fa3 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/test_card_footer_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/test_card_footer_core_express.py @@ -1,7 +1,8 @@ from playwright.sync_api import Page + from shiny.playwright import controller -from shiny.run import ShinyAppProc from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc app = create_app_fixture(["app-core.py", "app-express.py"]) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-express.py index 7136b540d..ccfd330d9 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-express.py @@ -1,5 +1,5 @@ from shiny import reactive -from shiny.express import input, ui, render +from shiny.express import input, render, ui # Add Font Awesome CSS for icons - this needs to be before any UI elements ui.head_content( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/test_input_action_button_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/test_input_action_button_core_express.py index daea1ba7f..74e9c4027 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/test_input_action_button_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/test_input_action_button_core_express.py @@ -1,4 +1,5 @@ from playwright.sync_api import Page + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/test_input_action_link_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/test_input_action_link_core_express.py index e5742a243..a782e897c 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/test_input_action_link_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/test_input_action_link_core_express.py @@ -1,4 +1,5 @@ from playwright.sync_api import Page, expect + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-express.py index c3ebbfd10..83a68c866 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-express.py @@ -1,6 +1,5 @@ from shiny import reactive -from shiny.express import input, ui, render - +from shiny.express import input, render, ui with ui.card(): ui.card_header("Checkbox Demo") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/test_input_checkbox_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/test_input_checkbox_core_express.py index c04f988b1..18b68ce4f 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/test_input_checkbox_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/test_input_checkbox_core_express.py @@ -1,4 +1,5 @@ from playwright.sync_api import Page + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-express.py index 3470d0dbb..797fd6c2a 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-express.py @@ -1,7 +1,6 @@ from shiny import reactive from shiny.express import input, render, ui - # Create sample choices with HTML formatting for demonstration choices = { "red": ui.span("Red", style="color: #FF0000;"), diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/test_input_checkbox_group_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/test_input_checkbox_group_core_express.py index fe9392e86..afcf9403b 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/test_input_checkbox_group_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/test_input_checkbox_group_core_express.py @@ -1,4 +1,5 @@ from playwright.sync_api import Page + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-express.py index a9fdd2006..1e4d68560 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-express.py @@ -1,5 +1,5 @@ from shiny import reactive -from shiny.express import input, ui, render +from shiny.express import input, render, ui # Add Font Awesome CSS ui.head_content( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/test_input_dark_mode_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/test_input_dark_mode_core_express.py index b1449a707..3f7436c5c 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/test_input_dark_mode_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/test_input_dark_mode_core_express.py @@ -1,4 +1,5 @@ from playwright.sync_api import Page + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-core.py index 992cc3dd4..b73f90b85 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-core.py @@ -1,4 +1,5 @@ from datetime import date + from shiny import App, reactive, render, ui app_ui = ui.page_fluid( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-express.py index 9be4f0aa0..073406af1 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-express.py @@ -1,6 +1,7 @@ from datetime import date + from shiny import reactive -from shiny.express import input, ui, render +from shiny.express import input, render, ui with ui.layout_column_wrap(): # Basic date input diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/test_input_date_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/test_input_date_core_express.py index 7a7487f70..86966c92e 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/test_input_date_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/test_input_date_core_express.py @@ -1,4 +1,5 @@ from playwright.sync_api import Page + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-core.py index 0140ee066..f7bac79f2 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-core.py @@ -1,4 +1,5 @@ from datetime import date + from shiny import App, reactive, render, ui # Define the UI diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-express.py index f270e713a..3ec2b8ba3 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-express.py @@ -1,7 +1,7 @@ from datetime import date -from shiny import reactive -from shiny.express import input, ui, render +from shiny import reactive +from shiny.express import input, render, ui # Add some descriptive text ui.h2("Date Range Input Example") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/test_input_date_range_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/test_input_date_range_core_express.py index 7d922a970..dbf081bf3 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/test_input_date_range_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/test_input_date_range_core_express.py @@ -1,4 +1,5 @@ from playwright.sync_api import Page + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py index 4714bcc34..ce6c9cd5d 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py @@ -1,4 +1,5 @@ import pandas as pd + from shiny import App, reactive, render, ui from shiny.types import FileInfo diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py index 4279891e2..eafb7f756 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py @@ -1,4 +1,5 @@ import pandas as pd + from shiny import reactive from shiny.express import input, render, ui from shiny.types import FileInfo diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/test_input_file_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/test_input_file_core_express.py index 9ac6786e6..a8bbe41fb 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/test_input_file_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/test_input_file_core_express.py @@ -1,4 +1,5 @@ from playwright.sync_api import Page + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-express.py index add71fbde..ab1fa3246 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-express.py @@ -1,5 +1,5 @@ from shiny import reactive -from shiny.express import input, ui, render +from shiny.express import input, render, ui # Set page title ui.page_opts(full_width=True) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/test_input_numeric_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/test_input_numeric_core_express.py index cac3d42c0..2b0e8f431 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/test_input_numeric_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/test_input_numeric_core_express.py @@ -1,4 +1,5 @@ from playwright.sync_api import Page + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-express.py index 07b7bcbe8..47cdf68b2 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-express.py @@ -1,5 +1,5 @@ from shiny import reactive -from shiny.express import input, ui, render +from shiny.express import input, render, ui # Set page title ui.page_opts(full_width=True) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/test_input_password_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/test_input_password_core_express.py index 903b747a5..3abf1e531 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/test_input_password_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/test_input_password_core_express.py @@ -1,4 +1,5 @@ from playwright.sync_api import Page + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/test_input_radio_buttons_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/test_input_radio_buttons_core_express.py index b57371fc5..0972fcf7e 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/test_input_radio_buttons_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/test_input_radio_buttons_core_express.py @@ -1,4 +1,5 @@ from playwright.sync_api import Page + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-express.py index d209df06f..efdf71232 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-express.py @@ -1,5 +1,5 @@ from shiny import reactive -from shiny.express import input, ui, render +from shiny.express import input, render, ui # Sample data for different types of choices simple_choices = ["A", "B", "C", "D"] diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/test_input_select_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/test_input_select_core_express.py index 6c0ae9078..8b0da4f9f 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/test_input_select_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/test_input_select_core_express.py @@ -1,4 +1,5 @@ from playwright.sync_api import Page + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py index 55f8b3b15..edea01a23 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py @@ -1,4 +1,5 @@ from datetime import date, datetime + from shiny import App, reactive, render, ui app_ui = ui.page_fluid( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py index 67f181d66..19f1e88b7 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py @@ -1,6 +1,7 @@ from datetime import date, datetime + from shiny import reactive -from shiny.express import input, ui, render +from shiny.express import input, render, ui ui.page_opts(title="Slider Parameters Demo", full_width=True) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py index d7d810ba8..83999034d 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py @@ -1,8 +1,10 @@ +from datetime import date, datetime + from playwright.sync_api import Page + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc -from datetime import date, datetime app = create_app_fixture(["app-core.py", "app-express.py"]) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/test_input_switch_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/test_input_switch_core_express.py index 056bf70d8..2c5ca3531 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/test_input_switch_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/test_input_switch_core_express.py @@ -1,4 +1,5 @@ from playwright.sync_api import Page + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-express.py index eea64648b..90f5c69d5 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-express.py @@ -1,5 +1,5 @@ from shiny import reactive -from shiny.express import input, ui, render +from shiny.express import input, render, ui # Page options for basic styling ui.page_opts(fillable=True) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/test_input_task_button_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/test_input_task_button_core_express.py index 7cc47b1a9..fee1076bc 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/test_input_task_button_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/test_input_task_button_core_express.py @@ -1,4 +1,5 @@ from playwright.sync_api import Page + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-express.py index fc7c14b15..00aaf9316 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-express.py @@ -1,5 +1,5 @@ from shiny import reactive -from shiny.express import input, ui, render +from shiny.express import input, render, ui # Set page options for a clean layout ui.page_opts(fillable=True) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/test_input_text_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/test_input_text_core_express.py index d277839c4..a5d6eb0d9 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/test_input_text_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/test_input_text_core_express.py @@ -1,4 +1,5 @@ from playwright.sync_api import Page + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/test_input_text_area_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/test_input_text_area_core_express.py index e20ecce9d..b82711cae 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/test_input_text_area_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/test_input_text_area_core_express.py @@ -1,4 +1,5 @@ from playwright.sync_api import Page + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/test_update_tooltip_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/test_update_tooltip_core_express.py index cf6948fd8..1202a7e2b 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/test_update_tooltip_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/test_update_tooltip_core_express.py @@ -1,4 +1,5 @@ from playwright.sync_api import Page + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py index 0b3325378..993c7f808 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py @@ -1,5 +1,5 @@ from shiny import reactive -from shiny.express import input, ui, render +from shiny.express import input, render, ui ui.page_opts(fillable=True) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/test_value_box_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/test_value_box_core_express.py index 7622c6e26..f5111c5f0 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/test_value_box_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/test_value_box_core_express.py @@ -1,4 +1,5 @@ from playwright.sync_api import Page + from shiny.playwright import controller from shiny.pytest import create_app_fixture from shiny.run import ShinyAppProc From 1fc21fcb57d922c1e43f1c3c1b5de9bbe0985691 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 6 Mar 2025 17:25:20 +0000 Subject: [PATCH 05/23] address flake8 issues --- .../tests_for_ai_generated_apps/accordion_panel/app-core.py | 2 +- .../accordion_panel/app-express.py | 1 - .../shiny/tests_for_ai_generated_apps/card/app-core.py | 2 +- .../shiny/tests_for_ai_generated_apps/card/app-express.py | 5 ++--- .../tests_for_ai_generated_apps/card_footer/app-core.py | 3 +-- .../input_action_button/app-core.py | 2 +- .../input_action_button/app-express.py | 1 - .../input_action_link/app-core.py | 2 +- .../input_action_link/app-express.py | 1 - .../tests_for_ai_generated_apps/input_checkbox/app-core.py | 2 +- .../input_checkbox/app-express.py | 1 - .../input_checkbox_group/app-core.py | 2 +- .../input_checkbox_group/app-express.py | 1 - .../tests_for_ai_generated_apps/input_dark_mode/app-core.py | 2 +- .../input_dark_mode/app-express.py | 1 - .../shiny/tests_for_ai_generated_apps/input_date/app-core.py | 2 +- .../tests_for_ai_generated_apps/input_date/app-express.py | 1 - .../tests_for_ai_generated_apps/input_date_range/app-core.py | 2 +- .../input_date_range/app-express.py | 1 - .../shiny/tests_for_ai_generated_apps/input_file/app-core.py | 2 +- .../tests_for_ai_generated_apps/input_file/app-express.py | 1 - .../input_file/test_input_file_core_express.py | 2 +- .../tests_for_ai_generated_apps/input_numeric/app-core.py | 2 +- .../tests_for_ai_generated_apps/input_numeric/app-express.py | 1 - .../input_numeric/test_input_numeric_core_express.py | 3 --- .../tests_for_ai_generated_apps/input_password/app-core.py | 2 +- .../input_password/app-express.py | 1 - .../input_radio_buttons/app-core.py | 2 +- .../input_radio_buttons/app-express.py | 1 - .../tests_for_ai_generated_apps/input_select/app-core.py | 2 +- .../tests_for_ai_generated_apps/input_select/app-express.py | 1 - .../tests_for_ai_generated_apps/input_slider/app-core.py | 2 +- .../tests_for_ai_generated_apps/input_slider/app-express.py | 2 +- .../tests_for_ai_generated_apps/input_switch/app-core.py | 2 +- .../tests_for_ai_generated_apps/input_switch/app-express.py | 1 - .../input_task_button/app-core.py | 2 +- .../input_task_button/app-express.py | 1 - .../shiny/tests_for_ai_generated_apps/input_text/app-core.py | 2 +- .../tests_for_ai_generated_apps/input_text/app-express.py | 1 - .../tests_for_ai_generated_apps/input_text_area/app-core.py | 2 +- .../input_text_area/app-express.py | 1 - .../update_tooltip/app-express.py | 2 +- .../tests_for_ai_generated_apps/value_box/app-express.py | 2 +- 43 files changed, 26 insertions(+), 48 deletions(-) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-core.py index d59c64751..1ef556042 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-core.py @@ -1,4 +1,4 @@ -from shiny import App, reactive, render, ui +from shiny import App, render, ui # Define the UI app_ui = ui.page_fillable( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-express.py index df6138eef..e4f72674d 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-express.py @@ -1,4 +1,3 @@ -from shiny import reactive from shiny.express import input, render, ui # Add Font Awesome CSS in the head section first diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-core.py index 9bc7d15e9..c84a329fd 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-core.py @@ -1,4 +1,4 @@ -from shiny import App, reactive, render, ui +from shiny import App, render, ui # Define the UI app_ui = ui.page_fillable( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-express.py index 1e1c92375..6a30cdd9a 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-express.py @@ -1,5 +1,4 @@ -from shiny import reactive -from shiny.express import input, render, ui +from shiny.express import render, ui # Set page options ui.page_opts(fillable=True) @@ -20,7 +19,7 @@ """ This is the main content of the card. The card has various parameters set including: - + * full_screen=True - allows expanding to full screen * height='300px' - sets fixed height * fill=True - allows card to grow/shrink diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-core.py index e14763beb..572ac84cd 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-core.py @@ -1,4 +1,4 @@ -from shiny import App, reactive, render, ui +from shiny import App, render, ui app_ui = ui.page_fillable( # First card with basic footer @@ -42,7 +42,6 @@ def server(input, output, session): - @output @render.text def click_count(): if not input.btn(): diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-core.py index a65d3b3cc..84e26dec3 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-core.py @@ -1,4 +1,4 @@ -from shiny import App, reactive, render, ui +from shiny import App, render, ui # Create the UI app_ui = ui.page_fluid( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-express.py index ccfd330d9..d65be4267 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-express.py @@ -1,4 +1,3 @@ -from shiny import reactive from shiny.express import input, render, ui # Add Font Awesome CSS for icons - this needs to be before any UI elements diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-core.py index e27f33c27..aaa54a556 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-core.py @@ -1,4 +1,4 @@ -from shiny import App, reactive, render, ui +from shiny import App, render, ui # Define the UI app_ui = ui.page_fillable( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-express.py index a3e293bfb..a3bb67e83 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-express.py @@ -1,4 +1,3 @@ -from shiny import reactive from shiny.express import input, render, ui # Add Font Awesome CSS in the head section diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-core.py index 46df2b9ea..e75e6e118 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-core.py @@ -1,4 +1,4 @@ -from shiny import App, reactive, render, ui +from shiny import App, render, ui # Define the UI app_ui = ui.page_fluid( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-express.py index 83a68c866..7e5a0bc61 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-express.py @@ -1,4 +1,3 @@ -from shiny import reactive from shiny.express import input, render, ui with ui.card(): diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-core.py index f572a55ab..298f65316 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-core.py @@ -1,4 +1,4 @@ -from shiny import App, reactive, render, ui +from shiny import App, render, ui # Create sample choices with HTML formatting for demonstration choices = { diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-express.py index 797fd6c2a..a51840354 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-express.py @@ -1,4 +1,3 @@ -from shiny import reactive from shiny.express import input, render, ui # Create sample choices with HTML formatting for demonstration diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-core.py index 1c3bd5707..8cb4a95b4 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-core.py @@ -1,4 +1,4 @@ -from shiny import App, reactive, render, ui +from shiny import App, render, ui # Define the UI app_ui = ui.page_fillable( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-express.py index 1e4d68560..f09e22482 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-express.py @@ -1,4 +1,3 @@ -from shiny import reactive from shiny.express import input, render, ui # Add Font Awesome CSS diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-core.py index b73f90b85..1bc10cfd2 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-core.py @@ -1,6 +1,6 @@ from datetime import date -from shiny import App, reactive, render, ui +from shiny import App, render, ui app_ui = ui.page_fluid( ui.layout_column_wrap( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-express.py index 073406af1..c1906f561 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-express.py @@ -1,6 +1,5 @@ from datetime import date -from shiny import reactive from shiny.express import input, render, ui with ui.layout_column_wrap(): diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-core.py index f7bac79f2..99ee33cf2 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-core.py @@ -1,6 +1,6 @@ from datetime import date -from shiny import App, reactive, render, ui +from shiny import App, render, ui # Define the UI app_ui = ui.page_fluid( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-express.py index 3ec2b8ba3..bbca2566b 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-express.py @@ -1,6 +1,5 @@ from datetime import date -from shiny import reactive from shiny.express import input, render, ui # Add some descriptive text diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py index ce6c9cd5d..e595783ad 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py @@ -1,6 +1,6 @@ import pandas as pd -from shiny import App, reactive, render, ui +from shiny import App, render, ui from shiny.types import FileInfo # Define the UI diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py index eafb7f756..6e378f887 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py @@ -1,6 +1,5 @@ import pandas as pd -from shiny import reactive from shiny.express import input, render, ui from shiny.types import FileInfo diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/test_input_file_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/test_input_file_core_express.py index a8bbe41fb..45da52e04 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/test_input_file_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/test_input_file_core_express.py @@ -1,4 +1,4 @@ -from playwright.sync_api import Page +from playwright.sync_api import FilePayload, Page from shiny.playwright import controller from shiny.pytest import create_app_fixture diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-core.py index c91208cec..3471a8b65 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-core.py @@ -1,4 +1,4 @@ -from shiny import App, reactive, render, ui +from shiny import App, render, ui app_ui = ui.page_fluid( ui.layout_column_wrap( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-express.py index ab1fa3246..7c3877994 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-express.py @@ -1,4 +1,3 @@ -from shiny import reactive from shiny.express import input, render, ui # Set page title diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/test_input_numeric_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/test_input_numeric_core_express.py index 2b0e8f431..82a97d6a8 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/test_input_numeric_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/test_input_numeric_core_express.py @@ -51,6 +51,3 @@ def test_numeric_inputs(page: Page, app: ShinyAppProc) -> None: with_width.expect_value("42") with_width.expect_width("200px") width_output.expect_value("Current value: 42") - - # Test all values output - all_values_output = controller.OutputText(page, "all_values") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-core.py index d5e541e2d..e36f5c381 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-core.py @@ -1,4 +1,4 @@ -from shiny import App, reactive, render, ui +from shiny import App, render, ui # Define the UI app_ui = ui.page_fluid( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-express.py index 47cdf68b2..335224daa 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-express.py @@ -1,4 +1,3 @@ -from shiny import reactive from shiny.express import input, render, ui # Set page title diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-core.py index f2d264082..1c939acc6 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-core.py @@ -1,4 +1,4 @@ -from shiny import App, reactive, render, ui +from shiny import App, render, ui # Create sample choices with HTML content choices = { diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-express.py index dc21dfe31..9ab37afe8 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-express.py @@ -1,4 +1,3 @@ -from shiny import reactive from shiny.express import input, render, ui # Set page title diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-core.py index fd308d6ef..e0d8ac126 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-core.py @@ -1,4 +1,4 @@ -from shiny import App, reactive, render, ui +from shiny import App, render, ui # Sample data for different types of choices simple_choices = ["A", "B", "C", "D"] diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-express.py index efdf71232..cabf7575e 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-express.py @@ -1,4 +1,3 @@ -from shiny import reactive from shiny.express import input, render, ui # Sample data for different types of choices diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py index edea01a23..e42d1cecc 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py @@ -1,4 +1,4 @@ -from datetime import date, datetime +from datetime import datetime from shiny import App, reactive, render, ui diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py index 19f1e88b7..78c7380d3 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py @@ -1,4 +1,4 @@ -from datetime import date, datetime +from datetime import datetime from shiny import reactive from shiny.express import input, render, ui diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-core.py index 1e3375d11..03bdae2fc 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-core.py @@ -1,4 +1,4 @@ -from shiny import App, reactive, render, ui +from shiny import App, render, ui # Define the UI app_ui = ui.page_fluid( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-express.py index 8ec1f43bb..2bf875fc4 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-express.py @@ -1,4 +1,3 @@ -from shiny import reactive from shiny.express import input, render, ui # Set page title diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-core.py index c99e646bb..3b12a6e1a 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-core.py @@ -1,4 +1,4 @@ -from shiny import App, reactive, render, ui +from shiny import App, render, ui # Define the UI app_ui = ui.page_fillable( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-express.py index 90f5c69d5..3c32fae22 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-express.py @@ -1,4 +1,3 @@ -from shiny import reactive from shiny.express import input, render, ui # Page options for basic styling diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-core.py index e97045f12..aa58431eb 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-core.py @@ -1,4 +1,4 @@ -from shiny import App, reactive, render, ui +from shiny import App, render, ui # Define the UI app_ui = ui.page_fillable( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-express.py index 00aaf9316..81b04b067 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-express.py @@ -1,4 +1,3 @@ -from shiny import reactive from shiny.express import input, render, ui # Set page options for a clean layout diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-core.py index 70ba252bb..bc190882b 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-core.py @@ -1,4 +1,4 @@ -from shiny import App, reactive, render, ui +from shiny import App, render, ui # Define the UI app_ui = ui.page_fluid( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-express.py index 5b3e1ae21..0f41661fd 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-express.py @@ -1,4 +1,3 @@ -from shiny import reactive from shiny.express import input, render, ui ui.page_opts(full_width=True) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/app-express.py index 8cbaec0d3..73a55f3e5 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/app-express.py @@ -1,5 +1,5 @@ from shiny import reactive -from shiny.express import input, render, ui +from shiny.express import input, ui # Page options ui.page_opts( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py index 993c7f808..3dd4c1bc1 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py @@ -1,5 +1,5 @@ from shiny import reactive -from shiny.express import input, render, ui +from shiny.express import ui ui.page_opts(fillable=True) From 7c59aab87c5721813812376710268cf84c2c7957 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 6 Mar 2025 17:59:20 +0000 Subject: [PATCH 06/23] fix missing imports --- .../input_action_link/test_input_action_link_core_express.py | 2 +- .../shiny/tests_for_ai_generated_apps/input_file/app-core.py | 2 +- .../tests_for_ai_generated_apps/input_file/app-express.py | 2 +- .../tests_for_ai_generated_apps/input_slider/app-core.py | 2 +- .../tests_for_ai_generated_apps/input_slider/app-express.py | 2 +- .../input_slider/test_input_slider_core_express.py | 4 +--- .../tests_for_ai_generated_apps/input_task_button/app-core.py | 2 +- .../input_task_button/app-express.py | 1 + .../tests_for_ai_generated_apps/value_box/app-express.py | 1 - 9 files changed, 8 insertions(+), 10 deletions(-) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/test_input_action_link_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/test_input_action_link_core_express.py index a782e897c..bba4557b8 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/test_input_action_link_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/test_input_action_link_core_express.py @@ -1,4 +1,4 @@ -from playwright.sync_api import Page, expect +from playwright.sync_api import Page from shiny.playwright import controller from shiny.pytest import create_app_fixture diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py index e595783ad..fc779fad3 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py @@ -1,6 +1,6 @@ import pandas as pd -from shiny import App, render, ui +from shiny import App, render, ui, reactive from shiny.types import FileInfo # Define the UI diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py index 6e378f887..4279891e2 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py @@ -1,5 +1,5 @@ import pandas as pd - +from shiny import reactive from shiny.express import input, render, ui from shiny.types import FileInfo diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py index e42d1cecc..edea01a23 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import date, datetime from shiny import App, reactive, render, ui diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py index 78c7380d3..19f1e88b7 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import date, datetime from shiny import reactive from shiny.express import input, render, ui diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py index 83999034d..928897cb7 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py @@ -1,5 +1,3 @@ -from datetime import date, datetime - from playwright.sync_api import Page from shiny.playwright import controller @@ -45,7 +43,7 @@ def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: value4 = controller.OutputText(page, "value4") value4.expect_value("Value: 2023-06-15") slider4.expect_label("Select a date") - slider4.expect_min("1672560000000.0") # 2023-01-01 + slider4.expect_min("1672531200000.0") # 2023-01-01 slider4.expect_max("1704009600000.0") # 2023-12-31 slider4.expect_value("2023-06-15") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-core.py index 3b12a6e1a..c99e646bb 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-core.py @@ -1,4 +1,4 @@ -from shiny import App, render, ui +from shiny import App, reactive, render, ui # Define the UI app_ui = ui.page_fillable( diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-express.py index 3c32fae22..90f5c69d5 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-express.py @@ -1,3 +1,4 @@ +from shiny import reactive from shiny.express import input, render, ui # Page options for basic styling diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py index 3dd4c1bc1..4c5c687ca 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py @@ -1,4 +1,3 @@ -from shiny import reactive from shiny.express import ui ui.page_opts(fillable=True) From ced84a29a33d25f3bd2108fd4d7a162dc3ea7795 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 6 Mar 2025 18:13:31 +0000 Subject: [PATCH 07/23] fix imports --- .../shiny/tests_for_ai_generated_apps/input_file/app-core.py | 2 +- .../shiny/tests_for_ai_generated_apps/input_file/app-express.py | 1 + .../tests_for_ai_generated_apps/input_slider/app-express.py | 1 - .../input_slider/test_input_slider_core_express.py | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py index fc779fad3..ce6c9cd5d 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py @@ -1,6 +1,6 @@ import pandas as pd -from shiny import App, render, ui, reactive +from shiny import App, reactive, render, ui from shiny.types import FileInfo # Define the UI diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py index 4279891e2..eafb7f756 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py @@ -1,4 +1,5 @@ import pandas as pd + from shiny import reactive from shiny.express import input, render, ui from shiny.types import FileInfo diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py index 19f1e88b7..bde2484c6 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py @@ -1,6 +1,5 @@ from datetime import date, datetime -from shiny import reactive from shiny.express import input, render, ui ui.page_opts(title="Slider Parameters Demo", full_width=True) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py index 928897cb7..f0585ef63 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py @@ -44,7 +44,7 @@ def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: value4.expect_value("Value: 2023-06-15") slider4.expect_label("Select a date") slider4.expect_min("1672531200000.0") # 2023-01-01 - slider4.expect_max("1704009600000.0") # 2023-12-31 + slider4.expect_max("1703980800000.0") # 2023-12-31 slider4.expect_value("2023-06-15") # Test animated slider From f0bc5b6dd48bc01d7ae8d7c4099343542bbfcb47 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 6 Mar 2025 18:28:20 +0000 Subject: [PATCH 08/23] fix times --- .../input_slider/test_input_slider_core_express.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py index f0585ef63..84ae6572e 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py @@ -85,7 +85,7 @@ def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: "Value: (datetime.date(2023, 3, 1), datetime.date(2023, 9, 30))" ) slider9.expect_label("Draggable range") - slider9.expect_min("1672560000000.0") # 2023-01-01 + slider9.expect_min("1672531200000.0") # 2023-01-01 slider9.expect_max("1704009600000.0") # 2023-12-31 slider9.expect_value(("2023-03-01", "2023-09-30")) slider9.expect_drag_range("true") @@ -96,7 +96,7 @@ def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: value10.expect_value("Value: 2023-06-15 19:30:00") slider10.expect_label("With time format") slider10.expect_min("1672560000000.0") # 2023-01-01 00:00 - slider10.expect_max("1704095940000.0") # 2023-12-31 23:59 + slider10.expect_max("1703980800000.0") # 2023-12-31 23:59 slider10.expect_value("2023-06-15 19:30") slider10.expect_time_format("%Y-%m-%d %H:%M") slider10.expect_timezone("+0000") From 9cb403c22c607b081d8c69b8107bbdd4989f8191 Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 6 Mar 2025 18:51:51 +0000 Subject: [PATCH 09/23] fix tests --- .../input_slider/test_input_slider_core_express.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py index 84ae6572e..3abdb317c 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py @@ -86,7 +86,7 @@ def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: ) slider9.expect_label("Draggable range") slider9.expect_min("1672531200000.0") # 2023-01-01 - slider9.expect_max("1704009600000.0") # 2023-12-31 + slider9.expect_max("1703980800000.0") # 2023-12-31 slider9.expect_value(("2023-03-01", "2023-09-30")) slider9.expect_drag_range("true") From b61850fa85fa5ad2fffa337ccd30a6fde6829d53 Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Thu, 6 Mar 2025 11:30:59 -0800 Subject: [PATCH 10/23] make apps use UTC timezone for consistent tests --- .../input_slider/app-core.py | 14 +++++++++----- .../input_slider/app-express.py | 14 +++++++++----- .../test_input_slider_core_express.py | 18 +++++++++--------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py index edea01a23..fb4bc226e 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py @@ -1,4 +1,4 @@ -from datetime import date, datetime +from datetime import date, datetime, timezone from shiny import App, reactive, render, ui @@ -36,6 +36,8 @@ min=date(2023, 1, 1), max=date(2023, 12, 31), value=date(2023, 6, 15), + time_format="%Y-%m-%d", + timezone="UTC", ), ui.output_text("value4"), ), @@ -79,6 +81,8 @@ min=date(2023, 1, 1), max=date(2023, 12, 31), value=(date(2023, 3, 1), date(2023, 9, 30)), + time_format="%Y-%m-%d", + timezone="UTC", drag_range=True, ), ui.output_text("value9"), @@ -89,11 +93,11 @@ ui.input_slider( "slider10", "With time format", - min=datetime(2023, 1, 1, 0, 0), - max=datetime(2023, 12, 31, 23, 59), - value=datetime(2023, 6, 15, 12, 30), + min=datetime(2023, 1, 1, 0, 0).replace(tzinfo=timezone.utc), + max=datetime(2023, 12, 31, 23, 59).replace(tzinfo=timezone.utc), + value=datetime(2023, 6, 15, 12, 30).replace(tzinfo=timezone.utc), time_format="%Y-%m-%d %H:%M", - timezone="+0000", + timezone="UTC", # Use UTC instead of "+0000" ), ui.output_text("value10"), ), diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py index bde2484c6..42cd45e19 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py @@ -1,4 +1,4 @@ -from datetime import date, datetime +from datetime import date, datetime, timezone from shiny.express import input, render, ui @@ -41,6 +41,8 @@ def value3(): min=date(2023, 1, 1), max=date(2023, 12, 31), value=date(2023, 6, 15), + time_format="%Y-%m-%d", + timezone="UTC", ) @render.text @@ -97,6 +99,8 @@ def value7(): max=date(2023, 12, 31), value=(date(2023, 3, 1), date(2023, 9, 30)), drag_range=True, + time_format="%Y-%m-%d", + timezone="UTC", ) @render.text @@ -109,11 +113,11 @@ def value9(): ui.input_slider( "slider10", "With time format", - min=datetime(2023, 1, 1, 0, 0), - max=datetime(2023, 12, 31, 23, 59), - value=datetime(2023, 6, 15, 12, 30), + min=datetime(2023, 1, 1, 0, 0).replace(tzinfo=timezone.utc), + max=datetime(2023, 12, 31, 23, 59).replace(tzinfo=timezone.utc), + value=datetime(2023, 6, 15, 12, 30).replace(tzinfo=timezone.utc), time_format="%Y-%m-%d %H:%M", - timezone="+0000", + timezone="UTC", ) @render.text diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py index 3abdb317c..15a3ab4f2 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py @@ -43,8 +43,8 @@ def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: value4 = controller.OutputText(page, "value4") value4.expect_value("Value: 2023-06-15") slider4.expect_label("Select a date") - slider4.expect_min("1672531200000.0") # 2023-01-01 - slider4.expect_max("1703980800000.0") # 2023-12-31 + slider4.expect_min("1672560000000.0") # 2023-01-01 + slider4.expect_max("1704009600000.0") # 2023-12-31 slider4.expect_value("2023-06-15") # Test animated slider @@ -85,18 +85,18 @@ def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: "Value: (datetime.date(2023, 3, 1), datetime.date(2023, 9, 30))" ) slider9.expect_label("Draggable range") - slider9.expect_min("1672531200000.0") # 2023-01-01 - slider9.expect_max("1703980800000.0") # 2023-12-31 + slider9.expect_min("1672560000000.0") # 2023-01-01 + slider9.expect_max("1704009600000.0") # 2023-12-31 slider9.expect_value(("2023-03-01", "2023-09-30")) slider9.expect_drag_range("true") # Test datetime slider slider10 = controller.InputSlider(page, "slider10") value10 = controller.OutputText(page, "value10") - value10.expect_value("Value: 2023-06-15 19:30:00") + value10.expect_value("Value: 2023-06-15 12:30:00") slider10.expect_label("With time format") - slider10.expect_min("1672560000000.0") # 2023-01-01 00:00 - slider10.expect_max("1703980800000.0") # 2023-12-31 23:59 - slider10.expect_value("2023-06-15 19:30") + slider10.expect_min("1672531200000.0") # 2023-01-01 00:00 + slider10.expect_max("1704067140000.0") # 2023-12-31 23:59 + slider10.expect_value("2023-06-15 12:30") slider10.expect_time_format("%Y-%m-%d %H:%M") - slider10.expect_timezone("+0000") + slider10.expect_timezone("UTC") From 5a1bc5c6e922fa20b7b2ef16dbc63433b4a74eaa Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Thu, 6 Mar 2025 12:11:35 -0800 Subject: [PATCH 11/23] use datetime instead of date --- .../input_slider/app-core.py | 9 ++++++--- .../input_slider/app-express.py | 11 +++++++---- .../input_slider/test_input_slider_core_express.py | 6 +++--- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py index fb4bc226e..91a38b0fa 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py @@ -78,9 +78,12 @@ ui.input_slider( "slider9", "Draggable range", - min=date(2023, 1, 1), - max=date(2023, 12, 31), - value=(date(2023, 3, 1), date(2023, 9, 30)), + min=datetime(2023, 1, 1, 0, 0).replace(tzinfo=timezone.utc), + max=datetime(2023, 12, 31, 0, 0).replace(tzinfo=timezone.utc), + value=( + datetime(2023, 3, 1, 0, 0).replace(tzinfo=timezone.utc), + datetime(2023, 9, 30, 0, 0).replace(tzinfo=timezone.utc), + ), time_format="%Y-%m-%d", timezone="UTC", drag_range=True, diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py index 42cd45e19..398e1b54a 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py @@ -95,12 +95,15 @@ def value7(): ui.input_slider( "slider9", "Draggable range", - min=date(2023, 1, 1), - max=date(2023, 12, 31), - value=(date(2023, 3, 1), date(2023, 9, 30)), - drag_range=True, + min=datetime(2023, 1, 1, 0, 0).replace(tzinfo=timezone.utc), + max=datetime(2023, 12, 31, 0, 0).replace(tzinfo=timezone.utc), + value=( + datetime(2023, 3, 1, 0, 0).replace(tzinfo=timezone.utc), + datetime(2023, 9, 30, 0, 0).replace(tzinfo=timezone.utc), + ), time_format="%Y-%m-%d", timezone="UTC", + drag_range=True, ) @render.text diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py index 15a3ab4f2..7248bad39 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py @@ -82,11 +82,11 @@ def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: slider9 = controller.InputSliderRange(page, "slider9") value9 = controller.OutputText(page, "value9") value9.expect_value( - "Value: (datetime.date(2023, 3, 1), datetime.date(2023, 9, 30))" + "Value: (datetime.datetime(2023, 3, 1, 0, 0), datetime.datetime(2023, 9, 30, 0, 0))" ) slider9.expect_label("Draggable range") - slider9.expect_min("1672560000000.0") # 2023-01-01 - slider9.expect_max("1704009600000.0") # 2023-12-31 + slider9.expect_min("1672531200000.0") # 2023-01-01 + slider9.expect_max("1703980800000.0") # 2023-12-31 slider9.expect_value(("2023-03-01", "2023-09-30")) slider9.expect_drag_range("true") From 4a48d5ccb403c25a165bc102a2380c16299274c3 Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Thu, 6 Mar 2025 12:52:29 -0800 Subject: [PATCH 12/23] use +0000 instead of UTC for timezone --- .../input_slider/app-core.py | 6 +- .../input_slider/app-express.py | 6 +- .../test_input_slider_core_express.py | 2 +- .../navset_pill/app-core.py | 55 +++++++++++++++ .../navset_pill/app-express.py | 39 +++++++++++ .../test_navset_pill_core_express.py | 67 +++++++++++++++++++ 6 files changed, 168 insertions(+), 7 deletions(-) create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/navset_pill/app-core.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/navset_pill/app-express.py create mode 100644 tests/playwright/shiny/tests_for_ai_generated_apps/navset_pill/test_navset_pill_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py index 91a38b0fa..97ecf8cb2 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py @@ -37,7 +37,7 @@ max=date(2023, 12, 31), value=date(2023, 6, 15), time_format="%Y-%m-%d", - timezone="UTC", + timezone="+0000", ), ui.output_text("value4"), ), @@ -85,7 +85,7 @@ datetime(2023, 9, 30, 0, 0).replace(tzinfo=timezone.utc), ), time_format="%Y-%m-%d", - timezone="UTC", + timezone="+0000", drag_range=True, ), ui.output_text("value9"), @@ -100,7 +100,7 @@ max=datetime(2023, 12, 31, 23, 59).replace(tzinfo=timezone.utc), value=datetime(2023, 6, 15, 12, 30).replace(tzinfo=timezone.utc), time_format="%Y-%m-%d %H:%M", - timezone="UTC", # Use UTC instead of "+0000" + timezone="+0000", # Use "+0000" instead of UTC ), ui.output_text("value10"), ), diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py index 398e1b54a..7a66f163a 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py @@ -42,7 +42,7 @@ def value3(): max=date(2023, 12, 31), value=date(2023, 6, 15), time_format="%Y-%m-%d", - timezone="UTC", + timezone="+0000", ) @render.text @@ -102,7 +102,7 @@ def value7(): datetime(2023, 9, 30, 0, 0).replace(tzinfo=timezone.utc), ), time_format="%Y-%m-%d", - timezone="UTC", + timezone="+0000", drag_range=True, ) @@ -120,7 +120,7 @@ def value9(): max=datetime(2023, 12, 31, 23, 59).replace(tzinfo=timezone.utc), value=datetime(2023, 6, 15, 12, 30).replace(tzinfo=timezone.utc), time_format="%Y-%m-%d %H:%M", - timezone="UTC", + timezone="+0000", ) @render.text diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py index 7248bad39..7e1e4040e 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py @@ -99,4 +99,4 @@ def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: slider10.expect_max("1704067140000.0") # 2023-12-31 23:59 slider10.expect_value("2023-06-15 12:30") slider10.expect_time_format("%Y-%m-%d %H:%M") - slider10.expect_timezone("UTC") + slider10.expect_timezone("+0000") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/navset_pill/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/navset_pill/app-core.py new file mode 100644 index 000000000..8da59279e --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/navset_pill/app-core.py @@ -0,0 +1,55 @@ +from shiny import App, render, ui + +# Define the UI +app_ui = ui.page_fillable( + # Create a navset_pill with all possible parameters + ui.navset_pill( + # Panel A + ui.nav_panel( + "A", + "This is content for Panel A", + ui.input_slider("n1", "N1", min=0, max=100, value=20), + ui.output_text("panel_a_text"), + ), + # Panel B + ui.nav_panel( + "B", + "This is content for Panel B", + ui.input_numeric("n2", "N2", value=10), + ui.output_text("panel_b_text"), + ), + # Panel C + ui.nav_panel( + "C", + "This is content for Panel C", + ui.input_text("txt", "Enter text", "Hello"), + ui.output_text("panel_c_text"), + ), + id="pills", + ), + # Show which panel is currently selected + ui.output_text("selected_panel"), +) + + +# Define the server +def server(input, output, session): + @render.text + def panel_a_text(): + return f"Value of n1: {input.n1()}" + + @render.text + def panel_b_text(): + return f"Value of n2: {input.n2()}" + + @render.text + def panel_c_text(): + return f"You entered: {input.txt()}" + + @render.text + def selected_panel(): + return f"Currently selected panel: {input.pills()}" + + +# Create the app +app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/navset_pill/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/navset_pill/app-express.py new file mode 100644 index 000000000..8ef6d6796 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/navset_pill/app-express.py @@ -0,0 +1,39 @@ +from shiny.express import input, render, ui + +# Page options for the app +ui.page_opts(fillable=True) + +# Create a navset_pill with all possible parameters +with ui.navset_pill(id="pills"): + # Panel A + with ui.nav_panel("A"): + "This is content for Panel A" + ui.input_slider("n1", "N1", min=0, max=100, value=20) + + @render.text + def panel_a_text(): + return f"Value of n1: {input.n1()}" + + # Panel B + with ui.nav_panel("B"): + "This is content for Panel B" + ui.input_numeric("n2", "N2", value=10) + + @render.text + def panel_b_text(): + return f"Value of n2: {input.n2()}" + + # Panel C + with ui.nav_panel("C"): + "This is content for Panel C" + ui.input_text("txt", "Enter text", "Hello") + + @render.text + def panel_c_text(): + return f"You entered: {input.txt()}" + + +# Show which panel is currently selected +@render.text +def selected_panel(): + return f"Currently selected panel: {input.pills()}" diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/navset_pill/test_navset_pill_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/navset_pill/test_navset_pill_core_express.py new file mode 100644 index 000000000..d080ca743 --- /dev/null +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/navset_pill/test_navset_pill_core_express.py @@ -0,0 +1,67 @@ +from playwright.sync_api import Page + +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_navset_pill_demo(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Test navset pill + navset = controller.NavsetPill(page, "pills") + selected_panel_text = controller.OutputText(page, "selected_panel") + + # Test initial state + navset.expect_nav_titles(["A", "B", "C"]) + navset.expect_nav_values(["A", "B", "C"]) + navset.expect_value("A") # First panel should be selected by default + selected_panel_text.expect_value("Currently selected panel: A") + + # Test Panel A components + slider = controller.InputSlider(page, "n1") + panel_a_text = controller.OutputText(page, "panel_a_text") + + slider.expect_label("N1") + slider.expect_min("0") + slider.expect_max("100") + slider.expect_value("20") + panel_a_text.expect_value("Value of n1: 20") + + # Change slider value and verify + slider.set("50") + panel_a_text.expect_value("Value of n1: 50") + + # Switch to Panel B and test its components + navset.set("B") + navset.expect_value("B") + selected_panel_text.expect_value("Currently selected panel: B") + + numeric = controller.InputNumeric(page, "n2") + panel_b_text = controller.OutputText(page, "panel_b_text") + + numeric.expect_label("N2") + numeric.expect_value("10") + panel_b_text.expect_value("Value of n2: 10") + + # Change numeric value and verify + numeric.set("25") + panel_b_text.expect_value("Value of n2: 25") + + # Switch to Panel C and test its components + navset.set("C") + navset.expect_value("C") + selected_panel_text.expect_value("Currently selected panel: C") + + text_input = controller.InputText(page, "txt") + panel_c_text = controller.OutputText(page, "panel_c_text") + + text_input.expect_label("Enter text") + text_input.expect_value("Hello") + panel_c_text.expect_value("You entered: Hello") + + # Change text value and verify + text_input.set("Testing") + panel_c_text.expect_value("You entered: Testing") From b5d103254c59cc66f4c4a5c6b56b4aef5254f8d7 Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Thu, 6 Mar 2025 13:06:15 -0800 Subject: [PATCH 13/23] use +0800 instead of +0000 --- .../tests_for_ai_generated_apps/input_slider/app-core.py | 6 +++--- .../tests_for_ai_generated_apps/input_slider/app-express.py | 6 +++--- .../input_slider/test_input_slider_core_express.py | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py index 97ecf8cb2..81587545d 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py @@ -37,7 +37,7 @@ max=date(2023, 12, 31), value=date(2023, 6, 15), time_format="%Y-%m-%d", - timezone="+0000", + timezone="+0800", ), ui.output_text("value4"), ), @@ -85,7 +85,7 @@ datetime(2023, 9, 30, 0, 0).replace(tzinfo=timezone.utc), ), time_format="%Y-%m-%d", - timezone="+0000", + timezone="+0800", drag_range=True, ), ui.output_text("value9"), @@ -100,7 +100,7 @@ max=datetime(2023, 12, 31, 23, 59).replace(tzinfo=timezone.utc), value=datetime(2023, 6, 15, 12, 30).replace(tzinfo=timezone.utc), time_format="%Y-%m-%d %H:%M", - timezone="+0000", # Use "+0000" instead of UTC + timezone="+0800", # Use "+0000" instead of UTC ), ui.output_text("value10"), ), diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py index 7a66f163a..befe563bc 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py @@ -42,7 +42,7 @@ def value3(): max=date(2023, 12, 31), value=date(2023, 6, 15), time_format="%Y-%m-%d", - timezone="+0000", + timezone="+0800", ) @render.text @@ -102,7 +102,7 @@ def value7(): datetime(2023, 9, 30, 0, 0).replace(tzinfo=timezone.utc), ), time_format="%Y-%m-%d", - timezone="+0000", + timezone="+0800", drag_range=True, ) @@ -120,7 +120,7 @@ def value9(): max=datetime(2023, 12, 31, 23, 59).replace(tzinfo=timezone.utc), value=datetime(2023, 6, 15, 12, 30).replace(tzinfo=timezone.utc), time_format="%Y-%m-%d %H:%M", - timezone="+0000", + timezone="+0800", ) @render.text diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py index 7e1e4040e..002034733 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py @@ -97,6 +97,6 @@ def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: slider10.expect_label("With time format") slider10.expect_min("1672531200000.0") # 2023-01-01 00:00 slider10.expect_max("1704067140000.0") # 2023-12-31 23:59 - slider10.expect_value("2023-06-15 12:30") + slider10.expect_value("2023-06-15 20:30") slider10.expect_time_format("%Y-%m-%d %H:%M") - slider10.expect_timezone("+0000") + slider10.expect_timezone("+0800") From 3e97957473c8707e194393dcc93672360519f93f Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Thu, 6 Mar 2025 19:04:09 -0800 Subject: [PATCH 14/23] use consistent timezones --- .../input_slider/app-core.py | 14 +++++++------- .../input_slider/app-express.py | 14 +++++++------- .../input_slider/test_input_slider_core_express.py | 14 +++++++------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py index 81587545d..8b0862df3 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py @@ -78,11 +78,11 @@ ui.input_slider( "slider9", "Draggable range", - min=datetime(2023, 1, 1, 0, 0).replace(tzinfo=timezone.utc), - max=datetime(2023, 12, 31, 0, 0).replace(tzinfo=timezone.utc), + min=datetime(2023, 1, 1, 0, 0), + max=datetime(2023, 12, 31, 0, 0), value=( - datetime(2023, 3, 1, 0, 0).replace(tzinfo=timezone.utc), - datetime(2023, 9, 30, 0, 0).replace(tzinfo=timezone.utc), + datetime(2023, 3, 1, 0, 0), + datetime(2023, 9, 30, 0, 0), ), time_format="%Y-%m-%d", timezone="+0800", @@ -96,9 +96,9 @@ ui.input_slider( "slider10", "With time format", - min=datetime(2023, 1, 1, 0, 0).replace(tzinfo=timezone.utc), - max=datetime(2023, 12, 31, 23, 59).replace(tzinfo=timezone.utc), - value=datetime(2023, 6, 15, 12, 30).replace(tzinfo=timezone.utc), + min=datetime(2023, 1, 1, 0, 0), + max=datetime(2023, 12, 31, 23, 59), + value=datetime(2023, 6, 15, 12, 30), time_format="%Y-%m-%d %H:%M", timezone="+0800", # Use "+0000" instead of UTC ), diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py index befe563bc..3a8e1f0ea 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py @@ -95,11 +95,11 @@ def value7(): ui.input_slider( "slider9", "Draggable range", - min=datetime(2023, 1, 1, 0, 0).replace(tzinfo=timezone.utc), - max=datetime(2023, 12, 31, 0, 0).replace(tzinfo=timezone.utc), + min=datetime(2023, 1, 1, 0, 0), + max=datetime(2023, 12, 31, 0, 0), value=( - datetime(2023, 3, 1, 0, 0).replace(tzinfo=timezone.utc), - datetime(2023, 9, 30, 0, 0).replace(tzinfo=timezone.utc), + datetime(2023, 3, 1, 0, 0), + datetime(2023, 9, 30, 0, 0), ), time_format="%Y-%m-%d", timezone="+0800", @@ -116,9 +116,9 @@ def value9(): ui.input_slider( "slider10", "With time format", - min=datetime(2023, 1, 1, 0, 0).replace(tzinfo=timezone.utc), - max=datetime(2023, 12, 31, 23, 59).replace(tzinfo=timezone.utc), - value=datetime(2023, 6, 15, 12, 30).replace(tzinfo=timezone.utc), + min=datetime(2023, 1, 1, 0, 0), + max=datetime(2023, 12, 31, 23, 59), + value=datetime(2023, 6, 15, 12, 30), time_format="%Y-%m-%d %H:%M", timezone="+0800", ) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py index 002034733..d429d9fbe 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py @@ -82,21 +82,21 @@ def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: slider9 = controller.InputSliderRange(page, "slider9") value9 = controller.OutputText(page, "value9") value9.expect_value( - "Value: (datetime.datetime(2023, 3, 1, 0, 0), datetime.datetime(2023, 9, 30, 0, 0))" + "Value: (datetime.datetime(2023, 3, 1, 8, 0), datetime.datetime(2023, 9, 30, 7, 0))" ) slider9.expect_label("Draggable range") - slider9.expect_min("1672531200000.0") # 2023-01-01 - slider9.expect_max("1703980800000.0") # 2023-12-31 + slider9.expect_min("1672560000000.0") # 2023-01-01 + slider9.expect_max("1704009600000.0") # 2023-12-31 slider9.expect_value(("2023-03-01", "2023-09-30")) slider9.expect_drag_range("true") # Test datetime slider slider10 = controller.InputSlider(page, "slider10") value10 = controller.OutputText(page, "value10") - value10.expect_value("Value: 2023-06-15 12:30:00") + value10.expect_value("Value: 2023-06-15 19:30:00") slider10.expect_label("With time format") - slider10.expect_min("1672531200000.0") # 2023-01-01 00:00 - slider10.expect_max("1704067140000.0") # 2023-12-31 23:59 - slider10.expect_value("2023-06-15 20:30") + slider10.expect_min("1672560000000.0") # 2023-01-01 00:00 + slider10.expect_max("1704095940000.0") # 2023-12-31 23:59 + slider10.expect_value("2023-06-16 03:30") slider10.expect_time_format("%Y-%m-%d %H:%M") slider10.expect_timezone("+0800") From 6ffc625f03792cc8e26d35db55d773275c336b36 Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Thu, 6 Mar 2025 20:46:55 -0800 Subject: [PATCH 15/23] fix failing tests --- .../input_date/app-core.py | 145 ++++++------ .../input_date/app-express.py | 216 ++++++++++-------- .../input_slider/app-core.py | 26 ++- .../input_slider/app-express.py | 26 ++- .../test_input_slider_core_express.py | 18 +- .../value_box/app-core.py | 60 ++++- .../value_box/app-express.py | 62 ++++- .../value_box/test_value_box_core_express.py | 1 - 8 files changed, 348 insertions(+), 206 deletions(-) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-core.py index 1bc10cfd2..8df9cf0ad 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-core.py @@ -3,81 +3,97 @@ from shiny import App, render, ui app_ui = ui.page_fluid( - ui.layout_column_wrap( - ui.div( - ui.input_date("date1", "Default date input:", value="2024-01-01"), - ui.output_text("selected_date1"), + ui.h2("Date Input Parameters Demo"), + # Basic date input example + ui.div( + ui.input_date("date1", "Default date input:", value="2024-01-01"), + ui.output_text("selected_date1"), + ), + ui.br(), + # Date input with minimum and maximum date constraints + ui.div( + ui.input_date( + "date2", + "Date input with min/max:", + value=date(2024, 1, 1), # Using a date object instead of string + min="2024-01-01", + max="2024-12-31", ), - ui.div( - ui.input_date( - "date2", - "Date input with min/max:", - value=date(2024, 1, 1), - min="2024-01-01", - max="2024-12-31", - ), - ui.output_text("selected_date2"), + ui.output_text("selected_date2"), + ), + ui.br(), + # Date input with custom date format + ui.div( + ui.input_date( + "date3", + "Custom format (mm/dd/yy):", + value="2024-01-01", + format="mm/dd/yy", # Changes how date is displayed ), - ui.div( - ui.input_date( - "date3", - "Custom format (mm/dd/yy):", - value="2024-01-01", - format="mm/dd/yy", - ), - ui.output_text("selected_date3"), + ui.output_text("selected_date3"), + ), + ui.br(), + # Date input that opens to decade view instead of default month view + ui.div( + ui.input_date( + "date4", "Start in decade view:", value="2024-01-01", startview="decade" ), - ui.div( - ui.input_date( - "date4", "Start in decade view:", value="2024-01-01", startview="decade" - ), - ui.output_text("selected_date4"), + ui.output_text("selected_date4"), + ), + ui.br(), + # Date input with week starting on Monday (1) instead of Sunday (0) + ui.div( + ui.input_date( + "date5", "Week starts on Monday:", value="2024-01-01", weekstart=1 ), - ui.div( - ui.input_date( - "date5", "Week starts on Monday:", value="2024-01-01", weekstart=1 - ), - ui.output_text("selected_date5"), + ui.output_text("selected_date5"), + ), + ui.br(), + # Date input with German language localization + ui.div( + ui.input_date("date6", "German language:", value="2024-01-01", language="de"), + ui.output_text("selected_date6"), + ), + ui.br(), + # Date input with custom width + ui.div( + ui.input_date("date7", "Custom width:", value="2024-01-01", width="400px"), + ui.output_text("selected_date7"), + ), + # Date input where calendar doesn't auto-close after selection + ui.div( + ui.input_date( + "date8", "Autoclose disabled:", value="2024-01-01", autoclose=False ), - ui.div( - ui.input_date( - "date6", "German language:", value="2024-01-01", language="de" - ), - ui.output_text("selected_date6"), + ui.output_text("selected_date8"), + ), + ui.br(), + # Date input with specific dates disabled/unavailable for selection + ui.div( + ui.input_date( + "date9", + "Specific dates disabled:", + value="2024-01-01", + datesdisabled=["2024-01-15", "2024-01-16", "2024-01-17"], ), - ui.div( - ui.input_date("date7", "Custom width:", value="2024-01-01", width="400px"), - ui.output_text("selected_date7"), + ui.output_text("selected_date9"), + ), + ui.br(), + # Date input with weekend days disabled/unavailable for selection + ui.div( + ui.input_date( + "date10", + "Weekends disabled:", + value="2024-01-01", + daysofweekdisabled=[0, 6], # 0 = Sunday, 6 = Saturday ), - ui.div( - ui.input_date( - "date8", "Autoclose disabled:", value="2024-01-01", autoclose=False - ), - ui.output_text("selected_date8"), - ), - ui.div( - ui.input_date( - "date9", - "Specific dates disabled:", - value="2024-01-01", - datesdisabled=["2024-01-15", "2024-01-16", "2024-01-17"], - ), - ui.output_text("selected_date9"), - ), - ui.div( - ui.input_date( - "date10", - "Weekends disabled:", - value="2024-01-01", - daysofweekdisabled=[0, 6], # 0 = Sunday, 6 = Saturday - ), - ui.output_text("selected_date10"), - ), - ) + ui.output_text("selected_date10"), + ), ) def server(input, output, session): + # Server functions to display the selected date for each input @render.text def selected_date1(): return f"Selected date: {input.date1()}" @@ -119,4 +135,5 @@ def selected_date10(): return f"Selected date: {input.date10()}" +# Create and define the Shiny app with UI and server components app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-express.py index c1906f561..591a6d045 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-express.py @@ -2,93 +2,129 @@ from shiny.express import input, render, ui -with ui.layout_column_wrap(): - # Basic date input - ui.input_date("date1", "Default date input:", value="2024-01-01") - - @render.text - def selected_date1(): - return f"Selected date: {input.date1()}" - - # Date input with min and max dates - ui.input_date( - "date2", - "Date input with min/max:", - value=date(2024, 1, 1), - min="2024-01-01", - max="2024-12-31", - ) - - @render.text - def selected_date2(): - return f"Selected date: {input.date2()}" - - # Date input with custom format - ui.input_date( - "date3", "Custom format (mm/dd/yy):", value="2024-01-01", format="mm/dd/yy" - ) - - @render.text - def selected_date3(): - return f"Selected date: {input.date3()}" - - # Date input with decade view - ui.input_date( - "date4", "Start in decade view:", value="2024-01-01", startview="decade" - ) - - @render.text - def selected_date4(): - return f"Selected date: {input.date4()}" - - # Date input with week starting on Monday - ui.input_date("date5", "Week starts on Monday:", value="2024-01-01", weekstart=1) - - @render.text - def selected_date5(): - return f"Selected date: {input.date5()}" - - # Date input with German language - ui.input_date("date6", "German language:", value="2024-01-01", language="de") - - @render.text - def selected_date6(): - return f"Selected date: {input.date6()}" - - # Date input with custom width - ui.input_date("date7", "Custom width:", value="2024-01-01", width="400px") - - @render.text - def selected_date7(): - return f"Selected date: {input.date7()}" - - # Date input with autoclose disabled - ui.input_date("date8", "Autoclose disabled:", value="2024-01-01", autoclose=False) - - @render.text - def selected_date8(): - return f"Selected date: {input.date8()}" - - # Date input with specific dates disabled - ui.input_date( - "date9", - "Specific dates disabled:", - value="2024-01-01", - datesdisabled=["2024-01-15", "2024-01-16", "2024-01-17"], - ) - - @render.text - def selected_date9(): - return f"Selected date: {input.date9()}" - - # Date input with specific days of week disabled - ui.input_date( - "date10", - "Weekends disabled:", - value="2024-01-01", - daysofweekdisabled=[0, 6], # 0 = Sunday, 6 = Saturday - ) - - @render.text - def selected_date10(): - return f"Selected date: {input.date10()}" +ui.page_opts(title="Date Input Parameters Demo", full_width=True) + +# Basic date input +ui.input_date("date1", "Default date input:", value="2024-01-01") + + +@render.text +def selected_date1(): + return f"Selected date: {input.date1()}" + + +ui.br() + +# Date input with min and max dates +ui.input_date( + "date2", + "Date input with min/max:", + value=date(2024, 1, 1), + min="2024-01-01", + max="2024-12-31", +) + + +@render.text +def selected_date2(): + return f"Selected date: {input.date2()}" + + +ui.br() + +# Date input with custom format +ui.input_date( + "date3", "Custom format (mm/dd/yy):", value="2024-01-01", format="mm/dd/yy" +) + + +@render.text +def selected_date3(): + return f"Selected date: {input.date3()}" + + +ui.br() + +# Date input with decade view +ui.input_date("date4", "Start in decade view:", value="2024-01-01", startview="decade") + + +@render.text +def selected_date4(): + return f"Selected date: {input.date4()}" + + +ui.br() + +# Date input with week starting on Monday +ui.input_date("date5", "Week starts on Monday:", value="2024-01-01", weekstart=1) + + +@render.text +def selected_date5(): + return f"Selected date: {input.date5()}" + + +ui.br() + +# Date input with German language +ui.input_date("date6", "German language:", value="2024-01-01", language="de") + + +@render.text +def selected_date6(): + return f"Selected date: {input.date6()}" + + +ui.br() + +# Date input with custom width +ui.input_date("date7", "Custom width:", value="2024-01-01", width="400px") + + +@render.text +def selected_date7(): + return f"Selected date: {input.date7()}" + + +ui.br() + +# Date input with autoclose disabled +ui.input_date("date8", "Autoclose disabled:", value="2024-01-01", autoclose=False) + + +@render.text +def selected_date8(): + return f"Selected date: {input.date8()}" + + +ui.br() + +# Date input with specific dates disabled +ui.input_date( + "date9", + "Specific dates disabled:", + value="2024-01-01", + datesdisabled=["2024-01-15", "2024-01-16", "2024-01-17"], +) + + +@render.text +def selected_date9(): + return f"Selected date: {input.date9()}" + + +ui.br() + +# Date input with specific days of week disabled +ui.input_date( + "date10", + "Weekends disabled:", + value="2024-01-01", + daysofweekdisabled=[0, 6], # 0 = Sunday, 6 = Saturday +) + + +@render.text +def selected_date10(): + return f"Selected date: {input.date10()}" diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py index 8b0862df3..5437ab25b 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py @@ -1,7 +1,11 @@ -from datetime import date, datetime, timezone +from datetime import date, datetime +from zoneinfo import ZoneInfo from shiny import App, reactive, render, ui +# Define a consistent timezone +TIMEZONE = ZoneInfo("Asia/Singapore") + app_ui = ui.page_fluid( ui.panel_title("Slider Parameters Demo"), ui.layout_column_wrap( @@ -37,7 +41,7 @@ max=date(2023, 12, 31), value=date(2023, 6, 15), time_format="%Y-%m-%d", - timezone="+0800", + timezone="Asia/Singapore", ), ui.output_text("value4"), ), @@ -78,14 +82,14 @@ ui.input_slider( "slider9", "Draggable range", - min=datetime(2023, 1, 1, 0, 0), - max=datetime(2023, 12, 31, 0, 0), + min=datetime(2023, 1, 1, 0, 0, tzinfo=TIMEZONE), + max=datetime(2023, 12, 31, 0, 0, tzinfo=TIMEZONE), value=( - datetime(2023, 3, 1, 0, 0), - datetime(2023, 9, 30, 0, 0), + datetime(2023, 3, 1, 0, 0, tzinfo=TIMEZONE), + datetime(2023, 9, 30, 0, 0, tzinfo=TIMEZONE), ), time_format="%Y-%m-%d", - timezone="+0800", + timezone="Asia/Singapore", drag_range=True, ), ui.output_text("value9"), @@ -96,11 +100,11 @@ ui.input_slider( "slider10", "With time format", - min=datetime(2023, 1, 1, 0, 0), - max=datetime(2023, 12, 31, 23, 59), - value=datetime(2023, 6, 15, 12, 30), + min=datetime(2023, 1, 1, 0, 0, tzinfo=TIMEZONE), + max=datetime(2023, 12, 31, 23, 59, tzinfo=TIMEZONE), + value=datetime(2023, 6, 15, 12, 30, tzinfo=TIMEZONE), time_format="%Y-%m-%d %H:%M", - timezone="+0800", # Use "+0000" instead of UTC + timezone="Asia/Singapore", ), ui.output_text("value10"), ), diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py index 3a8e1f0ea..c9fb16775 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py @@ -1,7 +1,11 @@ -from datetime import date, datetime, timezone +from datetime import date, datetime +from zoneinfo import ZoneInfo from shiny.express import input, render, ui +# Define a consistent timezone +TIMEZONE = ZoneInfo("Asia/Singapore") + ui.page_opts(title="Slider Parameters Demo", full_width=True) with ui.layout_column_wrap(width="400px"): @@ -42,7 +46,7 @@ def value3(): max=date(2023, 12, 31), value=date(2023, 6, 15), time_format="%Y-%m-%d", - timezone="+0800", + timezone="Asia/Singapore", ) @render.text @@ -95,14 +99,14 @@ def value7(): ui.input_slider( "slider9", "Draggable range", - min=datetime(2023, 1, 1, 0, 0), - max=datetime(2023, 12, 31, 0, 0), + min=datetime(2023, 1, 1, 0, 0, tzinfo=TIMEZONE), + max=datetime(2023, 12, 31, 0, 0, tzinfo=TIMEZONE), value=( - datetime(2023, 3, 1, 0, 0), - datetime(2023, 9, 30, 0, 0), + datetime(2023, 3, 1, 0, 0, tzinfo=TIMEZONE), + datetime(2023, 9, 30, 0, 0, tzinfo=TIMEZONE), ), time_format="%Y-%m-%d", - timezone="+0800", + timezone="Asia/Singapore", drag_range=True, ) @@ -116,11 +120,11 @@ def value9(): ui.input_slider( "slider10", "With time format", - min=datetime(2023, 1, 1, 0, 0), - max=datetime(2023, 12, 31, 23, 59), - value=datetime(2023, 6, 15, 12, 30), + min=datetime(2023, 1, 1, 0, 0, tzinfo=TIMEZONE), + max=datetime(2023, 12, 31, 23, 59, tzinfo=TIMEZONE), + value=datetime(2023, 6, 15, 12, 30, tzinfo=TIMEZONE), time_format="%Y-%m-%d %H:%M", - timezone="+0800", + timezone="Asia/Singapore", ) @render.text diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py index d429d9fbe..3e51f6e5e 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py @@ -82,21 +82,21 @@ def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: slider9 = controller.InputSliderRange(page, "slider9") value9 = controller.OutputText(page, "value9") value9.expect_value( - "Value: (datetime.datetime(2023, 3, 1, 8, 0), datetime.datetime(2023, 9, 30, 7, 0))" + "Value: (datetime.datetime(2023, 2, 28, 16, 0), datetime.datetime(2023, 9, 29, 16, 0))" ) slider9.expect_label("Draggable range") - slider9.expect_min("1672560000000.0") # 2023-01-01 - slider9.expect_max("1704009600000.0") # 2023-12-31 - slider9.expect_value(("2023-03-01", "2023-09-30")) + slider9.expect_min("1672502400000.0") # 2023-01-01 + slider9.expect_max("1703952000000.0") # 2023-12-31 + slider9.expect_value(("2023-02-28", "2023-09-29")) slider9.expect_drag_range("true") # Test datetime slider slider10 = controller.InputSlider(page, "slider10") value10 = controller.OutputText(page, "value10") - value10.expect_value("Value: 2023-06-15 19:30:00") + value10.expect_value("Value: 2023-06-15 04:30:00") slider10.expect_label("With time format") - slider10.expect_min("1672560000000.0") # 2023-01-01 00:00 - slider10.expect_max("1704095940000.0") # 2023-12-31 23:59 - slider10.expect_value("2023-06-16 03:30") + slider10.expect_min("1672502400000.0") # 2023-01-01 00:00 + slider10.expect_max("1704038340000.0") # 2023-12-31 23:59 + slider10.expect_value("2023-06-15 04:30") slider10.expect_time_format("%Y-%m-%d %H:%M") - slider10.expect_timezone("+0800") + slider10.expect_timezone("Asia/Singapore") diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-core.py index 3286146ca..6cc4ce28c 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-core.py @@ -1,15 +1,32 @@ +import pandas as pd +import plotly.graph_objects as go +import shinywidgets as sw + from shiny import App, ui # Create a custom icon for the showcase using Font Awesome -icon = ui.tags.i(class_="fa-solid fa-chart-simple", style="font-size: 2rem;") +chart_icon = ui.tags.i(class_="fa-solid fa-chart-simple", style="font-size: 8rem;") +chart_thumbs_up_icon = ui.tags.i( + class_="fa-solid fa-thumbs-up", style="font-size: 5rem;" +) +chart_star_icon = ui.tags.i(class_="fa-solid fa-star", style="font-size: 5rem;") +chart_heart_icon = ui.tags.i(class_="fa-solid fa-heart", style="font-size: 5rem;") +chart_lightbulb_icon = ui.tags.i( + class_="fa-solid fa-lightbulb", style="font-size: 10rem;" +) -app_ui = ui.page_fillable( +data = pd.DataFrame( + {"Year": range(2018, 2024), "Revenue": [100, 120, 110, 122, 118, 130]} +) + +app_ui = ui.page_fluid( # Add Font Awesome CSS to the app ui.head_content( ui.HTML( - '' + '' ) ), + ui.br(), ui.layout_column_wrap( # 1. Basic value box with left-center showcase layout (default) ui.value_box( @@ -17,9 +34,8 @@ "$5.2M", "Up 12% from last month", id="left_center_value_box", - showcase=icon, + showcase=chart_icon, theme="primary", - height="200px", ), # 2. Value box with top-right showcase layout ui.value_box( @@ -27,7 +43,7 @@ "2.4K", "Daily active users", id="top_right_value_box", - showcase=icon, + showcase=chart_thumbs_up_icon, showcase_layout="top right", theme="bg-gradient-purple-red", height="200px", @@ -38,7 +54,7 @@ "3.8%", "Increased by 0.5%", id="bottom_value_box", - showcase=icon, + showcase=sw.output_widget("graph"), showcase_layout="bottom", theme="text-success", height="200px", @@ -49,7 +65,7 @@ "8,742", "Year to date performance", id="full_screen_value_box", - showcase=icon, + showcase=chart_lightbulb_icon, full_screen=True, theme="bg-gradient-orange-red", height="600px", @@ -63,7 +79,7 @@ "156", "Requires attention", id="custom_bg_value_box", - showcase=icon, + showcase=chart_heart_icon, theme=None, height="200px", class_="bg-warning text-dark", @@ -74,7 +90,31 @@ def server(input, output, session): - pass + @sw.render_plotly + def graph(): + fig = go.Figure() + + # Add line trace + fig.add_trace( + go.Scatter( + x=data["Year"], + y=data["Revenue"], + mode="lines+markers", + line=dict(color="blue", width=2), + marker=dict(size=4), + ) + ) + + # Update layout for sparkline appearance + fig.update_layout( + showlegend=False, + paper_bgcolor="mistyrose", + plot_bgcolor="rgba(0,0,0,0)", + xaxis=dict(showgrid=False, zeroline=False), + yaxis=dict(showgrid=False, zeroline=False), + ) + + return fig app = App(app_ui, server) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py index 4c5c687ca..5f26ed9ca 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py @@ -1,22 +1,37 @@ +import pandas as pd +import plotly.graph_objects as go +import shinywidgets as sw + from shiny.express import ui -ui.page_opts(fillable=True) +ui.page_opts(full_width=True) # Create a custom icon for the showcase using Font Awesome -icon = ui.tags.i(class_="fa-solid fa-chart-simple", style="font-size: 2rem;") +chart_icon = ui.tags.i(class_="fa-solid fa-chart-simple", style="font-size: 8rem;") +chart_thumbs_up_icon = ui.tags.i( + class_="fa-solid fa-thumbs-up", style="font-size: 5rem;" +) +chart_star_icon = ui.tags.i(class_="fa-solid fa-star", style="font-size: 5rem;") +chart_heart_icon = ui.tags.i(class_="fa-solid fa-heart", style="font-size: 5rem;") +chart_lightbulb_icon = ui.tags.i( + class_="fa-solid fa-lightbulb", style="font-size: 10rem;" +) + +data = pd.DataFrame( + {"Year": range(2018, 2024), "Revenue": [100, 120, 110, 122, 118, 130]} +) # Add Font Awesome CSS to the app ui.head_content( ui.HTML( - '' + '' ) ) +ui.br() with ui.layout_column_wrap(width="400px"): # 1. Basic value box with left-center showcase layout (default) - with ui.value_box( - id="left_center_value_box", showcase=icon, theme="primary", height="200px" - ): + with ui.value_box(id="left_center_value_box", showcase=chart_icon, theme="primary"): "Revenue" "$5.2M" "Up 12% from last month" @@ -24,7 +39,7 @@ # 2. Value box with top-right showcase layout with ui.value_box( id="top_right_value_box", - showcase=icon, + showcase=chart_thumbs_up_icon, showcase_layout="top right", theme="bg-gradient-purple-red", height="200px", @@ -36,7 +51,7 @@ # 3. Value box with bottom showcase layout with ui.value_box( id="bottom_value_box", - showcase=icon, + showcase=sw.output_widget("graph"), showcase_layout="bottom", theme="text-success", height="200px", @@ -44,11 +59,38 @@ "Conversion Rate" "3.8%" "Increased by 0.5%" + with ui.hold(): + + @sw.render_plotly + def graph(): + fig = go.Figure() + + # Add line trace + fig.add_trace( + go.Scatter( + x=data["Year"], + y=data["Revenue"], + mode="lines+markers", + line=dict(color="blue", width=2), + marker=dict(size=4), + ) + ) + + # Update layout for sparkline appearance + fig.update_layout( + showlegend=False, + paper_bgcolor="mistyrose", + plot_bgcolor="rgba(0,0,0,0)", + xaxis=dict(showgrid=False, zeroline=False), + yaxis=dict(showgrid=False, zeroline=False), + ) + + return fig # 4. Value box with full screen capability and custom theme with ui.value_box( id="full_screen_value_box", - showcase=icon, + showcase=chart_lightbulb_icon, full_screen=True, theme="bg-gradient-orange-red", height="600px", @@ -63,7 +105,7 @@ # 5. Value box with custom background color using class_ with ui.value_box( id="custom_bg_value_box", - showcase=icon, + showcase=chart_heart_icon, theme=None, height="200px", class_="bg-warning text-dark", diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/test_value_box_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/test_value_box_core_express.py index f5111c5f0..37ab0b907 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/test_value_box_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/test_value_box_core_express.py @@ -14,7 +14,6 @@ def test_value_boxes(page: Page, app: ShinyAppProc) -> None: left_center_box = controller.ValueBox(page, "left_center_value_box") left_center_box.expect_title("Revenue") left_center_box.expect_value("$5.2M") - left_center_box.expect_height("200px") # Test top-right value box top_right_box = controller.ValueBox(page, "top_right_value_box") From 8c9c910a788bb81b89b9630678891c90cb3ffee7 Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Thu, 6 Mar 2025 21:14:17 -0800 Subject: [PATCH 16/23] use consistent timezone --- .../input_slider/app-core.py | 15 ++++++------ .../input_slider/app-express.py | 16 ++++++------- .../test_input_slider_core_express.py | 24 +++++++++---------- 3 files changed, 27 insertions(+), 28 deletions(-) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py index 5437ab25b..f67be899a 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py @@ -1,10 +1,10 @@ -from datetime import date, datetime +from datetime import datetime from zoneinfo import ZoneInfo from shiny import App, reactive, render, ui # Define a consistent timezone -TIMEZONE = ZoneInfo("Asia/Singapore") +TIMEZONE = ZoneInfo("UTC") app_ui = ui.page_fluid( ui.panel_title("Slider Parameters Demo"), @@ -37,11 +37,10 @@ ui.input_slider( "slider4", "Select a date", - min=date(2023, 1, 1), - max=date(2023, 12, 31), - value=date(2023, 6, 15), + min=datetime(2023, 1, 1, 0, 0, tzinfo=TIMEZONE), + max=datetime(2023, 12, 31, 0, 0, tzinfo=TIMEZONE), + value=datetime(2023, 6, 15, 12, 30, tzinfo=TIMEZONE), time_format="%Y-%m-%d", - timezone="Asia/Singapore", ), ui.output_text("value4"), ), @@ -89,7 +88,7 @@ datetime(2023, 9, 30, 0, 0, tzinfo=TIMEZONE), ), time_format="%Y-%m-%d", - timezone="Asia/Singapore", + timezone="UTC", drag_range=True, ), ui.output_text("value9"), @@ -104,7 +103,7 @@ max=datetime(2023, 12, 31, 23, 59, tzinfo=TIMEZONE), value=datetime(2023, 6, 15, 12, 30, tzinfo=TIMEZONE), time_format="%Y-%m-%d %H:%M", - timezone="Asia/Singapore", + timezone="UTC", ), ui.output_text("value10"), ), diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py index c9fb16775..9bf518a0f 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py @@ -1,10 +1,10 @@ -from datetime import date, datetime +from datetime import datetime from zoneinfo import ZoneInfo from shiny.express import input, render, ui # Define a consistent timezone -TIMEZONE = ZoneInfo("Asia/Singapore") +TIMEZONE = ZoneInfo("UTC") ui.page_opts(title="Slider Parameters Demo", full_width=True) @@ -42,11 +42,11 @@ def value3(): ui.input_slider( "slider4", "Select a date", - min=date(2023, 1, 1), - max=date(2023, 12, 31), - value=date(2023, 6, 15), + min=datetime(2023, 1, 1, 0, 0, tzinfo=TIMEZONE), + max=datetime(2023, 12, 31, 0, 0, tzinfo=TIMEZONE), + value=datetime(2023, 6, 15, 12, 30, tzinfo=TIMEZONE), time_format="%Y-%m-%d", - timezone="Asia/Singapore", + timezone="UTC", ) @render.text @@ -106,7 +106,7 @@ def value7(): datetime(2023, 9, 30, 0, 0, tzinfo=TIMEZONE), ), time_format="%Y-%m-%d", - timezone="Asia/Singapore", + timezone="UTC", drag_range=True, ) @@ -124,7 +124,7 @@ def value9(): max=datetime(2023, 12, 31, 23, 59, tzinfo=TIMEZONE), value=datetime(2023, 6, 15, 12, 30, tzinfo=TIMEZONE), time_format="%Y-%m-%d %H:%M", - timezone="Asia/Singapore", + timezone="UTC", ) @render.text diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py index 3e51f6e5e..e39b1ef98 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py @@ -41,10 +41,10 @@ def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: # Test date slider slider4 = controller.InputSlider(page, "slider4") value4 = controller.OutputText(page, "value4") - value4.expect_value("Value: 2023-06-15") + value4.expect_value("Value: 2023-06-15 12:30:00") slider4.expect_label("Select a date") - slider4.expect_min("1672560000000.0") # 2023-01-01 - slider4.expect_max("1704009600000.0") # 2023-12-31 + slider4.expect_min("1672531200000.0") # 2023-01-01 + slider4.expect_max("1703980800000.0") # 2023-12-31 slider4.expect_value("2023-06-15") # Test animated slider @@ -82,21 +82,21 @@ def test_slider_parameters(page: Page, app: ShinyAppProc) -> None: slider9 = controller.InputSliderRange(page, "slider9") value9 = controller.OutputText(page, "value9") value9.expect_value( - "Value: (datetime.datetime(2023, 2, 28, 16, 0), datetime.datetime(2023, 9, 29, 16, 0))" + "Value: (datetime.datetime(2023, 3, 1, 0, 0), datetime.datetime(2023, 9, 30, 0, 0))" ) slider9.expect_label("Draggable range") - slider9.expect_min("1672502400000.0") # 2023-01-01 - slider9.expect_max("1703952000000.0") # 2023-12-31 - slider9.expect_value(("2023-02-28", "2023-09-29")) + slider9.expect_min("1672531200000.0") # 2023-01-01 + slider9.expect_max("1703980800000.0") # 2023-12-31 + slider9.expect_value(("2023-03-01", "2023-09-30")) slider9.expect_drag_range("true") # Test datetime slider slider10 = controller.InputSlider(page, "slider10") value10 = controller.OutputText(page, "value10") - value10.expect_value("Value: 2023-06-15 04:30:00") + value10.expect_value("Value: 2023-06-15 12:30:00") slider10.expect_label("With time format") - slider10.expect_min("1672502400000.0") # 2023-01-01 00:00 - slider10.expect_max("1704038340000.0") # 2023-12-31 23:59 - slider10.expect_value("2023-06-15 04:30") + slider10.expect_min("1672531200000.0") # 2023-01-01 00:00 + slider10.expect_max("1704067140000.0") # 2023-12-31 23:59 + slider10.expect_value("2023-06-15 12:30") slider10.expect_time_format("%Y-%m-%d %H:%M") - slider10.expect_timezone("Asia/Singapore") + slider10.expect_timezone("UTC") From 8a0efdf391f1fb55ef5e6ce8b9f059cf24e7c487 Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Thu, 6 Mar 2025 21:24:44 -0800 Subject: [PATCH 17/23] add padding 2px --- .../input_text_area/test_input_text_area_core_express.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/test_input_text_area_core_express.py b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/test_input_text_area_core_express.py index b82711cae..00839927d 100644 --- a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/test_input_text_area_core_express.py +++ b/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/test_input_text_area_core_express.py @@ -19,7 +19,7 @@ def test_text_area_demo(page: Page, app: ShinyAppProc) -> None: "This is some default text.\nIt has multiple lines.\nYou can edit it!" ) text_area.expect_width("500px") - text_area.expect_height("192px") # 8 rows * 24px per row instead of 200px + text_area.expect_height("194px") # 200px - padding text_area.expect_cols("50") text_area.expect_rows("8") text_area.expect_placeholder("Type something here...") From 23a35148b62176132258e5718ab3e3f88cca1162 Mon Sep 17 00:00:00 2001 From: Karan Date: Fri, 7 Mar 2025 05:45:30 +0000 Subject: [PATCH 18/23] move ai generated apps to separate job and directory --- .github/workflows/pytest.yaml | 45 ++++++++++++++++++- Makefile | 5 +++ .../accordion/app-core.py | 0 .../accordion/app-express.py | 0 .../accordion/test_accordion_core_express.py | 0 .../accordion_panel/app-core.py | 0 .../accordion_panel/app-express.py | 0 .../test_accordion_panel_core_express.py | 0 .../card/app-core.py | 0 .../card/app-express.py | 0 .../card/test_card_core_express.py | 0 .../card_footer/app-core.py | 0 .../card_footer/app-express.py | 0 .../test_card_footer_core_express.py | 0 .../input_action_button/app-core.py | 0 .../input_action_button/app-express.py | 0 .../test_input_action_button_core_express.py | 0 .../input_action_link/app-core.py | 0 .../input_action_link/app-express.py | 0 .../test_input_action_link_core_express.py | 0 .../input_checkbox/app-core.py | 0 .../input_checkbox/app-express.py | 0 .../test_input_checkbox_core_express.py | 0 .../input_checkbox_group/app-core.py | 0 .../input_checkbox_group/app-express.py | 0 .../test_input_checkbox_group_core_express.py | 0 .../input_dark_mode/app-core.py | 0 .../input_dark_mode/app-express.py | 0 .../test_input_dark_mode_core_express.py | 0 .../input_date/app-core.py | 0 .../input_date/app-express.py | 0 .../test_input_date_core_express.py | 0 .../input_date_range/app-core.py | 0 .../input_date_range/app-express.py | 0 .../test_input_date_range_core_express.py | 0 .../input_file/app-core.py | 0 .../input_file/app-express.py | 0 .../test_input_file_core_express.py | 0 .../input_numeric/app-core.py | 0 .../input_numeric/app-express.py | 0 .../test_input_numeric_core_express.py | 0 .../input_password/app-core.py | 0 .../input_password/app-express.py | 0 .../test_input_password_core_express.py | 0 .../input_radio_buttons/app-core.py | 0 .../input_radio_buttons/app-express.py | 0 .../test_input_radio_buttons_core_express.py | 0 .../input_select/app-core.py | 0 .../input_select/app-express.py | 0 .../test_input_select_core_express.py | 0 .../input_slider/app-core.py | 0 .../input_slider/app-express.py | 0 .../test_input_slider_core_express.py | 0 .../input_switch/app-core.py | 0 .../input_switch/app-express.py | 0 .../test_input_switch_core_express.py | 0 .../input_task_button/app-core.py | 0 .../input_task_button/app-express.py | 0 .../test_input_task_button_core_express.py | 0 .../input_text/app-core.py | 0 .../input_text/app-express.py | 0 .../test_input_text_core_express.py | 0 .../input_text_area/app-core.py | 0 .../input_text_area/app-express.py | 0 .../test_input_text_area_core_express.py | 0 .../navset_pill/app-core.py | 0 .../navset_pill/app-express.py | 0 .../test_navset_pill_core_express.py | 0 .../update_tooltip/app-core.py | 0 .../update_tooltip/app-express.py | 0 .../test_update_tooltip_core_express.py | 0 .../value_box/app-core.py | 0 .../value_box/app-express.py | 0 .../value_box/test_value_box_core_express.py | 0 74 files changed, 49 insertions(+), 1 deletion(-) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/accordion/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/accordion/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/accordion/test_accordion_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/accordion_panel/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/accordion_panel/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/accordion_panel/test_accordion_panel_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/card/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/card/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/card/test_card_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/card_footer/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/card_footer/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/card_footer/test_card_footer_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_action_button/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_action_button/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_action_button/test_input_action_button_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_action_link/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_action_link/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_action_link/test_input_action_link_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_checkbox/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_checkbox/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_checkbox/test_input_checkbox_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_checkbox_group/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_checkbox_group/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_checkbox_group/test_input_checkbox_group_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_dark_mode/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_dark_mode/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_dark_mode/test_input_dark_mode_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_date/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_date/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_date/test_input_date_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_date_range/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_date_range/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_date_range/test_input_date_range_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_file/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_file/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_file/test_input_file_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_numeric/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_numeric/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_numeric/test_input_numeric_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_password/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_password/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_password/test_input_password_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_radio_buttons/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_radio_buttons/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_radio_buttons/test_input_radio_buttons_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_select/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_select/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_select/test_input_select_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_slider/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_slider/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_slider/test_input_slider_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_switch/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_switch/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_switch/test_input_switch_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_task_button/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_task_button/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_task_button/test_input_task_button_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_text/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_text/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_text/test_input_text_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_text_area/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_text_area/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/input_text_area/test_input_text_area_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/navset_pill/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/navset_pill/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/navset_pill/test_navset_pill_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/update_tooltip/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/update_tooltip/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/update_tooltip/test_update_tooltip_core_express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/value_box/app-core.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/value_box/app-express.py (100%) rename tests/playwright/{shiny/tests_for_ai_generated_apps => ai_generated_apps}/value_box/test_value_box_core_express.py (100%) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index a20a1a9a5..8c81a4d1b 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -187,7 +187,7 @@ jobs: - name: Install node.js uses: actions/setup-node@v4 with: - node-version: "18" + node-version: "22" cache: npm cache-dependency-path: examples/brownian/shinymediapipe/package-lock.json - name: Install node.js package @@ -206,6 +206,49 @@ jobs: path: test-results/ retention-days: 5 + playwright-ai: + if: github.event_name != 'release' + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.12", "3.11", "3.10", "3.9"] + browser: ["chromium", "firefox", "webkit"] + exclude: + - python-version: ${{ github.event.pull_request.draft && '3.11' }} + - python-version: ${{ github.event.pull_request.draft && '3.10' }} + - python-version: ${{ github.event.pull_request.draft && '3.9' }} + - browser: ${{ github.event.pull_request.draft && 'firefox' }} + - browser: ${{ github.event.pull_request.draft && 'webkit' }} + fail-fast: false + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup py-shiny + uses: ./.github/py-shiny/setup + with: + python-version: ${{ matrix.python-version }} + - name: Determine browsers for testing + uses: ./.github/py-shiny/pytest-browsers + id: browsers + with: + browser: ${{ matrix.browser }} + # If anything other than `true`, it will heavily reduce webkit performance + # Related: https://github.com/microsoft/playwright/issues/18119 + disable-playwright-diagnostics: ${{ matrix.browser == 'webkit' || matrix.browser == 'firefox' }} + + - name: Run playwright tests for AI generated apps + timeout-minutes: 60 + run: | + make playwright-ai SUB_FILE=". --numprocesses 3 ${{ steps.browsers.outputs.playwright-diagnostic-args }}" ${{ steps.browsers.outputs.browsers }} + - uses: actions/upload-artifact@v4 + if: failure() && steps.browsers.outputs.has-playwright-diagnostics + with: + name: "playright-examples-${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.browser }}-results" + path: test-results/ + retention-days: 5 + playwright-deploys-precheck: if: github.event_name != 'release' runs-on: ubuntu-latest diff --git a/Makefile b/Makefile index ca216e7dd..215ef4cb4 100644 --- a/Makefile +++ b/Makefile @@ -157,6 +157,7 @@ TEST_FILE:=tests/playwright/$(SUB_FILE) DEPLOYS_TEST_FILE:=tests/playwright/deploys$(SUB_FILE) SHINY_TEST_FILE:=tests/playwright/shiny/$(SUB_FILE) EXAMPLES_TEST_FILE:=tests/playwright/examples/$(SUB_FILE) +AI_TEST_FILE:=tests/playwright/ai_generated_apps/$(SUB_FILE) install-playwright: FORCE playwright install --with-deps @@ -187,6 +188,10 @@ playwright-deploys: FORCE playwright-examples: FORCE $(MAKE) playwright TEST_FILE="$(EXAMPLES_TEST_FILE)" +# end-to-end tests for all AI generated apps +playwright-ai: FORCE + $(MAKE) playwright TEST_FILE="$(AI_TEST_FILE)" + coverage: FORCE ## check combined code coverage (must run e2e last) pytest --cov-report term-missing --cov=shiny tests/pytest/ $(SHINY_TEST_FILE) $(PYTEST_BROWSERS) coverage html diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/accordion/app-core.py b/tests/playwright/ai_generated_apps/accordion/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/accordion/app-core.py rename to tests/playwright/ai_generated_apps/accordion/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/accordion/app-express.py b/tests/playwright/ai_generated_apps/accordion/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/accordion/app-express.py rename to tests/playwright/ai_generated_apps/accordion/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/accordion/test_accordion_core_express.py b/tests/playwright/ai_generated_apps/accordion/test_accordion_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/accordion/test_accordion_core_express.py rename to tests/playwright/ai_generated_apps/accordion/test_accordion_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-core.py b/tests/playwright/ai_generated_apps/accordion_panel/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-core.py rename to tests/playwright/ai_generated_apps/accordion_panel/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-express.py b/tests/playwright/ai_generated_apps/accordion_panel/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/app-express.py rename to tests/playwright/ai_generated_apps/accordion_panel/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/test_accordion_panel_core_express.py b/tests/playwright/ai_generated_apps/accordion_panel/test_accordion_panel_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/accordion_panel/test_accordion_panel_core_express.py rename to tests/playwright/ai_generated_apps/accordion_panel/test_accordion_panel_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-core.py b/tests/playwright/ai_generated_apps/card/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/card/app-core.py rename to tests/playwright/ai_generated_apps/card/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card/app-express.py b/tests/playwright/ai_generated_apps/card/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/card/app-express.py rename to tests/playwright/ai_generated_apps/card/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card/test_card_core_express.py b/tests/playwright/ai_generated_apps/card/test_card_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/card/test_card_core_express.py rename to tests/playwright/ai_generated_apps/card/test_card_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-core.py b/tests/playwright/ai_generated_apps/card_footer/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-core.py rename to tests/playwright/ai_generated_apps/card_footer/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-express.py b/tests/playwright/ai_generated_apps/card_footer/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/app-express.py rename to tests/playwright/ai_generated_apps/card_footer/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/test_card_footer_core_express.py b/tests/playwright/ai_generated_apps/card_footer/test_card_footer_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/card_footer/test_card_footer_core_express.py rename to tests/playwright/ai_generated_apps/card_footer/test_card_footer_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-core.py b/tests/playwright/ai_generated_apps/input_action_button/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-core.py rename to tests/playwright/ai_generated_apps/input_action_button/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-express.py b/tests/playwright/ai_generated_apps/input_action_button/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/app-express.py rename to tests/playwright/ai_generated_apps/input_action_button/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/test_input_action_button_core_express.py b/tests/playwright/ai_generated_apps/input_action_button/test_input_action_button_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_action_button/test_input_action_button_core_express.py rename to tests/playwright/ai_generated_apps/input_action_button/test_input_action_button_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-core.py b/tests/playwright/ai_generated_apps/input_action_link/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-core.py rename to tests/playwright/ai_generated_apps/input_action_link/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-express.py b/tests/playwright/ai_generated_apps/input_action_link/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/app-express.py rename to tests/playwright/ai_generated_apps/input_action_link/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/test_input_action_link_core_express.py b/tests/playwright/ai_generated_apps/input_action_link/test_input_action_link_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_action_link/test_input_action_link_core_express.py rename to tests/playwright/ai_generated_apps/input_action_link/test_input_action_link_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-core.py b/tests/playwright/ai_generated_apps/input_checkbox/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-core.py rename to tests/playwright/ai_generated_apps/input_checkbox/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-express.py b/tests/playwright/ai_generated_apps/input_checkbox/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/app-express.py rename to tests/playwright/ai_generated_apps/input_checkbox/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/test_input_checkbox_core_express.py b/tests/playwright/ai_generated_apps/input_checkbox/test_input_checkbox_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox/test_input_checkbox_core_express.py rename to tests/playwright/ai_generated_apps/input_checkbox/test_input_checkbox_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-core.py b/tests/playwright/ai_generated_apps/input_checkbox_group/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-core.py rename to tests/playwright/ai_generated_apps/input_checkbox_group/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-express.py b/tests/playwright/ai_generated_apps/input_checkbox_group/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/app-express.py rename to tests/playwright/ai_generated_apps/input_checkbox_group/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/test_input_checkbox_group_core_express.py b/tests/playwright/ai_generated_apps/input_checkbox_group/test_input_checkbox_group_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_checkbox_group/test_input_checkbox_group_core_express.py rename to tests/playwright/ai_generated_apps/input_checkbox_group/test_input_checkbox_group_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-core.py b/tests/playwright/ai_generated_apps/input_dark_mode/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-core.py rename to tests/playwright/ai_generated_apps/input_dark_mode/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-express.py b/tests/playwright/ai_generated_apps/input_dark_mode/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/app-express.py rename to tests/playwright/ai_generated_apps/input_dark_mode/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/test_input_dark_mode_core_express.py b/tests/playwright/ai_generated_apps/input_dark_mode/test_input_dark_mode_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_dark_mode/test_input_dark_mode_core_express.py rename to tests/playwright/ai_generated_apps/input_dark_mode/test_input_dark_mode_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-core.py b/tests/playwright/ai_generated_apps/input_date/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-core.py rename to tests/playwright/ai_generated_apps/input_date/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-express.py b/tests/playwright/ai_generated_apps/input_date/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_date/app-express.py rename to tests/playwright/ai_generated_apps/input_date/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date/test_input_date_core_express.py b/tests/playwright/ai_generated_apps/input_date/test_input_date_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_date/test_input_date_core_express.py rename to tests/playwright/ai_generated_apps/input_date/test_input_date_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-core.py b/tests/playwright/ai_generated_apps/input_date_range/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-core.py rename to tests/playwright/ai_generated_apps/input_date_range/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-express.py b/tests/playwright/ai_generated_apps/input_date_range/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/app-express.py rename to tests/playwright/ai_generated_apps/input_date_range/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/test_input_date_range_core_express.py b/tests/playwright/ai_generated_apps/input_date_range/test_input_date_range_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_date_range/test_input_date_range_core_express.py rename to tests/playwright/ai_generated_apps/input_date_range/test_input_date_range_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py b/tests/playwright/ai_generated_apps/input_file/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-core.py rename to tests/playwright/ai_generated_apps/input_file/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py b/tests/playwright/ai_generated_apps/input_file/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_file/app-express.py rename to tests/playwright/ai_generated_apps/input_file/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_file/test_input_file_core_express.py b/tests/playwright/ai_generated_apps/input_file/test_input_file_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_file/test_input_file_core_express.py rename to tests/playwright/ai_generated_apps/input_file/test_input_file_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-core.py b/tests/playwright/ai_generated_apps/input_numeric/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-core.py rename to tests/playwright/ai_generated_apps/input_numeric/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-express.py b/tests/playwright/ai_generated_apps/input_numeric/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/app-express.py rename to tests/playwright/ai_generated_apps/input_numeric/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/test_input_numeric_core_express.py b/tests/playwright/ai_generated_apps/input_numeric/test_input_numeric_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_numeric/test_input_numeric_core_express.py rename to tests/playwright/ai_generated_apps/input_numeric/test_input_numeric_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-core.py b/tests/playwright/ai_generated_apps/input_password/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-core.py rename to tests/playwright/ai_generated_apps/input_password/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-express.py b/tests/playwright/ai_generated_apps/input_password/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_password/app-express.py rename to tests/playwright/ai_generated_apps/input_password/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_password/test_input_password_core_express.py b/tests/playwright/ai_generated_apps/input_password/test_input_password_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_password/test_input_password_core_express.py rename to tests/playwright/ai_generated_apps/input_password/test_input_password_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-core.py b/tests/playwright/ai_generated_apps/input_radio_buttons/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-core.py rename to tests/playwright/ai_generated_apps/input_radio_buttons/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-express.py b/tests/playwright/ai_generated_apps/input_radio_buttons/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/app-express.py rename to tests/playwright/ai_generated_apps/input_radio_buttons/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/test_input_radio_buttons_core_express.py b/tests/playwright/ai_generated_apps/input_radio_buttons/test_input_radio_buttons_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_radio_buttons/test_input_radio_buttons_core_express.py rename to tests/playwright/ai_generated_apps/input_radio_buttons/test_input_radio_buttons_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-core.py b/tests/playwright/ai_generated_apps/input_select/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-core.py rename to tests/playwright/ai_generated_apps/input_select/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-express.py b/tests/playwright/ai_generated_apps/input_select/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_select/app-express.py rename to tests/playwright/ai_generated_apps/input_select/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_select/test_input_select_core_express.py b/tests/playwright/ai_generated_apps/input_select/test_input_select_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_select/test_input_select_core_express.py rename to tests/playwright/ai_generated_apps/input_select/test_input_select_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py b/tests/playwright/ai_generated_apps/input_slider/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-core.py rename to tests/playwright/ai_generated_apps/input_slider/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py b/tests/playwright/ai_generated_apps/input_slider/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/app-express.py rename to tests/playwright/ai_generated_apps/input_slider/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py b/tests/playwright/ai_generated_apps/input_slider/test_input_slider_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_slider/test_input_slider_core_express.py rename to tests/playwright/ai_generated_apps/input_slider/test_input_slider_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-core.py b/tests/playwright/ai_generated_apps/input_switch/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-core.py rename to tests/playwright/ai_generated_apps/input_switch/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-express.py b/tests/playwright/ai_generated_apps/input_switch/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/app-express.py rename to tests/playwright/ai_generated_apps/input_switch/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/test_input_switch_core_express.py b/tests/playwright/ai_generated_apps/input_switch/test_input_switch_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_switch/test_input_switch_core_express.py rename to tests/playwright/ai_generated_apps/input_switch/test_input_switch_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-core.py b/tests/playwright/ai_generated_apps/input_task_button/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-core.py rename to tests/playwright/ai_generated_apps/input_task_button/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-express.py b/tests/playwright/ai_generated_apps/input_task_button/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/app-express.py rename to tests/playwright/ai_generated_apps/input_task_button/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/test_input_task_button_core_express.py b/tests/playwright/ai_generated_apps/input_task_button/test_input_task_button_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_task_button/test_input_task_button_core_express.py rename to tests/playwright/ai_generated_apps/input_task_button/test_input_task_button_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-core.py b/tests/playwright/ai_generated_apps/input_text/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-core.py rename to tests/playwright/ai_generated_apps/input_text/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-express.py b/tests/playwright/ai_generated_apps/input_text/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_text/app-express.py rename to tests/playwright/ai_generated_apps/input_text/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text/test_input_text_core_express.py b/tests/playwright/ai_generated_apps/input_text/test_input_text_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_text/test_input_text_core_express.py rename to tests/playwright/ai_generated_apps/input_text/test_input_text_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-core.py b/tests/playwright/ai_generated_apps/input_text_area/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-core.py rename to tests/playwright/ai_generated_apps/input_text_area/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-express.py b/tests/playwright/ai_generated_apps/input_text_area/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/app-express.py rename to tests/playwright/ai_generated_apps/input_text_area/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/test_input_text_area_core_express.py b/tests/playwright/ai_generated_apps/input_text_area/test_input_text_area_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/input_text_area/test_input_text_area_core_express.py rename to tests/playwright/ai_generated_apps/input_text_area/test_input_text_area_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/navset_pill/app-core.py b/tests/playwright/ai_generated_apps/navset_pill/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/navset_pill/app-core.py rename to tests/playwright/ai_generated_apps/navset_pill/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/navset_pill/app-express.py b/tests/playwright/ai_generated_apps/navset_pill/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/navset_pill/app-express.py rename to tests/playwright/ai_generated_apps/navset_pill/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/navset_pill/test_navset_pill_core_express.py b/tests/playwright/ai_generated_apps/navset_pill/test_navset_pill_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/navset_pill/test_navset_pill_core_express.py rename to tests/playwright/ai_generated_apps/navset_pill/test_navset_pill_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/app-core.py b/tests/playwright/ai_generated_apps/update_tooltip/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/app-core.py rename to tests/playwright/ai_generated_apps/update_tooltip/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/app-express.py b/tests/playwright/ai_generated_apps/update_tooltip/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/app-express.py rename to tests/playwright/ai_generated_apps/update_tooltip/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/test_update_tooltip_core_express.py b/tests/playwright/ai_generated_apps/update_tooltip/test_update_tooltip_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/update_tooltip/test_update_tooltip_core_express.py rename to tests/playwright/ai_generated_apps/update_tooltip/test_update_tooltip_core_express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-core.py b/tests/playwright/ai_generated_apps/value_box/app-core.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-core.py rename to tests/playwright/ai_generated_apps/value_box/app-core.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py b/tests/playwright/ai_generated_apps/value_box/app-express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/value_box/app-express.py rename to tests/playwright/ai_generated_apps/value_box/app-express.py diff --git a/tests/playwright/shiny/tests_for_ai_generated_apps/value_box/test_value_box_core_express.py b/tests/playwright/ai_generated_apps/value_box/test_value_box_core_express.py similarity index 100% rename from tests/playwright/shiny/tests_for_ai_generated_apps/value_box/test_value_box_core_express.py rename to tests/playwright/ai_generated_apps/value_box/test_value_box_core_express.py From 71b91e911f721d761fce2dacf52257994e85031a Mon Sep 17 00:00:00 2001 From: Karan Date: Fri, 7 Mar 2025 05:49:29 +0000 Subject: [PATCH 19/23] update pyright ignore path for ai generated files dir --- pyrightconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrightconfig.json b/pyrightconfig.json index 23f58eacb..236aed7fc 100644 --- a/pyrightconfig.json +++ b/pyrightconfig.json @@ -10,7 +10,7 @@ "docs", "tests/playwright/deploys/*/app.py", "shiny/templates", - "tests/playwright/shiny/tests_for_ai_generated_apps" + "tests/playwright/ai_generated_apps", ], "typeCheckingMode": "strict", "reportImportCycles": "none", From 653d09becedbabd5384567c264a85cff72f1e487 Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Thu, 6 Mar 2025 22:00:16 -0800 Subject: [PATCH 20/23] correct name --- .github/workflows/pytest.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 8c81a4d1b..477044a02 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -245,7 +245,7 @@ jobs: - uses: actions/upload-artifact@v4 if: failure() && steps.browsers.outputs.has-playwright-diagnostics with: - name: "playright-examples-${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.browser }}-results" + name: "playright-ai-${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.browser }}-results" path: test-results/ retention-days: 5 From d2ce9268b94a0365b66e333e48d65715de2850ce Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Thu, 6 Mar 2025 22:34:19 -0800 Subject: [PATCH 21/23] add 2 more apps --- .../ai_generated_apps/update_text/app-core.py | 84 +++++++++++++++++++ .../update_text/app-express.py | 69 +++++++++++++++ .../test_update_text_core_express.py | 64 ++++++++++++++ .../update_text_area/app-core.py | 59 +++++++++++++ .../update_text_area/app-express.py | 51 +++++++++++ .../test_update_text_area_core_express.py | 65 ++++++++++++++ 6 files changed, 392 insertions(+) create mode 100644 tests/playwright/ai_generated_apps/update_text/app-core.py create mode 100644 tests/playwright/ai_generated_apps/update_text/app-express.py create mode 100644 tests/playwright/ai_generated_apps/update_text/test_update_text_core_express.py create mode 100644 tests/playwright/ai_generated_apps/update_text_area/app-core.py create mode 100644 tests/playwright/ai_generated_apps/update_text_area/app-express.py create mode 100644 tests/playwright/ai_generated_apps/update_text_area/test_update_text_area_core_express.py diff --git a/tests/playwright/ai_generated_apps/update_text/app-core.py b/tests/playwright/ai_generated_apps/update_text/app-core.py new file mode 100644 index 000000000..0a2ce7ffe --- /dev/null +++ b/tests/playwright/ai_generated_apps/update_text/app-core.py @@ -0,0 +1,84 @@ +from shiny import App, reactive, render, ui + +# Define the UI +app_ui = ui.page_fillable( + # Layout with two columns + ui.layout_column_wrap( + # First card with text input + ui.card( + ui.card_header("Text Input Demo"), + ui.input_text( + "txt", + "Original Text", + value="Initial value", + placeholder="Type something...", + ), + ui.output_text("current_value"), + ), + # Second card with control buttons + ui.card( + ui.card_header("Control Buttons"), + ui.layout_column_wrap( + ui.input_action_button( + "update_all", "Update All Parameters", class_="btn-primary mb-3" + ), + ui.input_action_button( + "update_label", "Update Label Only", class_="btn-secondary mb-3" + ), + ui.input_action_button( + "update_value", "Update Value Only", class_="btn-success mb-3" + ), + ui.input_action_button( + "update_placeholder", + "Update Placeholder Only", + class_="btn-info mb-3", + ), + ), + ), + width=1 / 2, + ), +) + + +# Define the server +def server(input, output, session): + # Render current value text + @render.text + def current_value(): + return f"Current value: {input.txt()}" + + # Effect for updating all parameters + @reactive.effect + @reactive.event(input.update_all) + def _(): + ui.update_text( + id="txt", + label="Updated Label", + value="Updated Value", + placeholder="Updated Placeholder", + ) + + # Effect for updating label only + @reactive.effect + @reactive.event(input.update_label) + def _(): + ui.update_text(id="txt", label=f"Label Updated {input.update_label()} times") + + # Effect for updating value only + @reactive.effect + @reactive.event(input.update_value) + def _(): + ui.update_text(id="txt", value=f"Value Updated {input.update_value()} times") + + # Effect for updating placeholder only + @reactive.effect + @reactive.event(input.update_placeholder) + def _(): + ui.update_text( + id="txt", + placeholder=f"Placeholder Updated {input.update_placeholder()} times", + ) + + +# Create and return the app +app = App(app_ui, server) diff --git a/tests/playwright/ai_generated_apps/update_text/app-express.py b/tests/playwright/ai_generated_apps/update_text/app-express.py new file mode 100644 index 000000000..7e2e6eb01 --- /dev/null +++ b/tests/playwright/ai_generated_apps/update_text/app-express.py @@ -0,0 +1,69 @@ +from shiny import reactive +from shiny.express import input, render, ui + +# Page title +ui.page_opts(fillable=True) + +with ui.layout_column_wrap(width=1 / 2): + # Input text that will be updated + with ui.card(): + ui.card_header("Text Input Demo") + ui.input_text( + "txt", + "Original Text", + value="Initial value", + placeholder="Type something...", + ) + + @render.text + def current_value(): + return f"Current value: {input.txt()}" + + # Buttons to trigger different update scenarios + with ui.card(): + ui.card_header("Control Buttons") + with ui.layout_column_wrap(): + ui.input_action_button( + "update_all", "Update All Parameters", class_="btn-primary mb-3" + ) + ui.input_action_button( + "update_label", "Update Label Only", class_="btn-secondary mb-3" + ) + ui.input_action_button( + "update_value", "Update Value Only", class_="btn-success mb-3" + ) + ui.input_action_button( + "update_placeholder", "Update Placeholder Only", class_="btn-info mb-3" + ) + + +# Effects to handle different update scenarios +@reactive.effect +@reactive.event(input.update_all) +def _(): + ui.update_text( + id="txt", + label="Updated Label", + value="Updated Value", + placeholder="Updated Placeholder", + ) + + +@reactive.effect +@reactive.event(input.update_label) +def _(): + ui.update_text(id="txt", label=f"Label Updated {input.update_label()} times") + + +@reactive.effect +@reactive.event(input.update_value) +def _(): + ui.update_text(id="txt", value=f"Value Updated {input.update_value()} times") + + +@reactive.effect +@reactive.event(input.update_placeholder) +def _(): + ui.update_text( + id="txt", placeholder=f"Placeholder Updated {input.update_placeholder()} times" + ) diff --git a/tests/playwright/ai_generated_apps/update_text/test_update_text_core_express.py b/tests/playwright/ai_generated_apps/update_text/test_update_text_core_express.py new file mode 100644 index 000000000..9b6d1526e --- /dev/null +++ b/tests/playwright/ai_generated_apps/update_text/test_update_text_core_express.py @@ -0,0 +1,64 @@ +from playwright.sync_api import Page + +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_update_text(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Get controllers for the components with IDs + text_input = controller.InputText(page, "txt") + text_output = controller.OutputText(page, "current_value") + update_all_btn = controller.InputActionButton(page, "update_all") + update_label_btn = controller.InputActionButton(page, "update_label") + update_value_btn = controller.InputActionButton(page, "update_value") + update_placeholder_btn = controller.InputActionButton(page, "update_placeholder") + + # Test initial state + text_input.expect_label("Original Text") + text_input.expect_value("Initial value") + text_input.expect_placeholder("Type something...") + text_output.expect_value("Current value: Initial value") + + # Test update all parameters + update_all_btn.click() + text_input.expect_label("Updated Label") + text_input.expect_value("Updated Value") + text_input.expect_placeholder("Updated Placeholder") + text_output.expect_value("Current value: Updated Value") + + # Test update label only + update_label_btn.click() + text_input.expect_label("Label Updated 1 times") + text_output.expect_value( + "Current value: Updated Value" + ) # Value should remain unchanged + + # Test update value only + update_value_btn.click() + text_input.expect_value("Value Updated 1 times") + text_output.expect_value("Current value: Value Updated 1 times") + text_input.expect_label("Label Updated 1 times") # Label should remain unchanged + + # Test update placeholder only + update_placeholder_btn.click() + text_input.expect_placeholder("Placeholder Updated 1 times") + text_output.expect_value( + "Current value: Value Updated 1 times" + ) # Value should remain unchanged + + # Test manual text input + text_input.set("User typed value") + text_output.expect_value("Current value: User typed value") + + # Test multiple updates + update_label_btn.click() + text_input.expect_label("Label Updated 2 times") + update_value_btn.click() + text_input.expect_value("Value Updated 2 times") + update_placeholder_btn.click() + text_input.expect_placeholder("Placeholder Updated 2 times") diff --git a/tests/playwright/ai_generated_apps/update_text_area/app-core.py b/tests/playwright/ai_generated_apps/update_text_area/app-core.py new file mode 100644 index 000000000..edecea96d --- /dev/null +++ b/tests/playwright/ai_generated_apps/update_text_area/app-core.py @@ -0,0 +1,59 @@ +from shiny import App, reactive, render, ui + +app_ui = ui.page_fillable( + # Set page title in the UI + ui.panel_title("Text Area Update Demo"), + # Initial text area with a card wrapper + ui.card( + ui.card_header("Text Area Demo"), + ui.input_text_area( + id="textarea", + label="Sample Text Area", + value="Initial text", + placeholder="Enter your text here", + rows=5, + height="200px", + ), + ), + # Controls for updating text area in a separate card + ui.card( + ui.card_header("Control Panel"), + ui.layout_column_wrap( + ui.input_text("new_label", "New Label", value="Updated Label"), + ui.input_text("new_value", "New Value", value="Updated text content"), + ui.input_text( + "new_placeholder", "New Placeholder", value="Updated placeholder text" + ), + ui.input_action_button("update", "Update Text Area", class_="btn-primary"), + width=1 / 2, + ), + ), + # Display current values for verification + ui.card(ui.card_header("Current Values"), ui.output_text("show_values")), + fillable_mobile=True, +) + + +def server(input, output, session): + # Display current values + @render.text + def show_values(): + return f""" + Current Label: {input.new_label()} + Current Value: {input.new_value()} + Current Placeholder: {input.new_placeholder()} + """ + + # Effect to update the text area when the button is clicked + @reactive.effect + @reactive.event(input.update) + def _(): + ui.update_text_area( + id="textarea", + label=input.new_label(), + value=input.new_value(), + placeholder=input.new_placeholder(), + ) + + +app = App(app_ui, server) diff --git a/tests/playwright/ai_generated_apps/update_text_area/app-express.py b/tests/playwright/ai_generated_apps/update_text_area/app-express.py new file mode 100644 index 000000000..4db5c2375 --- /dev/null +++ b/tests/playwright/ai_generated_apps/update_text_area/app-express.py @@ -0,0 +1,51 @@ +from shiny import reactive +from shiny.express import input, render, ui + +ui.page_opts(title="Text Area Update Demo", fillable=True) + +# Initial text area with a card wrapper for better visual organization +with ui.card(): + ui.card_header("Text Area Demo") + ui.input_text_area( + id="textarea", + label="Sample Text Area", + value="Initial text", + placeholder="Enter your text here", + rows=5, + height="200px", + ) + +# Controls for updating text area in a separate card +with ui.card(): + ui.card_header("Control Panel") + with ui.layout_column_wrap(width=1 / 2): + ui.input_text("new_label", "New Label", value="Updated Label") + ui.input_text("new_value", "New Value", value="Updated text content") + ui.input_text( + "new_placeholder", "New Placeholder", value="Updated placeholder text" + ) + ui.input_action_button("update", "Update Text Area", class_="btn-primary") + +# Display current values for verification +with ui.card(): + ui.card_header("Current Values") + + @render.text + def show_values(): + return f""" + Current Label: {input.new_label()} + Current Value: {input.new_value()} + Current Placeholder: {input.new_placeholder()} + """ + + +# Effect to update the text area when the button is clicked +@reactive.effect +@reactive.event(input.update) +def _(): + ui.update_text_area( + id="textarea", + label=input.new_label(), + value=input.new_value(), + placeholder=input.new_placeholder(), + ) diff --git a/tests/playwright/ai_generated_apps/update_text_area/test_update_text_area_core_express.py b/tests/playwright/ai_generated_apps/update_text_area/test_update_text_area_core_express.py new file mode 100644 index 000000000..292d6d37c --- /dev/null +++ b/tests/playwright/ai_generated_apps/update_text_area/test_update_text_area_core_express.py @@ -0,0 +1,65 @@ +from playwright.sync_api import Page + +from shiny.playwright import controller +from shiny.pytest import create_app_fixture +from shiny.run import ShinyAppProc + +app = create_app_fixture(["app-core.py", "app-express.py"]) + + +def test_update_text_area(page: Page, app: ShinyAppProc) -> None: + page.goto(app.url) + + # Get the text area controller + text_area = controller.InputTextArea(page, "textarea") + + new_label = controller.InputText(page, "new_label") + new_value = controller.InputText(page, "new_value") + new_placeholder = controller.InputText(page, "new_placeholder") + + show_values = controller.OutputText(page, "show_values") + show_values.expect_value( + """ + Current Label: Updated Label + Current Value: Updated text content + Current Placeholder: Updated placeholder text + """ + ) + + # Update text are button + update_button = controller.InputActionButton(page, "update") + + # Test initial state + text_area.expect_label("Sample Text Area") + text_area.expect_value("Initial text") + text_area.expect_placeholder("Enter your text here") + + new_label.expect_label("New Label") + new_label.expect_value("Updated Label") + + new_placeholder.expect_label("New Placeholder") + new_placeholder.expect_value("Updated placeholder text") + + new_value.expect_label("New Value") + new_value.expect_value("Updated text content") + + # Update the text area + new_label.set("New Label") + new_value.set("New text content") + new_placeholder.set("New placeholder text") + update_button.click() + text_area.expect_label("New Label") + text_area.expect_value("New text content") + text_area.expect_placeholder("New placeholder text") + + # Check the output + show_values.expect_value( + """ + Current Label: New Label + Current Value: New text content + Current Placeholder: New placeholder text + """ + ) + text_area.expect_label("New Label") + text_area.expect_value("New text content") + text_area.expect_placeholder("New placeholder text") From 9078ddf77dc5d48c35c579e4242ef11c84ad06d6 Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Fri, 7 Mar 2025 07:32:23 -0800 Subject: [PATCH 22/23] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c2b84243..3d4b61bc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Fixed an issue where the `.update_user_input()` method on `ui.Chat()` isn't working in shinylive. (#1891) +* Fixed an issue with the `.click()` method on InputActionButton controllers in `shiny.playwright.controllers` where the method would not work as expected. (#1886) + ## [1.3.0] - 2025-03-03 ### New features From 07707c4df125e1dd70a904539fe0bae6aea7a7ef Mon Sep 17 00:00:00 2001 From: Karan Date: Thu, 13 Mar 2025 10:19:40 -0700 Subject: [PATCH 23/23] Update .github/workflows/pytest.yaml --- .github/workflows/pytest.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 477044a02..ad355f70b 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -187,7 +187,6 @@ jobs: - name: Install node.js uses: actions/setup-node@v4 with: - node-version: "22" cache: npm cache-dependency-path: examples/brownian/shinymediapipe/package-lock.json - name: Install node.js package