#!/usr/bin/env node /** * ObsiGate — Settings section order + profile avatar (#113). * * Static checks (no jsdom — runs in the "Frontend unit tests" CI step): * - Order: the #config-nav TOC and the page sections must list the same * anchors in the same order, with #cfg-profile first and #cfg-about last * (regression guard for the reorganization). * - Avatar UI: the Profil section must carry the picker (preview, file * input, choose/remove buttons), config.js the resize/PATCH flow, auth.js * the sidebar image rendering, style.css the preview/img rules, and the * i18n keys must exist in FR and EN. * - Backend: backend/auth/router.py must validate the avatar data-URL. * * Usage: node tests/frontend/settings-order-avatar.test.mjs */ import { strict as assert } from "node:assert"; import { existsSync, readFileSync } from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const ROOT = path.join(__dirname, "..", ".."); const indexHtml = readFileSync(path.join(ROOT, "frontend", "index.html"), "utf8"); const configJs = readFileSync(path.join(ROOT, "frontend", "js", "config.js"), "utf8"); const authJs = readFileSync(path.join(ROOT, "frontend", "js", "auth.js"), "utf8"); const css = readFileSync(path.join(ROOT, "frontend", "style.css"), "utf8"); const routerPy = readFileSync(path.join(ROOT, "backend", "auth", "router.py"), "utf8"); const fr = JSON.parse(readFileSync(path.join(ROOT, "frontend", "locales", "fr.json"), "utf8")); const en = JSON.parse(readFileSync(path.join(ROOT, "frontend", "locales", "en.json"), "utf8")); function test(label, fn) { try { fn(); console.log(" ✓ " + label); } catch (err) { console.error(" ✗ " + label + "\n " + err.message); process.exitCode = 1; } } function tocHrefs() { const nav = indexHtml.match(/