Saltar al contenido

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:

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í.

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 implementation
beforeAll(() => {
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 implementation
beforeAll(() => {
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',
},
});
}
});
Desde 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.

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 implementation
beforeAll(() => {
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