Files
Classeo/frontend/tests/unit/lib/components/organisms/StudentSchedule/ScheduleWidget.test.ts
Mathias STRASSER 81e97c4f3b
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: Afficher la couleur des matières dans l'emploi du temps élève et parent
L'admin pouvait attribuer une couleur à chaque matière, mais cette
couleur n'était utilisée que dans la vue admin de l'emploi du temps.
Les APIs élève et parent ne renvoyaient pas cette information, ce qui
donnait un affichage générique (gris/bleu) pour tous les créneaux.

L'API renvoie désormais subjectColor dans chaque créneau, et les vues
jour/semaine/widget/détails affichent la bordure colorée correspondante.
Le marqueur "Prochain cours" conserve sa priorité visuelle via une
surcharge CSS variable.
2026-03-09 15:57:14 +01:00

129 lines
3.6 KiB
TypeScript

import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/svelte';
import ScheduleWidget from '$lib/components/organisms/StudentSchedule/ScheduleWidget.svelte';
import type { ScheduleSlot } from '$lib/features/schedule/api/schedule';
vi.mock('$lib/features/schedule/stores/scheduleCache.svelte', () => ({
isOffline: vi.fn(() => false),
getLastSyncDate: vi.fn(() => null)
}));
function makeSlot(overrides: Partial<ScheduleSlot> = {}): ScheduleSlot {
return {
slotId: 'slot-1',
date: '2026-03-05',
dayOfWeek: 4,
startTime: '08:00',
endTime: '09:00',
subjectId: 'sub-1',
subjectName: 'Mathématiques',
subjectColor: null,
teacherId: 'teacher-1',
teacherName: 'M. Dupont',
room: 'Salle 101',
isModified: false,
exceptionId: null,
...overrides
};
}
describe('ScheduleWidget', () => {
it('renders slots with subject, teacher, time and room', () => {
const slot = makeSlot();
render(ScheduleWidget, {
props: { slots: [slot], nextSlotId: null }
});
expect(screen.getByText('Mathématiques')).toBeTruthy();
expect(screen.getByText('M. Dupont')).toBeTruthy();
expect(screen.getByText('08:00')).toBeTruthy();
expect(screen.getByText('09:00')).toBeTruthy();
expect(screen.getByText('Salle 101')).toBeTruthy();
});
it('shows empty message when no slots', () => {
render(ScheduleWidget, {
props: { slots: [], nextSlotId: null }
});
expect(screen.getByText("Aucun cours aujourd'hui")).toBeTruthy();
});
it('shows loading state', () => {
render(ScheduleWidget, {
props: { slots: [], nextSlotId: null, isLoading: true }
});
expect(screen.getByText('Chargement...')).toBeTruthy();
});
it('shows error message', () => {
render(ScheduleWidget, {
props: { slots: [], nextSlotId: null, error: 'Erreur réseau' }
});
expect(screen.getByText('Erreur réseau')).toBeTruthy();
});
it('highlights next slot with "Prochain" badge', () => {
const slots = [
makeSlot({ slotId: 'slot-1', startTime: '08:00', endTime: '09:00' }),
makeSlot({
slotId: 'slot-2',
startTime: '10:00',
endTime: '11:00',
subjectName: 'Français',
teacherName: 'Mme Martin'
})
];
render(ScheduleWidget, {
props: { slots, nextSlotId: 'slot-2' }
});
expect(screen.getByText('Prochain')).toBeTruthy();
});
it('does not show "Prochain" badge when nextSlotId is null', () => {
render(ScheduleWidget, {
props: { slots: [makeSlot()], nextSlotId: null }
});
expect(screen.queryByText('Prochain')).toBeNull();
});
it('does not render room when room is null', () => {
const slot = makeSlot({ room: null });
const { container } = render(ScheduleWidget, {
props: { slots: [slot], nextSlotId: null }
});
expect(container.querySelector('.slot-room')).toBeNull();
});
it('applies subject color as CSS variable on slot', () => {
const slot = makeSlot({ subjectColor: '#e74c3c' });
const { container } = render(ScheduleWidget, {
props: { slots: [slot], nextSlotId: null }
});
const item = container.querySelector('[data-testid="schedule-slot"]') as HTMLElement;
expect(item.style.getPropertyValue('--slot-color')).toBe('#e74c3c');
});
it('renders multiple slots with data-testid', () => {
const slots = [
makeSlot({ slotId: 'slot-1' }),
makeSlot({ slotId: 'slot-2', subjectName: 'Français' }),
makeSlot({ slotId: 'slot-3', subjectName: 'Histoire' })
];
const { container } = render(ScheduleWidget, {
props: { slots, nextSlotId: null }
});
const items = container.querySelectorAll('[data-testid="schedule-slot"]');
expect(items.length).toBe(3);
});
});