test: remove redundant cases and repeated setup

This commit is contained in:
Amruth Pillai
2026-09-29 23:17:30 +02:00
parent 6cfcdea327
commit 48b27802fd
15 changed files with 106 additions and 322 deletions
+29 -180
View File
@@ -478,174 +478,6 @@ describe("agentService.messages.send", () => {
);
});
it("merges an answered ask-user-question tool result into the existing assistant message", async () => {
const activeThread = buildActiveThread();
const userMessage = {
id: "message-user-1",
userId: "user-1",
threadId: "thread-1",
role: "user",
status: "completed",
sequence: 0,
uiMessage: {
id: "ui-user-1",
role: "user",
parts: [{ type: "text", text: "Change the name" }],
},
};
const unansweredAssistantMessage = {
id: "message-assistant-1",
userId: "user-1",
threadId: "thread-1",
role: "assistant",
status: "completed",
sequence: 1,
uiMessage: {
id: "ui-assistant-1",
role: "assistant",
parts: [
{
type: "tool-ask_user_question",
toolCallId: "call-1",
state: "input-available",
input: {
question: "How broadly should I rename?",
choices: ["Only change the main resume header name"],
},
},
],
},
};
const answeredAssistantMessage = {
...unansweredAssistantMessage,
uiMessage: {
...unansweredAssistantMessage.uiMessage,
parts: [
{
type: "tool-ask_user_question",
toolCallId: "call-1",
state: "output-available",
input: {
question: "How broadly should I rename?",
choices: ["Only change the main resume header name"],
},
output: "Only change the main resume header name",
callProviderMetadata: { openai: { itemId: "fc_duplicate_item" } },
resultProviderMetadata: { openai: { itemId: "fc_duplicate_item" } },
},
],
},
};
const answeredAssistantModelInput = {
...answeredAssistantMessage.uiMessage,
parts: [
{
type: "tool-ask_user_question",
toolCallId: "call-1",
state: "output-available",
input: {
question: "How broadly should I rename?",
choices: ["Only change the main resume header name"],
},
output: "Only change the main resume header name",
},
],
};
const updateSets: unknown[] = [];
dbMock.select
.mockImplementationOnce(() => selectLimitResult([activeThread]))
.mockImplementationOnce(() => selectOrderByResult([userMessage, unansweredAssistantMessage]))
.mockImplementationOnce(() => selectOrderByResult([userMessage, answeredAssistantMessage]));
dbMock.update.mockImplementation(() => ({
set: vi.fn((value) => {
updateSets.push(value);
return { where: vi.fn(async () => undefined) };
}),
}));
claimActiveAgentRunMock.mockResolvedValue(true);
aiProvidersServiceMock.getRunnableById.mockResolvedValue({
id: "provider-1",
provider: "openai",
model: "gpt-5",
apiKey: "secret",
baseURL: null,
});
aiProvidersServiceMock.markUsed.mockResolvedValue(undefined);
const [{ convertToModelMessages, ToolLoopAgent }, { agentStreamLifecycle }] = await Promise.all([
import("ai"),
import("./streams"),
]);
vi.mocked(convertToModelMessages).mockResolvedValue([
{ role: "user", content: [{ type: "text", text: "Change the name" }] },
{
role: "assistant",
content: [{ type: "tool-call", toolCallId: "call-1", toolName: "ask_user_question", input: {} }],
},
{
role: "tool",
content: [
{
type: "tool-result",
toolCallId: "call-1",
toolName: "ask_user_question",
output: "Only change the main resume header name",
},
],
},
] as never);
class MockToolLoopAgent {
stream = vi.fn(async () => ({ toUIMessageStream: vi.fn(() => new ReadableStream()) }));
}
vi.mocked(ToolLoopAgent).mockImplementation(MockToolLoopAgent as never);
vi.mocked(agentStreamLifecycle.create).mockResolvedValue(new ReadableStream());
vi.mocked(streamToEventIterator).mockReturnValue("iterator" as never);
const { agentService } = await import("./service");
await agentService.messages.send({
threadId: "thread-1",
userId: "user-1",
message: {
id: "ui-assistant-1",
role: "assistant",
parts: [
{
type: "tool-ask_user_question",
toolCallId: "call-1",
state: "output-available",
input: {
question: "How broadly should I rename?",
choices: ["Only change the main resume header name"],
},
output: "Only change the main resume header name",
},
],
// biome-ignore lint/suspicious/noExplicitAny: minimal fixture for unit test
} as any,
});
expect(dbMock.insert).not.toHaveBeenCalled();
expect(updateSets).toContainEqual(
expect.objectContaining({
uiMessage: expect.objectContaining({
parts: [
expect.objectContaining({
type: "tool-ask_user_question",
toolCallId: "call-1",
state: "output-available",
output: "Only change the main resume header name",
}),
],
}),
}),
);
expect(convertToModelMessages).toHaveBeenCalledWith([userMessage.uiMessage, answeredAssistantModelInput]);
});
// Regression (defect 8): a question continuation streams into the SAME uiMessage id; onFinish
// must upsert the existing assistant row instead of inserting a duplicate row.
it("continues the existing assistant row on a question continuation instead of inserting a duplicate", async () => {
@@ -673,27 +505,41 @@ describe("agentService.messages.send", () => {
parts: [{ type: "tool-ask_user_question", toolCallId: "call-1", state: "input-available", input: question }],
},
};
const answeredAssistantModelInput = {
...unansweredAssistantMessage.uiMessage,
parts: [
{
type: "tool-ask_user_question",
toolCallId: "call-1",
state: "output-available",
input: question,
output: "Only the header",
},
],
};
const answeredAssistantMessage = {
...unansweredAssistantMessage,
uiMessage: {
...unansweredAssistantMessage.uiMessage,
parts: [
{
type: "tool-ask_user_question",
toolCallId: "call-1",
state: "output-available",
input: question,
output: "Only the header",
},
],
...answeredAssistantModelInput,
parts: answeredAssistantModelInput.parts.map((part) => ({
...part,
callProviderMetadata: { openai: { itemId: "fc_duplicate_item" } },
resultProviderMetadata: { openai: { itemId: "fc_duplicate_item" } },
})),
},
};
const updateSets: unknown[] = [];
dbMock.select
.mockImplementationOnce(() => selectLimitResult([activeThread]))
.mockImplementationOnce(() => selectOrderByResult([userMessage, unansweredAssistantMessage]))
.mockImplementationOnce(() => selectOrderByResult([userMessage, answeredAssistantMessage]));
dbMock.update.mockImplementation(() => ({ set: vi.fn(() => ({ where: vi.fn(async () => undefined) })) }));
dbMock.update.mockImplementation(() => ({
set: vi.fn((value) => {
updateSets.push(value);
return { where: vi.fn(async () => undefined) };
}),
}));
claimActiveAgentRunMock.mockResolvedValue(true);
aiProvidersServiceMock.getRunnableById.mockResolvedValue({
@@ -735,9 +581,12 @@ describe("agentService.messages.send", () => {
threadId: "thread-1",
userId: "user-1",
// biome-ignore lint/suspicious/noExplicitAny: minimal fixture for unit test
message: answeredAssistantMessage.uiMessage as any,
message: answeredAssistantModelInput as any,
});
expect(updateSets).toContainEqual(expect.objectContaining({ uiMessage: answeredAssistantModelInput }));
expect(convertToModelMessages).toHaveBeenCalledWith([userMessage.uiMessage, answeredAssistantModelInput]);
const onFinish = uiStreamOptions?.onFinish as (event: Record<string, unknown>) => Promise<void>;
const continuedMessage = {
...answeredAssistantMessage.uiMessage,