Files
Classeo/frontend/e2e/dashboard-responsive-nav.spec.ts
Mathias STRASSER 70babb77ef
Some checks failed
CI / Backend Tests (push) Has been cancelled
CI / Frontend Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Naming Conventions (push) Has been cancelled
CI / Build Check (push) Has been cancelled
feat: Permettre à l'élève de consulter ses notes et moyennes
L'élève avait accès à ses compétences mais pas à ses notes numériques.
Cette fonctionnalité lui donne une vue complète de sa progression scolaire
avec moyennes par matière, détail par évaluation, statistiques de classe,
et un mode "découverte" pour révéler ses notes à son rythme (FR14, FR15).

Les notes ne sont visibles qu'après publication par l'enseignant, ce qui
garantit que l'élève les découvre avant ses parents (délai 24h story 6.7).
2026-04-06 01:56:11 +02:00

142 lines
5.2 KiB
TypeScript

import { test, expect } from '@playwright/test';
import { execSync } from 'child_process';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const baseUrl = process.env.PLAYWRIGHT_BASE_URL || 'http://localhost:4173';
const urlMatch = baseUrl.match(/:(\d+)$/);
const PORT = urlMatch ? urlMatch[1] : '4173';
const ALPHA_URL = `http://ecole-alpha.classeo.local:${PORT}`;
const STUDENT_EMAIL = 'e2e-dash-nav-student@example.com';
const STUDENT_PASSWORD = 'DashNavStudent123';
const projectRoot = join(__dirname, '../..');
const composeFile = join(projectRoot, 'compose.yaml');
async function loginAsStudent(page: import('@playwright/test').Page) {
await page.goto(`${ALPHA_URL}/login`);
await page.locator('#email').fill(STUDENT_EMAIL);
await page.locator('#password').fill(STUDENT_PASSWORD);
await Promise.all([
page.waitForURL(/\/dashboard/, { timeout: 60000 }),
page.getByRole('button', { name: /se connecter/i }).click()
]);
}
test.describe('Dashboard Responsive Navigation', () => {
test.beforeAll(async () => {
execSync(
`docker compose -f "${composeFile}" exec -T php php bin/console app:dev:create-test-user --tenant=ecole-alpha --email=${STUDENT_EMAIL} --password=${STUDENT_PASSWORD} --role=ROLE_ELEVE 2>&1`,
{ encoding: 'utf-8' }
);
});
// =========================================================================
// MOBILE (375x667)
// =========================================================================
test.describe('Mobile (375x667)', () => {
test.use({ viewport: { width: 375, height: 667 } });
test('shows hamburger button and hides desktop nav', async ({ page }) => {
await loginAsStudent(page);
const hamburger = page.getByRole('button', { name: /ouvrir le menu/i });
await expect(hamburger).toBeVisible({ timeout: 10000 });
const desktopNav = page.locator('.desktop-nav');
await expect(desktopNav).not.toBeVisible();
});
test('opens drawer via hamburger and shows nav links', async ({ page }) => {
await loginAsStudent(page);
await page.getByRole('button', { name: /ouvrir le menu/i }).click();
const drawer = page.locator('[role="dialog"][aria-modal="true"]');
await expect(drawer).toBeVisible();
// Should show navigation links
await expect(drawer.getByText('Tableau de bord')).toBeVisible();
await expect(drawer.getByText('Mon emploi du temps')).toBeVisible();
await expect(drawer.getByText('Paramètres')).toBeVisible();
});
test('closes drawer via close button', async ({ page }) => {
await loginAsStudent(page);
await page.getByRole('button', { name: /ouvrir le menu/i }).click();
const drawer = page.locator('[role="dialog"][aria-modal="true"]');
await expect(drawer).toBeVisible();
await page.getByRole('button', { name: /fermer le menu/i }).click();
await expect(drawer).not.toBeVisible();
});
test('closes drawer on overlay click', async ({ page }) => {
await loginAsStudent(page);
await page.getByRole('button', { name: /ouvrir le menu/i }).click();
const drawer = page.locator('[role="dialog"][aria-modal="true"]');
await expect(drawer).toBeVisible();
const overlay = page.locator('.mobile-overlay');
await overlay.click({ position: { x: 350, y: 300 } });
await expect(drawer).not.toBeVisible();
});
test('navigates via mobile drawer and closes it', async ({ page }) => {
await loginAsStudent(page);
await page.getByRole('button', { name: /ouvrir le menu/i }).click();
const drawer = page.locator('[role="dialog"][aria-modal="true"]');
await expect(drawer).toBeVisible();
await drawer.getByText('Mon emploi du temps').click();
await expect(drawer).not.toBeVisible();
await expect(page).toHaveURL(/\/dashboard\/schedule/);
});
test('shows logout button in drawer footer', async ({ page }) => {
await loginAsStudent(page);
await page.getByRole('button', { name: /ouvrir le menu/i }).click();
const drawer = page.locator('[role="dialog"][aria-modal="true"]');
await expect(drawer).toBeVisible({ timeout: 10000 });
const logoutButton = drawer.locator('.mobile-logout');
await expect(logoutButton).toBeVisible({ timeout: 10000 });
await expect(logoutButton).toHaveText(/déconnexion/i);
});
});
// =========================================================================
// DESKTOP (1280x800)
// =========================================================================
test.describe('Desktop (1280x800)', () => {
test.use({ viewport: { width: 1280, height: 800 } });
test('hides hamburger and shows desktop nav', async ({ page }) => {
await loginAsStudent(page);
const hamburger = page.getByRole('button', { name: /ouvrir le menu/i });
await expect(hamburger).not.toBeVisible();
const desktopNav = page.locator('.desktop-nav');
await expect(desktopNav).toBeVisible({ timeout: 10000 });
});
test('desktop nav shows schedule link for student', async ({ page }) => {
await loginAsStudent(page);
const desktopNav = page.locator('.desktop-nav');
await expect(desktopNav.getByText('Mon EDT')).toBeVisible({ timeout: 10000 });
await expect(desktopNav.getByText('Tableau de bord')).toBeVisible();
});
});
});