feat: Provisionner automatiquement un nouvel établissement
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

Lorsqu'un super-admin crée un établissement via l'interface, le système
doit automatiquement créer la base tenant, exécuter les migrations,
créer le premier utilisateur admin et envoyer l'invitation — le tout
de manière asynchrone pour ne pas bloquer la réponse HTTP.

Ce mécanisme rend chaque établissement opérationnel dès sa création
sans intervention manuelle sur l'infrastructure.
This commit is contained in:
2026-04-08 13:55:41 +02:00
parent bec211ebf0
commit dc2be898d5
171 changed files with 11703 additions and 700 deletions

View File

@@ -86,10 +86,8 @@ test.describe('Branding Visual Customization', () => {
await page.goto(`${ALPHA_URL}/login`);
await page.locator('#email').fill(ADMIN_EMAIL);
await page.locator('#password').fill(ADMIN_PASSWORD);
await Promise.all([
page.waitForURL(/\/dashboard/, { timeout: 60000 }),
page.getByRole('button', { name: /se connecter/i }).click()
]);
await page.getByRole('button', { name: /se connecter/i }).click();
await page.waitForURL(/\/dashboard/, { timeout: 60000 });
}
/**
@@ -214,18 +212,23 @@ test.describe('Branding Visual Customization', () => {
await page.goto(`${ALPHA_URL}/admin/branding`);
await waitForPageLoaded(page);
// Set a dark blue color via color picker (more reliable than text input across browsers)
// Wrap in toPass() to handle Firefox timing where fill() may not immediately trigger change event
await expect(async () => {
await page.locator('#primaryColorPicker').fill('#1e3a5f');
await expect(page.getByRole('button', { name: /enregistrer/i })).toBeEnabled({ timeout: 2000 });
}).toPass({ timeout: 10000 });
// Set a dark blue color via JavaScript to ensure change event fires on all browsers
await page.locator('#primaryColorPicker').evaluate((el: HTMLInputElement) => {
el.value = '#1e3a5f';
el.dispatchEvent(new Event('input', { bubbles: true }));
el.dispatchEvent(new Event('change', { bubbles: true }));
});
// Wait for button to become enabled and click it
const saveBtn = page.getByRole('button', { name: /enregistrer/i });
await expect(saveBtn).toBeEnabled({ timeout: 10000 });
// Click save and wait for API response
const responsePromise = page.waitForResponse(
(resp) => resp.url().includes('/school/branding') && resp.request().method() === 'PUT'
(resp) => resp.url().includes('/school/branding') && resp.request().method() === 'PUT',
{ timeout: 30000 }
);
await page.getByRole('button', { name: /enregistrer/i }).click();
await saveBtn.click();
await responsePromise;
// Success message