feat(tests): Jest backend (38 tests), Jest RTL frontend (28 tests), Playwright E2E spec
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
// @ts-check
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
/**
|
||||
* E2E tests run against the full Docker stack (frontend on port 52867,
|
||||
* backend on port 3001). To run locally:
|
||||
* docker-compose up -d
|
||||
* npx playwright test
|
||||
*/
|
||||
|
||||
const BASE_URL = process.env.E2E_BASE_URL || 'http://localhost:52867';
|
||||
|
||||
test.describe('UI Flow — create experiment → add animal → log status', () => {
|
||||
test('full happy path', async ({ page }) => {
|
||||
await page.goto(BASE_URL);
|
||||
|
||||
// ── Create experiment ────────────────────────────────────────
|
||||
await page.click('button:has-text("New Experiment")');
|
||||
await expect(page.getByRole('dialog')).toBeVisible();
|
||||
|
||||
await page.getByLabel(/experiment title/i).fill('E2E Test Study');
|
||||
await page.click('button:has-text("Create Experiment")');
|
||||
|
||||
// Modal closes and new experiment appears in the list
|
||||
await expect(page.getByRole('dialog')).not.toBeVisible();
|
||||
await expect(page.getByText('E2E Test Study')).toBeVisible();
|
||||
|
||||
// ── Navigate into experiment ──────────────────────────────────
|
||||
await page.click('text=E2E Test Study');
|
||||
await expect(page.url()).toContain('/experiments/');
|
||||
|
||||
// ── Add animal ────────────────────────────────────────────────
|
||||
await page.click('button:has-text("Add Animal")');
|
||||
await expect(page.getByRole('dialog')).toBeVisible();
|
||||
|
||||
await page.getByLabel(/animal id/i).fill('M-E2E-001');
|
||||
await page.getByLabel(/animal name/i).fill('TestMouse');
|
||||
await page.click('button:has-text("Add Animal")');
|
||||
|
||||
await expect(page.getByRole('dialog')).not.toBeVisible();
|
||||
await expect(page.getByText('TestMouse')).toBeVisible();
|
||||
|
||||
// ── Navigate into animal ──────────────────────────────────────
|
||||
await page.click('text=TestMouse');
|
||||
await expect(page.url()).toContain('/animals/');
|
||||
|
||||
// ── Log daily status ──────────────────────────────────────────
|
||||
await page.click('button:has-text("Log Daily Status")');
|
||||
await expect(page.getByRole('dialog')).toBeVisible();
|
||||
|
||||
// Date is pre-filled with today; add vitals
|
||||
await page.getByLabel(/vitals/i).fill('HR 70, Temp 37.0');
|
||||
await page.getByLabel(/treatment/i).fill('Control');
|
||||
await page.click('button:has-text("Log Status")');
|
||||
|
||||
await expect(page.getByRole('dialog')).not.toBeVisible();
|
||||
await expect(page.getByText('HR 70, Temp 37.0')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('UX Flow — validation error states', () => {
|
||||
test('empty experiment title shows error', async ({ page }) => {
|
||||
await page.goto(BASE_URL);
|
||||
await page.click('button:has-text("New Experiment")');
|
||||
await page.click('button:has-text("Create Experiment")');
|
||||
await expect(page.getByRole('alert')).toContainText(/title is required/i);
|
||||
});
|
||||
|
||||
test('empty animal fields show errors', async ({ page }) => {
|
||||
await page.goto(BASE_URL);
|
||||
|
||||
// Need an experiment to navigate into — create one first
|
||||
await page.click('button:has-text("New Experiment")');
|
||||
await page.getByLabel(/experiment title/i).fill('UX Test Study');
|
||||
await page.click('button:has-text("Create Experiment")');
|
||||
await page.click('text=UX Test Study');
|
||||
|
||||
await page.click('button:has-text("Add Animal")');
|
||||
await page.click('button:has-text("Add Animal")'); // submit without filling
|
||||
const alerts = page.getByRole('alert');
|
||||
await expect(alerts).toHaveCount(2); // ID + Name errors
|
||||
});
|
||||
|
||||
test('missing date on daily status shows error', async ({ page }) => {
|
||||
await page.goto(BASE_URL);
|
||||
|
||||
// Create experiment + animal to get to daily status form
|
||||
await page.click('button:has-text("New Experiment")');
|
||||
await page.getByLabel(/experiment title/i).fill('Date Test Study');
|
||||
await page.click('button:has-text("Create Experiment")');
|
||||
await page.click('text=Date Test Study');
|
||||
|
||||
await page.click('button:has-text("Add Animal")');
|
||||
await page.getByLabel(/animal id/i).fill('M-DT-001');
|
||||
await page.getByLabel(/animal name/i).fill('DateTestMouse');
|
||||
await page.click('button:has-text("Add Animal")');
|
||||
await page.click('text=DateTestMouse');
|
||||
|
||||
await page.click('button:has-text("Log Daily Status")');
|
||||
// Clear the date field
|
||||
await page.getByLabel(/date/i).fill('');
|
||||
await page.click('button:has-text("Log Status")');
|
||||
await expect(page.getByRole('alert')).toContainText(/date is required/i);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user