Playwright: Interacting with Radio Button
Radio buttons are a small UI control, but they expose a few important testing patterns. They let users choose exactly one option from a group, which makes them useful for shipping methods, account preferences, filters, and status choices.
This guide focuses on the Codemo radio buttons playground. It covers the core scenarios you usually need in UI automation: standard selection, default values, disabled state, and value mapping.
Playground - General UI - Radio Buttons
Click here to practice radio button interactions in the Codemo Playground.
Why Test Radio Buttons?
Radio button tests help you verify that:
- a single option can be selected correctly
- the expected default option is already checked on load
- disabled radio buttons cannot be changed
- the UI label and the stored value stay aligned
These checks matter because radio buttons often control downstream form logic or conditional UI.
Basic Radio Button HTML
Before we test radio buttons, let's understand what a radio element looks like in HTML:
<input type="radio" id="option1" name="options" value="1" />
<label for="option1">Option 1</label>
<input type="radio" id="option2" name="options" value="2" />
<label for="option2">Option 2</label>
A radio input element can have attributes like:
type: Should beradiofor radio buttonsid: Unique identifier for the inputname: Groups radio buttons togethervalue: The value submitted when the radio button is selecteddisabled: Makes the radio button non-selectablearia-checked: Indicates the current checked state of the radio button (true or false)
Testing Standard Selection
The most basic case is selecting one option from the group and confirming the footer reflects that choice.
test("radio button should register a standard selection", async ({ page }) => {
await page.goto("https://codemo.dev/playground/general/radio-buttons/")
await page.getByRole("radio", { name: "Beta" }).check()
await expect(page.getByRole("radio", { name: "Beta" })).toBeChecked()
})
This verifies both the actual control state and the UI feedback that proves the selection was stored.
Testing Default Selection
Some forms pre-select a safe or recommended option. That is useful, but only if it stays correct across updates.
test("radio group should keep the default option selected", async ({ page }) => {
await page.goto("https://codemo.dev/playground/general/radio-buttons/")
await expect(page.getByRole("radio", { name: "Default" })).toBeChecked()
await expect(page.getByRole("radio", { name: "Option 2" })).not.toBeChecked()
await expect(page.getByRole("radio", { name: "Option 3" })).not.toBeChecked()
})
Default-state assertions are easy to skip, but they catch subtle regressions in initial form behavior.
Testing Disabled State
Disabled radio buttons should not respond to user input. This case checks that the existing value stays unchanged.
test("disabled radio buttons should stay unchanged", async ({ page }) => {
await page.goto("https://codemo.dev/playground/general/radio-buttons/")
await expect(page.getByRole("radio", { name: "Closed" })).toBeDisabled()
await expect(page.getByRole("radio", { name: "Open" })).toBeDisabled()
await expect(page.getByRole("radio", { name: "Closed" })).not.toBeChecked()
await expect(page.getByRole("radio", { name: "Open" })).toBeChecked()
})
Testing Stored Values Instead Of Labels
The most interesting case in this playground is the value-mapping scenario. The user sees labels such as Banana, Apple, and Cherry, but the stored values are lowercase.
test("radio group should store the internal value", async ({ page }) => {
await page.goto("https://codemo.dev/playground/general/radio-buttons/")
await page.getByRole("radio", { name: "Cherry" }).check()
await expect(page.getByRole("radio", { name: "Cherry" })).toHaveId(/cherry/i)
await expect(page.getByText("Selected value: cherry")).toBeVisible()
})
This is a practical reminder that UI labels and submitted values are not always identical. Your test should verify whichever one actually matters to the application
Practice With Codemo Playground
Codemo provides an interactive radio buttons playground where you can practice the main interaction patterns one case at a time.
Try these challenges:
- Select
Betain the standard case and confirm the footer changes. - Check that the default case already has
Defaultselected before any interaction. - Verify that the disabled radio group cannot be changed from
Open. - Select
Cherryin the value-selection case and confirm the footer showscherry.
Complete Test Example
import { test, expect } from "@playwright/test"
test.describe("Playground - General UI - Radio Buttons", () => {
test("radio button should register a standard selection", async ({ page }) => {
await page.goto("https://codemo.dev/playground/general/radio-buttons/")
await page.getByRole("radio", { name: "Beta" }).check()
await expect(page.getByRole("radio", { name: "Beta" })).toBeChecked()
})
test("radio group should keep the default option selected", async ({ page }) => {
await page.goto("https://codemo.dev/playground/general/radio-buttons/")
await expect(page.getByRole("radio", { name: "Default" })).toBeChecked()
await expect(page.getByRole("radio", { name: "Option 2" })).not.toBeChecked()
await expect(page.getByRole("radio", { name: "Option 3" })).not.toBeChecked()
})
test("disabled radio buttons should stay unchanged", async ({ page }) => {
await page.goto("https://codemo.dev/playground/general/radio-buttons/")
await expect(page.getByRole("radio", { name: "Closed" })).toBeDisabled()
await expect(page.getByRole("radio", { name: "Open" })).toBeDisabled()
await expect(page.getByRole("radio", { name: "Closed" })).not.toBeChecked()
await expect(page.getByRole("radio", { name: "Open" })).toBeChecked()
})
test("radio group should store the internal value", async ({ page }) => {
await page.goto("https://codemo.dev/playground/general/radio-buttons/")
await page.getByRole("radio", { name: "Cherry" }).check()
await expect(page.getByRole("radio", { name: "Cherry" })).toHaveId(/cherry/i)
await expect(page.getByText("Selected value: cherry")).toBeVisible()
})
})
Key Takeaways
- Use
getByLabel()orgetByRole("radio")to target radio controls reliably. - Always verify that only one option in the group is active at a time.
- Check default selections explicitly instead of assuming they are correct.
- Validate disabled state and internal stored values when those behaviors matter.