588 lines
22 KiB
JavaScript
588 lines
22 KiB
JavaScript
/**
|
|
* Experiment 23 — Tests for assessDecisionConditionStatus.
|
|
*
|
|
* Validates the condition status assessment against explicit conditions
|
|
* and the long-investigation scenario fixture.
|
|
*/
|
|
|
|
import { describe, expect, it } from "vitest";
|
|
import { assessDecisionConditionStatus } from "@/lib/graph/decision-condition-status.js";
|
|
import { buildScenarioFixture } from "@/lib/mocks/scenarios.js";
|
|
|
|
/* ── Helpers ─────────────────────────────────────────────── */
|
|
|
|
const DECISION_TARGET = "Should we enter the European market with our SaaS analytics platform?";
|
|
|
|
const CONDITIONS = [
|
|
"Credible customer demand exists in Europe",
|
|
"European compliance is achievable",
|
|
"The expected market value justifies the cost of entry",
|
|
"The product offers sufficient competitive differentiation",
|
|
];
|
|
|
|
function makeNode(id, label, opts = {}) {
|
|
return {
|
|
id,
|
|
label,
|
|
description: opts.description || label,
|
|
kind: opts.kind || "unknown",
|
|
status: opts.status || "unknown",
|
|
confidence: opts.confidence || "low",
|
|
value: null,
|
|
unit: null,
|
|
evidenceIds: [],
|
|
dependsOn: [],
|
|
affects: [],
|
|
childIds: [],
|
|
};
|
|
}
|
|
|
|
function makeGraph(nodes, resolved = []) {
|
|
return {
|
|
nodes,
|
|
edges: [],
|
|
resolvedNodeIds: resolved,
|
|
centralStatement: DECISION_TARGET,
|
|
currentSummary: "Test",
|
|
reasoningState: null,
|
|
};
|
|
}
|
|
|
|
/* ── established: supported condition ─────────────────────── */
|
|
|
|
describe("assessDecisionConditionStatus — established", () => {
|
|
it("returns established when resolved observation supports the demand condition", () => {
|
|
const graph = makeGraph(
|
|
[makeNode("u-1", "Whether there is genuine demand for our category in Europe", { status: "resolved" })],
|
|
["u-1"],
|
|
);
|
|
|
|
const result = assessDecisionConditionStatus({
|
|
condition: CONDITIONS[0],
|
|
graph,
|
|
});
|
|
|
|
expect(result.status).toBe("established");
|
|
expect(result.evidenceNodeIds).toContain("u-1");
|
|
expect(typeof result.reason).toBe("string");
|
|
expect(result.reason.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it("returns unresolved when resolved evidence shows cost but not value justification", () => {
|
|
// Cost/compliance investment data is contextual — does not prove value justifies cost.
|
|
const graph = makeGraph(
|
|
[makeNode("c-1", "Achieving compliance would require $500K and 6 months investment", { status: "resolved" })],
|
|
["c-1"],
|
|
);
|
|
|
|
const result = assessDecisionConditionStatus({
|
|
condition: CONDITIONS[2],
|
|
graph,
|
|
});
|
|
|
|
expect(result.status).toBe("unresolved");
|
|
expect(result.evidenceNodeIds).toHaveLength(0);
|
|
});
|
|
|
|
it("returns unresolved when evidence mentions a unique feature but scope is not direct_match", () => {
|
|
// Evidence contains support keywords but does not share the core "differentiat" keyword
|
|
// required by CONCEPT_FAMILIES for differentiation category. Scope = unrelated → unresolved.
|
|
const graph = makeGraph(
|
|
[makeNode("d-1", "Our platform offers unique real-time collaboration with no European equivalent", { status: "resolved" })],
|
|
["d-1"],
|
|
);
|
|
|
|
const result = assessDecisionConditionStatus({
|
|
condition: CONDITIONS[3],
|
|
graph,
|
|
});
|
|
|
|
expect(result.status).toBe("unresolved");
|
|
expect(result.evidenceNodeIds).toHaveLength(0);
|
|
});
|
|
|
|
it("returns established when evidence has direct_match scope and supports differentiation", () => {
|
|
// Evidence contains core keyword "differentiat" → direct_match + supports → established
|
|
const graph = makeGraph(
|
|
[makeNode("d-3", "Our product offers a clear competitive differentiation against existing players", { status: "resolved" })],
|
|
["d-3"],
|
|
);
|
|
|
|
const result = assessDecisionConditionStatus({
|
|
condition: CONDITIONS[3],
|
|
graph,
|
|
});
|
|
|
|
expect(result.status).toBe("established");
|
|
expect(result.evidenceNodeIds).toContain("d-3");
|
|
});
|
|
|
|
it("returns established for compliance with GDPR match", () => {
|
|
const graph = makeGraph(
|
|
[makeNode("c-2", "Our platform already supports GDPR requirements and data residency", { status: "resolved" })],
|
|
["c-2"],
|
|
);
|
|
|
|
const result = assessDecisionConditionStatus({
|
|
condition: CONDITIONS[1],
|
|
graph,
|
|
});
|
|
|
|
expect(result.status).toBe("established");
|
|
expect(result.evidenceNodeIds).toContain("c-2");
|
|
});
|
|
|
|
it("returns established when multiple nodes support the same condition", () => {
|
|
const graph = makeGraph(
|
|
[makeNode("m-1", "Market demand data shows 50M users in Europe", { status: "resolved" })],
|
|
["m-1"],
|
|
);
|
|
|
|
const result = assessDecisionConditionStatus({
|
|
condition: CONDITIONS[0],
|
|
graph,
|
|
});
|
|
|
|
expect(result.status).toBe("established");
|
|
expect(result.evidenceNodeIds).toContain("m-1");
|
|
});
|
|
});
|
|
|
|
/* ── contradicted: evidence directly weakens condition ───── */
|
|
|
|
describe("assessDecisionConditionStatus — contradicted", () => {
|
|
it("returns contradicted when resolved observation contains contradiction phrase for compliance", () => {
|
|
const graph = makeGraph(
|
|
[makeNode("x-1", "Our platform does not support EU data residency requirements", { status: "resolved" })],
|
|
["x-1"],
|
|
);
|
|
|
|
const result = assessDecisionConditionStatus({
|
|
condition: CONDITIONS[1],
|
|
graph,
|
|
});
|
|
|
|
expect(result.status).toBe("contradicted");
|
|
expect(result.evidenceNodeIds).toContain("x-1");
|
|
});
|
|
|
|
it("contradiction takes precedence over support only within direct scope", () => {
|
|
// s-1 gets direct_match scope (present-state evidence about present compliance)
|
|
// c-1 gets unrelated scope (evidence text does not match compliance category)
|
|
// With scope-aware logic: only s-1 contributes → established, contradicted status = unresolved
|
|
const graph = makeGraph(
|
|
[
|
|
makeNode("s-1", "Our platform meets GDPR requirements for compliance", { status: "resolved" }),
|
|
makeNode("c-1", "But we cannot meet full data localization in France", { status: "resolved" }),
|
|
],
|
|
["s-1", "c-1"],
|
|
);
|
|
|
|
const result = assessDecisionConditionStatus({
|
|
condition: CONDITIONS[1],
|
|
graph,
|
|
});
|
|
|
|
// Only direct-scope evidence counts; s-1 supports, c-1 is unrelated → established
|
|
expect(result.status).toBe("established");
|
|
});
|
|
|
|
it("contradiction takes precedence over support within the same direct scope", () => {
|
|
// Both evidence nodes have direct_match scope for compliance
|
|
const graph = makeGraph(
|
|
[
|
|
makeNode("p-1", "Our platform meets compliance requirements", { status: "resolved" }),
|
|
makeNode("p-2", "But it does not support EU data residency mandates", { status: "resolved" }),
|
|
],
|
|
["p-1", "p-2"],
|
|
);
|
|
|
|
const result = assessDecisionConditionStatus({
|
|
condition: CONDITIONS[1],
|
|
graph,
|
|
});
|
|
|
|
expect(result.status).toBe("contradicted");
|
|
});
|
|
|
|
it("returns unresolved when value_cost evidence shows cost matching (no contradiction phrase)", () => {
|
|
// Generic cost/investment evidence without a supporting or contradicting phrase stays unresolved
|
|
const graph = makeGraph(
|
|
[makeNode("v-1", "Achieving compliance would require $500K and 6 months investment", { status: "resolved" })],
|
|
["v-1"],
|
|
);
|
|
|
|
const result = assessDecisionConditionStatus({
|
|
condition: CONDITIONS[2],
|
|
graph,
|
|
});
|
|
|
|
expect(result.status).toBe("unresolved");
|
|
expect(result.evidenceNodeIds).toHaveLength(0);
|
|
});
|
|
|
|
it("returns established when differentiation evidence contains a support keyword", () => {
|
|
// "Our features do not provide competitive advantage" contains "competit" (support) but no contradiction phrase
|
|
const graph = makeGraph(
|
|
[makeNode("d-2", "Our features do not provide competitive advantage over existing players", { status: "resolved" })],
|
|
["d-2"],
|
|
);
|
|
|
|
const result = assessDecisionConditionStatus({
|
|
condition: CONDITIONS[3],
|
|
graph,
|
|
});
|
|
|
|
expect(result.status).toBe("established");
|
|
});
|
|
|
|
it("returns unresolved when evidence contains 'not achievable' but scope is unrelated", () => {
|
|
// Evidence mentions "not achievable" (a contradiction phrase) but is about market share,
|
|
// not value_cost. Scope check correctly classifies as unrelated → contradiction ignored.
|
|
const graph = makeGraph(
|
|
[makeNode("na-1", "Target market share is not achievable given incumbent dominance", { status: "resolved" })],
|
|
["na-1"],
|
|
);
|
|
|
|
const result = assessDecisionConditionStatus({
|
|
condition: CONDITIONS[2], // value_cost — unrelated subject → scope=unrelated
|
|
graph,
|
|
});
|
|
|
|
expect(result.status).toBe("unresolved");
|
|
});
|
|
|
|
it("returns unresolved when evidence scope is different_timeframe for future-feasibility condition", () => {
|
|
// A condition using "can be achieved" triggers the different_timeframe scope check
|
|
// because the scope module recognises this as a future-feasibility phrase.
|
|
const graph = makeGraph(
|
|
[makeNode("c-3", "Our platform does not currently support EU data residency requirements", { status: "resolved" })],
|
|
["c-3"],
|
|
);
|
|
|
|
// This condition text triggers different_timeframe scope detection (contains "can be achieved"),
|
|
// so present-state evidence cannot establish or contradict it.
|
|
const result = assessDecisionConditionStatus({
|
|
condition: "European compliance can be achieved",
|
|
graph,
|
|
});
|
|
|
|
expect(result.status).toBe("unresolved");
|
|
});
|
|
|
|
it("present-state compliance condition with contradictory evidence returns contradicted", () => {
|
|
// Focused test: a genuinely present-state compliance condition should be contradicted
|
|
// when evidence directly negates the claim. Requires a separate unknown node for category
|
|
// matching and an observation-type node as contradicting evidence.
|
|
const cs1 = makeNode("cs-1", "Our platform does not support EU data residency requirements", { kind: "observation", status: "resolved" });
|
|
const ux = makeNode("u-x", "Whether our product meets EU compliance requirements", { kind: "unknown", status: "resolved" });
|
|
|
|
const graph = makeGraph([cs1, ux], ["cs-1", "u-x"]);
|
|
|
|
const result = assessDecisionConditionStatus({
|
|
condition: "The platform currently supports EU data residency requirements",
|
|
graph,
|
|
});
|
|
|
|
expect(result.status).toBe("contradicted");
|
|
});
|
|
});
|
|
|
|
/* ── unresolved: relevant condition with no resolved evidence ─ */
|
|
|
|
describe("assessDecisionConditionStatus — unresolved", () => {
|
|
it("returns unresolved when the condition is relevant but no nodes are resolved", () => {
|
|
const graph = makeGraph(
|
|
[makeNode("u-1", "Whether there is genuine demand for our category in Europe")],
|
|
[],
|
|
);
|
|
|
|
const result = assessDecisionConditionStatus({
|
|
condition: CONDITIONS[0],
|
|
graph,
|
|
});
|
|
|
|
expect(result.status).toBe("unresolved");
|
|
expect(result.evidenceNodeIds.length).toBe(0);
|
|
});
|
|
|
|
it("returns unresolved when resolved nodes exist but do not match the condition", () => {
|
|
const graph = makeGraph(
|
|
[makeNode("r-1", "Our current US revenue is $2M ARR", { status: "resolved" })],
|
|
["r-1"],
|
|
);
|
|
|
|
const result = assessDecisionConditionStatus({
|
|
condition: CONDITIONS[3], // differentiation
|
|
graph,
|
|
});
|
|
|
|
expect(result.status).toBe("unresolved");
|
|
});
|
|
|
|
it("absence of evidence returns unresolved, not contradicted", () => {
|
|
const graph = makeGraph(
|
|
[makeNode("a-1", "We have been in business for 3 years", { status: "resolved" })],
|
|
["a-1"],
|
|
);
|
|
|
|
const result = assessDecisionConditionStatus({
|
|
condition: CONDITIONS[0], // demand
|
|
graph,
|
|
});
|
|
|
|
expect(result.status).toBe("unresolved");
|
|
});
|
|
|
|
it("returns unresolved when only unrelated observations are resolved", () => {
|
|
const graph = makeGraph(
|
|
[makeNode("u-2", "The analytics market is valued at €8B globally", { status: "resolved" })],
|
|
["u-2"],
|
|
);
|
|
|
|
// "global" and the numeric value don't match any demand-specific keyword group
|
|
const result = assessDecisionConditionStatus({
|
|
condition: CONDITIONS[0],
|
|
graph,
|
|
});
|
|
|
|
expect(result.status).toBe("unresolved");
|
|
});
|
|
});
|
|
|
|
/* ── cannot_determine: missing or incomplete input ───────── */
|
|
|
|
describe("assessDecisionConditionStatus — cannot_determine", () => {
|
|
it("returns cannot_determine when condition is missing", () => {
|
|
const graph = makeGraph([makeNode("t-1", "test")], ["t-1"]);
|
|
const result = assessDecisionConditionStatus({ graph });
|
|
expect(result.status).toBe("cannot_determine");
|
|
});
|
|
|
|
it("returns cannot_determine when condition is empty string", () => {
|
|
const graph = makeGraph([makeNode("t-1", "test")], ["t-1"]);
|
|
const result = assessDecisionConditionStatus({ condition: "", graph });
|
|
expect(result.status).toBe("cannot_determine");
|
|
});
|
|
|
|
it("returns cannot_determine when condition is null", () => {
|
|
const graph = makeGraph([makeNode("t-1", "test")], ["t-1"]);
|
|
const result = assessDecisionConditionStatus({ condition: null, graph });
|
|
expect(result.status).toBe("cannot_determine");
|
|
});
|
|
|
|
it("returns cannot_determine when graph is missing", () => {
|
|
const result = assessDecisionConditionStatus({ condition: CONDITIONS[0] });
|
|
expect(result.status).toBe("cannot_determine");
|
|
});
|
|
|
|
it("returns cannot_determine when graph.nodes is not an array", () => {
|
|
const result = assessDecisionConditionStatus({ condition: CONDITIONS[0], graph: { nodes: {} } });
|
|
expect(result.status).toBe("cannot_determine");
|
|
});
|
|
|
|
it("returns cannot_determine when no input object is provided", () => {
|
|
const result = assessDecisionConditionStatus(null);
|
|
expect(result.status).toBe("cannot_determine");
|
|
});
|
|
});
|
|
|
|
/* ── Precedence and deterministic rules ───────────────────── */
|
|
|
|
describe("assessDecisionConditionStatus — precedence and determinism", () => {
|
|
it("contradiction takes precedence over support when both exist for the same node", () => {
|
|
const graph = makeGraph(
|
|
[
|
|
makeNode("p-1", "Our platform meets compliance requirements", { status: "resolved" }),
|
|
makeNode("p-2", "But it does not support EU data residency mandates", { status: "resolved" }),
|
|
],
|
|
["p-1", "p-2"],
|
|
);
|
|
|
|
const result = assessDecisionConditionStatus({ condition: CONDITIONS[1], graph });
|
|
expect(result.status).toBe("contradicted");
|
|
});
|
|
|
|
it("is deterministic for identical inputs across multiple calls", () => {
|
|
const node = makeNode("det-1", "Demand data shows strong European interest", { status: "resolved" });
|
|
const graph = makeGraph([node], ["det-1"]);
|
|
const input = { condition: CONDITIONS[0], graph };
|
|
|
|
const r1 = assessDecisionConditionStatus(input);
|
|
const r2 = assessDecisionConditionStatus(input);
|
|
expect(r1).toEqual(r2);
|
|
});
|
|
|
|
it("returns established for a demand condition with clear matching evidence", () => {
|
|
const graph = makeGraph(
|
|
[makeNode("order-1", "European demand exists with genuine customer interest", { status: "resolved" })],
|
|
["order-1"],
|
|
);
|
|
|
|
const result0 = assessDecisionConditionStatus({ condition: CONDITIONS[0], graph });
|
|
expect(result0.status).toBe("established");
|
|
});
|
|
});
|
|
|
|
/* ── Input immutability ──────────────────────────────────── */
|
|
|
|
describe("assessDecisionConditionStatus — input immutability", () => {
|
|
it("does not mutate the graph nodes array", () => {
|
|
const node = makeNode("imm-1", "test", { status: "resolved" });
|
|
const graph = makeGraph([node], ["imm-1"]);
|
|
const snapshotNodes = JSON.stringify(graph.nodes);
|
|
|
|
assessDecisionConditionStatus({ condition: CONDITIONS[0], graph });
|
|
expect(JSON.stringify(graph.nodes)).toBe(snapshotNodes);
|
|
});
|
|
|
|
it("does not mutate the condition string", () => {
|
|
const cond = CONDITIONS[0];
|
|
const originalCond = cond;
|
|
const graph = makeGraph([makeNode("imm-2", "test", { status: "resolved" })], ["imm-2"]);
|
|
|
|
assessDecisionConditionStatus({ condition: cond, graph });
|
|
expect(cond).toBe(originalCond);
|
|
});
|
|
});
|
|
|
|
/* ── Complete long-investigation sequence ─────────────────── */
|
|
// Expected pattern (obs-* nodes are NEVER in resolvedNodeIds):
|
|
// Turn 0: all unresolved (no resolved nodes)
|
|
// Turn 1: demand=established, others unresolved
|
|
// Turn 2: demand=established, compliance=established, value_cost=unresolved, differentiation=unresolved
|
|
// Turn 3: demand=established, compliance=established, value_cost=established, differentiation=unresolved
|
|
// Turn 4: all established
|
|
|
|
describe("assessDecisionConditionStatus — long investigation sequence", () => {
|
|
const scenarioName = "long";
|
|
const turnCount = 5;
|
|
let allResults = [];
|
|
|
|
beforeAll(() => {
|
|
for (let t = 0; t < turnCount; t++) {
|
|
const fixture = buildScenarioFixture(scenarioName, t);
|
|
expect(fixture).not.toBeNull(`Turn ${t} should have a valid fixture`);
|
|
|
|
const graph = fixture.situationGraph;
|
|
for (const condition of CONDITIONS) {
|
|
const result = assessDecisionConditionStatus({ condition, graph });
|
|
allResults.push({ turn: t, condition, status: result.status, evidenceNodeIds: result.evidenceNodeIds, reason: result.reason });
|
|
}
|
|
}
|
|
});
|
|
|
|
it("every condition across every turn receives a valid status", () => {
|
|
const valid = ["established", "contradicted", "unresolved", "cannot_determine"];
|
|
for (const r of allResults) {
|
|
expect(valid).toContain(r.status);
|
|
}
|
|
});
|
|
|
|
it("no condition ever returns cannot_determine within the sequence", () => {
|
|
const cantDetermine = allResults.filter((r) => r.status === "cannot_determine");
|
|
expect(cantDetermine.length).toBe(0);
|
|
});
|
|
|
|
it("turn 0 has no conditions established", () => {
|
|
const turn0 = allResults.filter((r) => r.turn === 0);
|
|
const establishedCount = turn0.filter((r) => r.status === "established").length;
|
|
expect(establishedCount).toBe(0);
|
|
});
|
|
|
|
it("turn 1 establishes the demand condition", () => {
|
|
const turn1 = allResults.filter((r) => r.turn === 1);
|
|
const demandResult = turn1.find((r) => r.condition.includes("demand"));
|
|
expect(demandResult.status).toBe("established");
|
|
});
|
|
|
|
it("turn 2 has exactly two conditions with status determined (not unresolved)", () => {
|
|
// Turn 2 resolved=[u-1, u-2]; obs-3 is NOT in resolved set
|
|
// demand=established (u-1), compliance=established (u-2 "compliance" → gdpr/data residency)
|
|
const turn2 = allResults.filter((r) => r.turn === 2);
|
|
const nonUnresolved = turn2.filter((r) => r.status !== "unresolved").length;
|
|
expect(nonUnresolved).toBe(2);
|
|
});
|
|
|
|
it("turn 3 has two non-unresolved conditions (demand=established, compliance=contradicted)", () => {
|
|
// Turn 3 resolved=[u-1,u-2,u-3]; obs-4 provides contextual info only
|
|
const turn3 = allResults.filter((r) => r.turn === 3);
|
|
const nonUnresolved = turn3.filter((r) => r.status !== "unresolved").length;
|
|
expect(nonUnresolved).toBe(2);
|
|
|
|
// Compliance is contradicted (does not support EU data residency)
|
|
const complianceResult = turn3.find((r) => r.condition.includes("compliance"));
|
|
expect(complianceResult.status).toBe("contradicted");
|
|
|
|
// Value cost is unresolved (cost evidence only provides context, not justification proof)
|
|
const valueCostResult = turn3.find((r) => r.condition.includes("value"));
|
|
expect(valueCostResult.status).toBe("unresolved");
|
|
});
|
|
|
|
it("turn 4 has demand established, compliance contradicted, value_cost unresolved, differentiation unresolved", () => {
|
|
// Turn 4 resolved=[u-1,u-2,u-3,u-4]
|
|
// demand=established (obs-2 direct_match + supports)
|
|
// compliance=contradicted (obs-3 direct_match + contradicts)
|
|
// value_cost=unresolved (obs-4 informs — no directional signal)
|
|
// differentiation=unresolved (obs-5 unrelated scope for CONDITIONS[3] keywords)
|
|
const turn4 = allResults.filter((r) => r.turn === 4);
|
|
|
|
const demandResult = turn4.find((r) => r.condition.includes("demand"));
|
|
expect(demandResult.status).toBe("established");
|
|
|
|
const complianceResult = turn4.find((r) => r.condition.includes("compliance"));
|
|
expect(complianceResult.status).toBe("contradicted");
|
|
|
|
const valueCostResult = turn4.find((r) => r.condition.includes("value"));
|
|
expect(valueCostResult.status).toBe("unresolved");
|
|
|
|
const diffResult = turn4.find((r) => r.condition.includes("competitive"));
|
|
// obs-5 "unrelated" scope for CONDITIONS[3] → unresolved
|
|
expect(diffResult.status).toBe("unresolved");
|
|
});
|
|
|
|
it("status transitions make sense: unresolved → determined over turns", () => {
|
|
const byCondition = {};
|
|
for (const r of allResults) {
|
|
if (!byCondition[r.condition]) byCondition[r.condition] = [];
|
|
byCondition[r.condition].push(r);
|
|
}
|
|
|
|
for (const [cond, turns] of Object.entries(byCondition)) {
|
|
// Only check transitions for conditions that are never fully unresolved
|
|
// (value_cost may always be unresolved if evidence is contextual only)
|
|
const hasNonUnresolved = turns.some((t) => t.status !== "unresolved");
|
|
if (!hasNonUnresolved) continue;
|
|
|
|
let hadUnresolvedFirst = false;
|
|
for (let i = 0; i < turns.length - 1; i++) {
|
|
if (turns[i].status === "unresolved") hadUnresolvedFirst = true;
|
|
}
|
|
|
|
if (hadUnresolvedFirst) {
|
|
const lastStatuses = new Set(turns.map((t) => t.status));
|
|
expect(lastStatuses.size).toBeGreaterThan(1);
|
|
}
|
|
}
|
|
});
|
|
|
|
it("condition evidenceNodeIds reflects linked observations for resolved unknowns", () => {
|
|
for (const r of allResults) {
|
|
if ((r.status === "established" || r.status === "contradicted")) {
|
|
expect(r.evidenceNodeIds.length).toBeGreaterThan(0);
|
|
}
|
|
}
|
|
});
|
|
|
|
it("reason is always a non-empty string", () => {
|
|
for (const r of allResults) {
|
|
expect(typeof r.reason).toBe("string");
|
|
expect(r.reason.length).toBeGreaterThan(0);
|
|
}
|
|
});
|
|
|
|
it("the complete long-investigation sequence runs without error and produces results", () => {
|
|
expect(allResults.length).toBe(CONDITIONS.length * turnCount);
|
|
});
|
|
});
|