Files
planflow/tests/unit/navigation.test.ts
T
Claude 93852c2602 Fix four defects the screenshots and tests exposed
Verifying the rendered pages rather than the build turned up real bugs:

- The WP-00 health page still sat at src/app/page.tsx and silently won
  the route over the new Aperçu screen, so the home page was a database
  status readout. Moved to /api/sante, where a probe belongs, and wired
  into the compose healthcheck.
- The unassigned row showed a +14 h delta against a contract of zero,
  reading as an overshoot when it is simply the volume left to staff.
  It now shows what there is to fill.
- Two sidebar entries lit at once: an anchor link matched its own page,
  and /equipe matched an employee record. Highlighting now resolves to
  the most specific match, and a test asserts exactly one entry lights
  per screen.
- Section tabs with no built screen pointed at the home page, which
  reads as a broken tab. They now lead to their first entry's
  placeholder.

Also gives truncated compliance alerts a title attribute, so a narrow
cell no longer says there is a problem without saying which.

Playwright can reuse a preinstalled browser through
PLAYWRIGHT_CHROMIUM_PATH when its revision differs from the bundled one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cr9dkEHwbDgkWPnyGj1Rjv
2026-08-07 22:26:38 +00:00

70 lines
2.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, it } from 'vitest';
import {
activeItem,
isActive,
matches,
NAVIGATION,
sectionForPath,
} from '@/components/shell/navigation';
describe('matches', () => {
it('reconnaît la racine sans capturer tout le site', () => {
expect(matches('/', '/')).toBe(true);
expect(matches('/', '/equipe')).toBe(false);
});
it('couvre les sous-routes', () => {
expect(matches('/equipe', '/equipe')).toBe(true);
expect(matches('/equipe', '/equipe/camille-ferrand')).toBe(true);
expect(matches('/equipe', '/equipements')).toBe(false);
});
it('écarte les liens d’ancre', () => {
expect(matches('/conges#attente', '/conges')).toBe(false);
});
});
describe('activeItem', () => {
it('retient la correspondance la plus spécifique', () => {
// Sur une fiche, « Membres » (/equipe) et « Fiche salarié » correspondent
// tous deux ; c'est la fiche qui doit s'allumer.
expect(activeItem('/equipe/camille-ferrand')?.id).toBe('fiche');
expect(activeItem('/equipe')?.id).toBe('membres');
});
it('ne renvoie rien pour une route hors navigation', () => {
expect(activeItem('/inconnu')).toBeUndefined();
});
});
describe('isActive', () => {
it('n’allume qu’une entrée par écran', () => {
const targets = NAVIGATION.flatMap((section) => section.items)
.map((item) => item.href)
.filter(
(href): href is string =>
typeof href === 'string' && !href.includes('#'),
);
for (const pathname of [...targets, '/equipe/sarah-lemoine']) {
const lit = NAVIGATION.flatMap((section) => section.items).filter(
(item) => item.href && isActive(item.href, pathname),
);
expect(lit.length, `${pathname} allume ${lit.length} entrées`).toBe(1);
}
});
});
describe('sectionForPath', () => {
it('trouve la section portant la route courante', () => {
expect(sectionForPath('/planning/semaine').id).toBe('plannings');
expect(sectionForPath('/equipe/camille-ferrand').id).toBe('equipe');
expect(sectionForPath('/conges').id).toBe('conges');
});
it('retombe sur la première section pour une route inconnue', () => {
expect(sectionForPath('/inconnu').id).toBe('apercu');
});
});