import { describe, it, expect } from 'vitest' import { hasAccessRoles, hasObjective, hasSummary } from '../extract.js' describe('extract-doc / hasObjective — i18n JSON', () => { it('detects a top-level objective body key (user FLAT)', () => { const json = `{ "title": "SLA", "subtitle": "...", "sections": { "objective": "Objectif", "access": "Accès" }, "objective": "Suivre les engagements de niveau de service." }` expect(hasObjective(json, 'fr/docs-support-sla.json')).toBe(true) }) it('detects sections.objective alone (the heading label)', () => { const json = `{ "sections": { "objective": "Objectif", "access": "Accès" } }` expect(hasObjective(json, 'fr/docs-support-sla.json')).toBe(true) }) it('detects overview.objective (DocRenderer nested shape)', () => { const json = `{ "docsAdministrationUsers": { "overview": { "objective": "Gérer les comptes utilisateurs." } } }` expect(hasObjective(json, 'fr/docs-administration-users.json')).toBe(true) }) it('does NOT detect "objective" appearing only as a VALUE', () => { // The word in free text / an array value is not a structural key → not a hit. const json = `{ "faq": { "1": { "answer": "Le principal objective est le suivi." } }, "labels": ["access", "objective-like"] }` expect(hasObjective(json, 'fr/docs-support-sla.json')).toBe(false) }) it('returns false when no objective key exists anywhere', () => { const json = `{ "title": "SLA", "sections": { "access": "Accès", "faq": "FAQ" }, "access": { "navigation": "Navigation" } }` expect(hasObjective(json, 'fr/docs-support-sla.json')).toBe(false) }) it('tolerates the French key spelling "objectif" (section present, just mis-keyed)', () => { // The real myspace/tenants doc keyed it `objectif` (FR) — it HAS the section, // so it must NOT be falsely reported missing. const json = `{ "title": "Mes Espaces de Travail", "sections": { "objectif": "Objectif", "access": "Accès" }, "objectif": "La page liste tous les espaces auxquels l'utilisateur a accès." }` expect(hasObjective(json, 'fr/docs-myspace-tenants.json')).toBe(true) }) it('tolerates t(\'objectif\') in TSX', () => { expect(hasObjective(`
{t('objective')}
{t('access.navigation')}
{t('summary')}
`, 'sla/index.tsx')).toBe(true) expect(hasSummary(`{t('valueProposition')}
`, 'sla/index.tsx')).toBe(true) }) it('regression — the real tenants i18n (no tagline) returns false', () => { // Mirrors docs-myspace-tenants.json: title → subtitle, no summary/valueProposition. const json = `{ "title": "Mes Espaces de Travail", "subtitle": "Accédez à vos espaces professionnels et personnels…", "header": { "businessRules": "règles métier", "apiEndpoints": "endpoints API" } }` expect(hasSummary(json, 'fr/docs-myspace-tenants.json')).toBe(false) }) }) describe('extract-doc / hasAccessRoles — Section 2 role table', () => { it('detects the access.columns i18n block (canonical shape)', () => { const json = `{ "sections": { "access": "Accès & rôles" }, "access": { "columns": { "role": "Rôle", "actions": "Peut faire", "scope": "Portée" }, "roles": { "admin": { "name": "Administrateur", "actions": "Tout", "scope": "toutes" } } } }` expect(hasAccessRoles(json, 'fr/docs-crm-pipeline.json')).toBe(true) }) it('detects an access.roles-first block too', () => { const json = `{ "access": { "roles": { "admin": { "name": "Admin" } } } }` expect(hasAccessRoles(json, 'fr/docs-crm-pipeline.json')).toBe(true) }) it('does NOT match the legacy access.navigation-only shape', () => { const json = `{ "sections": { "access": "Accès" }, "access": { "navigation": "Navigation" } }` expect(hasAccessRoles(json, 'fr/docs-crm-pipeline.json')).toBe(false) }) it('detects the TSX table references, incl. the template-literal row keys', () => { expect(hasAccessRoles(`{t('access.navigation')}
/crm/pipeline