learning-website-nextjs1-7 Exercise 3: Do the "Try It Yourself" Answer Blocks Work? ====================================================================================== Most of the language lessons end with a "Try It Yourself" block whose answers are hidden until asked for. In the files they are plain
elements with a ("Show answer"): no script, so there is nothing to re-run (Chapter 4) and nothing to break. That is a claim about a real browser, so it was tested in one. 196 of the 601 pages of the site contain such blocks. Save as answers-test.mjs: // Do the "Try It Yourself" answer blocks work in a real browser? They are plain
elements with no script. // node answers-test.mjs import { spawn } from "node:child_process"; import { mkdtempSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; const url = process.argv[2]; const chrome = spawn("C:/Program Files/Google/Chrome/Application/chrome.exe", [ "--headless=new", "--disable-gpu", "--remote-debugging-port=9336", `--user-data-dir=${mkdtempSync(join(tmpdir(), "lw-chrome-"))}`, "about:blank", ], { stdio: "ignore" }); const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); let targets; for (let i = 0; i < 40; i++) { try { targets = await (await fetch("http://127.0.0.1:9336/json")).json(); if (targets.length) break; } catch { /* not up yet */ } await sleep(250); } const ws = new WebSocket(targets.find((t) => t.type === "page").webSocketDebuggerUrl); await new Promise((r) => ws.addEventListener("open", r)); let id = 0; const pending = new Map(); ws.addEventListener("message", (e) => { const m = JSON.parse(e.data); if (m.id && pending.has(m.id)) { pending.get(m.id)(m); pending.delete(m.id); } }); const send = (method, params = {}) => new Promise((r) => { const n = ++id; pending.set(n, r); ws.send(JSON.stringify({ id: n, method, params })); }); const evaluate = async (expression) => (await send("Runtime.evaluate", { expression, returnByValue: true })).result?.result?.value; await send("Page.enable"); await send("Page.navigate", { url }); await sleep(2500); const probe = `(() => { const all = [...document.querySelectorAll("details")]; const d = all[0]; if (!d) return JSON.stringify({ blocks: 0 }); const body = [...d.children].find((c) => c.tagName !== "SUMMARY"); const height = Math.round(d.getBoundingClientRect().height); return JSON.stringify({ blocks: all.length, open: d.open, height, summary: d.querySelector("summary")?.textContent.trim().slice(0, 40), answer: (body?.textContent || d.textContent).trim().slice(0, 50) }); })()`; const before = JSON.parse(await evaluate(probe)); await evaluate('document.querySelector("details summary").click()'); await sleep(500); const after = JSON.parse(await evaluate(probe)); await evaluate('document.querySelector("details summary").click()'); await sleep(500); const closed = JSON.parse(await evaluate(probe)); console.log("blocks on the page:", before.blocks); console.log("before the click: ", JSON.stringify({ open: before.open, heightPx: before.height })); console.log("after one click: ", JSON.stringify({ open: after.open, heightPx: after.height })); console.log("after a second: ", JSON.stringify({ open: closed.open, heightPx: closed.height })); console.log("summary:", before.summary, "| answer starts:", after.answer); ws.close(); chrome.kill(); process.exit(0); node answers-test.mjs http://localhost:3001/germany/german-basic-1/german_basic_conversation_1_1 blocks on the page: 5 before the click: {"open":false,"heightPx":24} after one click: {"open":true,"heightPx":60} after a second: {"open":false,"heightPx":24} summary: Show answer | answer starts: Guten Morgen, Frau Weber! (You'd use Sie with a ne... The block opens when its summary is clicked (24 px high closed, 60 px open) and closes when clicked again. A mistake in the test itself, and how it was found: the first version measured "is the answer's own element visible?" and reported "visible" whether the block was open or closed, because a closed
still reports a size for its content. A check that gives the same answer in both states checks nothing, so it was replaced with the height of the whole block, which does change. The takeaway: before trusting a check, run it in a state where the answer is known to be "no". The language marks from Chapter 4 are still there (the Hungarian lesson has its 38 lang="hu" marks), and a lesson's own accent colour (green for Hungarian, gold for German, red for Japanese, blue for French) is its own scoped style, which Chapter 5 showed the shared tokens do not override. What was NOT tested: keyboard operation of the blocks (a
opens with Enter or Space on its summary in browsers, but that was not tried here), a screen reader, other browsers, or the lessons' print layout. WHY THIS WORKS AS AN ANSWER --------------------------- It tests the behaviour a learner relies on in the real page, and records that the first measurement could not tell open from closed.