Skip to content
16 changes: 14 additions & 2 deletions shiny/playwright/controller/_input_controls.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
UiWithContainerP,
UiWithLabel,
WidthContainerM,
WidthLocM,
all_missing,
not_is_missing,
)
Expand All @@ -30,7 +29,7 @@
)


class _InputSliderBase(WidthLocM, UiWithLabel):
class _InputSliderBase(UiWithLabel):

loc_irs: Locator
"""
Expand Down Expand Up @@ -203,6 +202,19 @@ def expect_max(self, value: AttrValue, *, timeout: Timeout = None) -> None:
self.loc, "data-max", value=value, timeout=timeout
)

def expect_width(self, value: str, *, timeout: Timeout = None) -> None:
"""
Expects the slider to have the specified width.

Parameters
----------
value
The expected width.
timeout
The maximum time to wait for the width to be visible and interactable. Defaults to `None`.
"""
_expect_style_to_have_value(self.loc_container, "width", value, timeout=timeout)

def expect_step(self, value: AttrValue, *, timeout: Timeout = None) -> None:
"""
Expect the input element to have the expected `step` attribute value.
Expand Down
26 changes: 25 additions & 1 deletion tests/playwright/shiny/inputs/input_slider/app.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import datetime
import typing

from shiny import App, Inputs, Outputs, Session, render, ui
Expand Down Expand Up @@ -50,6 +51,7 @@ def slider_row(
value=0,
step=2500,
pre="$",
post=".00",
sep=",",
animate=True,
ticks=True,
Expand All @@ -70,7 +72,29 @@ def slider_row(
step=1,
animate=ui.AnimationOptions(interval=100, loop=False),
),
# TODO-future; Test dates
slider_row(
"Date format",
min=(datetime.date(2024, 1, 1)),
max=(datetime.date(2024, 1, 10)),
value=(datetime.date(2024, 1, 5)),
time_format="%m/%d/%y",
timezone="-0500",
),
slider_row(
"Time format",
min=(datetime.datetime(2024, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)),
max=(datetime.datetime(2024, 1, 10, 23, 59, tzinfo=datetime.timezone.utc)),
value=(datetime.datetime(2024, 1, 5, 12, 00, tzinfo=datetime.timezone.utc)),
width="600px",
timezone="0000",
),
slider_row(
"Drag Range (Disabled)",
min=0,
max=1000,
value=(200, 500),
drag_range=False,
),
)


Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import datetime
import re
import time

Expand All @@ -8,6 +9,20 @@
from shiny.types import MISSING


def convert_to_utc_date(date_str: str) -> str:
date_obj = datetime.datetime.strptime(date_str, "%m/%d/%y")
epoch_time_milliseconds = date_obj.timestamp() * 1000
return str(epoch_time_milliseconds)


def convert_to_utc_date_time(date_time_str: str) -> str:
date_time_obj = datetime.datetime.strptime(date_time_str, "%Y-%m-%d %H:%M:%S")
utc_timestamp = (
date_time_obj.replace(tzinfo=datetime.timezone.utc).timestamp() * 1000
)
return str(utc_timestamp)


def test_slider_regular(page: Page, local_app: ShinyAppProc) -> None:
page.goto(local_app.url)

Expand Down Expand Up @@ -71,22 +86,22 @@ def test_slider_custom_format(page: Page, local_app: ShinyAppProc) -> None:

s2 = controller.InputSlider(page, "s2")
s2.expect_label("Custom Format")
s2.expect_value("$0")
s2.expect_value("$0.00")
s2.expect_min("0")
s2.expect_max("10000")
s2.expect_step("2500")
s2.expect_ticks("true")
s2.expect_sep(",")
s2.expect_pre("$")
s2.expect_post(None)
s2.expect_post(".00")
s2.expect_time_format(None)
s2.expect_timezone(None)
s2.expect_drag_range(None)
s2.expect_animate_options(loop=True, interval=500)
controller.OutputTextVerbatim(page, "txt2").expect_value("0")

s2.set("$7,500")
s2.expect_value("$7,500")
s2.set("$7,500.00")
s2.expect_value("$7,500.00")
controller.OutputTextVerbatim(page, "txt2").expect_value("7500")


Expand Down Expand Up @@ -147,3 +162,58 @@ def test_slider_play(page: Page, local_app: ShinyAppProc) -> None:
s4.expect_value("5")
s4.click_play() # can click again!
s4.expect_value("5")


def test_slider_date_format(page: Page, local_app: ShinyAppProc) -> None:
page.goto(local_app.url)

s5 = controller.InputSlider(page, "s5")
s5.expect_label("Date format")
s5.expect_value("01/05/24")
s5.expect_min(convert_to_utc_date("01/01/24"))
s5.expect_max(convert_to_utc_date("01/10/24"))
s5.expect_time_format("%m/%d/%y")
s5.expect_timezone("-0500")
s5.expect_drag_range(None)
controller.OutputTextVerbatim(page, "txt5").expect_value("2024-01-05")

new_val = "01/08/24"
s5.set(new_val)
s5.expect_value(new_val)
controller.OutputTextVerbatim(page, "txt5").expect_value("2024-01-08")


def test_slider_time_format(page: Page, local_app: ShinyAppProc) -> None:
page.goto(local_app.url)

s6 = controller.InputSlider(page, "s6")
s6.expect_label("Time format")
s6.expect_timezone("0000")
s6.expect_value("2024-01-05 12:00:00")
s6.expect_min(convert_to_utc_date_time("2024-01-01 00:00:00"))
s6.expect_max(convert_to_utc_date_time("2024-01-10 23:59:00"))
s6.expect_time_format("%F %T")
s6.expect_width("600px")
s6.expect_drag_range(None)
controller.OutputTextVerbatim(page, "txt6").expect_value("2024-01-05 12:00:00")

new_val = "2024-01-01 00:00:00"
s6.set(new_val)
s6.expect_value(new_val)
controller.OutputTextVerbatim(page, "txt6").expect_value("2024-01-01 00:00:00")


def test_slider_drag_range_disabled(page: Page, local_app: ShinyAppProc) -> None:
page.goto(local_app.url)

s7 = controller.InputSliderRange(page, "s7")
s7.expect_label("Drag Range (Disabled)")
s7.expect_value(("200", "500"))
s7.expect_min("0")
s7.expect_max("1000")
s7.expect_drag_range("false")
new_val = ("25", "502")
s7.set(new_val, max_err_values=1000)
controller.OutputTextVerbatim(page, "txt7").expect_value(
f"({new_val[0]}, {new_val[1]})"
)