Instalação, E2E, API, Page Objects e testflow-selenium
Chrome · JavaScript · Allure · GitHub ActionsPadrão W3C WebDriver para automação de browsers — controla Chrome, Firefox e Safari via protocolo HTTP, com bindings em várias linguagens.
selenium-webdriver — cliente oficial para Node.jsBuilder().forBrowser('chrome')5050 — mesma app dos suites Cypress/Playwright@smoke, @regression)describe / it, hooks globais, timeout configurável e grep por tag.
expect(x).to.equal(y) — BDD style, familiar para quem vem de Jest/Mocha.
Sem framework extra — WebDriver direto + helpers próprios (getByTestId).
allure-mocha no CI · mochawesome local — HTML rico com screenshots.
5050qaschool/testflow)
Antes de clonar:
Node 20+,
Git e
Docker
(TestFlow na porta 5050).
brew install node@20 git
brew link --overwrite node@20
brew install --cask google-chrome docker
node --version # v20+
git --version
docker run --rm -p 5050:5050 qaschool/testflow:latest
# alternativa: nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
nvm install 20 && nvm use 20
winget install OpenJS.NodeJS.LTS
winget install Git.Git
winget install Google.Chrome
winget install Docker.DockerDesktop
node --version
git --version
docker run --rm -p 5050:5050 qaschool/testflow:latest
git clone https://github.com/lflucasferreira/testflow-selenium.git
cd testflow-selenium && npm install
Use PowerShell ou
Git Bash para os comandos npm.
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs git
# Chrome headless (CI pattern)
sudo apt-get install -y google-chrome-stable
sudo apt-get install -y docker.io
sudo usermod -aG docker $USER # relogar depois
docker run --rm -p 5050:5050 qaschool/testflow:latest
npm ci && npm run test:smoke
Selenium Manager baixa o ChromeDriver compatível automaticamente.
git clone https://github.com/lflucasferreira/testflow-selenium.gitcd testflow-selenium && npm install
cp .env.example .env — BASE_URL, HEADLESS, credenciais demo
docker run -p 5050:5050 qaschool/testflow:latest
npm test · npm run test:smoke · npm run test:api
testflow-selenium/
├── .mocharc.cjs # Mocha + Allure/mochawesome
├── config/env.js # BASE_URL, headless, credenciais
├── support/
│ ├── driver.js # Builder + Chrome options
│ ├── helpers.js # getByTestId, waits, screenshots
│ ├── auth.js # loginViaApi, visitWithSession
│ └── api.js # fetch + publicRequest
├── pages/ # Page Object Model
├── tests/ # 11 arquivos *.test.js
│ └── hooks.js # beforeAll/afterEach global
└── scripts/ # wd-run.sh, Allure, Pages
pages/ — ações e assertions por telasupport/auth.js — seed de sessão via APItests/**/*.test.js — Mocha + Chai@smoke · @regression · @api · @critical// support/driver.js
const driver = await new Builder()
.forBrowser('chrome')
.setChromeOptions(options) // --headless=new, window-size
.build()
// .mocharc.cjs
module.exports = {
require: ['tests/hooks.js'],
timeout: 120000,
reporter: process.env.CI ? 'allure-mocha' : 'mochawesome',
spec: 'tests/**/*.test.js',
}
tests/hooks.js cria o WebDriver uma vez, expõe getHelpers() global e tira screenshot em falha.
// tests/auth/login.test.js
const LoginPage = require('../../pages/LoginPage')
const { getConfig } = require('../../support/driver')
describe('Authentication @regression', function () {
beforeEach(async function () {
const helpers = getHelpers()
await clearSession(helpers)
loginPage = new LoginPage(helpers)
await loginPage.open()
})
it('logs in via UI and redirects to dashboard @smoke @critical', async function () {
const config = getConfig()
await loginPage.loginWith(config.demoEmail, config.demoPassword)
await loginPage.shouldRedirectToDashboard()
})
})
| API | Uso no TestFlow |
|---|---|
driver.get(url) | Abrir login, dashboard, páginas /web/*.html |
driver.getCurrentUrl() | Assert redirect pós-login |
driver.getTitle() | Smoke — título da página |
driver.executeScript(fn) | sessionStorage, skip onboarding tour |
driver.wait(until…) | Explicit wait por condição |
driver.takeScreenshot() | Allure attachment on failure |
driver.manage().window() | Viewport 1280×800 |
| API | Exemplo TestFlow |
|---|---|
By.css('[data-testid="…"]') | Locator principal do projeto |
findElement / findElements | Um ou múltiplos elementos |
.click() | Submit, sidebar, nav links |
.sendKeys(text) | Email, senha, busca |
.clear() | Limpar campo antes de fill |
.getText() | KPIs, erros, labels |
.getAttribute(name) | placeholder, type=password |
until.elementIsVisible | Wait explícito no helper |
Select(element) | Dropdowns run-suite, run-env |
| Assertion | Exemplo |
|---|---|
expect(x).to.equal(y) | Status HTTP, contadores |
expect(x).to.be.true | Botão submit habilitado |
expect(x).to.include(str) | URL contém /web/dashboard.html |
expect(x).to.be.an('array') | Lista de users na API |
expect(x).to.match(regex) | Formato de email válido |
| Page Object throws | shouldRedirectToDashboard() — erro descritivo |
getByTestId// support/helpers.js
async getByTestId(testId, timeout = TIMEOUTS.DEFAULT) {
return this.waitForVisible(
By.css(`[data-testid="${testId}"]`), timeout
)
}
async clickByTestId(testId) {
const el = await this.getByTestId(testId)
await el.click()
}
async typeByTestId(testId, text) {
const el = await this.getByTestId(testId)
await el.clear()
await el.sendKeys(text)
}
// support/auth.js
async function loginViaApi(helpers, email, password) {
const res = await fetch(`${config.baseUrl}/api/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password }),
})
const body = await res.json()
cachedAuth = { email, token: body.token, name: body.user?.name }
return cachedAuth
}
async function visitWithSession(helpers, path) {
await seedAuthSession(helpers) // sessionStorage sandbox-auth
await helpers.driver.get(`${config.baseUrl}${path}`)
}
Evita login UI repetido — specs focam na feature sob teste.
// tests/api/auth.api.test.js
const { publicRequest } = require('../../support/api')
const { validateWithSchema } = require('../../support/schemaValidator')
describe('API @api @regression — POST /api/auth/login', function () {
it('returns status 200 @smoke @api', async function () {
const res = await publicRequest('/api/auth/login', {
method: 'POST', body: VALID,
})
expect(res.status).to.equal(200)
})
it('validates response against auth-login schema', function () {
validateWithSchema(res.body, loadFixture('schemas/auth-login.json'))
})
})
npm run test:api # sem browser — só Node.js + fetch
| Tag | Uso | Comando |
|---|---|---|
@smoke | Fluxos críticos rápidos | npm run test:smoke |
@regression | Cobertura ampla E2E | npm run test:regression |
@api | Contratos REST | npm run test:api |
@critical | Login, navegação essencial | npm run test:critical |
Tags no título do describe ou it — filtradas via scripts/wd-run.sh --grep '@smoke'.
helpers.getByTestIdloginWith)shouldRedirect…)| Área | Arquivo | Tag |
|---|---|---|
| Smoke | smoke/navigation.test.js | @smoke |
| Auth | auth/login.test.js | @regression |
| Dashboard | dashboard/dashboard.test.js | @regression |
| Team / Settings | team/ · settings/ | @regression |
| Wizard / Advanced | wizard/ · advanced/ | @regression |
| Activity / States | activity/ · states/ | @regression |
| Components page | components/components.test.js | @regression |
| API | api/auth.api.test.js | @api |
Sem suites de a11y (axe), regressão visual ou component testing isolado — foco em E2E browser + API REST.
| Comando | Descrição |
|---|---|
| Execução principal | |
npm test | Suite E2E completa (Mocha) |
npm run test:headed | Browser visível (HEADLESS=false) |
npm run test:smoke | Filtra @smoke |
npm run test:regression | Filtra @regression |
npm run test:api | Só tests/api/** — sem browser |
npm run test:critical | Filtra @critical |
| Comando | Descrição |
|---|---|
| Por pasta | |
npm run test:auth | tests/auth/** |
npm run test:dashboard | tests/dashboard/** |
npm run test:team | tests/team/** |
npm run test:wizard | tests/wizard/** |
| Relatório | |
npm run report:open | Abre mochawesome HTML local |
npm run report:allure | Gera Allure report |
npm run test:smoke:report | Smoke + abre relatório |
npm run test:smoke
npm run report:allure
npm run report:allure:open
# CI publica em GitHub Pages
npm run pages:prepare-allure
afterEach hook)allure-mocha no CI · mochawesome localpublish-allure em push na main@smoke contra TestFlow Docker — gate rápido no PR
@regression — cobertura ampla E2E
Suite completa npm test — Chrome headless Ubuntu
Merge Allure + deploy GitHub Pages com relatório HTML
Service container qaschool/testflow:latest · health check /health · artefatos de screenshot e allure-results em falha.
data-testid centralizados em helpers.jsvisitWithSession no beforeEach — specs focam na featuregetByTestId — explicit wait antes de interagirBASE_URL via config/env.js — não hardcode localhostfetch nativo + validação JSON Schema (Ajv)@smoke, @api nos scripts npm[TC-xxxx] em support/enums/testCases.jsit() — falhas legíveis no AllureVocê já sabe instalar Selenium WebDriver 4, configurar Mocha + Chai e rodar E2E no TestFlow.
← → slides | ↓ ↑ sub-slides | F tela cheia | ESC overview