75 lines
2.5 KiB
TypeScript
75 lines
2.5 KiB
TypeScript
/**
|
|
* Parent portal smoke + happy-path coverage.
|
|
*/
|
|
import { test, expect } from '@playwright/test';
|
|
import { loginAs } from '../helpers/auth';
|
|
import { ROUTES_PER_ROLE, ROLE_LANDING } from '../helpers/nav';
|
|
import {
|
|
captureConsoleErrors,
|
|
expectNoConsoleErrors,
|
|
expectPageMounted,
|
|
} from '../helpers/assertions';
|
|
|
|
const BASE = 'http://localhost:3000';
|
|
const PARENT_CHROME = ['Africa Alert', 'Parent', 'Dashboard'];
|
|
|
|
test.describe('Parent portal — smoke @smoke', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await loginAs(page, 'parent');
|
|
});
|
|
|
|
for (const route of ROUTES_PER_ROLE.parent) {
|
|
test(`mounts ${route}`, async ({ page }) => {
|
|
const cap = captureConsoleErrors(page);
|
|
try {
|
|
await page.goto(`${BASE}${route}`);
|
|
await expectPageMounted(page, route, [route.split('/').pop() || route, ...PARENT_CHROME]);
|
|
} finally {
|
|
cap.dispose();
|
|
expectNoConsoleErrors(cap.errors);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
test.describe('Parent portal — happy path @flow', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await loginAs(page, 'parent');
|
|
});
|
|
|
|
test('lands on the parent dashboard after login', async ({ page }) => {
|
|
await page.goto(`${BASE}/`);
|
|
await expect(page).toHaveURL(new RegExp(`${ROLE_LANDING.parent.replace(/\//g, '\\/')}$`));
|
|
});
|
|
|
|
test('academic-progress: child progress page renders', async ({ page }) => {
|
|
await page.goto(`${BASE}/academic-progress`);
|
|
await expect(page.locator('h1, h2').first()).toBeVisible();
|
|
});
|
|
|
|
test('attendance/history: history page renders', async ({ page }) => {
|
|
await page.goto(`${BASE}/attendance/history`);
|
|
await expect(page.locator('h1, h2').first()).toBeVisible();
|
|
// Either a table of attendance rows or an empty state.
|
|
const history = page
|
|
.locator('table')
|
|
.or(page.getByText(/no attendance|no records|empty/i));
|
|
await expect(history.first()).toBeVisible({ timeout: 5_000 });
|
|
});
|
|
|
|
test('fees: parent fee page shows paynow action', async ({ page }) => {
|
|
await page.goto(`${BASE}/fees`);
|
|
await expect(page.locator('h1, h2').first()).toBeVisible();
|
|
// Parent has Pay permission — there should be a Paynow or Pay button.
|
|
const pay = page
|
|
.getByRole('button', { name: /pay|paynow/i })
|
|
.or(page.getByText(/balance|outstanding/i));
|
|
await expect(pay.first()).toBeVisible({ timeout: 5_000 });
|
|
});
|
|
|
|
test('calendar: events page renders', async ({ page }) => {
|
|
await page.goto(`${BASE}/calendar`);
|
|
await expect(page.locator('h1, h2').first()).toBeVisible();
|
|
});
|
|
});
|