All challenges · Core Interactions
Challenge 8 of 29 · Building fluency · Core Interactions
Fill a Login Form
Fill a username and password through their labels and submit the form, as a user would. A hidden check confirms the login worked.
Skills you will practise
- label locators
- form filling
- submitting
The concept
A login form is the classic first end-to-end test. Users find fields by their labels (“Email”, “Password”), so your test should too. getByLabel('Password') finds the input associated with that <label>, whether through for/id, wrapping, or aria-labelledby.
The submit button is found by role and name, and the real check comes after: did the login work? Assert on something only a signed-in user sees, such as a welcome heading, a URL change or a “Sign out” button. Checking that the button was clicked proves nothing.
Keep test credentials out of your code where you can. In a real project, read them from environment variables.
The fragile version
await page.locator('input[type=text]').fill('ada');
await page.locator('input[type=password]').fill('secret');
await page.locator('form button').click();Why it breaks: Attribute selectors break when a field becomes type=email, a second text input is added, or a “Show password” button appears inside the form. And there is no check that sign-in succeeded.
A robust Playwright version
await page.getByLabel('Username').fill('ada');
await page.getByLabel('Password').fill(process.env.TEST_PASSWORD);
await page.getByRole('button', { name: 'Sign in' }).click();
await expect(page.getByRole('heading', { name: /welcome/i })).toBeVisible();Fields are found the way users find them, and the final assertion proves the login actually worked.
This is a general example on a made-up page, not the challenge’s reference solution.
Common mistakes
- Ending the test at the click with no assertion on the outcome.
- Using placeholder text when a real label exists.
- Hard-coding real credentials in the test file.
FAQ
How does getByLabel find an input?
It matches <label> text linked to the input, aria-labelledby, or aria-label.
What should I assert after logging in?
Something only an authenticated user sees: a URL, a heading, or a sign-out control.
Should I log in through the UI in every test?
Usually not. Log in once and reuse storageState, keeping one UI login test.
Try it
Practise this in Challenge 8. You write the code in the browser editor with no setup. It runs in a fresh Chromium, a hidden validator checks what actually happened, and you get pass or fail, the logs and a video of the run. Challenges 1 to 10 are open without an account; create a free one any time to keep your progress. The reference solution and the hidden validator are shown only after you pass. We never publish solutions here.