- Introduced a Makefile for streamlined commands related to building, running, and managing presentations. - Created package.json to define project metadata, dependencies, and scripts for development and testing. - Added .gitignore entries to exclude build artifacts and temporary files from version control. - Included playwright.config.mjs for end-to-end testing setup with Playwright. - Added README.md for project documentation, outlining setup instructions and development guidelines.
147 lines
4.3 KiB
JavaScript
147 lines
4.3 KiB
JavaScript
import { test, describe } from 'node:test'
|
|
import assert from 'node:assert'
|
|
import fs from 'node:fs'
|
|
import os from 'node:os'
|
|
import path from 'node:path'
|
|
import {
|
|
escHtml,
|
|
escMd,
|
|
pickFeatured,
|
|
buildFeaturedHtml,
|
|
readAllMeta,
|
|
generateListPageMarkdown,
|
|
generateDetailPageMarkdown,
|
|
patchIndexFeaturedContent,
|
|
FEATURED_START,
|
|
FEATURED_END,
|
|
} from '../tools/presentation-contracts.mjs'
|
|
|
|
function mockSitePath(p) {
|
|
return p.startsWith('/') ? p : `/${p}`
|
|
}
|
|
|
|
describe('escHtml / escMd', () => {
|
|
test('escHtml neutralise < > & "', () => {
|
|
assert.strictEqual(escHtml('<a href="x">'), '<a href="x">')
|
|
})
|
|
|
|
test('escMd échappe les pipes tableaux markdown', () => {
|
|
assert.strictEqual(escMd('a|b'), 'a\\|b')
|
|
})
|
|
})
|
|
|
|
describe('pickFeatured', () => {
|
|
test('priorité aux entrées featured puis order', () => {
|
|
const items = [
|
|
{ slug: 'c', title: 'C', order: 3, featured: false },
|
|
{ slug: 'a', title: 'A', order: 1, featured: true },
|
|
{ slug: 'b', title: 'B', order: 2, featured: true },
|
|
]
|
|
const got = pickFeatured(items)
|
|
assert.deepStrictEqual(
|
|
got.map((x) => x.slug),
|
|
['a', 'b'],
|
|
)
|
|
})
|
|
|
|
test('sans featured : trois premiers par order', () => {
|
|
const items = [
|
|
{ slug: 'z', title: 'Z', order: 10 },
|
|
{ slug: 'a', title: 'A', order: 1 },
|
|
{ slug: 'b', title: 'B', order: 2 },
|
|
{ slug: 'c', title: 'C', order: 3 },
|
|
]
|
|
const got = pickFeatured(items)
|
|
assert.deepStrictEqual(
|
|
got.map((x) => x.slug),
|
|
['a', 'b', 'c'],
|
|
)
|
|
})
|
|
|
|
test('liste vide', () => {
|
|
assert.deepStrictEqual(pickFeatured([]), [])
|
|
})
|
|
})
|
|
|
|
describe('buildFeaturedHtml', () => {
|
|
test('génère des liens et échappe le titre', () => {
|
|
const html = buildFeaturedHtml(
|
|
[{ slug: 'x', title: '<evil>', description: 'd & co', order: 1 }],
|
|
mockSitePath,
|
|
)
|
|
assert.match(html, /href="\/presentations\/x\/"/)
|
|
assert.match(html, /<evil>/)
|
|
assert.match(html, /d & co/)
|
|
})
|
|
|
|
test('aucune présentation : commentaire', () => {
|
|
assert.strictEqual(buildFeaturedHtml([], mockSitePath), '<!-- (aucune présentation) -->')
|
|
})
|
|
})
|
|
|
|
describe('readAllMeta (répertoire temporaire)', () => {
|
|
test('ignore dossier sans meta.json', () => {
|
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'talks-slides-'))
|
|
fs.mkdirSync(path.join(dir, 'empty'), { recursive: true })
|
|
const okDir = path.join(dir, 'ok')
|
|
fs.mkdirSync(okDir, { recursive: true })
|
|
fs.writeFileSync(path.join(okDir, 'meta.json'), JSON.stringify({ title: 'T', description: '', order: 1 }))
|
|
const list = readAllMeta(dir)
|
|
assert.strictEqual(list.length, 1)
|
|
assert.strictEqual(list[0].slug, 'ok')
|
|
assert.strictEqual(list[0].title, 'T')
|
|
})
|
|
})
|
|
|
|
describe('generateListPageMarkdown / generateDetailPageMarkdown', () => {
|
|
const p = {
|
|
slug: 'demo',
|
|
title: 'Démo',
|
|
description: 'Desc',
|
|
tags: ['a', 'b'],
|
|
order: 1,
|
|
}
|
|
|
|
test('liste contient fiche + slides + tags', () => {
|
|
const md = generateListPageMarkdown([p], mockSitePath)
|
|
assert.match(md, /href="\/presentations\/demo\/"/)
|
|
assert.match(md, /href="\/slides\/demo\/1"/)
|
|
assert.match(md, /vp-raw/)
|
|
assert.match(md, /`a` · `b`/)
|
|
})
|
|
|
|
test('détail contient QrEncode et boutons', () => {
|
|
const md = generateDetailPageMarkdown(p, mockSitePath)
|
|
assert.match(md, /<QrEncode path="\/slides\/demo\/1" \/>/)
|
|
assert.match(md, /class="vp-button vp-raw"/)
|
|
assert.match(md, /Voir les slides/)
|
|
assert.match(md, /## Partager les slides/)
|
|
})
|
|
|
|
test('détail sans tags : pas de ligne Tags', () => {
|
|
const md = generateDetailPageMarkdown({ ...p, tags: [] }, mockSitePath)
|
|
assert.ok(!md.includes('**Tags :**'))
|
|
})
|
|
})
|
|
|
|
describe('patchIndexFeaturedContent', () => {
|
|
test('remplace la zone entre marqueurs', () => {
|
|
const raw = `head\n${FEATURED_START}\nold\n${FEATURED_END}\ntail`
|
|
const { ok, content } = patchIndexFeaturedContent(
|
|
raw,
|
|
[{ slug: 's', title: 'T', description: 'D', order: 1 }],
|
|
mockSitePath,
|
|
)
|
|
assert.strictEqual(ok, true)
|
|
assert.ok(content.includes('talk-card'))
|
|
assert.ok(content.includes('head'))
|
|
assert.ok(content.includes('tail'))
|
|
assert.ok(!content.includes('old'))
|
|
})
|
|
|
|
test('marqueurs absents : ok false', () => {
|
|
const { ok } = patchIndexFeaturedContent('nope', [], mockSitePath)
|
|
assert.strictEqual(ok, false)
|
|
})
|
|
})
|