Simular las API de Tauri
Al escribir tus pruebas de frontend, es común tener un entorno "falso" de Tauri para simular ventanas o interceptar llamadas IPC, lo que se conoce como mocking.
El módulo @tauri-apps/api/mocks proporciona algunas herramientas útiles para facilitarte esto:
Solicitudes IPC
Sección titulada “Solicitudes IPC”Lo más común es que quieras interceptar solicitudes IPC; esto puede ser útil en una variedad de situaciones:
- Asegurarse de que se realicen las llamadas al backend correctas
- Simular diferentes resultados de las funciones del backend
Tauri proporciona la función mockIPC para interceptar solicitudes IPC. Puedes encontrar más detalles sobre la API específica aquí.
Simular comandos para invoke
Sección titulada “Simular comandos para invoke”import { beforeAll, expect, test } from "vitest";import { randomFillSync } from "crypto";
import { mockIPC } from "@tauri-apps/api/mocks";import { invoke } from "@tauri-apps/api/core";
// jsdom doesn't come with a WebCrypto implementationbeforeAll(() => { Object.defineProperty(window, 'crypto', { value: { // @ts-ignore getRandomValues: (buffer) => { return randomFillSync(buffer); }, }, });});
test("invoke simple", async () => { mockIPC((cmd, args) => { // simulated rust command called "add" that just adds two numbers if(cmd === "add") { return (args.a as number) + (args.b as number); } });});A veces quieres rastrear más información sobre una llamada IPC; ¿cuántas veces se invocó el comando? ¿Llegó a invocarse siquiera?
Puedes usar mockIPC() con otras herramientas de espionaje y simulación para probar esto:
import { beforeAll, expect, test, vi } from "vitest";import { randomFillSync } from "crypto";
import { mockIPC } from "@tauri-apps/api/mocks";import { invoke } from "@tauri-apps/api/core";
// jsdom doesn't come with a WebCrypto implementationbeforeAll(() => { Object.defineProperty(window, 'crypto', { value: { // @ts-ignore getRandomValues: (buffer) => { return randomFillSync(buffer); }, }, });});
test("invoke", async () => { mockIPC((cmd, args) => { // simulated rust command called "add" that just adds two numbers if(cmd === "add") { return (args.a as number) + (args.b as number); } });
// we can use the spying tools provided by vitest to track the mocked function const spy = vi.spyOn(window.__TAURI_INTERNALS__, "invoke");
expect(invoke("add", { a: 12, b: 15 })).resolves.toBe(27); expect(spy).toHaveBeenCalled();});Para simular solicitudes IPC a un sidecar o comando shell, necesitas obtener el ID del controlador de eventos cuando se llama a spawn() o execute() y usar este ID para emitir los eventos que el backend devolvería:
mockIPC(async (cmd, args) => { if (args.message.cmd === 'execute') { const eventCallbackId = `_${args.message.onEventFn}`; const eventEmitter = window[eventCallbackId];
// 'Stdout' event can be called multiple times eventEmitter({ event: 'Stdout', payload: 'some data sent from the process', });
// 'Terminated' event must be called at the end to resolve the promise eventEmitter({ event: 'Terminated', payload: { code: 0, signal: 'kill', }, }); }});Simular eventos
Sección titulada “Simular eventos”2.7.0
Existe un soporte parcial del Sistema de eventos para simular eventos emitidos por tu código de Rust mediante la opción shouldMockEvents:
import { mockIPC, clearMocks } from '@tauri-apps/api/mocks';import { emit, listen } from '@tauri-apps/api/event';import { afterEach, expect, test, vi } from 'vitest';
test('mocked event', () => { mockIPC(() => {}, { shouldMockEvents: true }); // enable event mocking
const eventHandler = vi.fn(); listen('test-event', eventHandler);
emit('test-event', { foo: 'bar' }); expect(eventHandler).toHaveBeenCalledWith({ event: 'test-event', payload: { foo: 'bar' }, });});emitTo y emit_filter aún no son compatibles.
Ventanas
Sección titulada “Ventanas”A veces tienes código específico para una ventana (una ventana de pantalla de bienvenida/splash screen, por ejemplo), por lo que necesitas simular diferentes ventanas.
Puedes usar el método mockWindows() para crear etiquetas de ventana falsas. La primera cadena identifica la ventana "actual" (es decir, la ventana en la que tu JavaScript cree estar), y todas las demás cadenas se tratan como ventanas adicionales.
import { beforeAll, expect, test } from 'vitest';import { randomFillSync } from 'crypto';
import { mockWindows } from '@tauri-apps/api/mocks';
// jsdom doesn't come with a WebCrypto implementationbeforeAll(() => { Object.defineProperty(window, 'crypto', { value: { // @ts-ignore getRandomValues: (buffer) => { return randomFillSync(buffer); }, }, });});
test('invoke', async () => { mockWindows('main', 'second', 'third');
const { getCurrent, getAll } = await import('@tauri-apps/api/webviewWindow');
expect(getCurrent()).toHaveProperty('label', 'main'); expect(getAll().map((w) => w.label)).toEqual(['main', 'second', 'third']);});© 2026 Colaboradores de Tauri. CC-BY / MIT