Files
my-pi/pi-ask-user/test/normalize.test.ts
T

87 lines
3.2 KiB
TypeScript

import assert from "node:assert/strict";
import test from "node:test";
import { formatAnswers, normalizeQuestions, orderedAnswers } from "../src/normalize.ts";
import type { UserAnswer } from "../src/types.ts";
test("normalizes select and text questions with bounded defaults", () => {
const questions = normalizeQuestions([
{
id: "language",
label: " Language ",
prompt: " Choose a language ",
type: "select",
options: [{ value: "ts", label: " TypeScript " }],
},
{
id: "notes",
prompt: "Anything else?",
type: "text",
required: false,
},
]);
assert.deepEqual(questions[0], {
id: "language",
label: "Language",
prompt: "Choose a language",
type: "select",
options: [{ value: "ts", label: "TypeScript" }],
allowCustom: true,
required: true,
});
assert.equal(questions[1]?.label, "Q2");
assert.equal(questions[1]?.allowCustom, false);
assert.equal(questions[1]?.required, false);
});
test("rejects invalid ids, duplicate ids, invalid option combinations, and duplicate values", () => {
assert.throws(() => normalizeQuestions([{ id: "bad id", prompt: "Bad", type: "text" }]), /must start with a letter/);
assert.throws(() => normalizeQuestions([null as never]), /must be an object/);
assert.throws(() => normalizeQuestions([{ id: "bad_flag", prompt: "Bad", type: "text", required: "yes" as never }]), /must be a boolean/);
assert.throws(() => normalizeQuestions([
{ id: "same", prompt: "One", type: "text" },
{ id: "same", prompt: "Two", type: "text" },
]), /duplicate question id/);
assert.throws(() => normalizeQuestions([{ id: "pick", prompt: "Pick", type: "select" }]), /at least one option/);
assert.throws(() => normalizeQuestions([{ id: "text", prompt: "Write", type: "text", options: [{ value: "x", label: "X" }] }]), /must not define options/);
assert.throws(() => normalizeQuestions([{
id: "pick",
prompt: "Pick",
type: "select",
options: [{ value: "x", label: "X" }, { value: "x", label: "Again" }],
}]), /duplicate option value/);
});
test("orders and formats answers by question order", () => {
const questions = normalizeQuestions([
{ id: "first", prompt: "First?", type: "text" },
{ id: "second", prompt: "Second?", type: "select", options: [{ value: "yes", label: "Yes" }] },
{ id: "third", prompt: "Third?", type: "text", required: false },
]);
const answer = (id: string, overrides: Partial<UserAnswer>): UserAnswer => ({
id,
question: `${id}?`,
type: "text",
answer: id,
value: id,
label: id,
custom: false,
skipped: false,
...overrides,
});
const answers = new Map<string, UserAnswer>([
["third", answer("third", { answer: "", value: "", label: "Skipped", skipped: true })],
["second", answer("second", { type: "select", answer: "Yes", value: "yes", label: "Yes" })],
["first", answer("first", { answer: "hello", value: "hello", label: "hello", custom: true })],
]);
const ordered = orderedAnswers(questions, answers);
assert.deepEqual(ordered.map((item) => item.id), ["first", "second", "third"]);
assert.equal(formatAnswers(ordered), [
"first: user wrote: hello",
"second: user selected: Yes (value: yes)",
"third: skipped",
].join("\n"));
});