FieldOps/e2e/tests-auth/login.spec.ts

87 lines
3.4 KiB
TypeScript

import { test, expect } from '@playwright/test';
import { ADMIN_BASE } from '../playwright.auth.config';
/**
* Real-login E2E tests — runs with AUTH_DEV_AUTOLOGIN=false.
* Both apps enforce authentication via middleware.
*
* Preconditions (`pnpm db:seed` + docker compose running):
* - op1@demo.local PIN 1111
* - admin@demo.local password admin1234
*
* Run: pnpm test:e2e:auth (no servers running on 3000/3001 — this starts its own)
*/
// ── Operator — PIN login (baseURL = localhost:3000) ──────────────────────────
test('operator: wrong PIN shows error, correct PIN enters the app', async ({ page }) => {
await page.goto('/select-operator');
// Picker is accessible without a session (it IS the login page)
await expect(page.getByText('op1@demo.local')).toBeVisible({ timeout: 15_000 });
// Select op1
await page.getByRole('button', { name: 'op1@demo.local' }).click();
await expect(page.getByText('Operador selecionado')).toBeVisible();
// Wrong PIN: 9 9 9 9
for (const d of ['9', '9', '9', '9']) {
await page.getByRole('button', { name: d }).click();
}
await page.getByRole('button', { name: 'Entrar' }).click();
await expect(
page.getByText('PIN incorreto ou conta bloqueada. Tente novamente.'),
).toBeVisible({ timeout: 10_000 });
// Digits are cleared after error — type correct PIN
for (const d of ['1', '1', '1', '1']) {
await page.getByRole('button', { name: d }).click();
}
await page.getByRole('button', { name: 'Entrar' }).click();
// Successful login → home page with "Pedir manutenção" CTA
await expect(page.getByTestId('btn-request-maintenance')).toBeVisible({ timeout: 15_000 });
});
test('operator: unauthenticated root redirects to picker', async ({ page }) => {
await page.goto('/');
// Without autologin and no session, middleware redirects to /select-operator
await expect(page).toHaveURL(/\/select-operator/, { timeout: 10_000 });
});
// ── Admin — password login (separate describe gives an isolated browser context
// with baseURL = localhost:3001, avoiding cross-port URL confusion) ──────────
test.describe('Admin password login', () => {
test.use({ baseURL: ADMIN_BASE });
test('protected route redirects to /login without session', async ({ page }) => {
await page.goto('/maintenance');
// Middleware redirects to /login (may include ?callbackUrl= query param)
await expect(page).toHaveURL(/\/login/, { timeout: 10_000 });
});
test('wrong password shows error, correct password enters the queue', async ({ page }) => {
await page.goto('/login');
await expect(page.locator('input#email')).toBeVisible({ timeout: 15_000 });
// Wrong password
await page.fill('input#email', 'admin@demo.local');
await page.fill('input#password', 'wrongpassword');
await page.getByRole('button', { name: 'Entrar' }).click();
await expect(
page.getByText('Email ou password incorretos. Tente novamente.'),
).toBeVisible({ timeout: 10_000 });
// Correct password
await page.fill('input#password', 'admin1234');
await page.getByRole('button', { name: 'Entrar' }).click();
// Successful login → maintenance queue
await expect(page).toHaveURL(/\/maintenance$/, { timeout: 15_000 });
await expect(
page.getByText('Fila de manutenção').or(page.getByText('pedidos abertos')),
).toBeVisible({ timeout: 10_000 });
});
});