feat(tickets): conservation des tickets en sprint, affichage du statut & filtres (#37)
Les tickets restent rattachés à leur sprint ; SprintManager affiche le statut et propose des filtres via useTicketSearch. Frontend / read-query. QA vert : tsc --noEmit exit 0, vitest 62 fichiers / 623 tests passés. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -955,4 +955,84 @@ describe("SprintManager (#11)", () => {
|
||||
expect(fresh.sprintId).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
/** Seeds sprint "Holder" with one open and one closed ticket assigned. */
|
||||
async function seedSprintWithOpenAndClosed(): Promise<void> {
|
||||
ticket._seedSprint(PROJECT_ID, { id: "s1", order: 1, name: "Holder" });
|
||||
const openT = await ticket.create(PROJECT_ID, {
|
||||
title: "Open member",
|
||||
priority: "high",
|
||||
});
|
||||
await ticket.setTicketSprint(PROJECT_ID, openT.ref, "s1", openT.version);
|
||||
const closedT = await ticket.create(PROJECT_ID, {
|
||||
title: "Closed member",
|
||||
priority: "low",
|
||||
});
|
||||
const upd = await ticket.update(PROJECT_ID, closedT.ref, {
|
||||
status: "closed",
|
||||
expectedVersion: closedT.version,
|
||||
});
|
||||
await ticket.setTicketSprint(PROJECT_ID, closedT.ref, "s1", upd.version);
|
||||
}
|
||||
|
||||
it("keeps closed tickets visible in the sprint with status/priority badges (#37)", async () => {
|
||||
await seedSprintWithOpenAndClosed();
|
||||
const dialog = await openManager();
|
||||
|
||||
const row = await within(dialog).findByLabelText("sprint row Holder");
|
||||
// Both the open and the closed ticket are listed (closed is NOT hidden).
|
||||
expect(within(row).getByText("Open member")).toBeTruthy();
|
||||
expect(within(row).getByText("Closed member")).toBeTruthy();
|
||||
// Each row carries its status + priority badge (scoped to the sprint row so
|
||||
// the facet-bar labels don't collide).
|
||||
expect(within(row).getByText("Closed")).toBeTruthy();
|
||||
expect(within(row).getByText("Open")).toBeTruthy();
|
||||
expect(within(row).getByText("High")).toBeTruthy();
|
||||
expect(within(row).getByText("Low")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("filters the sprint tickets by status via its own facets bar (#37)", async () => {
|
||||
await seedSprintWithOpenAndClosed();
|
||||
const dialog = await openManager();
|
||||
|
||||
await within(dialog).findByText("Open member");
|
||||
expect(within(dialog).getByText("Closed member")).toBeTruthy();
|
||||
|
||||
// Constrain the sprint view to Closed only → the open ticket drops out.
|
||||
fireEvent.click(within(dialog).getByLabelText("filter status Closed"));
|
||||
await waitFor(() =>
|
||||
expect(within(dialog).queryByText("Open member")).toBeNull(),
|
||||
);
|
||||
expect(within(dialog).getByText("Closed member")).toBeTruthy();
|
||||
|
||||
// Clearing the facet brings the open ticket back.
|
||||
fireEvent.click(within(dialog).getByLabelText("filter status Closed"));
|
||||
await waitFor(() =>
|
||||
expect(within(dialog).getByText("Open member")).toBeTruthy(),
|
||||
);
|
||||
});
|
||||
|
||||
it("sprint ticket view is independent of the main panel filter (#37)", async () => {
|
||||
await seedSprintWithOpenAndClosed();
|
||||
|
||||
renderView(ticket, system, agent);
|
||||
await waitFor(() =>
|
||||
expect(
|
||||
screen.getByRole("button", { name: "manage sprints" }),
|
||||
).toBeTruthy(),
|
||||
);
|
||||
|
||||
// Constrain the MAIN Tickets panel to Open only → the closed ticket leaves
|
||||
// the main list (there is a single main facets bar on screen at this point).
|
||||
fireEvent.click(screen.getByLabelText("filter status Open"));
|
||||
await waitFor(() => expect(screen.queryByText("Closed member")).toBeNull());
|
||||
|
||||
// Open the sprint manager: its own query ignores the main filter, so the
|
||||
// closed ticket is still shown inside its sprint.
|
||||
fireEvent.click(screen.getByRole("button", { name: "manage sprints" }));
|
||||
const dialog = await screen.findByRole("dialog", { name: "manage sprints" });
|
||||
const row = await within(dialog).findByLabelText("sprint row Holder");
|
||||
expect(await within(row).findByText("Closed member")).toBeTruthy();
|
||||
expect(within(row).getByText("Open member")).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user