feat(tickets): assignation de sprint en masse via multi-sélection
Permet de sélectionner plusieurs tickets dans TicketsPanel et de leur assigner un sprint en une seule action, au lieu d'un ticket à la fois. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@ -886,6 +886,76 @@ describe("TicketsView", () => {
|
||||
expect(screen.queryByRole("toolbar", { name: "bulk ticket actions" })).toBeNull();
|
||||
});
|
||||
|
||||
it("selects several rows and assigns their sprint from the bulk action bar (#112)", async () => {
|
||||
ticket._seedSprint(PROJECT_ID, { id: "s1", order: 1, name: "Target" });
|
||||
const a = await ticket.create(PROJECT_ID, { title: "Sprint Bulk A" });
|
||||
const b = await ticket.create(PROJECT_ID, { title: "Sprint Bulk B" });
|
||||
await ticket.create(PROJECT_ID, { title: "Unselected sprint item" });
|
||||
const setSpy = vi.spyOn(ticket, "setTicketSprint");
|
||||
|
||||
renderView(ticket, system, agent);
|
||||
|
||||
fireEvent.click(await screen.findByLabelText(`select ticket row ${a.ref}`));
|
||||
fireEvent.click(screen.getByLabelText(`select ticket row ${b.ref}`));
|
||||
|
||||
const toolbar = screen.getByRole("toolbar", { name: "bulk ticket actions" });
|
||||
fireEvent.click(within(toolbar).getByRole("button", { name: "Sprint" }));
|
||||
fireEvent.click(await screen.findByLabelText("select sprint Target"));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(setSpy).toHaveBeenCalledWith(PROJECT_ID, a.ref, "s1", a.version);
|
||||
expect(setSpy).toHaveBeenCalledWith(PROJECT_ID, b.ref, "s1", b.version);
|
||||
});
|
||||
await waitFor(async () => {
|
||||
expect((await ticket.read(PROJECT_ID, a.ref)).sprintId).toBe("s1");
|
||||
expect((await ticket.read(PROJECT_ID, b.ref)).sprintId).toBe("s1");
|
||||
});
|
||||
expect(screen.getByRole("status").textContent).toMatch(
|
||||
/Sprint mis à jour pour 2 tickets/i,
|
||||
);
|
||||
expect(screen.queryByRole("toolbar", { name: "bulk ticket actions" })).toBeNull();
|
||||
});
|
||||
|
||||
it("keeps failed refs selected after a partial bulk sprint assignment (#112)", async () => {
|
||||
ticket._seedSprint(PROJECT_ID, { id: "s1", order: 1, name: "Target" });
|
||||
const a = await ticket.create(PROJECT_ID, { title: "Sprint Partial A" });
|
||||
const b = await ticket.create(PROJECT_ID, { title: "Sprint Partial B" });
|
||||
const originalSetTicketSprint = ticket.setTicketSprint.bind(ticket);
|
||||
vi.spyOn(ticket, "setTicketSprint").mockImplementation(
|
||||
async (projectId, ref, sprintId, expectedVersion) => {
|
||||
if (ref === b.ref) {
|
||||
throw { code: "CONFLICT", message: "version conflict" };
|
||||
}
|
||||
return originalSetTicketSprint(projectId, ref, sprintId, expectedVersion);
|
||||
},
|
||||
);
|
||||
|
||||
renderView(ticket, system, agent);
|
||||
|
||||
fireEvent.click(await screen.findByLabelText(`select ticket row ${a.ref}`));
|
||||
fireEvent.click(screen.getByLabelText(`select ticket row ${b.ref}`));
|
||||
const toolbar = screen.getByRole("toolbar", { name: "bulk ticket actions" });
|
||||
fireEvent.click(within(toolbar).getByRole("button", { name: "Sprint" }));
|
||||
fireEvent.click(await screen.findByLabelText("select sprint Target"));
|
||||
|
||||
await waitFor(async () => {
|
||||
expect((await ticket.read(PROJECT_ID, a.ref)).sprintId).toBe("s1");
|
||||
expect((await ticket.read(PROJECT_ID, b.ref)).sprintId).toBeNull();
|
||||
});
|
||||
expect((await screen.findByRole("alert")).textContent).toContain(
|
||||
`1 ticket(s) non modifié(s): ${b.ref}`,
|
||||
);
|
||||
expect(screen.getByRole("status").textContent).toMatch(/1\/2 tickets/i);
|
||||
expect(
|
||||
(screen.getByLabelText(`select ticket row ${b.ref}`) as HTMLInputElement)
|
||||
.checked,
|
||||
).toBe(true);
|
||||
expect(
|
||||
(screen.getByLabelText(`select ticket row ${a.ref}`) as HTMLInputElement)
|
||||
.checked,
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("selects several rows and deletes them after bulk confirmation", async () => {
|
||||
const a = await ticket.create(PROJECT_ID, { title: "Delete A" });
|
||||
const b = await ticket.create(PROJECT_ID, { title: "Delete B" });
|
||||
|
||||
Reference in New Issue
Block a user