// What Table Setup holds while it is open. // // It is the one panel the tool opens by itself, on a table nobody has set up yet — so // it is most of what a dealer sees the first time they arrive. Measured on a fresh // table, before this: the panel stood 886px on a 667px phone, and the whole page 2076. // // The order was the problem more than the length. The two figures the panel's own // summary glances at — "10 seats · $1/$2" — were the seat count at the top and the // blinds 218px further down, under three switches and three paragraphs explaining // them: a dedicated dealer, a card sheet at every street, and whether the phone is // allowed to sleep. A dealer setting up a $1/$2 game read all of that on the way to // the two boxes they came for. // // The three have gone into "While you deal", with the paragraphs that explain them. // That is not a new idea in this panel — House take and Without live betting were // already nested disclosures — it is the same idea applied to the things that were not // about money. Afterwards: the panel is 529px, the page 1719 on the same phone and // 1275 on a 1280x900 desktop, and the first two rows are the seats and the blinds. // // A switch nobody can see is a switch nobody remembers turning on, so the disclosure // carries a glance of its own. const test = require("node:test"); const { describe } = require("node:test"); const assert = require("node:assert"); const fs = require("fs"); const path = require("path"); const { Render, makeTable } = require("./load"); const ROOT = path.join(__dirname, "..", "..", "JoshHeaps.Net"); const PAGE = fs.readFileSync(path.join(ROOT, "Pages", "Casino", "TexasHoldem.cshtml"), "utf8"); const CSS = fs.readFileSync(path.join(ROOT, "wwwroot", "css", "casino", "holdem.css"), "utf8"); const MAIN = fs.readFileSync(path.join(ROOT, "wwwroot", "js", "casino", "holdem", "main.js"), "utf8"); // The Table Setup panel, from its opening tag to the panel after it. const setupPanel = () => { const at = PAGE.indexOf('
'); assert.ok(at >= 0, "there is no Table Setup panel"); const end = PAGE.indexOf('
at, "the panel after Table Setup has gone"); return PAGE.slice(at, end); }; // What the panel shows without anything being opened: everything before the first // nested disclosure. const alwaysShowing = () => { const panel = setupPanel(); const firstSub = panel.indexOf('
'); assert.ok(firstSub >= 0, "the panel has no nested disclosures at all"); return panel.slice(0, firstSub); }; const ruleFor = selector => { const at = CSS.indexOf(`\n${selector} {`); assert.ok(at >= 0, `there is no \`${selector}\` rule`); return CSS.slice(at, CSS.indexOf("}", at)); }; const glance = state => (Render.panelGlances(state).glanceWhileYouDeal || {}).text; const table = () => makeTable({ seatCount: 9, seated: [], stack: 0 }); // --------------------------------------------------------------------------- describe("what the open panel leads with", () => { // The two the summary already glances at. They were first and seventh. test("the seats and the blinds, in that order, above everything else", () => { const body = alwaysShowing(); const seats = body.indexOf('id="seatCountInput"'); const small = body.indexOf('id="smallBlindInput"'); const big = body.indexOf('id="bigBlindInput"'); const stack = body.indexOf('id="defaultStackInput"'); assert.ok(seats >= 0 && small >= 0 && big >= 0 && stack >= 0, "one of the four numbers is no longer in the part of the panel that shows"); assert.ok(seats < small, "the seat count is below the blinds"); assert.ok(small < big && big < stack, "the blinds and the stack have swapped"); }); test("and nothing in it is a switch about how the tool behaves", () => { const body = alwaysShowing(); ["dedicatedDealerToggle", "trackBoardToggle", "keepScreenAwakeToggle"].forEach(id => { assert.ok(!body.includes(id), `${id} is still on the panel's first screen`); }); }); // One line, and it is about the boxes directly above it. test("one paragraph survives, the short one", () => { const hints = alwaysShowing().match(/

/g) || []; assert.equal(hints.length, 1, "the panel's first screen is back to being prose"); assert.match(alwaysShowing(), /Blinds post themselves each hand/); }); }); describe("where the three switches went", () => { const dealing = () => { const panel = setupPanel(); const at = panel.indexOf("

While you deal"); assert.ok(at >= 0, 'there is no "While you deal" disclosure'); return panel.slice(panel.lastIndexOf("", at)); }; test("all three of them, with the paragraphs that explain them", () => { const body = dealing(); ["dedicatedDealerToggle", "trackBoardToggle", "keepScreenAwakeToggle"].forEach(id => { assert.ok(body.includes(id), `${id} did not come with the rest`); }); assert.match(body, /no seat shows the dealer button/); assert.match(body, /a sheet asks which cards came off the deck/); assert.match(body, /Stops the phone dimming and locking/); }); // The same shape House take and Without live betting already had. A disclosure that // ships open is a disclosure that has saved nobody anything. test("it is shut, like the two money ones beside it", () => { const panel = setupPanel(); assert.ok(!/
]*\bopen\b/.test(panel), "a nested disclosure in this panel ships open"); }); test("and it sits above them, because it is not about money", () => { const panel = setupPanel(); assert.ok(panel.indexOf("While you deal") < panel.indexOf("House take")); assert.ok(panel.indexOf("House take") < panel.indexOf("Without live betting")); }); }); describe("the glance on a shut disclosure", () => { test("silence when all three are where they ship", () => { const state = table(); assert.equal(glance(state), ""); }); test("and a name when one of them is not", () => { const state = table(); state.trackBoard = true; assert.equal(glance(state), "Asking for cards"); const other = table(); other.dedicatedDealer = true; assert.equal(glance(other), "House dealer"); }); // The only one that ships on, so it is its absence that is worth saying. test("the screen setting speaks by going quiet, not by being on", () => { const on = table(); on.keepScreenAwake = true; assert.equal(glance(on), ""); const off = table(); off.keepScreenAwake = false; assert.equal(glance(off), "Screen may sleep"); }); // Joined, the three run to 49 characters, and this row is 44px of a 320px column // with a label already on it. "House dealer · Asking for c…" has told nobody // anything; the one most likely to be the surprise has. test("one of them, never a list of three", () => { const state = table(); state.trackBoard = true; state.dedicatedDealer = true; state.keepScreenAwake = false; assert.equal(glance(state), "Asking for cards"); assert.ok(glance(state).length <= 24); }); test("it is a row this sidebar knows how to write", () => { assert.ok(Render.PANEL_GLANCES.includes("glanceWhileYouDeal"), "the glance is computed and never written, so the row keeps its old text all night"); const panel = setupPanel(); const at = panel.indexOf('id="glanceWhileYouDeal"'); assert.ok(at >= 0, "there is nowhere to write it"); assert.match(panel.slice(panel.lastIndexOf("", at)), /hidden/); }); }); describe("what had to be true for it to hang there", () => { // Without this the span anchors to whichever ancestor is positioned, which is the // sidebar — the glance would appear at the top right of the whole column. test("the summary it hangs off is a positioned box", () => { assert.match(ruleFor(".subPanel > summary"), /position:\s*relative/); }); // A footnote on a line that is itself a footnote. At the weight of "Off by $40" the // eye stops on a row saying nothing has gone wrong. test("and it is drawn a step quieter than the panel headings' own", () => { const sub = ruleFor(".subPanelGlance"); assert.match(sub, /font-size:\s*var\(--fs-xs\)/); assert.match(sub, /color:\s*var\(--text-dim\)/); assert.match(ruleFor(".panelGlance"), /font-size:\s*var\(--fs-sm\)/); }); }); describe("the panel still opens itself only when it should", () => { test("on a table nobody has touched, and not on the fourth hand", () => { const at = MAIN.indexOf('document.getElementById("tableSetupPanel")'); assert.ok(at >= 0, "nothing decides whether the panel starts open"); const block = MAIN.slice(at, at + 400); assert.match(block, /Number\(state\.handNumber\) \|\| 1\) === 1/); assert.match(block, /!state\.seats\.some\(seat => HoldemState\.seatInPlay\(seat\)\)/); assert.match(block, /panel\.open = fresh/); }); test("what was measured is written beside the decision", () => { const at = MAIN.indexOf("Table Setup used to ship open"); assert.ok(at >= 0); const note = MAIN.slice(at, at + 1200); assert.match(note, /886px/); assert.match(note, /529px/); }); });