⚠️ Broken Form Demo
Submit with bad inputs to see inline errors. Fill everything correctly to reach the success state.
How to automate this page
Each step targets a specific validation scenario. Run them individually with --grep to isolate failures.
npm init playwright@latest
# Run your tests
npx playwright test
# Open the HTML report
npx playwright show-report
1 ▼
Click submit on an untouched form. All four fields (name, email, country, checkbox) should show their individual error messages at the same time.
import { test, expect } from '@playwright/test';
test('shows all required field errors on empty submit', async ({ page }) => {
await page.goto('https://falcoma.com/tetsing-lab/broken-form-demo');
await page.click('[data-testid=btn-submit]');
await expect(page.locator('[data-testid=error-name]'))
.toHaveText('Full name is required.');
await expect(page.locator('[data-testid=error-email]'))
.toHaveText('Email address is required.');
await expect(page.locator('[data-testid=error-country]'))
.toHaveText('Please select a country.');
await expect(page.locator('[data-testid=error-agree]'))
.toHaveText('You must agree to continue.');
});
2 ▼
Type a string that looks like an email but is not valid. The error should switch from "required" to "invalid format". This tests that the validation rule for format is separate from the required check.
import { test, expect } from '@playwright/test';
test('rejects invalid email format', async ({ page }) => {
await page.goto('https://falcoma.com/tetsing-lab/broken-form-demo');
await page.fill('[data-testid=input-email]', 'not-an-email');
await page.click('[data-testid=btn-submit]');
await expect(page.locator('[data-testid=error-email]'))
.toHaveText('Please enter a valid email address.');
});
3 ▼
Fill every field correctly and submit. The form wrapper disappears and the success banner takes its place. This is a full end-to-end happy path test.
import { test, expect } from '@playwright/test';
test('shows success banner on fully valid submission', async ({ page }) => {
await page.goto('https://falcoma.com/tetsing-lab/broken-form-demo');
await page.fill('[data-testid=input-name]', 'Vincent Wong');
await page.fill('[data-testid=input-email]', 'vincent@falcoma.com');
await page.selectOption('[data-testid=select-country]', 'de');
await page.check('[data-testid=checkbox-agree]');
await page.click('[data-testid=btn-submit]');
await expect(page.locator('[data-testid=success-banner]')).toBeVisible();
await expect(page.locator('[data-testid=form-wrapper]')).not.toBeVisible();
});
4 ▼
After a successful submission, clicking Reset should hide the banner and bring the form back in its clean, empty state.
import { test, expect } from '@playwright/test';
test('reset button brings the form back after success', async ({ page }) => {
await page.goto('https://falcoma.com/tetsing-lab/broken-form-demo');
// Submit a valid form first
await page.fill('[data-testid=input-name]', 'Vincent Wong');
await page.fill('[data-testid=input-email]', 'vincent@falcoma.com');
await page.selectOption('[data-testid=select-country]', 'de');
await page.check('[data-testid=checkbox-agree]');
await page.click('[data-testid=btn-submit]');
await expect(page.locator('[data-testid=success-banner]')).toBeVisible();
// Click reset and confirm the form is back
await page.click('[data-testid=btn-reset]');
await expect(page.locator('[data-testid=form-wrapper]')).toBeVisible();
await expect(page.locator('[data-testid=success-banner]')).not.toBeVisible();
});