feat: livrable ticket #91 — notification fin BackgroundTask enrichie

- Backend: enrichissement HeadlessRendezvous avec requester/target/conversationId
- Frontend: toast 'Requester -> Target completed/...' explicite
- Clic ouvrant viewer de conversation pour visualiser l'échange
This commit is contained in:
2026-07-27 09:05:34 +02:00
parent 02603441c1
commit 038e90ecec
12 changed files with 563 additions and 35 deletions

View File

@ -90,10 +90,17 @@ function fixedConversation(): ConversationGateway {
};
}
function renderView(project: MockProjectGateway) {
const agent = new MockAgentGateway();
function renderView(
project: MockProjectGateway,
overrides: {
agent?: MockAgentGateway;
system?: MockSystemGateway;
} = {},
) {
const agent = overrides.agent ?? new MockAgentGateway();
const system = overrides.system ?? new MockSystemGateway();
const gateways = {
system: new MockSystemGateway(),
system,
project,
agent,
profile: new MockProfileGateway(),
@ -224,4 +231,75 @@ describe("ProjectsView — LS7 conversation viewer integration", () => {
screen.queryByRole("button", { name: "← Retour aux terminaux" }),
).toBeNull();
});
it("labels rendezvous completion toasts with requester and target, then opens the conversation", async () => {
const project = new MockProjectGateway();
const created = await project.createProject("alpha", "/p/a");
const agent = new MockAgentGateway();
const system = new MockSystemGateway();
const requester = await agent.createAgent(created.id, {
name: "Main",
profileId: "codex",
});
const target = await agent.createAgent(created.id, {
name: "DevBackend",
profileId: "codex",
});
renderView(project, { agent, system });
await openProjectAndWorkTab("/p/a");
system.emit({
type: "backgroundTaskChanged",
projectId: created.id,
agentId: target.id,
taskId: "task-rendezvous-91",
state: "completed",
requesterAgentId: requester.id,
targetAgentId: target.id,
conversationId: CONV_ID,
});
const toast = await screen.findByRole("button", {
name: /Main -> DevBackend completed/i,
});
expect(within(toast).getByText("Task task-ren")).toBeTruthy();
fireEvent.click(toast);
expect(
await screen.findByRole("button", { name: "← Retour aux terminaux" }),
).toBeTruthy();
expect(await screen.findByText("contenu du fil ouvert")).toBeTruthy();
expect(
screen.queryByRole("button", { name: /Main -> DevBackend completed/i }),
).toBeNull();
});
it("keeps the generic background-task toast when rendezvous agent ids are absent", async () => {
const project = new MockProjectGateway();
const created = await project.createProject("alpha", "/p/a");
const system = new MockSystemGateway();
renderView(project, { system });
await openProjectAndWorkTab("/p/a");
system.emit({
type: "backgroundTaskChanged",
projectId: created.id,
agentId: "agent-generic-1",
taskId: "task-generic-1",
state: "failed",
});
const toast = await screen.findByRole("button", {
name: /Background task failed/i,
});
expect(within(toast).getByText("agent-ge · task-gen")).toBeTruthy();
fireEvent.click(toast);
expect(
screen.queryByRole("button", { name: "← Retour aux terminaux" }),
).toBeNull();
expect(await screen.findByText("Work")).toBeTruthy();
});
});