7baebebc09
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
122 lines
5.8 KiB
TypeScript
122 lines
5.8 KiB
TypeScript
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('<h2');
|
|
expect(g.html).toContain('Testo di prova');
|
|
});
|
|
|
|
it('rifiuta un H1 non riconosciuto', () => {
|
|
expect(() => parseGuide('# Titolo qualunque\n\ntesto', 'lezione-99-x', 1)).toThrow(/H1 non riconosciuto/);
|
|
});
|
|
});
|
|
|
|
describe('rewriteAssets', () => {
|
|
it('riscrive i path relativi delle immagini verso la route protetta', () => {
|
|
const html = '<img src="assets/slide/slide-hrv/fig-01.png" alt="x"><img src="/altro.png">';
|
|
expect(rewriteAssets(html)).toBe(
|
|
'<img src="/campus/assets/slide/slide-hrv/fig-01.png" alt="x"><img src="/altro.png">');
|
|
});
|
|
});
|
|
|
|
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]));
|
|
});
|
|
});
|