Files

42 lines
1.8 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest'
const { invokeMock } = vi.hoisted(() => ({ invokeMock: vi.fn() }))
vi.mock('@tauri-apps/api/core', () => ({ invoke: invokeMock }))
vi.mock('../../src/platform/runtime', () => ({ isTauriRuntime: () => true }))
import { invokeEnvelope, invokeNative, NativeCommandError } from '../../src/platform/invoke'
describe('native error boundary', () => {
beforeEach(() => vi.clearAllMocks())
it('preserves business failures as envelopes', async () => {
const response = { success: false, error: 'bad data', errorCode: 'native.invalidBase64' }
invokeMock.mockResolvedValueOnce(response)
expect(await invokeNative('write_file')).toBe(response)
})
it('normalizes structured rejections without losing their code or cause', async () => {
const cause = { error: 'invalid encoding', errorCode: 'native.invalidBase64' }
invokeMock.mockRejectedValueOnce(cause)
const error = await invokeNative('write_file').catch((value: unknown) => value)
expect(error).toBeInstanceOf(NativeCommandError)
expect(error).toMatchObject({
command: 'write_file',
detail: 'invalid encoding',
errorCode: cause.errorCode,
originalError: cause,
})
expect((error as Error).message).not.toContain('[object Object]')
})
it('retains codes when adapting rejected calls to envelopes', async () => {
invokeMock.mockRejectedValueOnce({ error: 'join failed', errorCode: 'native.taskJoin' })
expect(await invokeEnvelope('read_file')).toMatchObject({ success: false, errorCode: 'native.taskJoin' })
})
it('preserves plain rejection messages', async () => {
invokeMock.mockRejectedValueOnce('custom native failure')
await expect(invokeNative('test')).rejects.toThrow('custom native failure')
})
})