import { fireEvent, render, screen, waitFor, within } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { StrictMode } from "react"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import App from "./App"; const bootstrap = { theme: "white", s2sUrl: "ws://localhost:8420/v1/realtime", apipilot: true }; beforeEach(() => { window.history.replaceState({}, "", "/?debug=true&phoneNumber=1234"); vi.spyOn(HTMLDialogElement.prototype, "showModal").mockImplementation(function (this: HTMLDialogElement) { this.open = true; }); vi.spyOn(HTMLDialogElement.prototype, "close").mockImplementation(function (this: HTMLDialogElement) { this.open = false; }); vi.stubGlobal( "fetch", vi.fn((input: string) => { const path = new URL(input, window.location.origin).pathname; const data: Record = { "/api/config": bootstrap, "/api/user/phone": { result: { name: "Ana Vargas", contact: { emailAddress: "ana@example.test" } } }, "/api/user/reports": { count: 1, entries: [{ sourceScheduleLabel: null, date: null }], hints: [], truncated: true, note: "Lista abreviada", }, "/api/apipilot/tools": { success: true, data: { tools: [{ name: "get_reports", description: "Consulta tus reportes", parameters: {} }] }, }, }; return Promise.resolve(new Response(JSON.stringify(data[path] ?? {}))); }), ); }); afterEach(() => { vi.unstubAllGlobals(); window.history.replaceState({}, "", "/"); }); describe("React application", () => { it("loads the configured theme and persists voice settings across remounts under StrictMode", async () => { const user = userEvent.setup(); const view = render( , ); await user.click(await screen.findByRole("button", { name: "Configuración" })); expect(document.documentElement.dataset.theme).toBe("white"); await user.selectOptions(screen.getByRole("combobox"), "Serena"); expect(localStorage.getItem("s2s.ws.voice")).toBe("Serena"); await user.click(screen.getByRole("button", { name: "Guardar" })); expect(screen.queryByRole("dialog")).not.toBeInTheDocument(); view.unmount(); render( , ); await user.click(await screen.findByRole("button", { name: "Configuración" })); expect(screen.getByRole("combobox")).toHaveValue("Serena"); }); it("saves and clears session-only RAG context and supports keyboard dialog dismissal", async () => { const user = userEvent.setup(); render(); await user.click(await screen.findByRole("button", { name: "Contexto RAG personalizado" })); await user.type(screen.getByRole("textbox"), "Datos de prueba para esta conversación"); await user.click(screen.getByRole("button", { name: "Enviar a la sesión" })); expect(within(screen.getByRole("dialog")).getByRole("status")).toHaveTextContent("Contexto actualizado"); fireEvent(screen.getByRole("dialog"), new Event("cancel", { bubbles: true })); expect(screen.queryByRole("dialog")).not.toBeInTheDocument(); await user.click(screen.getByRole("button", { name: "Contexto RAG personalizado" })); expect(screen.getByRole("textbox")).toHaveValue("Datos de prueba para esta conversación"); await user.click(screen.getByRole("button", { name: "Vaciar" })); expect(screen.getByRole("textbox")).toHaveValue(""); }); it("shows nested profile fields and discovers remote tools after bootstrap", async () => { const user = userEvent.setup(); render(); await user.click(await screen.findByRole("button", { name: "Ver datos de Ana Vargas" })); expect(within(screen.getByRole("dialog")).getByRole("link", { name: "ana@example.test" })).toHaveAttribute( "href", "mailto:ana@example.test", ); await user.click(screen.getByRole("button", { name: "Cerrar" })); await user.click(screen.getByRole("button", { name: "Herramientas" })); await waitFor(() => { expect(screen.getByText("get_reports")).toBeInTheDocument(); }); expect(screen.getByText("Consulta tus reportes")).toBeInTheDocument(); }); it("keeps debug controls out of the normal user screen", async () => { window.history.replaceState({}, "", "/"); render(); expect(await screen.findByRole("button", { name: "Iniciar conversación de voz" })).toBeEnabled(); expect(screen.queryByRole("button", { name: "Configuración" })).not.toBeInTheDocument(); expect(screen.getByText("Aún no hay mensajes")).toBeInTheDocument(); }); });