A Selenium test has a shape you will write hundreds of times. Here it is, testing the Nimbus login page:
const { Builder, By, until } = require('selenium-webdriver');
const assert = require('assert');
describe('Nimbus login', function () {
it('shows validation errors for an empty form', async function () {
const driver = await new Builder().forBrowser('chrome').build();
await driver.get('/');
await driver.findElement(By.css('[data-testid="login-button"]')).click();
const emailError = await driver.wait(
until.elementLocated(By.css('[data-testid="email-error"]')),
5000
);
assert.ok(await emailError.isDisplayed());
await driver.quit();
});
});
Read it as five layers:
describe/itcome from the test runner (Mocha here).itis one test, and its name is a claim about the app, "shows validation errors for an empty form" tells a reader exactly what broke when it fails.- Setup:
build()starts the browser,get('/')loads the page. - Act like a user: find the Sign in button, click it.
- Wait, then assert.
driver.wait(until.elementLocated(...), 5000)polls until the error message exists (up to 5 seconds), thenassert.ok(...)states what must be true. The assert is the test. Without it, the code runs, clicks, finishes, and passes whether the app works or not. - Teardown:
quit()ends the session. Always.
That fourth point is the difference between code that runs and a test that proves something. A test with no check passes against a completely broken app.
I once reviewed a test file with fourteen tests and no checks at all. Every test clicked through a form and finished. The suite was green for three months. It had never tested anything.
When you solve problems here, we check this for real: we break the app on purpose, and your test must turn red.
The official first-script guide: Your first Selenium script.
Now prove it: write this exact test yourself in the problem below, and we will check it catches the bug.