import { test } from "node:test"; import assert from "node:assert/strict"; import { failedValues, formValues, seedChecked, seedValue, type FormErrorState, type FormState, } from "./formState"; // Run with: pnpm --filter editor test test("formValues keeps each name's first value and skips files", () => { const fd = new FormData(); fd.append("siteTitle", "Typed title"); fd.append("digestSections", "chapters"); fd.append("digestSections", "tags"); fd.append("upload", new File(["x"], "x.txt")); fd.append("empty", ""); assert.deepEqual(formValues(fd), { siteTitle: "Typed title", digestSections: "chapters", empty: "", }); }); test("formValues keeps a field named like an Object.prototype key", () => { const fd = new FormData(); fd.append("__proto__", "a"); fd.append("constructor", "b"); const values = formValues(fd); assert.equal(Object.getPrototypeOf(values), Object.prototype); assert.equal(Object.hasOwn(values, "__proto__"), true); assert.equal(values.constructor, "b"); assert.deepEqual(Object.keys(values), ["__proto__", "constructor"]); }); test("seedValue: no state, a success, or a failure without values → initial", () => { const ok: FormState<{ siteId: string }> = { ok: true, siteId: "x" }; const bare: FormState = { ok: false, error: "no" }; for (const state of [undefined, null, ok, bare]) { assert.equal(seedValue(state, "siteTitle", "Stored"), "Stored"); } }); test("seedValue: a failure with values → what was submitted, even empty", () => { const state: FormState = { ok: false, error: "Site ID must be …", values: { siteTitle: "Typed", wordmarkLead: "" }, }; assert.equal(seedValue(state, "siteTitle", "Stored"), "Typed"); // Cleared on purpose is kept cleared: "" is a value, not an absence. assert.equal(seedValue(state, "wordmarkLead", "Jer"), ""); }); test("seedValue: a name the failed submit did not carry keeps its initial", () => { // A disabled field, or one not rendered at the time, posts nothing. const state: FormState = { ok: false, error: "no", values: { a: "1" } }; assert.equal(seedValue(state, "notPosted", "Stored"), "Stored"); // Not fooled by Object.prototype. assert.equal(seedValue(state, "toString", "Stored"), "Stored"); }); test("seedChecked: no state, a success, or no values → initial", () => { const ok: FormState = { ok: true }; const bare: FormState = { ok: false, error: "no" }; for (const state of [undefined, null, ok, bare]) { assert.equal(seedChecked(state, "pwa", true), true); assert.equal(seedChecked(state, "pwa", false), false); } }); test("seedChecked: with values, present is ticked and ABSENT is unticked", () => { // An unticked box sends nothing, so absence is the answer, not "unknown". const state: FormState = { ok: false, error: "no", values: { pwa: "on", commit: "true" }, }; assert.equal(seedChecked(state, "pwa", false), true); assert.equal(seedChecked(state, "commit", false), true); assert.equal(seedChecked(state, "archives", true), false); assert.equal(seedChecked(state, "hasOwnProperty", true), false); }); test("the channels flavour reads through the same helpers", () => { const failed: FormErrorState = { error: "already exists", values: { name: "Typed", fetchPlaylist: "on" }, }; const success: FormErrorState = undefined; assert.deepEqual(failedValues(failed), { name: "Typed", fetchPlaylist: "on", }); assert.equal(seedValue(failed, "name", "Stored"), "Typed"); assert.equal(seedChecked(failed, "fetchPlaylist", false), true); assert.equal(seedChecked(failed, "prioritizeDownload", true), false); assert.equal(failedValues(success), undefined); assert.equal(seedValue(success, "name", "Stored"), "Stored"); // An error with no values (an action that returns none) seeds from initial. assert.equal(seedValue({ error: "no" }, "name", "Stored"), "Stored"); });