Skip to content

[Bug]: out-of-order values cause expect_selected() to fail for shiny.playwright.controller.InputCheckboxGroup #2123

Description

@rkaramc

Component

Other

Severity

P3 - Low (minor inconvenience)

Shiny Version

1.5.0

Python Version

3.13.7

Minimal Reproducible Example

from shiny import App, ui
app_ui = ui.page_fluid(
    ui.input_checkbox_group(
        "parameters",
        "Parameters",
        choices={"A": "a", "B": "b", "C": "c", "D": "d"},
        selected=["A"],
        inline=True,
    ),
)
def server(input, output, session):
    pass
app = App(app_ui, server)

## test_checkboxgroup.py
from playwright.sync_api import Page
from shiny.playwright import controller
from shiny.run import ShinyAppProc

def test_cbg_works(page: Page, local_app: ShinyAppProc):
    page.goto(local_app.url)
    input_control = controller.InputCheckboxGroup(page, "parameters")
    input_control.expect_selected(["A"])

def test_cbg_works_with_values_in_same_order(page: Page, local_app: ShinyAppProc):
    page.goto(local_app.url)
    input_control = controller.InputCheckboxGroup(page, "parameters")
    input_control.set(["B", "C"])  # works
    input_control.expect_selected(["B", "C"])  # works

def test_cbg_works_with_values_in_different_order(page: Page, local_app: ShinyAppProc):
    page.goto(local_app.url)
    input_control = controller.InputCheckboxGroup(page, "parameters")
    input_control.set(["B", "A"])  # works
    input_control.expect_selected(["B", "A"])  # does not work

Behavior

Current: Verifying selected checkboxes in a InputCheckboxGroup fails if the list of values is not in the same order as in the checkbox definition.
Expected: Regardless of ordering, the .expect_selected() method should verify and assert that the checkboxes are selected.

Error Messages (if any)

=========================== short test summary info ===========================
FAILED tests/features/test_checkboxgroup.py::test_cbg_works_with_values_in_different_order[chromium] - AssertionError: Locator expected to have attribute 'B'
Actual value: A 
Call log:
  - Expect "to_have_attribute" with timeout 5000ms
  - waiting for locator("div#parameters.shiny-input-checkboxgroup.shiny-bound-input").locator(locator("input[type=checkbox]:checked")).first
    9 × locator resolved to <input value="A" type="checkbox" name="parameters" checked="checked"/>
      - unexpected value "A"
======================== 1 failed, 2 passed in 13.85s =========================
Finished running tests!

Environment

OS: win11
Browser: Chromium 140
uv: 0.9.10
pytest: 8.4.2
playwright: 1.55.0

Activity

  1. added
    Priority: LowLow-impact bug, docs polish, papercut, or unclear low-severity request.
    ai-triage:doneMarks an issue whose AI triage workflow is complete.
    on Aug 6, 2026
  2. schloerke commented on Aug 26, 2026

    @schloerke
    Collaborator

    Thanks for the clear report, @rkaramc — and sorry for the wait.

    We're not going to make expect_selected() order-independent, but the failure you hit is still a bug on our side: the error message is useless.

    The reason we're keeping it ordered is that the order carries information. A checkbox group's input value is always in choices order, never click order:

    ui.input_checkbox_group("cbg", "Letters", choices=["a", "b", "c"])
    # check `c`, then `b`
    input.cbg()
    # -> ('b', 'c')

    So the list you pass to expect_selected() is exactly the tuple your server sees, and we'd like to keep that one-to-one. (Order-independence also turns out to be surprisingly hard to assert correctly — details in #2468.)

    What we will fix: when the assertion fails only because of ordering, you'll get an error that says so and shows expected vs. found, instead of Locator expected to have attribute 'B' / Actual value: A. We'll document the order contract on the method too.

    In the meantime, input_control.expect_selected(["A", "B"]) — choices order — is the working form of your third test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Priority: LowLow-impact bug, docs polish, papercut, or unclear low-severity request.ai-triage:doneMarks an issue whose AI triage workflow is complete.bugSomething isn't workingneeds-triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions