Automate a multi-field registration form โ dropdowns, text inputs, a date picker, radio buttons, and validation โ with Selenium, Cypress, or Playwright.
๐ We do not store any data โ use only dummy data for automation practice.
A multi-field registration form is where you practice the full toolbox: selecting from dropdowns, typing into text fields, picking a date, choosing a radio option, submitting, and asserting both validation errors and the success state. Nothing you enter is stored โ use dummy data only.
The same scenario written for two popular frameworks. These use the stable id and data-testid locators documented in the cheat sheet below.
import { test, expect } from '@playwright/test';
test('a fully valid form submits successfully', async ({ page }) => {
await page.goto('https://www.qapractice.com/practice-forms');
await page.getByTestId('forms-country').selectOption('India');
await page.getByTestId('forms-title').selectOption('Dr.');
await page.getByTestId('forms-first-name').fill('Ada');
await page.getByTestId('forms-last-name').fill('Lovelace');
// Date-of-birth is a react-datepicker input, located by id
await page.locator('#forms-dob').fill('1990-05-20');
await page.getByTestId('forms-doj').fill('01/06/2021');
await page.getByTestId('forms-email').fill('ada@example.com');
await page.getByTestId('forms-phone-code').selectOption('+91');
await page.getByTestId('forms-phone-number').fill('9876543210');
await page.getByTestId('forms-comm-email').check();
await page.getByTestId('forms-submit').click();
await expect(page.getByTestId('forms-success'))
.toContainText('Details Successfully Added');
});
test('submitting an empty form shows validation errors', async ({ page }) => {
await page.goto('https://www.qapractice.com/practice-forms');
await page.getByTestId('forms-submit').click();
await expect(page.getByText('First Name is required')).toBeVisible();
});import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
public class WebFormTest {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
driver.get("https://www.qapractice.com/practice-forms");
new Select(driver.findElement(By.id("forms-country"))).selectByVisibleText("India");
new Select(driver.findElement(By.id("forms-title"))).selectByVisibleText("Dr.");
driver.findElement(By.id("forms-first-name")).sendKeys("Ada");
driver.findElement(By.id("forms-last-name")).sendKeys("Lovelace");
driver.findElement(By.id("forms-dob")).sendKeys("1990-05-20");
driver.findElement(By.id("forms-doj")).sendKeys("01/06/2021");
driver.findElement(By.id("forms-email")).sendKeys("ada@example.com");
new Select(driver.findElement(By.id("forms-phone-code"))).selectByVisibleText("+91");
driver.findElement(By.id("forms-phone-number")).sendKeys("9876543210");
driver.findElement(By.id("forms-comm-email")).click();
driver.findElement(By.id("forms-submit")).click();
String msg = wait.until(ExpectedConditions.visibilityOfElementLocated(
By.id("forms-success"))).getText();
assert msg.contains("Details Successfully Added");
driver.quit();
}
}Every interactive element on this page exposes a stable id and/or data-testid so your scripts don't depend on brittle positions or styling.
| Element | id | data-testid | Playwright locator | Selenium locator |
|---|---|---|---|---|
| Country dropdown | forms-country | forms-country | getByTestId('forms-country').selectOption('India') | new Select(driver.findElement(By.id("forms-country"))) |
| Title dropdown | forms-title | forms-title | getByTestId('forms-title').selectOption('Dr.') | new Select(driver.findElement(By.id("forms-title"))) |
| First name | forms-first-name | forms-first-name | getByTestId('forms-first-name') | By.id("forms-first-name") |
| Last name | forms-last-name | forms-last-name | getByTestId('forms-last-name') | By.id("forms-last-name") |
| Date of birth (picker) | forms-dob | โ | locator('#forms-dob') | By.id("forms-dob") |
| Date of joining | forms-doj | forms-doj | getByTestId('forms-doj') | By.id("forms-doj") |
forms-email | forms-email | getByTestId('forms-email') | By.id("forms-email") | |
| Phone country code | forms-phone-code | forms-phone-code | getByTestId('forms-phone-code').selectOption('+91') | new Select(driver.findElement(By.id("forms-phone-code"))) |
| Phone number | forms-phone-number | forms-phone-number | getByTestId('forms-phone-number') | By.id("forms-phone-number") |
| Communication: Email radio | forms-comm-email | forms-comm-email | getByTestId('forms-comm-email') | By.id("forms-comm-email") |
| Communication: Phone radio | forms-comm-phone | forms-comm-phone | getByTestId('forms-comm-phone') | By.id("forms-comm-phone") |
| Clear button | forms-clear | forms-clear | getByTestId('forms-clear') | By.id("forms-clear") |
| Submit button | forms-submit | forms-submit | getByTestId('forms-submit') | By.id("forms-submit") |
| Success message | forms-success | forms-success | getByTestId('forms-success') | By.id("forms-success") |
Use these as a checklist to build your automation suite. Download them as a Markdown file to keep alongside your test project.
| ID | Scenario | Steps | Expected Result |
|---|---|---|---|
| TC01 | Submit a fully valid form |
| Success message "Details Successfully Added!" is shown. |
| TC02 | Submit an empty form |
| A "required" error appears under each mandatory field. |
| TC03 | Invalid email format |
| Error "Invalid Email Address" is shown. |
| TC04 | Date of joining wrong format |
| Error "Date of Joining format should be dd/mm/yyyy" is shown. |
| TC05 | Missing communication preference |
| Error "Please select a Communication Preference" is shown. |
| TC06 | Country dropdown options |
| Options include United States, Canada, United Kingdom, India, Australia, Other. |
| TC07 | Clear resets the form |
| All fields return to their empty/default state. |
| TC08 | Radio buttons are mutually exclusive |
| Only Phone stays selected; the two radios are mutually exclusive. |