- 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.
91 lines
3.7 KiB
JavaScript
91 lines
3.7 KiB
JavaScript
/**
|
||
* Invariant du dépôt : chaque slides/<slug>/meta.json a une entrée et des fichiers générés.
|
||
* Exécuter après `npm run sync` (la CI lance sync avant les tests).
|
||
*/
|
||
import { test, describe, before } from 'node:test'
|
||
import assert from 'node:assert'
|
||
import fs from 'node:fs'
|
||
import path from 'node:path'
|
||
import { fileURLToPath } from 'node:url'
|
||
import { spawnSync } from 'node:child_process'
|
||
|
||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||
const repoRoot = path.resolve(__dirname, '..')
|
||
|
||
before(() => {
|
||
const r = spawnSync(process.execPath, [path.join(repoRoot, 'tools', 'sync-portal.mjs')], {
|
||
cwd: repoRoot,
|
||
encoding: 'utf8',
|
||
})
|
||
assert.strictEqual(r.status, 0, r.stderr || r.stdout)
|
||
})
|
||
|
||
describe('Cohérence slides ↔ portail (après sync)', () => {
|
||
test('presentations.json existe et liste les dossiers slides', () => {
|
||
const jsonPath = path.join(repoRoot, 'portal', '.vitepress', 'data', 'presentations.json')
|
||
assert.ok(fs.existsSync(jsonPath), 'presentations.json manquant')
|
||
const data = JSON.parse(fs.readFileSync(jsonPath, 'utf8'))
|
||
assert.ok(Array.isArray(data))
|
||
assert.ok(data.length >= 1, 'au moins une présentation attendue dans ce dépôt')
|
||
|
||
const slideDirs = fs
|
||
.readdirSync(path.join(repoRoot, 'slides'), { withFileTypes: true })
|
||
.filter((d) => d.isDirectory() && !d.name.startsWith('_'))
|
||
.map((d) => d.name)
|
||
.filter((name) => fs.existsSync(path.join(repoRoot, 'slides', name, 'meta.json')))
|
||
|
||
assert.strictEqual(
|
||
data.length,
|
||
slideDirs.length,
|
||
'nombre d’entrées JSON = nombre de dossiers slides avec meta.json',
|
||
)
|
||
|
||
const slugs = new Set(data.map((p) => p.slug))
|
||
for (const dir of slideDirs) {
|
||
assert.ok(slugs.has(dir), `slug manquant pour le dossier slides/${dir}`)
|
||
}
|
||
})
|
||
|
||
test('chaque entrée a title, description, slug', () => {
|
||
const jsonPath = path.join(repoRoot, 'portal', '.vitepress', 'data', 'presentations.json')
|
||
const data = JSON.parse(fs.readFileSync(jsonPath, 'utf8'))
|
||
for (const p of data) {
|
||
assert.ok(typeof p.title === 'string' && p.title.length > 0, `title requis: ${p.slug}`)
|
||
assert.ok(typeof p.description === 'string', `description requise: ${p.slug}`)
|
||
assert.ok(typeof p.slug === 'string' && p.slug.length > 0)
|
||
}
|
||
})
|
||
|
||
test('chaque deck a un global-bottom.vue (pied de page portail)', () => {
|
||
const data = JSON.parse(
|
||
fs.readFileSync(path.join(repoRoot, 'portal', '.vitepress', 'data', 'presentations.json'), 'utf8'),
|
||
)
|
||
for (const p of data) {
|
||
const gb = path.join(repoRoot, 'slides', p.slug, 'global-bottom.vue')
|
||
assert.ok(fs.existsSync(gb), `slides/${p.slug}/global-bottom.vue manquant (pied de page)`)
|
||
const raw = fs.readFileSync(gb, 'utf8')
|
||
assert.ok(
|
||
raw.includes('_shared/DeckFooter'),
|
||
`global-bottom doit importer le pied de page partagé: ${p.slug}`,
|
||
)
|
||
}
|
||
})
|
||
|
||
test('fiche et liste générées pour chaque slug', () => {
|
||
const data = JSON.parse(
|
||
fs.readFileSync(path.join(repoRoot, 'portal', '.vitepress', 'data', 'presentations.json'), 'utf8'),
|
||
)
|
||
const listMd = path.join(repoRoot, 'portal', 'presentations', 'index.md')
|
||
const listContent = fs.readFileSync(listMd, 'utf8')
|
||
|
||
for (const p of data) {
|
||
const detail = path.join(repoRoot, 'portal', 'presentations', p.slug, 'index.md')
|
||
assert.ok(fs.existsSync(detail), `fiche manquante: presentations/${p.slug}/index.md`)
|
||
const body = fs.readFileSync(detail, 'utf8')
|
||
assert.match(body, new RegExp(`slides/${p.slug}/`, ''), 'lien deck dans la fiche')
|
||
assert.match(body, /<QrEncode path="/, 'composant QR présent')
|
||
assert.ok(listContent.includes(p.title), 'titre présent dans la liste')
|
||
}
|
||
})
|
||
})
|