Add Makefile, package.json, and initial configuration for VitePress and Slidev integration

- 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.
This commit is contained in:
Le Prévost-Corvellec Arnault
2026-04-11 15:59:20 +02:00
parent 10f7798afb
commit 354c8cd9ef
70 changed files with 16388 additions and 2469 deletions
+69
View File
@@ -0,0 +1,69 @@
// @ts-check
import { test, expect } from '@playwright/test'
test.describe('Portail (build statique)', () => {
test('accueil : titre, intro, liens rapides, grille présentations', async ({ page }) => {
await page.goto('/')
await expect(page.getByRole('heading', { name: 'Talks', level: 1 })).toBeVisible()
await expect(page.getByRole('heading', { name: 'À propos de ce site' })).toBeVisible()
await expect(page.getByRole('heading', { name: 'Liens rapides' })).toBeVisible()
await expect(page.getByRole('heading', { name: 'Présentations' })).toBeVisible()
const qrCanvases = page.locator('.qr-section canvas')
// Un seul QR sur l’accueil quand talkRepoUrl est vide (QR dépôt optionnel).
await expect(qrCanvases).toHaveCount(1)
const cards = page.locator('.talks-section--home .talk-card')
await expect(cards).toHaveCount(2)
})
test('navigation : liste → fiche → href slides cohérents', async ({ page }) => {
await page.goto('/presentations/')
await expect(page.getByRole('heading', { name: 'Présentations', level: 1 })).toBeVisible()
await expect(page.locator('article.talk-card--list')).toHaveCount(2)
await page
.locator('article.talk-card--list')
.filter({ hasText: 'Kubernetes Operators' })
.getByRole('link', { name: 'Kubernetes Operators' })
.click()
await expect(page).toHaveURL(/\/presentations\/kubernetes-operators\/?$/)
const slidesLink = page.getByRole('link', { name: 'Voir les slides' })
await expect(slidesLink).toHaveAttribute('href', /\/slides\/kubernetes-operators\/1\/?$/)
})
test('fiche kubernetes-operators : clic « Voir les slides » ouvre la 1ère planche Slidev', async ({ page }) => {
await page.goto('/presentations/kubernetes-operators/')
await expect(page.getByRole('heading', { name: 'Kubernetes Operators', level: 1 })).toBeVisible()
await page.getByRole('link', { name: 'Voir les slides' }).click()
await expect(page).toHaveURL(/\/slides\/kubernetes-operators\/1\/?$/)
await expect(page.locator('#app')).toBeAttached()
await expect(page).toHaveTitle(/Kubernetes Operators/i)
})
test('fiche : boutons slides + bloc QR deck', async ({ page }) => {
await page.goto('/presentations/spring-ai/')
await expect(page.getByRole('heading', { name: 'Spring AI', level: 1 })).toBeVisible()
await expect(page.getByRole('link', { name: 'Voir les slides' })).toHaveAttribute(
'href',
/\/slides\/spring-ai\/1\/?$/,
)
await expect(page.getByRole('heading', { name: 'Partager les slides' })).toBeVisible()
await expect(page.locator('.qr-deck canvas')).toHaveCount(1)
})
test('deck Slidev servi sous /slides/<slug>/1', async ({ page }) => {
await page.goto('/slides/kubernetes-operators/1')
await expect(page.locator('#app')).toBeAttached()
await expect(page).toHaveTitle(/Kubernetes Operators/i)
})
test('lien accueil → liste complète', async ({ page }) => {
await page.goto('/')
await page.getByRole('link', { name: /Voir toutes les présentations/ }).click()
await expect(page).toHaveURL(/\/presentations\/?$/)
})
})
+25
View File
@@ -0,0 +1,25 @@
// @ts-check
import { readFileSync } from 'fs'
import { join as pathJoin } from 'path'
import { test, expect } from '@playwright/test'
const presJson = pathJoin(process.cwd(), 'portal', '.vitepress', 'data', 'presentations.json')
const SLUGS = JSON.parse(readFileSync(presJson, 'utf8')).map((p) => p.slug)
const ROUTES = ['/', '/presentations/', ...SLUGS.map((s) => `/presentations/${s}/`)]
test.describe('HTTP / routes statiques', () => {
for (const route of ROUTES) {
test(`GET ${route} → 200`, async ({ request }) => {
const res = await request.get(route)
expect(res.ok(), await res.text()).toBeTruthy()
})
}
test('GET slides decks → 200', async ({ request }) => {
for (const slug of SLUGS) {
const res = await request.get(`/slides/${slug}/1`)
expect(res.ok(), `slides ${slug}: ${await res.text()}`).toBeTruthy()
}
})
})
+39
View File
@@ -0,0 +1,39 @@
// @ts-check
import { readFileSync } from 'fs'
import { join as pathJoin } from 'path'
import { test, expect } from '@playwright/test'
const presJson = pathJoin(process.cwd(), 'portal', '.vitepress', 'data', 'presentations.json')
const SLUGS = JSON.parse(readFileSync(presJson, 'utf8')).map((p) => p.slug)
test.describe('Matrice présentations (chaque slug)', () => {
for (const slug of SLUGS) {
test(`fiche ${slug} : titre, liens, QR`, async ({ page }) => {
await page.goto(`/presentations/${slug}/`)
await expect(page.locator('h1')).toBeVisible()
const title = await page.locator('h1').textContent()
expect(title.length).toBeGreaterThan(0)
const deckPath = new RegExp(`/slides/${slug}/1/?$`)
await expect(page.getByRole('link', { name: 'Voir les slides' })).toHaveAttribute('href', deckPath)
await expect(page.getByRole('link', { name: 'Ouvrir dans un nouvel onglet' })).toHaveAttribute('href', deckPath)
await expect(page.locator('.qr-deck canvas')).toHaveCount(1)
})
test(`deck Slidev ${slug} : #app + titre`, async ({ page }) => {
await page.goto(`/slides/${slug}/1`)
await expect(page.locator('#app')).toBeAttached()
const t = await page.title()
expect(t.length).toBeGreaterThan(0)
})
test(`liste : carte ${slug} avec actions Fiche / Slides`, async ({ page }) => {
await page.goto('/presentations/')
const card = page
.locator('article.talk-card--list')
.filter({ has: page.locator(`a[href="/presentations/${slug}/"], a[href$="/presentations/${slug}/"]`) })
await expect(card.getByRole('link', { name: 'Fiche' })).toHaveAttribute('href', new RegExp(`/presentations/${slug}/`))
await expect(card.getByRole('link', { name: 'Slides' })).toHaveAttribute('href', new RegExp(`/slides/${slug}/1`))
})
}
})