mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-08-28 08:35:57 +00:00
87 lines
3.2 KiB
TypeScript
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"));
|
|
});
|