feat: Provisionner automatiquement un nouvel établissement
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:
@@ -0,0 +1,172 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
// Mock $app/environment
|
||||
vi.mock('$app/environment', () => ({
|
||||
browser: true
|
||||
}));
|
||||
|
||||
describe('gradePreferences', () => {
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
vi.resetModules();
|
||||
});
|
||||
|
||||
async function loadModule() {
|
||||
return await import('$lib/features/grades/stores/gradePreferences.svelte');
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// Reveal mode (discover vs immediate)
|
||||
// ==========================================================================
|
||||
describe('reveal mode', () => {
|
||||
it('defaults to immediate mode', async () => {
|
||||
const prefs = await loadModule();
|
||||
expect(prefs.getRevealMode()).toBe('immediate');
|
||||
expect(prefs.isDiscoverMode()).toBe(false);
|
||||
});
|
||||
|
||||
it('switches to discover mode', async () => {
|
||||
const prefs = await loadModule();
|
||||
prefs.setRevealMode('discover');
|
||||
|
||||
expect(prefs.getRevealMode()).toBe('discover');
|
||||
expect(prefs.isDiscoverMode()).toBe(true);
|
||||
});
|
||||
|
||||
it('switches back to immediate mode', async () => {
|
||||
const prefs = await loadModule();
|
||||
prefs.setRevealMode('discover');
|
||||
prefs.setRevealMode('immediate');
|
||||
|
||||
expect(prefs.getRevealMode()).toBe('immediate');
|
||||
expect(prefs.isDiscoverMode()).toBe(false);
|
||||
});
|
||||
|
||||
it('persists reveal mode to localStorage', async () => {
|
||||
const prefs = await loadModule();
|
||||
prefs.setRevealMode('discover');
|
||||
|
||||
const stored = JSON.parse(localStorage.getItem('classeo_grade_preferences')!);
|
||||
expect(stored.revealMode).toBe('discover');
|
||||
});
|
||||
|
||||
it('restores reveal mode from localStorage on init', async () => {
|
||||
localStorage.setItem(
|
||||
'classeo_grade_preferences',
|
||||
JSON.stringify({ revealMode: 'discover' })
|
||||
);
|
||||
|
||||
const prefs = await loadModule();
|
||||
expect(prefs.getRevealMode()).toBe('discover');
|
||||
expect(prefs.isDiscoverMode()).toBe(true);
|
||||
});
|
||||
|
||||
it('handles corrupted localStorage gracefully', async () => {
|
||||
localStorage.setItem('classeo_grade_preferences', 'not-json');
|
||||
|
||||
const prefs = await loadModule();
|
||||
expect(prefs.getRevealMode()).toBe('immediate');
|
||||
});
|
||||
});
|
||||
|
||||
// ==========================================================================
|
||||
// Grade reveal state (per-grade reveal tracking)
|
||||
// ==========================================================================
|
||||
describe('grade reveal state', () => {
|
||||
it('reports grades as not revealed by default', async () => {
|
||||
const prefs = await loadModule();
|
||||
expect(prefs.isGradeRevealed('grade-1')).toBe(false);
|
||||
});
|
||||
|
||||
it('reveals a grade individually', async () => {
|
||||
const prefs = await loadModule();
|
||||
prefs.revealGrade('grade-1');
|
||||
|
||||
expect(prefs.isGradeRevealed('grade-1')).toBe(true);
|
||||
expect(prefs.isGradeRevealed('grade-2')).toBe(false);
|
||||
});
|
||||
|
||||
it('persists revealed grades to localStorage', async () => {
|
||||
const prefs = await loadModule();
|
||||
prefs.revealGrade('grade-1');
|
||||
prefs.revealGrade('grade-2');
|
||||
|
||||
const stored = JSON.parse(localStorage.getItem('classeo_grades_revealed')!);
|
||||
expect(stored).toContain('grade-1');
|
||||
expect(stored).toContain('grade-2');
|
||||
});
|
||||
|
||||
it('restores revealed grades from localStorage on init', async () => {
|
||||
localStorage.setItem(
|
||||
'classeo_grades_revealed',
|
||||
JSON.stringify(['grade-1', 'grade-3'])
|
||||
);
|
||||
|
||||
const prefs = await loadModule();
|
||||
expect(prefs.isGradeRevealed('grade-1')).toBe(true);
|
||||
expect(prefs.isGradeRevealed('grade-3')).toBe(true);
|
||||
expect(prefs.isGradeRevealed('grade-2')).toBe(false);
|
||||
});
|
||||
|
||||
it('handles corrupted revealed localStorage gracefully', async () => {
|
||||
localStorage.setItem('classeo_grades_revealed', '{invalid}');
|
||||
|
||||
const prefs = await loadModule();
|
||||
expect(prefs.isGradeRevealed('grade-1')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// ==========================================================================
|
||||
// Grade "new" badge (seen tracking)
|
||||
// ==========================================================================
|
||||
describe('grade new badge', () => {
|
||||
it('reports unseen grades as new', async () => {
|
||||
const prefs = await loadModule();
|
||||
expect(prefs.isGradeNew('grade-1')).toBe(true);
|
||||
});
|
||||
|
||||
it('marks grades as seen', async () => {
|
||||
const prefs = await loadModule();
|
||||
prefs.markGradesSeen(['grade-1', 'grade-2']);
|
||||
|
||||
expect(prefs.isGradeNew('grade-1')).toBe(false);
|
||||
expect(prefs.isGradeNew('grade-2')).toBe(false);
|
||||
expect(prefs.isGradeNew('grade-3')).toBe(true);
|
||||
});
|
||||
|
||||
it('persists seen grades to localStorage', async () => {
|
||||
const prefs = await loadModule();
|
||||
prefs.markGradesSeen(['grade-1']);
|
||||
|
||||
const stored = JSON.parse(localStorage.getItem('classeo_grades_seen')!);
|
||||
expect(stored).toContain('grade-1');
|
||||
});
|
||||
|
||||
it('restores seen grades from localStorage on init', async () => {
|
||||
localStorage.setItem(
|
||||
'classeo_grades_seen',
|
||||
JSON.stringify(['grade-1'])
|
||||
);
|
||||
|
||||
const prefs = await loadModule();
|
||||
expect(prefs.isGradeNew('grade-1')).toBe(false);
|
||||
expect(prefs.isGradeNew('grade-2')).toBe(true);
|
||||
});
|
||||
|
||||
it('accumulates seen grades across multiple calls', async () => {
|
||||
const prefs = await loadModule();
|
||||
prefs.markGradesSeen(['grade-1']);
|
||||
prefs.markGradesSeen(['grade-2']);
|
||||
|
||||
expect(prefs.isGradeNew('grade-1')).toBe(false);
|
||||
expect(prefs.isGradeNew('grade-2')).toBe(false);
|
||||
});
|
||||
|
||||
it('handles corrupted seen localStorage gracefully', async () => {
|
||||
localStorage.setItem('classeo_grades_seen', 'broken');
|
||||
|
||||
const prefs = await loadModule();
|
||||
expect(prefs.isGradeNew('grade-1')).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user