// The things the dealer wrote down, in the file they hand over. // // The export already carried the hands, the standings and the settle-up. It didn't // carry either of the two places a dealer types context — the per-seat fields and the // table's own notes — so the one place an IOU was written down was the one place it // couldn't leave. const test = require("node:test"); const assert = require("node:assert"); const { HandHistoryExport, HoldemState, makeTable } = require("./load"); const tableWithNotes = () => { const state = makeTable({ seatCount: 6, seated: [0, 1, 2], stack: 200 }); ["Ann", "Ben", "Cal"].forEach((name, i) => { state.seats[i].name = name; state.seats[i].buyIns = 200; }); state.seats[0].customFields = [ { label: "Seat rent", value: "paid to 2am" }, { label: "Venmo", value: "@ann" }, ]; state.seats[1].customFields = [{ label: "IOU", value: "$20 to Ann" }]; return state; }; test("a seat's own fields ride along with its standings row", () => { const state = tableWithNotes(); const csv = HandHistoryExport.toCsv([], HoldemState.sessionStandings(state)); assert.match(csv, /Seat rent: paid to 2am; Venmo: @ann/); assert.match(csv, /IOU: \$20 to Ann/); }); test("the money columns keep their order, with notes on the end", () => { const state = tableWithNotes(); const csv = HandHistoryExport.toCsv([], HoldemState.sessionStandings(state)); assert.match(csv, /Player,Paid In,Won,Net,Bought In,Chips Now,Up\/Down,Notes/); }); test("a seat with nothing written against it gets an empty cell, not the word undefined", () => { const state = tableWithNotes(); const csv = HandHistoryExport.toCsv([], HoldemState.sessionStandings(state)); const calRow = csv.split("\r\n").find(line => line.startsWith("Cal,")); assert.ok(calRow, "Cal should have a row"); assert.ok(calRow.endsWith(","), `expected an empty last cell, got ${calRow}`); assert.ok(!/undefined|null/.test(calRow)); }); test("a blank label or value doesn't produce a stray colon", () => { const state = tableWithNotes(); state.seats[2].customFields = [{ label: "Note", value: "" }, { label: "", value: "" }]; const csv = HandHistoryExport.toCsv([], HoldemState.sessionStandings(state)); const calRow = csv.split("\r\n").find(line => line.startsWith("Cal,")); assert.match(calRow, /Note/); assert.ok(!/;\s*;/.test(calRow), "an entirely blank field shouldn't take a slot"); }); test("the table's notes are in the file", () => { const state = tableWithNotes(); state.notes = "High-hand promo until midnight."; const csv = HandHistoryExport.toCsv([], HoldemState.sessionStandings(state), { notes: state.notes }); assert.match(csv, /Table Notes/); assert.match(csv, /High-hand promo until midnight\./); }); test("a multi-line note survives as one cell", () => { // csvField quotes anything with a line break in it, so the note doesn't turn into // rows a spreadsheet reads as more players. const state = tableWithNotes(); const notes = "Line one\nLine two, with a comma\nLine \"three\""; const csv = HandHistoryExport.toCsv([], HoldemState.sessionStandings(state), { notes }); assert.match(csv, /"Line one\nLine two, with a comma\nLine ""three"""/); }); test("no notes means no section, not an empty heading", () => { const state = tableWithNotes(); const csv = HandHistoryExport.toCsv([], HoldemState.sessionStandings(state), { notes: " " }); assert.ok(!/Table Notes/.test(csv)); }); test("the export still works with no standings at all", () => { assert.doesNotThrow(() => HandHistoryExport.toCsv([], [], { notes: "just a note" })); const csv = HandHistoryExport.toCsv([], [], { notes: "just a note" }); assert.match(csv, /Table Notes/); }); test("asking for the standings doesn't change the seats", () => { const state = tableWithNotes(); const before = JSON.stringify(state.seats); HoldemState.sessionStandings(state); assert.equal(JSON.stringify(state.seats), before); });