fix(confidence-engine): distinguish completed focused result
This commit is contained in:
@@ -1393,3 +1393,214 @@ describe("INVESTIGATING cue on Open Question buttons (normal render path)", () =
|
||||
expect(badgeUntouched).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
// ── NARROW TEXTAREA RENDERING CONDITION (v0.49 completed-result repair) ───
|
||||
// The response textarea must appear IFF the current displayed turn is NOT already completed.
|
||||
|
||||
function shouldShowResponseTextarea(focused, processingStep) {
|
||||
// Mirrors the exact render condition in FocusedQuestionBody:
|
||||
// focused?.question?.trim() && processingStep !== "active" && focused.status === "formulated"
|
||||
// PLUS the repair: must NOT already have a completed answer.
|
||||
const hasAnswer = Boolean(focused?.answer);
|
||||
return (
|
||||
Boolean(focused?.question?.trim()) &&
|
||||
processingStep !== "active" &&
|
||||
focused.status === "formulated" &&
|
||||
!hasAnswer
|
||||
);
|
||||
}
|
||||
|
||||
function shouldShowResponseTextarea_OLD(focused, processingStep) {
|
||||
// Mirrors the OLD buggy render condition in FocusedQuestionBody (pre-fix):
|
||||
// missing !focused.answer check — causes textarea to show for completed turns
|
||||
return (
|
||||
Boolean(focused?.question?.trim()) &&
|
||||
processingStep !== "active" &&
|
||||
focused.status === "formulated"
|
||||
);
|
||||
}
|
||||
|
||||
// ── PRE-FIX REGRESSION PROOF: OLD condition incorrectly shows textarea ──
|
||||
describe("Pre-fix regression: OLD condition erroneously shows textarea for completed turns", () => {
|
||||
it("OLD condition shows textarea for reopened completed turn (PROVES defect exists)", () => {
|
||||
const contrib = {
|
||||
id: "contrib-1",
|
||||
question: "Onboarding funnel step with highest abandonment?",
|
||||
answer: "Step 3 — email verification, 42% drop-off.",
|
||||
status: "formulated",
|
||||
};
|
||||
|
||||
const focused = {
|
||||
status: "formulated",
|
||||
question: contrib.question,
|
||||
answer: contrib.answer,
|
||||
result: null,
|
||||
error: null,
|
||||
};
|
||||
|
||||
// OLD condition: all three checks pass → textarea incorrectly shown
|
||||
// This PROVES the defect exists in dac19a3
|
||||
expect(shouldShowResponseTextarea_OLD(focused, "idle")).toBe(true);
|
||||
});
|
||||
|
||||
it("FIXED condition does NOT show textarea for reopened completed turn", () => {
|
||||
const contrib = {
|
||||
id: "contrib-1",
|
||||
question: "Onboarding funnel step with highest abandonment?",
|
||||
answer: "Step 3 — email verification, 42% drop-off.",
|
||||
status: "formulated",
|
||||
};
|
||||
|
||||
const focused = {
|
||||
status: "formulated",
|
||||
question: contrib.question,
|
||||
answer: contrib.answer,
|
||||
result: null,
|
||||
error: null,
|
||||
};
|
||||
|
||||
// FIXED condition: !hasAnswer is false → textarea suppressed
|
||||
expect(shouldShowResponseTextarea(focused, "idle")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Narrow textarea rendering condition — v0.49 completed-result repair", () => {
|
||||
// ── Simulated fixture: a completed contribution with question + answer ──
|
||||
function makeCompletedContrib() {
|
||||
return {
|
||||
id: "contrib-completed-1",
|
||||
targetNodeId: "oq-test",
|
||||
originatingTargetNodeId: "oq-test",
|
||||
question: "What specific step of the onboarding funnel has the highest abandonment rate?",
|
||||
answer: "Step 3 — email verification. Data shows 42% drop-off at this gate.",
|
||||
sequence: 1,
|
||||
observations: ["Step 3 is the critical drop point"],
|
||||
possibleFollowUpQuestions: [
|
||||
"What drives the Step 3 abandonment?",
|
||||
"Can we reduce friction at Step 3?",
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
function makeContributions(n) {
|
||||
return Array.from({ length: n }, (_, i) => ({
|
||||
id: `contrib-${i}`,
|
||||
targetNodeId: "oq-test",
|
||||
originatingTargetNodeId: "oq-test",
|
||||
question: `Question ${i + 1}`,
|
||||
answer: `Answer ${i + 1} — completed with data.`,
|
||||
sequence: i + 1,
|
||||
observations: [`Observation ${i + 1}`],
|
||||
possibleFollowUpQuestions: [`Follow-up from turn ${i + 1}`],
|
||||
}));
|
||||
}
|
||||
|
||||
// ── CASE A — reopened completed result must NOT show textarea ──
|
||||
describe("Case A — reopened completed result suppresses textarea", () => {
|
||||
const contrib = makeCompletedContrib();
|
||||
|
||||
it("single completed turn: has question + answer, should NOT show textarea", () => {
|
||||
// Simulated startFocused reopen path: reconstructs latest Contribution
|
||||
const focused = {
|
||||
status: "formulated",
|
||||
question: contrib.question,
|
||||
answer: contrib.answer, // non-null = completed turn
|
||||
result: { observations: contrib.observations, possibleFollowUpQuestions: contrib.possibleFollowUpQuestions },
|
||||
error: null,
|
||||
};
|
||||
|
||||
const processingStep = "idle"; // not processing anything
|
||||
|
||||
expect(focused.question?.trim()).toBeTruthy();
|
||||
expect(focused.status).toBe("formulated");
|
||||
expect(focused.answer).toBeTruthy();
|
||||
// The repaired condition: answer exists → no textarea
|
||||
expect(shouldShowResponseTextarea(focused, processingStep)).toBe(false);
|
||||
});
|
||||
|
||||
it("multiple completed turns (3): latest has answer, should NOT show textarea", () => {
|
||||
const contributions = makeContributions(3);
|
||||
const latest = contributions[2];
|
||||
|
||||
const focused = {
|
||||
status: "formulated",
|
||||
question: latest.question,
|
||||
answer: latest.answer,
|
||||
result: { observations: latest.observations, possibleFollowUpQuestions: latest.possibleFollowUpQuestions },
|
||||
error: null,
|
||||
};
|
||||
|
||||
expect(shouldShowResponseTextarea(focused, "idle")).toBe(false);
|
||||
});
|
||||
|
||||
it("contributions exist but answer is null (data integrity edge): shows textarea", () => {
|
||||
// Edge case: what if an answer somehow became null?
|
||||
const contrib = makeCompletedContrib();
|
||||
const focused = {
|
||||
status: "formulated",
|
||||
question: contrib.question,
|
||||
answer: null, // should not happen normally but let's handle it
|
||||
result: null,
|
||||
error: null,
|
||||
};
|
||||
|
||||
// If answer is genuinely missing, textarea appears so user can provide one
|
||||
expect(shouldShowResponseTextarea(focused, "idle")).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
// ── CASE B — explicit follow-up selection shows textarea ──
|
||||
describe("Case B — explicit follow-up selection creates unanswered state", () => {
|
||||
it("after setFollowUpQuestion: answer=null → textarea appears", () => {
|
||||
const contributions = makeContributions(1);
|
||||
|
||||
// Step 1: reopen completed thread (answer is non-null)
|
||||
const beforeSelect = {
|
||||
status: "formulated",
|
||||
question: contributions[0].question,
|
||||
answer: contributions[0].answer,
|
||||
result: null,
|
||||
error: null,
|
||||
};
|
||||
|
||||
expect(shouldShowResponseTextarea(beforeSelect, "idle")).toBe(false);
|
||||
|
||||
// Step 2: user selects a follow-up — simulates setFollowUpQuestion()
|
||||
const focusedAfterSelect = {
|
||||
...beforeSelect,
|
||||
question: contributions[0].possibleFollowUpQuestions[0],
|
||||
answer: null, // setFollowUpQuestion sets answer: null
|
||||
};
|
||||
|
||||
// After explicit selection: textarea should appear
|
||||
expect(shouldShowResponseTextarea(focusedAfterSelect, "idle")).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
// ── CASE C — fresh investigation preserves textarea ──
|
||||
describe("Case C — fresh investigation preserves textarea", () => {
|
||||
it("fresh formulated question with no prior answer: shows textarea", () => {
|
||||
const focused = {
|
||||
status: "formulated",
|
||||
question: "What do you think about this approach?",
|
||||
answer: null, // no prior completion
|
||||
result: null,
|
||||
error: null,
|
||||
};
|
||||
|
||||
expect(shouldShowResponseTextarea(focused, "idle")).toBe(true);
|
||||
});
|
||||
|
||||
it("processing active: does NOT show textarea even with question", () => {
|
||||
const focused = {
|
||||
status: "formulated",
|
||||
question: "Active analysis in progress",
|
||||
answer: null,
|
||||
result: null,
|
||||
error: null,
|
||||
};
|
||||
|
||||
expect(shouldShowResponseTextarea(focused, "active")).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user