diff --git a/auth-ui.test.js b/auth-ui.test.js new file mode 100644 index 0000000..d60aabd --- /dev/null +++ b/auth-ui.test.js @@ -0,0 +1,42 @@ +// Structural check for T22's login/register UI in live.html and dance.html +// (dev-plan-3.md). No browser/DOM tooling is available to `node --test` +// here, so this can't render the pages — but it catches the easy mistake +// in this style of plain-HTML+inline-JS codebase: an element id renamed in +// the markup without updating the matching getElementById() call, which +// would otherwise fail silently in a real browser (getElementById returns +// null, then the first click throws and nothing visibly explains why). +// The actual end-to-end behavior (register/login/logout, nickname binding +// from an existing viewer_uid cookie) was verified manually in a real +// browser against the running server; see the session notes. +const test = require("node:test"); +const assert = require("node:assert/strict"); +const fs = require("node:fs"); +const path = require("node:path"); + +const AUTH_IDS = ["authBtn", "authModal", "authTitle", "authEmail", "authPassword", "authError", "authSubmitBtn", "authToggleBtn", "authCloseBtn"]; +// register/login share one call site (`` `/api/auth/${authMode}` ``, authMode +// is "register" or "login"), so check for that template plus the two literal +// endpoints separately, rather than four literal path strings. +const AUTH_ENDPOINTS = ["/api/auth/${authMode}", "/api/auth/logout", "/api/auth/me"]; + +for (const page of ["live.html", "dance.html"]) { + test(`${page}: every auth element id used in the script is actually declared in the markup`, () => { + const html = fs.readFileSync(path.join(__dirname, page), "utf8"); + for (const id of AUTH_IDS) { + assert.match(html, new RegExp(`id="${id}"`), `markup is missing id="${id}"`); + assert.match(html, new RegExp(`getElementById\\("${id}"\\)`), `script never looks up #${id}`); + } + }); + + test(`${page}: wires up all four auth endpoints`, () => { + const html = fs.readFileSync(path.join(__dirname, page), "utf8"); + for (const endpoint of AUTH_ENDPOINTS) { + assert.ok(html.includes(endpoint), `script never calls ${endpoint}`); + } + }); + + test(`${page}: the auth modal is hidden by default (must not force a login gate)`, () => { + const html = fs.readFileSync(path.join(__dirname, page), "utf8"); + assert.match(html, /