import { describe, it, expect } from 'vitest'; // @ts-expect-error — modulo JS senza tipi, usato solo dallo script di sync import { parseGuide, kindOf, rewriteAssets } from '../scripts/campus/parse.mjs'; // @ts-expect-error — idem import { sourceDirFor, CHAPTERS, AREAS, CH_COLORS } from '../scripts/campus/structure.mjs'; const body = ` > Sintesi di studio basata sulla trascrizione della lezione del corso. ## In sintesi Testo di prova. ## Concetti chiave - **Il sonno è il pilastro.** Spiegazione. - **Ritmi circadiani.** Altra spiegazione. `; describe('kindOf / sourceDirFor', () => { it('riconosce il tipo dallo slug', () => { expect(kindOf('lezione-01-ottimizzazione-del-sonno')).toBe('lezione'); expect(kindOf('lezione-live-1-2026-02-24')).toBe('live'); expect(kindOf('accelerator-1-2025-11-11')).toBe('accelerator'); expect(kindOf('slide-hrv')).toBe('slide'); expect(kindOf('speaker-resta-marketing')).toBe('speaker'); expect(kindOf('consulenza-2025-02-04-cristina-ruggeri')).toBe('consulenza'); expect(kindOf('masterclass-2025-10-08-luca-ruggeri')).toBe('masterclass'); expect(kindOf('qa-01-tony-04')).toBe('qa'); }); it('mappa lo slug alla cartella sorgente', () => { expect(sourceDirFor('lezione-01-ottimizzazione-del-sonno')).toBe('studio'); expect(sourceDirFor('lezione-live-1-2026-02-24')).toBe('lezioni-live'); expect(sourceDirFor('qa-01-tony-04')).toBe('qa'); expect(sourceDirFor('consulenza-2025-02-04-cristina-ruggeri')).toBe('consulenze'); }); }); describe('parseGuide', () => { it('lezione numerata con parte e relatore', () => { const raw = '# Lezione 2 — Movimento e fitness (Parte 1) (Tony Manfron) — Guida allo studio' + body; const g = parseGuide(raw, 'lezione-02-movimento-fitness-parte1', 1); expect(g).toMatchObject({ kind: 'lezione', num: 2, relatore: 'Tony Manfron', parte: 'Parte 1', titleFull: 'Movimento e fitness (Parte 1)', titleShort: 'Movimento e fitness', label: 'L2 · Parte 1', }); }); it('lezione live e accelerator usano la data come titolo', () => { const live = parseGuide( '# Lezione live 1 — 24 febbraio 2026 (Massimo Filippi) — Guida allo studio' + body, 'lezione-live-1-2026-02-24', 1); expect(live).toMatchObject({ kind: 'live', num: 1, titleFull: 'Lezione live 1 — 24 febbraio 2026', titleShort: 'Lezione live 1', relatore: 'Massimo Filippi · 24 febbraio 2026', label: 'LV1', }); const acc = parseGuide( '# Accelerator 3 — 28 gennaio 2026 (Massimo Filippi) — Guida allo studio' + body, 'accelerator-3-2026-01-28', 3); expect(acc).toMatchObject({ kind: 'accelerator', num: 3, titleShort: 'Accelerator 3', label: 'A3' }); }); it('slide, speaker, consulenza, masterclass e Q&A', () => { expect(parseGuide('# Slide — HRV: Variabilità della frequenza cardiaca — Guida allo studio' + body, 'slide-hrv', 1)) .toMatchObject({ kind: 'slide', num: 1, titleFull: 'HRV: Variabilità della frequenza cardiaca', label: 'SL1' }); expect(parseGuide('# Intervento — Marketing nel BioHacking (Roberto Resta) — Guida allo studio' + body, 'speaker-resta-marketing', 5)) .toMatchObject({ kind: 'speaker', titleFull: 'Marketing nel BioHacking', relatore: 'Roberto Resta', label: 'SP5' }); expect(parseGuide('# Consulenza — Cristina Ruggeri (04/02/2025) — Guida allo studio' + body, 'consulenza-2025-02-04-cristina-ruggeri', 1)) .toMatchObject({ kind: 'consulenza', titleFull: 'Cristina Ruggeri', relatore: '04/02/2025', label: 'C1' }); expect(parseGuide('# Masterclass — Luca Ruggeri (08/10/2025) — Guida allo studio' + body, 'masterclass-2025-10-08-luca-ruggeri', 1)) .toMatchObject({ kind: 'masterclass', titleFull: 'Luca Ruggeri', relatore: '08/10/2025', label: 'MC1' }); expect(parseGuide('# Q&A Tony n°4 — Guida allo studio' + body, 'qa-01-tony-04', 1)) .toMatchObject({ kind: 'qa', titleFull: 'Q&A Tony n°4', label: 'QA1' }); }); it('estrae i concetti chiave in grassetto e rimuove H1 e blockquote', () => { const g = parseGuide('# Lezione 1 — Sonno (Tony Manfron) — Guida allo studio' + body, 'lezione-01-ottimizzazione-del-sonno', 1); expect(g.concetti).toEqual(['Il sonno è il pilastro', 'Ritmi circadiani']); expect(g.html).not.toContain('Guida allo studio'); expect(g.html).not.toContain('Sintesi di studio basata'); expect(g.html).toContain('

';
expect(rewriteAssets(html)).toBe(
'
');
});
});
describe('struttura del corso', () => {
it('ogni capitolo ha un colore e ogni area capitoli esistenti', () => {
const nums = CHAPTERS.map((c: [number, string, string, string[]]) => c[0]);
expect(CH_COLORS.length).toBe(CHAPTERS.length);
for (const [, , , , chapterNums] of AREAS as [string, string, string, string, number[]][])
for (const n of chapterNums) expect(nums).toContain(n);
});
it('nessuno slug duplicato e ogni capitolo è in una sola area', () => {
const slugs = CHAPTERS.flatMap((c: [number, string, string, string[]]) => c[3]);
expect(new Set(slugs).size).toBe(slugs.length);
const assigned = (AREAS as [string, string, string, string, number[]][]).flatMap((a) => a[4]);
expect(new Set(assigned).size).toBe(assigned.length);
expect(assigned.sort((a, b) => a - b)).toEqual(CHAPTERS.map((c: [number, string, string, string[]]) => c[0]));
});
});