import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; import fc from 'fast-check'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const HTML_FILES = ['dashboard.html', 'admin.html', 'hf_console.html']; const REQUIRED_CSS = ['/static/css/unified-ui.css', '/static/css/components.css']; const REQUIRED_JS_BASE = '/static/js/ui-feedback.js'; const PAGE_CONTROLLERS = { 'dashboard.html': '/static/js/dashboard-app.js', 'admin.html': '/static/js/admin-app.js', 'hf_console.html': '/static/js/hf-console.js' }; function readHTMLFile(filename) { const filePath = path.join(__dirname, '..', filename); return fs.readFileSync(filePath, 'utf-8'); } function extractLinks(html, tag, attr) { const regex = new RegExp(`<${tag}[^>]*${attr}=["']([^"']+)["']`, 'g'); const matches = []; let match; while ((match = regex.exec(html)) !== null) { matches.push(match[1]); } return matches; } console.log('Running Property-Based Tests for HTML Structure...\n'); HTML_FILES.forEach(filename => { console.log(`\nTesting ${filename}:`); const html = readHTMLFile(filename); console.log(' Property 12.1: Should load only unified-ui.css and components.css'); const cssLinks = extractLinks(html, 'link', 'href') .filter(href => href.includes('.css') && !href.includes('fonts.googleapis.com')); if (cssLinks.length !== 2) { throw new Error(`Expected 2 CSS files, found ${cssLinks.length}: ${cssLinks.join(', ')}`); } if (!cssLinks.includes(REQUIRED_CSS[0])) { throw new Error(`Missing required CSS: ${REQUIRED_CSS[0]}`); } if (!cssLinks.includes(REQUIRED_CSS[1])) { throw new Error(`Missing required CSS: ${REQUIRED_CSS[1]}`); } console.log(' ✓ Loads only unified-ui.css and components.css'); console.log(' Property 12.2: Should load only ui-feedback.js and page-specific controller'); const jsScripts = extractLinks(html, 'script', 'src'); if (jsScripts.length !== 2) { throw new Error(`Expected 2 JS files, found ${jsScripts.length}: ${jsScripts.join(', ')}`); } if (!jsScripts.includes(REQUIRED_JS_BASE)) { throw new Error(`Missing required JS: ${REQUIRED_JS_BASE}`); } if (!jsScripts.includes(PAGE_CONTROLLERS[filename])) { throw new Error(`Missing page controller: ${PAGE_CONTROLLERS[filename]}`); } console.log(' ✓ Loads only ui-feedback.js and page-specific controller'); console.log(' Property 12.3: Should use relative URLs for all static assets'); const allAssets = [...cssLinks, ...jsScripts]; allAssets.forEach(asset => { if (!asset.startsWith('/static/')) { throw new Error(`Asset does not use /static/ prefix: ${asset}`); } }); console.log(' ✓ All static assets use relative URLs with /static/ prefix'); console.log(' Property 12.4: Should have consistent navigation structure'); if (!html.includes('