c4107b84a5
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
72 lines
2.6 KiB
TypeScript
72 lines
2.6 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { getNav, findArea, findLesson, chapterOf, readLessonHtml, resolveAsset } from '../src/lib/campus';
|
|
|
|
// I test girano sui contenuti reali generati da `npm run sync-campus`.
|
|
const nav = getNav();
|
|
|
|
describe('getNav', () => {
|
|
it('carica aree e capitoli dai contenuti generati', () => {
|
|
expect(nav).not.toBeNull();
|
|
expect(nav!.count).toBeGreaterThan(100);
|
|
expect(nav!.areas.map((a) => a.slug)).toEqual(
|
|
['corso-base', 'slide', 'live-e-ospiti', 'consulenze-masterclass', 'qa']);
|
|
for (const a of nav!.areas) expect(a.chapters.length).toBeGreaterThan(0);
|
|
});
|
|
});
|
|
|
|
describe('lookup', () => {
|
|
it('trova area e guida, e il capitolo della guida', () => {
|
|
const area = findArea(nav!, 'corso-base');
|
|
expect(area?.title).toBe('Corso base');
|
|
const l = findLesson(nav!, 'lezione-01-ottimizzazione-del-sonno');
|
|
expect(l).toMatchObject({ area: 'corso-base', chapter: 1, label: 'L1' });
|
|
expect(chapterOf(nav!, l!)?.title).toBe('Sonno e ritmi');
|
|
});
|
|
|
|
it('ritorna null per slug inesistenti', () => {
|
|
expect(findArea(nav!, 'inventata')).toBeNull();
|
|
expect(findLesson(nav!, 'lezione-99-inventata')).toBeNull();
|
|
});
|
|
|
|
it('la catena prev/next collega tutte le guide in ordine', () => {
|
|
const all = nav!.areas.flatMap((a) => a.chapters.flatMap((c) => c.lessons));
|
|
expect(all[0].prev).toBeNull();
|
|
expect(all.at(-1)!.next).toBeNull();
|
|
for (let i = 0; i < all.length - 1; i++) expect(all[i].next?.slug).toBe(all[i + 1].slug);
|
|
});
|
|
});
|
|
|
|
describe('readLessonHtml', () => {
|
|
it('legge il frammento di una guida esistente', () => {
|
|
const html = readLessonHtml('lezione-01-ottimizzazione-del-sonno');
|
|
expect(html).toContain('<h2');
|
|
expect(html).not.toContain('Guida allo studio</h1>');
|
|
});
|
|
|
|
it('ritorna null per una guida inesistente', () => {
|
|
expect(readLessonHtml('non-esiste')).toBeNull();
|
|
});
|
|
|
|
it('le immagini puntano alla route protetta', () => {
|
|
const html = readLessonHtml('slide-hrv')!;
|
|
expect(html).toContain('src="/campus/assets/');
|
|
expect(html).not.toContain('src="assets/');
|
|
});
|
|
});
|
|
|
|
describe('resolveAsset', () => {
|
|
it('risolve un asset esistente', () => {
|
|
expect(resolveAsset('slide/slide-hrv')).toMatch(/campus-content\/assets\/slide\/slide-hrv$/);
|
|
});
|
|
|
|
it('rifiuta i path traversal e i path assoluti', () => {
|
|
expect(resolveAsset('../pages/lezione-01-ottimizzazione-del-sonno.html')).toBeNull();
|
|
expect(resolveAsset('../../package.json')).toBeNull();
|
|
expect(resolveAsset('/etc/passwd')).toBeNull();
|
|
});
|
|
|
|
it('ritorna null per un asset inesistente', () => {
|
|
expect(resolveAsset('slide/non-esiste.png')).toBeNull();
|
|
});
|
|
});
|