bulk operations test coverage

- tickets_missing_carnet: backend test coverage
- ticket.test.ts: frontend adapter test coverage
This commit is contained in:
2026-07-28 20:41:46 +02:00
parent bd4f76ae74
commit 6fa41013ed
2 changed files with 117 additions and 0 deletions

View File

@ -96,3 +96,78 @@ async fn idea_ticket_read_is_best_effort_but_read_carnet_stays_strict_when_carne
.expect_err("strict carnet read must fail when carnet.md is missing"); .expect_err("strict carnet read must fail when carnet.md is missing");
assert_eq!(strict_err.code, "notFound"); assert_eq!(strict_err.code, "notFound");
} }
#[tokio::test]
async fn idea_ticket_bulk_delete_deletes_each_ref_and_reports_partial_errors() {
let state = AppState::build(temp_path("appdata"));
let project_root = temp_path("project").to_string_lossy().into_owned();
let project = state
.create_project
.execute(CreateProjectInput {
name: "App Tauri Bulk Delete".to_owned(),
root: project_root,
remote: None,
default_profile_id: None,
})
.await
.expect("test project is created")
.project;
let first = state
.ticket_tool_binder
.handle_ticket_tool(
&project,
"qa-agent",
"idea_ticket_create",
json!({ "title": "Bulk delete A" }),
)
.await
.expect("first ticket create succeeds");
let second = state
.ticket_tool_binder
.handle_ticket_tool(
&project,
"qa-agent",
"idea_ticket_create",
json!({ "title": "Bulk delete B" }),
)
.await
.expect("second ticket create succeeds");
let first_ref = first["ref"].as_str().expect("first ref").to_owned();
let second_ref = second["ref"].as_str().expect("second ref").to_owned();
let out = state
.ticket_tool_binder
.handle_ticket_tool(
&project,
"qa-agent",
"idea_ticket_bulk_delete",
json!({ "refs": [first_ref.clone(), "#999", second_ref.clone()] }),
)
.await
.expect("bulk delete dispatch succeeds");
let items = out["items"].as_array().expect("bulk items");
assert_eq!(items.len(), 3);
assert_eq!(items[0]["ref"], first_ref);
assert_eq!(items[0]["ok"], true);
assert_eq!(items[1]["ref"], "#999");
assert_eq!(items[1]["ok"], false);
assert_eq!(items[1]["error"]["code"], "NOT_FOUND");
assert_eq!(items[2]["ref"], second_ref);
assert_eq!(items[2]["ok"], true);
for deleted_ref in [first_ref, second_ref] {
let err = state
.ticket_tool_binder
.handle_ticket_tool(
&project,
"qa-agent",
"idea_ticket_read",
json!({ "ref": deleted_ref }),
)
.await
.expect_err("deleted ticket read must fail");
assert_eq!(err.code, "notFound");
}
}

View File

@ -0,0 +1,42 @@
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"],
},
});
});
});