fix: Corriger les tests E2E après l'introduction du cache-aside paginé
Le commit 23dd717 a introduit un cache Redis (paginated_queries.cache)
pour les requêtes paginées. Les tests E2E qui modifient les données via
SQL direct (beforeAll, cleanup) contournent la couche applicative et ne
déclenchent pas l'invalidation du cache, provoquant des données obsolètes.
De plus, plusieurs problèmes d'isolation entre tests ont été découverts :
- Les tests classes.spec.ts supprimaient les données d'autres specs via
DELETE FROM school_classes sans nettoyer les FK dépendantes
- Les tests user-blocking utilisaient des emails partagés entre les
projets Playwright (chromium/firefox/webkit) exécutés en parallèle,
causant des race conditions sur l'état du compte utilisateur
- Le handler NotifyTeachersPedagogicalDayHandler s'exécutait de manière
synchrone, bloquant la réponse HTTP pendant l'envoi des emails
- La sélection d'un enseignant remplaçant effaçait l'autre dropdown car
{#if} supprimait l'option sélectionnée du DOM
Corrections appliquées :
- Ajout de cache:pool:clear après chaque modification SQL directe
- Nettoyage des FK dépendantes avant les DELETE (classes, subjects)
- Emails uniques par projet navigateur pour éviter les race conditions
- Routage de JourneePedagogiqueAjoutee vers le transport async
- Remplacement de {#if} par disabled sur les selects de remplacement
- Recherche par nom sur la page classes pour gérer la pagination
- Patterns toPass() pour la fiabilité Firefox sur les color pickers
This commit is contained in:
@@ -15,6 +15,45 @@ const ALPHA_URL = `http://ecole-alpha.classeo.local:${PORT}`;
|
||||
// Test credentials
|
||||
const ADMIN_EMAIL = 'e2e-classes-admin@example.com';
|
||||
const ADMIN_PASSWORD = 'ClassesTest123';
|
||||
const TENANT_ID = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890';
|
||||
|
||||
const projectRoot = join(__dirname, '../..');
|
||||
const composeFile = join(projectRoot, 'compose.yaml');
|
||||
|
||||
function runSql(sql: string) {
|
||||
execSync(
|
||||
`docker compose -f "${composeFile}" exec -T php php bin/console dbal:run-sql "${sql}" 2>&1`,
|
||||
{ encoding: 'utf-8' }
|
||||
);
|
||||
}
|
||||
|
||||
function clearCache() {
|
||||
try {
|
||||
execSync(
|
||||
`docker compose -f "${composeFile}" exec -T php php bin/console cache:pool:clear paginated_queries.cache 2>&1`,
|
||||
{ encoding: 'utf-8' }
|
||||
);
|
||||
} catch {
|
||||
// Cache pool may not exist in all environments
|
||||
}
|
||||
}
|
||||
|
||||
function cleanupClasses() {
|
||||
const sqls = [
|
||||
`DELETE FROM replacement_classes WHERE replacement_id IN (SELECT id FROM teacher_replacements WHERE tenant_id = '${TENANT_ID}')`,
|
||||
`DELETE FROM teacher_replacements WHERE tenant_id = '${TENANT_ID}'`,
|
||||
`DELETE FROM teacher_assignments WHERE tenant_id = '${TENANT_ID}'`,
|
||||
`DELETE FROM class_assignments WHERE tenant_id = '${TENANT_ID}'`,
|
||||
`DELETE FROM school_classes WHERE tenant_id = '${TENANT_ID}'`,
|
||||
];
|
||||
for (const sql of sqls) {
|
||||
try {
|
||||
runSql(sql);
|
||||
} catch {
|
||||
// Table may not exist yet
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Force serial execution to ensure Empty State runs first
|
||||
test.describe.configure({ mode: 'serial' });
|
||||
@@ -22,22 +61,13 @@ test.describe.configure({ mode: 'serial' });
|
||||
test.describe('Classes Management (Story 2.1)', () => {
|
||||
// Create admin user and clean up classes before running tests
|
||||
test.beforeAll(async () => {
|
||||
const projectRoot = join(__dirname, '../..');
|
||||
const composeFile = join(projectRoot, 'compose.yaml');
|
||||
|
||||
execSync(
|
||||
`docker compose -f "${composeFile}" exec -T php php bin/console app:dev:create-test-user --tenant=ecole-alpha --email=${ADMIN_EMAIL} --password=${ADMIN_PASSWORD} --role=ROLE_ADMIN 2>&1`,
|
||||
{ encoding: 'utf-8' }
|
||||
);
|
||||
|
||||
execSync(
|
||||
`docker compose -f "${composeFile}" exec -T php php bin/console dbal:run-sql "DELETE FROM class_assignments WHERE tenant_id = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'" 2>&1`,
|
||||
{ encoding: 'utf-8' }
|
||||
);
|
||||
execSync(
|
||||
`docker compose -f "${composeFile}" exec -T php php bin/console dbal:run-sql "DELETE FROM school_classes WHERE tenant_id = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'" 2>&1`,
|
||||
{ encoding: 'utf-8' }
|
||||
);
|
||||
cleanupClasses();
|
||||
clearCache();
|
||||
});
|
||||
|
||||
// Helper to login as admin
|
||||
@@ -78,21 +108,9 @@ test.describe('Classes Management (Story 2.1)', () => {
|
||||
// ============================================================================
|
||||
test.describe('Empty State', () => {
|
||||
test('shows empty state message when no classes exist', async ({ page }) => {
|
||||
// Clean up classes right before this specific test to avoid race conditions with parallel browsers
|
||||
const projectRoot = join(__dirname, '../..');
|
||||
const composeFile = join(projectRoot, 'compose.yaml');
|
||||
try {
|
||||
execSync(
|
||||
`docker compose -f "${composeFile}" exec -T php php bin/console dbal:run-sql "DELETE FROM class_assignments WHERE tenant_id = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'" 2>&1`,
|
||||
{ encoding: 'utf-8' }
|
||||
);
|
||||
execSync(
|
||||
`docker compose -f "${composeFile}" exec -T php php bin/console dbal:run-sql "DELETE FROM school_classes WHERE tenant_id = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'" 2>&1`,
|
||||
{ encoding: 'utf-8' }
|
||||
);
|
||||
} catch {
|
||||
// Ignore cleanup errors
|
||||
}
|
||||
// Clean up classes and all dependent tables right before this test
|
||||
cleanupClasses();
|
||||
clearCache();
|
||||
|
||||
await loginAsAdmin(page);
|
||||
await page.goto(`${ALPHA_URL}/admin/classes`);
|
||||
|
||||
Reference in New Issue
Block a user