initial commit
This commit is contained in:
180
question-core.test.mjs
Normal file
180
question-core.test.mjs
Normal file
@@ -0,0 +1,180 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import {
|
||||
SOMETHING_ELSE_LABEL,
|
||||
SOMETHING_ELSE_VALUE,
|
||||
allQuestionsAnswered,
|
||||
createAnsweredResult,
|
||||
createCancelledResult,
|
||||
createCustomAnswer,
|
||||
createPredefinedAnswer,
|
||||
nextTabAfterAnswer,
|
||||
normalizeQuestions,
|
||||
summarizeAnswers,
|
||||
wrapPrefixedText,
|
||||
} from "./question-core.mjs";
|
||||
|
||||
test("normalizeQuestions adds default labels and appends the Something else option", () => {
|
||||
const [question] = normalizeQuestions([
|
||||
{
|
||||
id: "scope",
|
||||
prompt: "Which scope fits best?",
|
||||
options: [{ value: "small", label: "Small change" }],
|
||||
},
|
||||
]);
|
||||
|
||||
assert.equal(question.label, "Q1");
|
||||
assert.deepEqual(question.options[0], { value: "small", label: "Small change" });
|
||||
assert.deepEqual(question.options.at(-1), {
|
||||
value: SOMETHING_ELSE_VALUE,
|
||||
label: SOMETHING_ELSE_LABEL,
|
||||
});
|
||||
});
|
||||
|
||||
test("normalizeQuestions keeps provided labels and descriptions intact before the synthetic option", () => {
|
||||
const [question] = normalizeQuestions([
|
||||
{
|
||||
id: "priority",
|
||||
label: "Priority",
|
||||
prompt: "Which priority?",
|
||||
options: [
|
||||
{ value: "p0", label: "P0", description: "Need this now" },
|
||||
{ value: "p1", label: "P1" },
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
assert.equal(question.label, "Priority");
|
||||
assert.deepEqual(question.options.slice(0, 2), [
|
||||
{ value: "p0", label: "P0", description: "Need this now" },
|
||||
{ value: "p1", label: "P1" },
|
||||
]);
|
||||
assert.equal(question.options[2].label, SOMETHING_ELSE_LABEL);
|
||||
});
|
||||
|
||||
test("answer helpers preserve machine values and summary lines distinguish predefined vs custom answers", () => {
|
||||
const questions = normalizeQuestions([
|
||||
{
|
||||
id: "scope",
|
||||
label: "Scope",
|
||||
prompt: "Which scope fits best?",
|
||||
options: [{ value: "small", label: "Small change" }],
|
||||
},
|
||||
{
|
||||
id: "notes",
|
||||
label: "Notes",
|
||||
prompt: "Anything else?",
|
||||
options: [{ value: "none", label: "No extra notes" }],
|
||||
},
|
||||
]);
|
||||
|
||||
const predefined = createPredefinedAnswer("scope", questions[0].options[0], 1);
|
||||
const custom = createCustomAnswer("notes", "Needs to work with tmux");
|
||||
|
||||
assert.deepEqual(predefined, {
|
||||
id: "scope",
|
||||
value: "small",
|
||||
label: "Small change",
|
||||
wasCustom: false,
|
||||
index: 1,
|
||||
});
|
||||
assert.deepEqual(custom, {
|
||||
id: "notes",
|
||||
value: "Needs to work with tmux",
|
||||
label: "Needs to work with tmux",
|
||||
wasCustom: true,
|
||||
});
|
||||
assert.deepEqual(summarizeAnswers(questions, [predefined, custom]), [
|
||||
"Scope: user selected: 1. Small change",
|
||||
"Notes: user wrote: Needs to work with tmux",
|
||||
]);
|
||||
});
|
||||
|
||||
test("createCancelledResult returns a structured cancelled payload", () => {
|
||||
const questions = normalizeQuestions([
|
||||
{
|
||||
id: "scope",
|
||||
prompt: "Which scope fits best?",
|
||||
options: [{ value: "small", label: "Small change" }],
|
||||
},
|
||||
]);
|
||||
|
||||
assert.deepEqual(createCancelledResult(questions), {
|
||||
questions,
|
||||
answers: [],
|
||||
cancelled: true,
|
||||
});
|
||||
});
|
||||
|
||||
test("createAnsweredResult keeps answers in question order", () => {
|
||||
const questions = normalizeQuestions([
|
||||
{
|
||||
id: "scope",
|
||||
label: "Scope",
|
||||
prompt: "Which scope fits best?",
|
||||
options: [{ value: "small", label: "Small change" }],
|
||||
},
|
||||
{
|
||||
id: "notes",
|
||||
label: "Notes",
|
||||
prompt: "Anything else?",
|
||||
options: [{ value: "none", label: "No extra notes" }],
|
||||
},
|
||||
]);
|
||||
|
||||
const second = createCustomAnswer("notes", "Custom note");
|
||||
const first = createPredefinedAnswer("scope", questions[0].options[0], 1);
|
||||
const result = createAnsweredResult(questions, [second, first]);
|
||||
|
||||
assert.equal(result.cancelled, false);
|
||||
assert.deepEqual(result.answers.map((answer) => answer.id), ["scope", "notes"]);
|
||||
});
|
||||
|
||||
test("allQuestionsAnswered only returns true when every question has an answer", () => {
|
||||
const questions = normalizeQuestions([
|
||||
{
|
||||
id: "scope",
|
||||
prompt: "Scope?",
|
||||
options: [{ value: "small", label: "Small" }],
|
||||
},
|
||||
{
|
||||
id: "priority",
|
||||
prompt: "Priority?",
|
||||
options: [{ value: "p1", label: "P1" }],
|
||||
},
|
||||
]);
|
||||
|
||||
const answers = new Map([
|
||||
["scope", createPredefinedAnswer("scope", questions[0].options[0], 1)],
|
||||
]);
|
||||
|
||||
assert.equal(allQuestionsAnswered(questions, answers), false);
|
||||
answers.set("priority", createCustomAnswer("priority", "Ship this week"));
|
||||
assert.equal(allQuestionsAnswered(questions, answers), true);
|
||||
});
|
||||
|
||||
test("nextTabAfterAnswer advances through questions and then to the submit tab", () => {
|
||||
assert.equal(nextTabAfterAnswer(0, 3), 1);
|
||||
assert.equal(nextTabAfterAnswer(1, 3), 2);
|
||||
assert.equal(nextTabAfterAnswer(2, 3), 3);
|
||||
});
|
||||
|
||||
test("wrapPrefixedText wraps long prompts and keeps the prefix on continuation lines", () => {
|
||||
assert.deepEqual(wrapPrefixedText("Pick the best rollout strategy for this change", 18, " "), [
|
||||
" Pick the best",
|
||||
" rollout strategy",
|
||||
" for this change",
|
||||
]);
|
||||
});
|
||||
|
||||
test("wrapPrefixedText supports a different continuation prefix for wrapped option labels", () => {
|
||||
assert.deepEqual(wrapPrefixedText("Very long option label", 16, "> 1. ", " "), [
|
||||
"> 1. Very long",
|
||||
" option",
|
||||
" label",
|
||||
]);
|
||||
});
|
||||
|
||||
test("wrapPrefixedText breaks oversized words when there is no whitespace boundary", () => {
|
||||
assert.deepEqual(wrapPrefixedText("supercalifragilistic", 8), ["supercal", "ifragili", "stic"]);
|
||||
});
|
||||
Reference in New Issue
Block a user