Skip to content

Commit 85d0a5a

Browse files
committed
add playwright tests
1 parent 8de4d68 commit 85d0a5a

File tree

4 files changed

+165
-0
lines changed

4 files changed

+165
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from shiny import reactive
2+
from shiny.express import input, ui
3+
4+
ui.page_opts(
5+
title="Hello input bindings in Chat",
6+
fillable=True,
7+
fillable_mobile=True,
8+
)
9+
10+
welcome = f"""
11+
**Hello! Here are some inputs:**
12+
13+
{ui.input_select("select", "", choices=["a", "b", "c"])}
14+
{ui.input_slider("slider", "", min=0, max=100, value=50)}
15+
"""
16+
17+
chat = ui.Chat(
18+
id="chat",
19+
messages=[welcome],
20+
)
21+
chat.ui()
22+
23+
24+
@reactive.effect
25+
async def _():
26+
await chat.append_message(f"Now selected: {input.select()} and {input.slider()}")
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from playwright.sync_api import Page, expect
2+
from utils.deploy_utils import skip_on_webkit
3+
4+
from shiny.playwright import controller
5+
from shiny.run import ShinyAppProc
6+
7+
8+
@skip_on_webkit
9+
def test_validate_chat_shiny_output(page: Page, local_app: ShinyAppProc) -> None:
10+
page.goto(local_app.url)
11+
12+
TIMEOUT = 30 * 1000
13+
14+
chat = controller.Chat(page, "chat")
15+
expect(chat.loc).to_be_visible(timeout=TIMEOUT)
16+
17+
select = controller.InputSelect(page, "select")
18+
slider = controller.InputSlider(page, "slider")
19+
expect(select.loc).to_be_visible(timeout=TIMEOUT)
20+
expect(slider.loc).to_be_visible(timeout=TIMEOUT)
21+
22+
chat.expect_latest_message("Now selected: a and 50")
23+
24+
select.set("b")
25+
chat.expect_latest_message("Now selected: b and 50")
26+
27+
slider.set("5")
28+
chat.expect_latest_message("Now selected: b and 5")
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import ipyleaflet as ipyl
2+
import pandas as pd
3+
import plotly.express as px
4+
from shinywidgets import render_plotly, render_widget
5+
6+
from shiny import reactive, render
7+
from shiny.express import ui
8+
9+
ui.page_opts(
10+
title="Hello output bindings in Chat",
11+
fillable=True,
12+
fillable_mobile=True,
13+
)
14+
15+
with ui.hold() as map_ui:
16+
17+
@render_widget
18+
def map():
19+
return ipyl.Map(center=(52, 10), zoom=8)
20+
21+
22+
chat = ui.Chat(
23+
id="chat",
24+
messages=[map_ui],
25+
)
26+
27+
chat.ui()
28+
29+
with ui.hold() as df_1:
30+
31+
@render.data_frame
32+
def df1():
33+
dat = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
34+
return render.DataTable(dat, height="auto")
35+
36+
37+
@reactive.effect
38+
async def _():
39+
await chat.append_message(df_1)
40+
41+
42+
with ui.hold() as df_2:
43+
44+
@render.data_frame
45+
def df2():
46+
dat = pd.DataFrame({"c": [1, 2, 3], "d": [4, 5, 6]})
47+
return render.DataGrid(dat, selection_mode="rows")
48+
49+
50+
@reactive.effect
51+
async def _():
52+
await chat.append_message_stream(df_2)
53+
54+
55+
with ui.hold() as plot_ui:
56+
57+
@render_plotly
58+
def plot():
59+
dat = pd.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
60+
return px.scatter(dat, x="x", y="y")
61+
62+
63+
@reactive.effect
64+
async def _():
65+
await chat.append_message_stream(plot_ui)
66+
67+
68+
@render.code
69+
def selected_data():
70+
return str(df2.data_view(selected=True))
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from playwright.sync_api import Page, expect
2+
from utils.deploy_utils import skip_on_webkit
3+
4+
from shiny.playwright import controller
5+
from shiny.run import ShinyAppProc
6+
7+
8+
@skip_on_webkit
9+
def test_validate_chat_shiny_output(page: Page, local_app: ShinyAppProc) -> None:
10+
page.goto(local_app.url)
11+
12+
TIMEOUT = 30 * 1000
13+
14+
chat = controller.Chat(page, "chat")
15+
expect(chat.loc).to_be_visible(timeout=TIMEOUT)
16+
17+
# Test that ipyleaflet map has rendered
18+
# (this make sure we can render HTMLDependency()s statically)
19+
map_loc = page.locator("#map .leaflet-container")
20+
expect(map_loc).to_be_visible(timeout=TIMEOUT)
21+
22+
df1 = controller.OutputDataFrame(page, "df1")
23+
df2 = controller.OutputDataFrame(page, "df2")
24+
expect(df1.loc).to_be_visible(timeout=TIMEOUT)
25+
expect(df2.loc).to_be_visible(timeout=TIMEOUT)
26+
27+
selection = controller.OutputCode(page, "selected_data")
28+
expect(selection.loc).to_be_visible(timeout=TIMEOUT)
29+
30+
df1.expect_column_labels(["a", "b"])
31+
df2.expect_column_labels(["c", "d"])
32+
33+
expect(selection.loc).to_contain_text("Empty DataFrame")
34+
35+
df2.select_rows([0])
36+
expect(selection.loc).to_contain_text("c d\n0 1 4\n")
37+
38+
# Test that plotly plot has rendered
39+
# (this make sure we can render HTMLDependency()s dynamically)
40+
plot_loc = page.locator("#plot .plotly")
41+
expect(plot_loc).to_be_visible(timeout=TIMEOUT)

0 commit comments

Comments
 (0)