Essai 3 - trace brute assainie
Essai 3 - sortie brute
Contenu conserve tel que produit. Seuls les chemins et adresses internes eventuels sont neutralises.
```json
{
"index_html": "<!DOCTYPE html>\n<html lang=\"fr\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Carnet des heures manquantes</title>\n <style>\n body {\n font-family: Arial, sans-serif;\n margin: 20px;\n }\n .event {\n border-bottom: 1px solid #ccc;\n padding: 10px 0;\n }\n .filters {\n margin-bottom: 20px;\n }\n button {\n margin-right: 5px;\n }\n </style>\n</head>\n<body>\n <h1>Carnet des heures manquantes</h1>\n <div class=\"filters\">\n <button onclick=\"filterEvents('all')\">Tous</button>\n <button onclick=\"filterEvents('note')\">Notes</button>\n <button onclick=\"filterEvents('decision')\">Décisions</button>\n <button onclick=\"filterEvents('question')\">Questions</button>\n </div>\n <div id=\"events\"></div>\n <div id=\"summary\"></div>\n\n <script>\n const events = [\n {\"heure\":\"09:10\",\"type\":\"note\",\"texte\":\"Café, reprise du chantier WSL.\"},\n {\"heure\":\"11:40\",\"type\":\"decision\",\"texte\":\"Garder le local comme socle principal.\"},\n {\"heure\":\"18:05\",\"type\":\"question\",\"texte\":\"Quel modèle léger utiliser pour les brouillons ?\"},\n {\"heure\":\"23:20\",\"type\":\"note\"}\n ];\n\n function displayEvents(filter) {\n const eventContainer = document.getElementById('events');\n eventContainer.innerHTML = '';\n events.forEach(event => {\n if (filter === 'all' || event.type === filter) {\n const div = document.createElement('div');\n div.className = 'event';\n div.innerHTML = `<strong>${event.heure}</strong> - ${event.type}: ${event.texte || 'Texte manquant'}`;\n eventContainer.appendChild(div);\n }\n });\n }\n\n function updateSummary() {\n const summary = document.getElementById('summary');\n const totalEvents = events.length;\n const missingTextEvent = events.find(event => !event.texte);\n summary.innerHTML = `Total d'événements: ${totalEvents}. Texte manquant à ${missingTextEvent.heure}.`;\n }\n\n function filterEvents(filter) {\n displayEvents(filter);\n updateSummary();\n }\n\n document.addEventListener('DOMContentLoaded', () => {\n displayEvents('all');\n updateSummary();\n });\n </script>\n</body>\n</html>",
"test_js": "const fs = require('fs');\nconst path = require('path');\n\nfunction parseJSON(data) {\n try {\n return JSON.parse(data);\n } catch (error) {\n console.error('Erreur de parsing JSON:', error);\n process.exit(1);\n }\n}\n\nconst indexHTMLPath = path.join(__dirname, 'index.html');\nconst testJSPath = path.join(__dirname, 'test.js');\n\nif (!fs.existsSync(indexHTMLPath) || !fs.existsSync(testJSPath)) {\n console.error('Fichiers manquants.');\n process.exit(1);\n}\n\nconst indexHTMLContent = fs.readFileSync(indexHTMLPath, 'utf8');\nconst testJSContent = fs.readFileSync(testJSPath, 'utf8');\n\nif (!indexHTMLContent.includes('<title>Carnet des heures manquantes</title>')) {\n console.error('Titre incorrect dans index.html.');\n process.exit(1);\n}\n\nif (!testJSContent.includes('parseJSON(data)')) {\n console.error('Fonction parseJSON non trouvée dans test.js.');\n process.exit(1);\n}\n\nconst eventsData = `[\n {\"heure\":\"09:10\",\"type\":\"note\",\"texte\":\"Café, reprise du chantier WSL.\"},\n {\"heure\":\"11:40\",\"type\":\"decision\",\"texte\":\"Garder le local comme socle principal.\"},\n {\"heure\":\"18:05\",\"type\":\"question\",\"texte\":\"Quel modèle léger utiliser pour les brouillons ?\"},\n {\"heure\":\"23:20\",\"type\":\"note\"}\n]`;\n\nconst events = parseJSON(eventsData);\n\nif (events.length !== 4) {\n console.error('Nombre incorrect d\'événements.');\n process.exit(1);\n}\n\nconst missingTextEvent = events.find(event => !event.texte);\n\nif (!missingTextEvent || missingTextEvent.heure !== '23:20') {\n console.error('Événement avec texte manquant incorrect.');\n process.exit(1);\n}\n\nconsole.log('Tous les tests passent.');\nprocess.exit(0);"
}
```