Sequential / Stateful Responses
Use sequenceIndex in fixture match criteria to return different responses for
the same query on each successive call. This enables testing multi-step agent
conversations and retry logic.
How It Works
- The router tracks how many times each unique match pattern has been hit
-
sequenceIndex: 0matches the first request,sequenceIndex: 1the second, etc. - Different match patterns have independent counters
- If a sequenceIndex fixture does not match the current count, routing falls through to the next fixture
-
Fixtures without
sequenceIndexmatch any occurrence (backward compatible) - Counters reset on
mock.reset()
Unit Test: 2-Step Sequence
sequence.test.ts ts
const mock = new LLMock();
await mock.start();
mock.on({ userMessage: "plan", sequenceIndex: 0 }, { content: "Step 1: planning..." });
mock.on({ userMessage: "plan", sequenceIndex: 1 }, { content: "Step 2: done!" });
// First request → first response
const res1 = await fetch(`${mock.url}/v1/chat/completions`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "gpt-4",
messages: [{ role: "user", content: "plan" }],
stream: false,
}),
});
const body1 = await res1.json();
expect(body1.choices[0].message.content).toBe("Step 1: planning...");
// Second request → second response
const res2 = await fetch(`${mock.url}/v1/chat/completions`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "gpt-4",
messages: [{ role: "user", content: "plan" }],
stream: false,
}),
});
const body2 = await res2.json();
expect(body2.choices[0].message.content).toBe("Step 2: done!");
Fallback After Sequence Exhaustion
sequence-fallback.test.ts ts
// First call matches sequenceIndex 0, subsequent calls fall through to fallback
mock.on({ userMessage: "once", sequenceIndex: 0 }, { content: "only-first-time" });
mock.on({ userMessage: "once" }, { content: "fallback" });
// Request 1 → "only-first-time" (sequenceIndex 0 matches)
// Request 2 → "fallback" (sequenceIndex 0 won't match, falls through)
JSON Fixture
fixtures/sequence.json json
{
"fixtures": [
{
"match": { "userMessage": "plan", "sequenceIndex": 0 },
"response": { "content": "Step 1: planning..." }
},
{
"match": { "userMessage": "plan", "sequenceIndex": 1 },
"response": { "content": "Step 2: done!" }
}
]
}
Sequence counters are per-fixture-match, not global. If you have fixtures matching "alpha" and "beta", their counters are tracked independently.