Skip to content

Commit cc8f0dd

Browse files
committed
test: integration tests for turnIndex and hasToolResult
Cross-provider tests (OpenAI, Anthropic, Gemini), concurrency verification, combined AND-logic, JSON fixture loading, and validateFixtures type/shadowing coverage.
1 parent d362f63 commit cc8f0dd

2 files changed

Lines changed: 760 additions & 0 deletions

File tree

src/__tests__/fixture-loader.test.ts

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,66 @@ describe("validateFixtures", () => {
800800
expect(validateFixtures(fixtures)).toHaveLength(0);
801801
});
802802

803+
// --- match.turnIndex / match.hasToolResult type checks ---
804+
805+
it("error: turnIndex is negative", () => {
806+
const fixtures = [makeFixture({ match: { userMessage: "test", turnIndex: -1 } })];
807+
const results = validateFixtures(fixtures);
808+
expect(results.some((r) => r.severity === "error" && r.message.includes("turnIndex"))).toBe(
809+
true,
810+
);
811+
});
812+
813+
it("error: turnIndex is a float", () => {
814+
const fixtures = [makeFixture({ match: { userMessage: "test", turnIndex: 1.5 } })];
815+
const results = validateFixtures(fixtures);
816+
expect(results.some((r) => r.severity === "error" && r.message.includes("turnIndex"))).toBe(
817+
true,
818+
);
819+
});
820+
821+
it("error: turnIndex is a string", () => {
822+
const fixtures = [makeFixture({ match: { userMessage: "test", turnIndex: "zero" as never } })];
823+
const results = validateFixtures(fixtures);
824+
expect(results.some((r) => r.severity === "error" && r.message.includes("turnIndex"))).toBe(
825+
true,
826+
);
827+
});
828+
829+
it("no error: turnIndex is 0 (falsy but valid)", () => {
830+
const fixtures = [makeFixture({ match: { userMessage: "test", turnIndex: 0 } })];
831+
const results = validateFixtures(fixtures);
832+
expect(results.filter((r) => r.message.includes("turnIndex"))).toHaveLength(0);
833+
});
834+
835+
it("no error: turnIndex is a positive integer", () => {
836+
const fixtures = [makeFixture({ match: { userMessage: "test", turnIndex: 3 } })];
837+
const results = validateFixtures(fixtures);
838+
expect(results.filter((r) => r.message.includes("turnIndex"))).toHaveLength(0);
839+
});
840+
841+
it("error: hasToolResult is a string", () => {
842+
const fixtures = [
843+
makeFixture({ match: { userMessage: "test", hasToolResult: "yes" as never } }),
844+
];
845+
const results = validateFixtures(fixtures);
846+
expect(results.some((r) => r.severity === "error" && r.message.includes("hasToolResult"))).toBe(
847+
true,
848+
);
849+
});
850+
851+
it("no error: hasToolResult is false (falsy but valid)", () => {
852+
const fixtures = [makeFixture({ match: { userMessage: "test", hasToolResult: false } })];
853+
const results = validateFixtures(fixtures);
854+
expect(results.filter((r) => r.message.includes("hasToolResult"))).toHaveLength(0);
855+
});
856+
857+
it("no error: hasToolResult is true", () => {
858+
const fixtures = [makeFixture({ match: { userMessage: "test", hasToolResult: true } })];
859+
const results = validateFixtures(fixtures);
860+
expect(results.filter((r) => r.message.includes("hasToolResult"))).toHaveLength(0);
861+
});
862+
803863
// --- Warning checks ---
804864

805865
it("warning: duplicate userMessage", () => {
@@ -813,6 +873,53 @@ describe("validateFixtures", () => {
813873
);
814874
});
815875

876+
it("no warning: same userMessage but different turnIndex", () => {
877+
const fixtures = [
878+
makeFixture({ match: { userMessage: "hello", turnIndex: 0 } }),
879+
makeFixture({ match: { userMessage: "hello", turnIndex: 1 } }),
880+
];
881+
const results = validateFixtures(fixtures);
882+
const duplicateWarnings = results.filter(
883+
(r) => r.severity === "warning" && r.message.includes("duplicate"),
884+
);
885+
expect(duplicateWarnings).toHaveLength(0);
886+
});
887+
888+
it("no warning: same userMessage but different hasToolResult", () => {
889+
const fixtures = [
890+
makeFixture({ match: { userMessage: "hello", hasToolResult: false } }),
891+
makeFixture({ match: { userMessage: "hello", hasToolResult: true } }),
892+
];
893+
const results = validateFixtures(fixtures);
894+
const duplicateWarnings = results.filter(
895+
(r) => r.severity === "warning" && r.message.includes("duplicate"),
896+
);
897+
expect(duplicateWarnings).toHaveLength(0);
898+
});
899+
900+
it("no warning: same userMessage but different sequenceIndex", () => {
901+
const fixtures = [
902+
makeFixture({ match: { userMessage: "hello", sequenceIndex: 0 } }),
903+
makeFixture({ match: { userMessage: "hello", sequenceIndex: 1 } }),
904+
];
905+
const results = validateFixtures(fixtures);
906+
const duplicateWarnings = results.filter(
907+
(r) => r.severity === "warning" && r.message.includes("duplicate"),
908+
);
909+
expect(duplicateWarnings).toHaveLength(0);
910+
});
911+
912+
it("warning: same userMessage with identical turnIndex/hasToolResult/sequenceIndex", () => {
913+
const fixtures = [
914+
makeFixture({ match: { userMessage: "hello", turnIndex: 1, hasToolResult: true } }),
915+
makeFixture({ match: { userMessage: "hello", turnIndex: 1, hasToolResult: true } }),
916+
];
917+
const results = validateFixtures(fixtures);
918+
expect(results.some((r) => r.severity === "warning" && r.message.includes("duplicate"))).toBe(
919+
true,
920+
);
921+
});
922+
816923
it("warning: catch-all not in last position", () => {
817924
const fixtures = [makeFixture({ match: {} }), makeFixture({ match: { userMessage: "hello" } })];
818925
const results = validateFixtures(fixtures);

0 commit comments

Comments
 (0)