feat(domain,application,infrastructure,backend,web-server,app-tauri,frontend): lot utilisateur #325 #326 — icônes projet avec watermark CLI custom et localisation FR/EN (QA verte)
Lot en un seul commit: les deux features partagent les mêmes contrats (domain/settings.rs, DTO, commandes Tauri/HTTP, web-server) et les mêmes surfaces UI — la séparation par fichiers était impossible sans chirurgie de hunks risquant des états intermédiaires non compilables (convention lot des batches #310-#313 et #315). #325 — icône configurable par projet, watermark CLI custom: - domaine: ProjectIconSet (devicon, simple-icons, lucide, idea), ProjectIconRef validé (nom ASCII 1..=64, -_. internes), champ icon optionnel sur ProjectSettings; sérialisation camelCase et try_from strict - application: UpdateProjectSettings.execute accepte un patch theme_color OU icon (absent = inchangé, null = défaut produit), tests in-dependants avec store mémoire - backend/app-tauri/web-server: ProjectIconRefDto, UpdateProjectSettingsRequestDto avec icon optionnel (désérialisation additive), commandes update_project_settings alignées Tauri/HTTP, tests DTO et HTTP (défaut null, set, clear, nom invalide rejeté) - frontend: catalogue projectIcons (recherche EN), ProjectIconPicker en grille multi-lignes dans Paramètres projet, affichage de l'icône dans ProjectTabs et watermark grand format à faible opacité en fond de CLI custom; ports ProjectSettings.icon, Partial<ProjectSettings>, adapters tauri/mock/http et tests alignés #326 — localisation FR/EN et traduction des textes IdeA: - domaine: IdeaLanguage (fr | en), champ language optionnel sur IdeaUserSettings (absence = défaut produit, série additive validée) - backend/web-server: UserSettingsDto.language, update_user_settings accepte language, tests HTTP alignés; fixtures structured_launch_d3 mises à jour - frontend: i18n/ (catalogue FR/EN, I18nProvider, scan anti-régression des sources visibles), GeneralSettings avec sélecteur de langue dans les paramètres, setupI18n dans vitest; migration de l'ensemble des textes hardcodés vers le catalogue sur toutes les surfaces (agents, layout, projets, tickets, sprints, web, plugins, permissions, git, templates, skills, mémoire, model servers, embedder, first-run, devices, scheduled tasks, workstate, dialogs), FR conservé par défaut; recherche d'icônes #325 en anglais conformément au ticket QA verte sur feature/batch-325-326-project-icons-localisation. Aucun push.
This commit is contained in:
@ -11,6 +11,7 @@ import {
|
||||
__resetProjectCliInteractionActivityForTests,
|
||||
hasProjectCliInteraction,
|
||||
} from "@/features/projects/projectCliInteractionActivity";
|
||||
import { publishProjectIconChanged } from "@/features/projects/projectIcons";
|
||||
import {
|
||||
PluginCommandRegistry,
|
||||
PluginLayoutRegistry,
|
||||
@ -197,6 +198,23 @@ describe("CustomAgentChatView", () => {
|
||||
__resetProjectCliInteractionActivityForTests();
|
||||
});
|
||||
|
||||
it("renders the project icon as a non-interactive custom-CLI watermark and updates it immediately", async () => {
|
||||
const agent = {
|
||||
reattachAgentChat: vi.fn(async (sessionId: string) => ({ sessionId, scrollback: [] })),
|
||||
sendAgentChat: vi.fn(), cancelAgentChat: vi.fn(), closeAgentChat: vi.fn(),
|
||||
};
|
||||
const project = { readProjectSettings: vi.fn(async () => ({ themeColor: null, icon: { set: "devicon" as const, name: "python" } })) };
|
||||
render(<DIProvider gateways={{ agent, project, system: { pickFile: vi.fn(async () => null) } } as unknown as Gateways}>
|
||||
<CustomAgentChatView projectId="project-1" agentId="agent-1" agentName="Worker" profile={profile} cwd="/repo" nodeId="node-1" sessionId="chat-1" conversationId="conversation-1" onSessionId={vi.fn()} onConversationId={vi.fn()} />
|
||||
</DIProvider>);
|
||||
|
||||
const watermark = await screen.findByTestId("project-icon-watermark");
|
||||
expect(watermark.style.pointerEvents).toBe("none");
|
||||
expect(watermark.textContent).toBe("Py");
|
||||
publishProjectIconChanged({ projectId: "project-1", icon: { set: "lucide", name: "star" } });
|
||||
await waitFor(() => expect(watermark.textContent).toBe("★"));
|
||||
});
|
||||
|
||||
it("settles an isolated conversation id without recovered turns as an actionable unavailable state (#307/#314)", async () => {
|
||||
const agent = {
|
||||
launchAgentChat: vi.fn(async () => ({
|
||||
@ -246,7 +264,7 @@ describe("CustomAgentChatView", () => {
|
||||
expect(
|
||||
await screen.findByText("La conversation liée n’a pas pu être restaurée."),
|
||||
).toBeTruthy();
|
||||
expect(screen.getByText("Son transcript n’est plus disponible après la reprise.")).toBeTruthy();
|
||||
expect(screen.getByText("Sa transcription n’est plus disponible après la reprise.")).toBeTruthy();
|
||||
expect(
|
||||
screen.queryByText("Conversation liée — récupération du transcript en cours."),
|
||||
).toBeNull();
|
||||
@ -370,10 +388,10 @@ describe("CustomAgentChatView", () => {
|
||||
});
|
||||
|
||||
expect(
|
||||
await screen.findByText("------- redemarrage de l'agent -------"),
|
||||
await screen.findByText("------- redémarrage de l’agent -------"),
|
||||
).not.toBeNull();
|
||||
expect(
|
||||
screen.getByText("------- redemarrage de l'agent termine -------"),
|
||||
screen.getByText("------- redémarrage de l’agent terminé -------"),
|
||||
).not.toBeNull();
|
||||
expect(screen.getAllByTestId("agent-restart-separator")).toHaveLength(2);
|
||||
|
||||
@ -403,7 +421,7 @@ describe("CustomAgentChatView", () => {
|
||||
});
|
||||
});
|
||||
expect(
|
||||
screen.getByText("------- redemarrage de l'agent echoue -------"),
|
||||
screen.getByText("------- redémarrage de l’agent échoué -------"),
|
||||
).not.toBeNull();
|
||||
expect(screen.getByText("runtime unavailable")).not.toBeNull();
|
||||
});
|
||||
@ -676,7 +694,7 @@ describe("CustomAgentChatView", () => {
|
||||
</DIProvider>,
|
||||
);
|
||||
|
||||
const composer = await screen.findByLabelText(/message CLI custom/) as HTMLTextAreaElement;
|
||||
const composer = await screen.findByLabelText(/Message CLI personnalisée/) as HTMLTextAreaElement;
|
||||
await waitFor(() => expect(agent.reattachAgentChat).toHaveBeenCalled());
|
||||
|
||||
fireEvent.change(composer, { target: { value: "first prompt" } });
|
||||
@ -712,7 +730,7 @@ describe("CustomAgentChatView", () => {
|
||||
it("recalls history from the exact end of a multiline draft and restores it verbatim", async () => {
|
||||
const agent = renderHistoryChat();
|
||||
const composer = (await screen.findByLabelText(
|
||||
/message CLI custom/,
|
||||
/Message CLI personnalisée/,
|
||||
)) as HTMLTextAreaElement;
|
||||
await waitFor(() => expect(agent.reattachAgentChat).toHaveBeenCalled());
|
||||
await sendHistoryPrompt(composer, agent, "historic prompt");
|
||||
@ -742,7 +760,7 @@ describe("CustomAgentChatView", () => {
|
||||
it("keeps ArrowUp native away from a simple end caret or during modified/IME input", async () => {
|
||||
const agent = renderHistoryChat();
|
||||
const composer = (await screen.findByLabelText(
|
||||
/message CLI custom/,
|
||||
/Message CLI personnalisée/,
|
||||
)) as HTMLTextAreaElement;
|
||||
await waitFor(() => expect(agent.reattachAgentChat).toHaveBeenCalled());
|
||||
await sendHistoryPrompt(composer, agent, "historic prompt");
|
||||
@ -778,7 +796,7 @@ describe("CustomAgentChatView", () => {
|
||||
it("does not consume ArrowUp with empty history and never mutates recalled entries", async () => {
|
||||
const agent = renderHistoryChat();
|
||||
const composer = (await screen.findByLabelText(
|
||||
/message CLI custom/,
|
||||
/Message CLI personnalisée/,
|
||||
)) as HTMLTextAreaElement;
|
||||
await waitFor(() => expect(agent.reattachAgentChat).toHaveBeenCalled());
|
||||
|
||||
@ -838,7 +856,7 @@ describe("CustomAgentChatView", () => {
|
||||
</DIProvider>,
|
||||
);
|
||||
|
||||
let composer = await screen.findByLabelText(/message CLI custom/) as HTMLTextAreaElement;
|
||||
let composer = await screen.findByLabelText(/Message CLI personnalisée/) as HTMLTextAreaElement;
|
||||
fireEvent.change(composer, { target: { value: "remember me" } });
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
await waitFor(() => expect(agent.sendAgentChat).toHaveBeenCalledWith(
|
||||
@ -859,7 +877,7 @@ describe("CustomAgentChatView", () => {
|
||||
</DIProvider>,
|
||||
);
|
||||
|
||||
composer = await screen.findByLabelText(/message CLI custom/) as HTMLTextAreaElement;
|
||||
composer = await screen.findByLabelText(/Message CLI personnalisée/) as HTMLTextAreaElement;
|
||||
fireEvent.keyDown(composer, { key: "ArrowUp" });
|
||||
await waitFor(() => expect(composer.value).toBe("remember me"));
|
||||
});
|
||||
@ -897,7 +915,7 @@ describe("CustomAgentChatView", () => {
|
||||
</DIProvider>,
|
||||
);
|
||||
|
||||
const composer = await screen.findByLabelText(/message CLI custom/);
|
||||
const composer = await screen.findByLabelText(/Message CLI personnalisée/);
|
||||
fireEvent.change(composer, { target: { value: "persist before send" } });
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
|
||||
@ -911,7 +929,7 @@ describe("CustomAgentChatView", () => {
|
||||
});
|
||||
try {
|
||||
const agent = renderHistoryChat();
|
||||
const composer = await screen.findByLabelText(/message CLI custom/);
|
||||
const composer = await screen.findByLabelText(/Message CLI personnalisée/);
|
||||
fireEvent.change(composer, { target: { value: "still send" } });
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
|
||||
@ -1020,7 +1038,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "Initial prompt" },
|
||||
});
|
||||
nowMs = userReceivedAtMs;
|
||||
@ -1100,7 +1118,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "Initial prompt" },
|
||||
});
|
||||
nowMs = userReceivedAtMs;
|
||||
@ -1235,9 +1253,9 @@ describe("CustomAgentChatView", () => {
|
||||
|
||||
try {
|
||||
render(<Harness />);
|
||||
const composer = await screen.findByLabelText(/message CLI custom/) as HTMLTextAreaElement;
|
||||
const composer = await screen.findByLabelText(/Message CLI personnalisée/) as HTMLTextAreaElement;
|
||||
const handle = screen.getByRole("button", {
|
||||
name: "redimensionner le composer node-1",
|
||||
name: "Redimensionner l’éditeur node-1",
|
||||
});
|
||||
expect(composer.style.height).toBe("64px");
|
||||
expect(handle.style.cursor).toBe("ns-resize");
|
||||
@ -1401,7 +1419,7 @@ describe("CustomAgentChatView", () => {
|
||||
|
||||
expect(screen.getByText("Initial reply")).toBeTruthy();
|
||||
expect(screen.getByRole("button", { name: "Envoyer" }).hasAttribute("disabled")).toBe(true);
|
||||
expect(screen.getByLabelText(/message CLI custom/).hasAttribute("disabled")).toBe(true);
|
||||
expect(screen.getByLabelText(/Message CLI personnalisée/).hasAttribute("disabled")).toBe(true);
|
||||
|
||||
act(() => {
|
||||
secondReattach.resolve({ sessionId: "chat-session-1", scrollback });
|
||||
@ -1411,7 +1429,7 @@ describe("CustomAgentChatView", () => {
|
||||
expect(screen.getByText("Partial answer while away")).toBeTruthy();
|
||||
expect(screen.queryByText(/Reprise effectuée:/)).toBeNull();
|
||||
expect(screen.getByRole("button", { name: "Stop" })).toBeTruthy();
|
||||
expect(screen.getByLabelText(/message CLI custom/).hasAttribute("disabled")).toBe(true);
|
||||
expect(screen.getByLabelText(/Message CLI personnalisée/).hasAttribute("disabled")).toBe(true);
|
||||
});
|
||||
|
||||
it("restores visible conversation from conversationId cache when layout returns before sessionId", async () => {
|
||||
@ -1594,7 +1612,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "first turn" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -1619,12 +1637,12 @@ describe("CustomAgentChatView", () => {
|
||||
);
|
||||
expect(agent.cancelAgentChat).toHaveBeenCalledTimes(1);
|
||||
resolveCancel();
|
||||
await waitFor(() => expect(screen.getByText("Request stopped.")).toBeTruthy());
|
||||
await waitFor(() => expect(screen.getByText("Demande arrêtée.")).toBeTruthy());
|
||||
expect(hasProjectCliInteraction("project-1")).toBe(false);
|
||||
expect(onSessionId).not.toHaveBeenCalledWith(null);
|
||||
expect(agent.stopLiveAgent).not.toHaveBeenCalled();
|
||||
expect(agent.closeAgentChat).not.toHaveBeenCalled();
|
||||
const composer = screen.getByLabelText(/message CLI custom/);
|
||||
const composer = screen.getByLabelText(/Message CLI personnalisée/);
|
||||
expect(composer).toHaveProperty("disabled", false);
|
||||
|
||||
fireEvent.change(composer, {
|
||||
@ -1696,7 +1714,7 @@ describe("CustomAgentChatView", () => {
|
||||
</DIProvider>,
|
||||
);
|
||||
|
||||
const composer = await screen.findByLabelText(/message CLI custom/);
|
||||
const composer = await screen.findByLabelText(/Message CLI personnalisée/);
|
||||
await waitFor(() => expect(composer).toHaveProperty("disabled", true));
|
||||
expect(screen.getByRole("button", { name: "Stop" })).toBeTruthy();
|
||||
|
||||
@ -1791,7 +1809,7 @@ describe("CustomAgentChatView", () => {
|
||||
);
|
||||
|
||||
expect(await screen.findByText("Main attend Architect")).toBeTruthy();
|
||||
expect(screen.getByLabelText(/message CLI custom/)).toHaveProperty("disabled", true);
|
||||
expect(screen.getByLabelText(/Message CLI personnalisée/)).toHaveProperty("disabled", true);
|
||||
});
|
||||
|
||||
it("falls back to a fresh launch when reattach reports NOT_FOUND", async () => {
|
||||
@ -1895,7 +1913,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "hello agent" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -1974,13 +1992,13 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "first request" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
await screen.findByText("final first request");
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "second request" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -2117,16 +2135,16 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "ship progress UI" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
|
||||
await screen.findByText("Progress");
|
||||
await screen.findByText("Progression");
|
||||
expect(screen.getAllByTestId("chat-turn-marker")).toHaveLength(2);
|
||||
expect(screen.getByText("turn.started")).toBeTruthy();
|
||||
expect(screen.getByText("turn.completed")).toBeTruthy();
|
||||
expect(screen.getByText("Progress").closest("[data-testid='chat-progress-status']")).toBeTruthy();
|
||||
expect(screen.getByText("Progression").closest("[data-testid='chat-progress-status']")).toBeTruthy();
|
||||
expect(screen.getByText("Analyse")).toBeTruthy();
|
||||
expect(screen.getByText("Lecture du contexte disponible.")).toBeTruthy();
|
||||
expect(screen.getByText("MCP")).toBeTruthy();
|
||||
@ -2203,13 +2221,13 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "first" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
await screen.findByText("done first");
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "second" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -2251,7 +2269,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "first request" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -2271,7 +2289,7 @@ describe("CustomAgentChatView", () => {
|
||||
});
|
||||
});
|
||||
expect(screen.getByText("Running first request")).toBeTruthy();
|
||||
expect(screen.getByText("Tool").parentElement?.textContent).toContain("En cours");
|
||||
expect(screen.getByText("Outil").parentElement?.textContent).toContain("En cours");
|
||||
|
||||
act(() => {
|
||||
harness.emit(0, {
|
||||
@ -2289,7 +2307,7 @@ describe("CustomAgentChatView", () => {
|
||||
});
|
||||
await screen.findByText("final first request");
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "second request" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -2308,7 +2326,7 @@ describe("CustomAgentChatView", () => {
|
||||
});
|
||||
});
|
||||
expect(screen.getByText("Second request context loaded.")).toBeTruthy();
|
||||
expect(screen.getByText("Progress").parentElement?.textContent).toContain("En cours");
|
||||
expect(screen.getByText("Progression").parentElement?.textContent).toContain("En cours");
|
||||
|
||||
act(() => {
|
||||
harness.emit(1, {
|
||||
@ -2379,7 +2397,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "first request" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -2412,7 +2430,7 @@ describe("CustomAgentChatView", () => {
|
||||
});
|
||||
await screen.findByText("done first request");
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "second request" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -2487,7 +2505,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "first request" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -2522,7 +2540,7 @@ describe("CustomAgentChatView", () => {
|
||||
});
|
||||
await screen.findByText("done first request");
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "second request" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -2599,7 +2617,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "first request" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -2636,7 +2654,7 @@ describe("CustomAgentChatView", () => {
|
||||
});
|
||||
expect(screen.queryByText("Late first request completion")).toBeNull();
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "second request" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -2727,7 +2745,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "delegate after intent" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -2831,7 +2849,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "delegate once" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -2882,7 +2900,7 @@ describe("CustomAgentChatView", () => {
|
||||
expect(screen.getAllByText("validate")).toHaveLength(2);
|
||||
expect(screen.queryByText("Appel inter-agent")).toBeNull();
|
||||
expect(screen.queryByText("reply delivered")).toBeNull();
|
||||
expect(screen.queryByText("Tool")).toBeNull();
|
||||
expect(screen.queryByText("Outil")).toBeNull();
|
||||
expect(screen.queryByText("started")).toBeNull();
|
||||
await waitFor(() =>
|
||||
expect(screen.queryByRole("status", { name: "Loading" })).toBeNull(),
|
||||
@ -2939,7 +2957,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "read many tickets" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -3032,7 +3050,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "read ticket" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -3108,7 +3126,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "download model" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -3134,7 +3152,7 @@ describe("CustomAgentChatView", () => {
|
||||
expect(screen.getAllByTestId("chat-tool-progress")).toHaveLength(1);
|
||||
expect(screen.queryByText("Downloading 10%")).toBeNull();
|
||||
expect(screen.getByText("Downloading 75%")).toBeTruthy();
|
||||
expect(screen.getByText("Tool").parentElement?.textContent).toContain("En cours");
|
||||
expect(screen.getByText("Outil").parentElement?.textContent).toContain("En cours");
|
||||
});
|
||||
|
||||
it("expands only truncated MCP progress details and preserves expansion across updates", async () => {
|
||||
@ -3187,7 +3205,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "inspect mcp payloads" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -3308,7 +3326,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "stream progress" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -3382,7 +3400,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "run tools" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -3473,7 +3491,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "call tool" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -3499,7 +3517,7 @@ describe("CustomAgentChatView", () => {
|
||||
expect(screen.getAllByTestId("chat-tool-progress")).toHaveLength(1);
|
||||
expect(screen.queryByText("Searching...")).toBeNull();
|
||||
expect(screen.getByText("Found results")).toBeTruthy();
|
||||
expect(screen.getByText("Tool").parentElement?.textContent).toContain("Terminé");
|
||||
expect(screen.getByText("Outil").parentElement?.textContent).toContain("Terminé");
|
||||
|
||||
act(() => {
|
||||
emitChunk?.({ kind: "final", content: "done" });
|
||||
@ -3560,7 +3578,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "ship progress UI" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -3580,7 +3598,7 @@ describe("CustomAgentChatView", () => {
|
||||
});
|
||||
|
||||
expect(screen.queryByRole("status", { name: "Loading" })).toBeNull();
|
||||
expect(screen.getByText("Progress").parentElement?.textContent).toContain("En cours");
|
||||
expect(screen.getByText("Progression").parentElement?.textContent).toContain("En cours");
|
||||
|
||||
act(() => {
|
||||
emitChunk?.({ kind: "final", content: "done" });
|
||||
@ -3591,7 +3609,7 @@ describe("CustomAgentChatView", () => {
|
||||
expect(screen.queryByRole("status", { name: "Loading" })).toBeNull(),
|
||||
);
|
||||
expect(screen.getByText("Lecture du contexte disponible.")).toBeTruthy();
|
||||
expect(screen.getByText("Progress").parentElement?.textContent).toContain("Terminé");
|
||||
expect(screen.getByText("Progression").parentElement?.textContent).toContain("Terminé");
|
||||
});
|
||||
|
||||
it("ignores late progress chunks after the final answer without reopening the turn", async () => {
|
||||
@ -3644,7 +3662,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "ship ordered stream" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -3734,7 +3752,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
const composer = screen.getByLabelText(/message CLI custom/) as HTMLTextAreaElement;
|
||||
const composer = screen.getByLabelText(/Message CLI personnalisée/) as HTMLTextAreaElement;
|
||||
fireEvent.change(composer, { target: { value: "/c" } });
|
||||
|
||||
const menu = await screen.findByRole("listbox", {
|
||||
@ -3804,7 +3822,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
const composer = screen.getByLabelText(/message CLI custom/) as HTMLTextAreaElement;
|
||||
const composer = screen.getByLabelText(/Message CLI personnalisée/) as HTMLTextAreaElement;
|
||||
fireEvent.change(composer, { target: { value: "hello /c" } });
|
||||
expect(screen.queryByRole("listbox", { name: "suggestions commandes slash" })).toBeNull();
|
||||
expect(agent.listSlashCommands).not.toHaveBeenCalled();
|
||||
@ -3889,7 +3907,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
const composer = screen.getByLabelText(/message CLI custom/) as HTMLTextAreaElement;
|
||||
const composer = screen.getByLabelText(/Message CLI personnalisée/) as HTMLTextAreaElement;
|
||||
fireEvent.change(composer, { target: { value: "/explain focus this" } });
|
||||
fireEvent.keyDown(composer, { key: "Enter" });
|
||||
|
||||
@ -3958,7 +3976,7 @@ describe("CustomAgentChatView", () => {
|
||||
|
||||
expect(await screen.findByText("old conversation")).toBeTruthy();
|
||||
|
||||
const composer = screen.getByLabelText(/message CLI custom/) as HTMLTextAreaElement;
|
||||
const composer = screen.getByLabelText(/Message CLI personnalisée/) as HTMLTextAreaElement;
|
||||
fireEvent.change(composer, { target: { value: "/clean" } });
|
||||
fireEvent.keyDown(composer, { key: "Enter" });
|
||||
|
||||
@ -4053,7 +4071,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
const composer = screen.getByLabelText(/message CLI custom/) as HTMLTextAreaElement;
|
||||
const composer = screen.getByLabelText(/Message CLI personnalisée/) as HTMLTextAreaElement;
|
||||
fireEvent.change(composer, { target: { value: "/help" } });
|
||||
fireEvent.keyDown(composer, { key: "Enter" });
|
||||
|
||||
@ -4135,7 +4153,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
const composer = screen.getByLabelText(/message CLI custom/);
|
||||
const composer = screen.getByLabelText(/Message CLI personnalisée/);
|
||||
fireEvent.change(composer, { target: { value: "/explain" } });
|
||||
fireEvent.keyDown(composer, { key: "Enter" });
|
||||
|
||||
@ -4219,7 +4237,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
const composer = screen.getByLabelText(/message CLI custom/) as HTMLTextAreaElement;
|
||||
const composer = screen.getByLabelText(/Message CLI personnalisée/) as HTMLTextAreaElement;
|
||||
fireEvent.change(composer, { target: { value: "/profile" } });
|
||||
fireEvent.keyDown(composer, { key: "Enter" });
|
||||
|
||||
@ -4232,14 +4250,14 @@ describe("CustomAgentChatView", () => {
|
||||
expect(agent.sendAgentChat).not.toHaveBeenCalled();
|
||||
|
||||
const confirmButton = screen.getByRole("button", {
|
||||
name: "Reset et changer le profil",
|
||||
name: "Réinitialiser et changer le profil",
|
||||
}) as HTMLButtonElement;
|
||||
expect(confirmButton.disabled).toBe(true);
|
||||
|
||||
fireEvent.change(screen.getByLabelText("profil cible"), {
|
||||
fireEvent.change(screen.getByLabelText("Profil cible"), {
|
||||
target: { value: "codex-high" },
|
||||
});
|
||||
fireEvent.click(screen.getByLabelText("Je confirme que la session courante sera reset."));
|
||||
fireEvent.click(screen.getByLabelText("Je confirme que la session courante sera réinitialisée."));
|
||||
expect(confirmButton.disabled).toBe(false);
|
||||
fireEvent.click(confirmButton);
|
||||
|
||||
@ -4314,7 +4332,7 @@ describe("CustomAgentChatView", () => {
|
||||
Object.defineProperty(file, "arrayBuffer", {
|
||||
value: vi.fn(async () => new Uint8Array([1, 2, 3]).buffer),
|
||||
});
|
||||
const composer = screen.getByLabelText(/message CLI custom/) as HTMLTextAreaElement;
|
||||
const composer = screen.getByLabelText(/Message CLI personnalisée/) as HTMLTextAreaElement;
|
||||
fireEvent.paste(composer, {
|
||||
clipboardData: {
|
||||
items: [
|
||||
@ -4332,7 +4350,7 @@ describe("CustomAgentChatView", () => {
|
||||
expect(screen.getByTestId("attachment-preview-clipboard.png")).toBeTruthy();
|
||||
await waitFor(() => expect(composer.value).toBe("[Image 1]"));
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "retirer clipboard.png" }));
|
||||
fireEvent.click(screen.getByRole("button", { name: "Retirer clipboard.png" }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(screen.queryByText("Fichier joint: clipboard.png")).toBeNull(),
|
||||
@ -4402,7 +4420,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.paste(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.paste(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
clipboardData: {
|
||||
items: [],
|
||||
files: [],
|
||||
@ -4492,7 +4510,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.paste(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.paste(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
clipboardData: {
|
||||
items: [],
|
||||
files: [],
|
||||
@ -4564,7 +4582,7 @@ describe("CustomAgentChatView", () => {
|
||||
Object.defineProperty(file, "arrayBuffer", {
|
||||
value: vi.fn(async () => new Uint8Array([1, 2, 3]).buffer),
|
||||
});
|
||||
fireEvent.paste(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.paste(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
clipboardData: {
|
||||
items: [
|
||||
{
|
||||
@ -4645,7 +4663,7 @@ describe("CustomAgentChatView", () => {
|
||||
Object.defineProperty(file, "arrayBuffer", {
|
||||
value: vi.fn(async () => new Uint8Array([4, 5, 6]).buffer),
|
||||
});
|
||||
fireEvent.paste(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.paste(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
clipboardData: {
|
||||
items: [],
|
||||
files: [file],
|
||||
@ -4716,7 +4734,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
const composer = screen.getByLabelText(/message CLI custom/) as HTMLTextAreaElement;
|
||||
const composer = screen.getByLabelText(/Message CLI personnalisée/) as HTMLTextAreaElement;
|
||||
fireEvent.change(composer, { target: { value: "prefix suffix" } });
|
||||
composer.setSelectionRange(7, 13);
|
||||
|
||||
@ -4802,7 +4820,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
const composer = screen.getByLabelText(/message CLI custom/) as HTMLTextAreaElement;
|
||||
const composer = screen.getByLabelText(/Message CLI personnalisée/) as HTMLTextAreaElement;
|
||||
fireEvent.change(composer, { target: { value: "voir maintenant" } });
|
||||
composer.setSelectionRange(5, 5);
|
||||
const file = new File(["ignored"], "cursor.png", { type: "image/png" });
|
||||
@ -4904,7 +4922,7 @@ describe("CustomAgentChatView", () => {
|
||||
files: [file],
|
||||
getData: () => "",
|
||||
};
|
||||
const composer = screen.getByLabelText(/message CLI custom/);
|
||||
const composer = screen.getByLabelText(/Message CLI personnalisée/);
|
||||
|
||||
fireEvent.paste(composer, { clipboardData });
|
||||
await screen.findByText("Fichier joint: duplicate.pdf");
|
||||
@ -4994,7 +5012,7 @@ describe("CustomAgentChatView", () => {
|
||||
</DIProvider>,
|
||||
);
|
||||
await waitFor(() =>
|
||||
expect((screen.getByLabelText(/message CLI custom/) as HTMLTextAreaElement).value).toBe(""),
|
||||
expect((screen.getByLabelText(/Message CLI personnalisée/) as HTMLTextAreaElement).value).toBe(""),
|
||||
);
|
||||
|
||||
rerender(
|
||||
@ -5028,7 +5046,7 @@ describe("CustomAgentChatView", () => {
|
||||
</DIProvider>,
|
||||
);
|
||||
await waitFor(() =>
|
||||
expect((screen.getByLabelText(/message CLI custom/) as HTMLTextAreaElement).value).toBe(""),
|
||||
expect((screen.getByLabelText(/Message CLI personnalisée/) as HTMLTextAreaElement).value).toBe(""),
|
||||
);
|
||||
});
|
||||
|
||||
@ -5083,7 +5101,7 @@ describe("CustomAgentChatView", () => {
|
||||
await waitFor(() =>
|
||||
expect(agent.readChatDraft).toHaveBeenCalledWith(scope),
|
||||
);
|
||||
const composer = screen.getByLabelText(/message CLI custom/) as HTMLTextAreaElement;
|
||||
const composer = screen.getByLabelText(/Message CLI personnalisée/) as HTMLTextAreaElement;
|
||||
fireEvent.change(composer, { target: { value: "draft with file" } });
|
||||
|
||||
const file = new File(["ignored"], "not-persisted.png", { type: "image/png" });
|
||||
@ -5159,7 +5177,7 @@ describe("CustomAgentChatView", () => {
|
||||
|
||||
await waitFor(() => expect(agent.sendAgentChat).toHaveBeenCalledTimes(1));
|
||||
expect(agent.clearChatDraft).toHaveBeenCalledWith(scope);
|
||||
expect((screen.getByLabelText(/message CLI custom/) as HTMLTextAreaElement).value).toBe("");
|
||||
expect((screen.getByLabelText(/Message CLI personnalisée/) as HTMLTextAreaElement).value).toBe("");
|
||||
});
|
||||
|
||||
it("clears the persisted draft when a slash command is consumed", async () => {
|
||||
@ -5224,7 +5242,7 @@ describe("CustomAgentChatView", () => {
|
||||
}),
|
||||
);
|
||||
expect(agent.clearChatDraft).toHaveBeenCalledWith(scope);
|
||||
expect((screen.getByLabelText(/message CLI custom/) as HTMLTextAreaElement).value).toBe("");
|
||||
expect((screen.getByLabelText(/Message CLI personnalisée/) as HTMLTextAreaElement).value).toBe("");
|
||||
});
|
||||
|
||||
it("keeps the chat shell bounded with a scrollable message area and fixed composer", async () => {
|
||||
@ -5457,7 +5475,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "please recover" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -5531,7 +5549,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "please recover" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -5595,7 +5613,7 @@ describe("CustomAgentChatView", () => {
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/message CLI custom/), {
|
||||
fireEvent.change(screen.getByLabelText(/Message CLI personnalisée/), {
|
||||
target: { value: "long turn" },
|
||||
});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
@ -5603,7 +5621,7 @@ describe("CustomAgentChatView", () => {
|
||||
|
||||
fireEvent.click(await screen.findByRole("button", { name: "Stop" }));
|
||||
|
||||
expect(await screen.findByText("Request already stopped.")).toBeTruthy();
|
||||
expect(await screen.findByText("Demande déjà arrêtée.")).toBeTruthy();
|
||||
expect(onSessionId).not.toHaveBeenCalledWith(null);
|
||||
expect(agent.cancelAgentChat).toHaveBeenCalledWith("gone-session");
|
||||
expect(agent.stopLiveAgent).not.toHaveBeenCalled();
|
||||
|
||||
Reference in New Issue
Block a user