Les lignes de ticket persistées avant l'introduction de ces champs peuvent arriver sans assignedAgentIds (ni links/attachments), ce que TicketsPanel déréférence sans garde côté rendu : la fenêtre de liste rend quelques lignes puis devient noire dès qu'une ligne legacy est itérée. Les deux gateways (Tauri et HTTP/stream) normalisent désormais chaque ticket et chaque item de liste avant de les retourner à l'UI. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
144 lines
3.7 KiB
TypeScript
144 lines
3.7 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
|
|
const invoke = vi.fn();
|
|
vi.mock("@tauri-apps/api/core", () => ({
|
|
invoke: (...args: unknown[]) => invoke(...args),
|
|
Channel: class {
|
|
onmessage: ((chunk: unknown) => void) | null = null;
|
|
},
|
|
}));
|
|
|
|
import { TauriTicketGateway } from "./ticket";
|
|
|
|
describe("TauriTicketGateway invoke payloads", () => {
|
|
beforeEach(() => invoke.mockReset().mockResolvedValue({ items: [] }));
|
|
|
|
it("bulk status wraps refs and status in the request DTO", async () => {
|
|
await new TauriTicketGateway().bulkUpdateStatus(
|
|
"proj-1",
|
|
["#1", "#2"],
|
|
"inProgress",
|
|
);
|
|
|
|
expect(invoke).toHaveBeenCalledWith("ticket_bulk_update_status", {
|
|
request: {
|
|
projectId: "proj-1",
|
|
refs: ["#1", "#2"],
|
|
status: "inProgress",
|
|
},
|
|
});
|
|
});
|
|
|
|
it("bulk delete wraps refs in the request DTO", async () => {
|
|
await new TauriTicketGateway().bulkDelete("proj-1", ["#3", "#4"]);
|
|
|
|
expect(invoke).toHaveBeenCalledWith("ticket_bulk_delete", {
|
|
request: {
|
|
projectId: "proj-1",
|
|
refs: ["#3", "#4"],
|
|
},
|
|
});
|
|
});
|
|
|
|
it("passes createdBy through the ticket list request DTO", async () => {
|
|
await new TauriTicketGateway().list("proj-1", {
|
|
createdBy: { kind: "agent", agentId: "agent-1" },
|
|
});
|
|
|
|
expect(invoke).toHaveBeenCalledWith("ticket_list", {
|
|
request: {
|
|
projectId: "proj-1",
|
|
statuses: [],
|
|
priorities: [],
|
|
createdBy: { kind: "agent", agentId: "agent-1" },
|
|
},
|
|
});
|
|
});
|
|
|
|
it("normalizes legacy ticket list rows that omit assignedAgentIds", async () => {
|
|
invoke.mockResolvedValueOnce({
|
|
items: [
|
|
{
|
|
ref: "#12",
|
|
path: ".ideai/tickets/12/issue.md",
|
|
title: "Legacy row",
|
|
status: "open",
|
|
priority: "medium",
|
|
createdBy: { kind: "user" },
|
|
updatedAt: 1,
|
|
},
|
|
],
|
|
});
|
|
|
|
const list = await new TauriTicketGateway().list("proj-1");
|
|
|
|
expect(list.items[0]?.assignedAgentIds).toEqual([]);
|
|
});
|
|
|
|
it("wraps ticket attachment commands in the request DTO", async () => {
|
|
const gateway = new TauriTicketGateway();
|
|
|
|
await gateway.addAttachment(
|
|
"proj-1",
|
|
"#12",
|
|
"/tmp/note.txt",
|
|
3,
|
|
"text/plain",
|
|
);
|
|
await gateway.readAttachment("proj-1", "#12", "att-1");
|
|
await gateway.markAttachmentSummarized("proj-1", "#12", "att-1", 4);
|
|
|
|
expect(invoke).toHaveBeenNthCalledWith(1, "ticket_attachment_add", {
|
|
request: {
|
|
projectId: "proj-1",
|
|
ref: "#12",
|
|
path: "/tmp/note.txt",
|
|
expectedVersion: 3,
|
|
mime: "text/plain",
|
|
},
|
|
});
|
|
expect(invoke).toHaveBeenNthCalledWith(2, "ticket_attachment_read", {
|
|
request: {
|
|
projectId: "proj-1",
|
|
ref: "#12",
|
|
attachmentId: "att-1",
|
|
},
|
|
});
|
|
expect(invoke).toHaveBeenNthCalledWith(
|
|
3,
|
|
"ticket_attachment_mark_summarized",
|
|
{
|
|
request: {
|
|
projectId: "proj-1",
|
|
ref: "#12",
|
|
attachmentId: "att-1",
|
|
expectedVersion: 4,
|
|
},
|
|
},
|
|
);
|
|
});
|
|
|
|
it("normalizes legacy ticket payloads that omit array fields", async () => {
|
|
invoke.mockResolvedValueOnce({
|
|
id: "issue-1",
|
|
ref: "#12",
|
|
number: 12,
|
|
title: "Legacy",
|
|
description: "",
|
|
status: "open",
|
|
priority: "medium",
|
|
createdBy: { kind: "user" },
|
|
updatedBy: { kind: "user" },
|
|
createdAt: 1,
|
|
updatedAt: 1,
|
|
version: 1,
|
|
});
|
|
|
|
const ticket = await new TauriTicketGateway().read("proj-1", "#12", true);
|
|
|
|
expect(ticket.links).toEqual([]);
|
|
expect(ticket.assignedAgentIds).toEqual([]);
|
|
expect(ticket.attachments).toEqual([]);
|
|
});
|
|
});
|