feat(tickets): attribution d'un sprint à la création via popup SprintPicker (#38)
Nouveau composant SprintPicker permettant de choisir un sprint lors de la création d'un ticket depuis TicketsPanel ; export ajouté à l'index des features tickets. Frontend-pur. QA vert : tsc --noEmit exit 0, vitest 63 fichiers / 634 tests passés. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -214,6 +214,80 @@ describe("TicketsView", () => {
|
||||
expect(await screen.findByText("Live created")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("creates a ticket and assigns the sprint chosen via the picker (#38)", async () => {
|
||||
ticket._seedSprint(PROJECT_ID, { id: "s1", order: 1, name: "Alpha" });
|
||||
const setSpy = vi.spyOn(ticket, "setTicketSprint");
|
||||
|
||||
renderView(ticket, system, agent);
|
||||
fireEvent.click(await screen.findByRole("button", { name: "New" }));
|
||||
fireEvent.change(screen.getByLabelText("new ticket title"), {
|
||||
target: { value: "With sprint" },
|
||||
});
|
||||
|
||||
// Field defaults to "Sans sprint"; open the picker and pick Alpha.
|
||||
const sprintField = screen.getByLabelText("choose sprint for new ticket");
|
||||
expect(sprintField.textContent).toContain("Sans sprint");
|
||||
fireEvent.click(sprintField);
|
||||
fireEvent.click(await screen.findByLabelText("select sprint Alpha"));
|
||||
expect(
|
||||
screen.getByLabelText("choose sprint for new ticket").textContent,
|
||||
).toContain("Alpha");
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "Create" }));
|
||||
|
||||
// create → setTicketSprint(projectId, ref, "s1", version).
|
||||
await waitFor(() => expect(setSpy).toHaveBeenCalledTimes(1));
|
||||
const call = setSpy.mock.calls[0];
|
||||
expect(call[0]).toBe(PROJECT_ID);
|
||||
expect(call[2]).toBe("s1");
|
||||
await waitFor(async () => {
|
||||
const fresh = await ticket.read(PROJECT_ID, call[1]);
|
||||
expect(fresh.sprintId).toBe("s1");
|
||||
});
|
||||
});
|
||||
|
||||
it("creates a ticket without a sprint — setTicketSprint is not called (#38)", async () => {
|
||||
const setSpy = vi.spyOn(ticket, "setTicketSprint");
|
||||
|
||||
renderView(ticket, system, agent);
|
||||
fireEvent.click(await screen.findByRole("button", { name: "New" }));
|
||||
fireEvent.change(screen.getByLabelText("new ticket title"), {
|
||||
target: { value: "No sprint" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Create" }));
|
||||
|
||||
await waitFor(async () => {
|
||||
const list = await ticket.list(PROJECT_ID);
|
||||
expect(list.items.map((i) => i.title)).toContain("No sprint");
|
||||
});
|
||||
expect(setSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("keeps the created ticket and surfaces the error when sprint assignment fails (#38)", async () => {
|
||||
ticket._seedSprint(PROJECT_ID, { id: "s1", order: 1, name: "Alpha" });
|
||||
vi.spyOn(ticket, "setTicketSprint").mockRejectedValueOnce({
|
||||
code: "INTERNAL",
|
||||
message: "assign boom",
|
||||
});
|
||||
|
||||
renderView(ticket, system, agent);
|
||||
fireEvent.click(await screen.findByRole("button", { name: "New" }));
|
||||
fireEvent.change(screen.getByLabelText("new ticket title"), {
|
||||
target: { value: "Kept anyway" },
|
||||
});
|
||||
fireEvent.click(screen.getByLabelText("choose sprint for new ticket"));
|
||||
fireEvent.click(await screen.findByLabelText("select sprint Alpha"));
|
||||
fireEvent.click(screen.getByRole("button", { name: "Create" }));
|
||||
|
||||
// The ticket was created despite the failed assignment (no data lost)…
|
||||
await waitFor(async () => {
|
||||
const list = await ticket.list(PROJECT_ID);
|
||||
expect(list.items.map((i) => i.title)).toContain("Kept anyway");
|
||||
});
|
||||
// …and the assignment failure is surfaced.
|
||||
expect(await screen.findByText(/assign boom/)).toBeTruthy();
|
||||
});
|
||||
|
||||
it("multi-selects status/priority facets (OR intra, AND inter) and clears (#12)", async () => {
|
||||
const listSpy = vi.spyOn(ticket, "list");
|
||||
await ticket.create(PROJECT_ID, {
|
||||
|
||||
Reference in New Issue
Block a user