Explorer reports addition
We have added a new Explorer feature to reports, with a timeline scrubber and easy anomaly detection.
Test form submission and validation using Playwright with LoadForge
LoadForge can record your browser, graphically build tests, scan your site with a wizard and more. Sign up now to run your first test.
This guide demonstrates how to test form submission and validation using Playwright in LoadForge. Perfect for testing user registration, login forms, contact forms, and complex multi-step forms.
from locust import task
from locust_plugins.users.playwright import PlaywrightUser, PageWithRetry, pw, event
from faker import Faker
fake = Faker()
class FormTestingUser(PlaywrightUser):
@task(3)
@pw
async def login_form_test(self, page: PageWithRetry):
"""Test login form submission and validation"""
async with event(self, "Load Login Page"):
await page.goto("/login")
# Test valid login
await page.fill('input[name="email"]', 'test@example.com')
await page.fill('input[name="password"]', 'validpassword123')
async with event(self, "Valid Login Submit"):
async with page.expect_navigation():
await page.click('button:has-text("Log in")')
# Verify successful login
assert await page.locator('text=Dashboard').is_visible(), "Login failed"
@task(2)
@pw
async def registration_form_test(self, page: PageWithRetry):
"""Test user registration form with validation"""
async with event(self, "Load Registration Page"):
await page.goto("/register")
# Fill registration form with generated data
await page.fill('input[name="first_name"]', fake.first_name())
await page.fill('input[name="last_name"]', fake.last_name())
await page.fill('input[name="email"]', fake.email())
await page.fill('input[name="password"]', 'SecurePass123!')
await page.fill('input[name="password_confirmation"]', 'SecurePass123!')
# Select from dropdown
await page.select_option('select[name="country"]', 'US')
# Check terms checkbox
await page.check('input[name="terms"]')
async with event(self, "Registration Submit"):
async with page.expect_navigation():
await page.click('button:has-text("Register")')
# Verify registration success
success_msg = await page.locator('.success-message').is_visible()
assert success_msg, "Registration did not show success message"
@task(2)
@pw
async def contact_form_test(self, page: PageWithRetry):
"""Test contact form with file upload"""
async with event(self, "Load Contact Page"):
await page.goto("/contact")
# Fill contact form
await page.fill('input[name="name"]', fake.name())
await page.fill('input[name="email"]', fake.email())
await page.fill('input[name="subject"]', 'Test Subject')
await page.fill('textarea[name="message"]', fake.text(max_nb_chars=200))
# Select inquiry type
await page.select_option('select[name="inquiry_type"]', 'support')
async with event(self, "Contact Form Submit"):
await page.click('button:has-text("Send Message")')
# Wait for success message without navigation
await page.wait_for_selector('.alert-success', timeout=5000)
@task(1)
@pw
async def form_validation_test(self, page: PageWithRetry):
"""Test form validation errors"""
async with event(self, "Load Form for Validation"):
await page.goto("/register")
# Test email validation
await page.fill('input[name="email"]', 'invalid-email')
await page.fill('input[name="password"]', '123') # Too short
async with event(self, "Submit Invalid Form"):
await page.click('button:has-text("Register")')
# Check for validation errors
email_error = await page.locator('.error:has-text("email")').is_visible()
password_error = await page.locator('.error:has-text("password")').is_visible()
assert email_error or password_error, "Form validation errors not displayed"
@task(1)
@pw
async def multi_step_form_test(self, page: PageWithRetry):
"""Test multi-step form process"""
async with event(self, "Load Multi-step Form"):
await page.goto("/onboarding")
# Step 1: Personal Info
await page.fill('input[name="first_name"]', fake.first_name())
await page.fill('input[name="last_name"]', fake.last_name())
await page.fill('input[name="phone"]', fake.phone_number())
async with event(self, "Step 1 Complete"):
await page.click('button:has-text("Next")')
# Step 2: Address Info
await page.fill('input[name="address"]', fake.address())
await page.fill('input[name="city"]', fake.city())
await page.fill('input[name="zip"]', fake.zipcode())
await page.select_option('select[name="state"]', 'CA')
async with event(self, "Step 2 Complete"):
await page.click('button:has-text("Next")')
# Step 3: Preferences
await page.check('input[name="newsletter"]')
await page.select_option('select[name="language"]', 'en')
async with event(self, "Final Submit"):
await page.click('button:has-text("Complete")')
# Verify completion
await page.wait_for_selector('.onboarding-complete')
@task(1)
@pw
async def dynamic_form_test(self, page: PageWithRetry):
"""Test forms with dynamic fields"""
async with event(self, "Load Dynamic Form"):
await page.goto("/dynamic-form")
# Select option that shows additional fields
await page.select_option('select[name="user_type"]', 'business')
# Wait for dynamic fields to appear
await page.wait_for_selector('input[name="company_name"]')
# Fill dynamic fields
await page.fill('input[name="company_name"]', fake.company())
await page.fill('input[name="tax_id"]', '12-3456789')
# Fill regular fields
await page.fill('input[name="email"]', fake.email())
async with event(self, "Dynamic Form Submit"):
await page.click('button:has-text("Submit")')
# Verify submission
await page.wait_for_selector('.form-success')
await page.fill('input[name="username"]', 'testuser')
await page.fill('input[type="email"]', 'test@example.com')
await page.fill('textarea[name="description"]', 'Long text content')
# By value
await page.select_option('select[name="country"]', 'US')
# By label
await page.select_option('select[name="country"]', label='United States')
# Multiple selections
await page.select_option('select[name="skills"]', ['python', 'javascript'])
# Check/uncheck
await page.check('input[name="terms"]')
await page.uncheck('input[name="newsletter"]')
# Radio buttons
await page.click('input[name="plan"][value="premium"]')
# Single file
await page.set_input_files('input[type="file"]', 'test-file.pdf')
# Multiple files
await page.set_input_files('input[type="file"]', ['file1.pdf', 'file2.jpg'])
@task
@pw
async def client_validation_test(self, page: PageWithRetry):
await page.goto("/form")
# Test required field validation
await page.click('button[type="submit"]')
# Check for HTML5 validation
is_valid = await page.evaluate("""
document.querySelector('form').checkValidity()
""")
assert not is_valid, "Form should be invalid when required fields are empty"
@task
@pw
async def server_validation_test(self, page: PageWithRetry):
await page.goto("/form")
# Submit invalid data
await page.fill('input[name="email"]', 'existing@example.com') # Duplicate email
await page.click('button[type="submit"]')
# Wait for server validation error
await page.wait_for_selector('.field-error:has-text("already exists")')
@task
@pw
async def csrf_protected_form(self, page: PageWithRetry):
await page.goto("/protected-form")
# CSRF token is automatically included in form
await page.fill('input[name="data"]', 'test data')
await page.click('button[type="submit"]')
# Verify successful submission
await page.wait_for_selector('.success-message')
@task
@pw
async def ajax_form_test(self, page: PageWithRetry):
await page.goto("/ajax-form")
await page.fill('input[name="email"]', fake.email())
# Click submit but don't expect navigation
await page.click('button[type="submit"]')
# Wait for AJAX response
await page.wait_for_selector('.response-message')
# Check if form was reset
email_value = await page.input_value('input[name="email"]')
assert email_value == '', "Form should be reset after successful AJAX submission"
@task
@pw
async def network_error_test(self, page: PageWithRetry):
await page.goto("/form")
# Simulate network failure
await page.route('**/api/submit', lambda route: route.abort())
await page.fill('input[name="data"]', 'test')
await page.click('button[type="submit"]')
# Check error handling
await page.wait_for_selector('.network-error')
event() to measure form submission timesThis comprehensive form testing script covers various form scenarios and validation patterns commonly found in web applications.