Files
vocero-client/s2s-frontend/src/App.test.tsx
T

105 lines
4.6 KiB
TypeScript

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<string, unknown> = {
"/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(
<StrictMode>
<App />
</StrictMode>,
);
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(
<StrictMode>
<App />
</StrictMode>,
);
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(<App />);
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(<App />);
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(<App />);
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();
});
});