Skip to content
QA Knowledge Hub

Login with errors and lockout

Beginner

A login form with a valid account, error messages, a lockout after three wrong attempts and a protected page.

Practice area

Tasks to automate

  1. Log in with the valid account and assert that the welcome message appears.
  2. Try a wrong password and assert the exact error text.
  3. Leave both fields empty and assert both field errors.
  4. Fail three times and assert that the form is locked and the button is disabled.
  5. After logging in, log out and assert that the login form is shown again.
  6. Write this as a data-driven test with a table of inputs and expected messages.

Model solutions

Try the tasks first. These show one good way, not the only way.

Selenium (Java)
@DataProvider
Object[][] attempts() {
    return new Object[][] {
        {"[email protected]", "Test@1234", "Welcome, Tester"},
        {"[email protected]", "wrong",     "Email or password is incorrect"},
        {"",                    "",          "Email is required"},
    };
}

@Test(dataProvider = "attempts")
void login(String email, String pw, String expected) {
    driver.get(BASE + "/playground/login");
    driver.findElement(By.id("pg-login-email")).sendKeys(email);
    driver.findElement(By.id("pg-login-password")).sendKeys(pw);
    driver.findElement(By.id("pg-login-submit")).click();
    assertTrue(driver.findElement(By.tagName("main")).getText().contains(expected));
}
Playwright (TypeScript)
const cases = [
  ['[email protected]', 'Test@1234', 'Welcome, Tester'],
  ['[email protected]', 'wrong', 'Email or password is incorrect'],
  ['', '', 'Email is required'],
];
for (const [email, pw, expected] of cases) {
  test(`login with "${email}" / "${pw}"`, async ({ page }) => {
    await page.goto('/playground/login');
    await page.locator('#pg-login-email').fill(email);
    await page.locator('#pg-login-password').fill(pw);
    await page.locator('#pg-login-submit').click();
    await expect(page.locator('main')).toContainText(expected);
  });
}

Element IDs on this page are stable and will not change. Nothing you do here is sent to a server.