Files
NotesAgentic/frontend/src/services/pluginService.spec.ts
T

86 lines
3.3 KiB
TypeScript

// @vitest-environment happy-dom
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import * as pluginService from './pluginService'
function jsonResponse(body: unknown) {
return new Response(JSON.stringify(body), {
status: 200,
headers: { 'Content-Type': 'application/json' },
})
}
beforeEach(() => {
vi.stubGlobal('fetch', vi.fn())
})
afterEach(() => {
vi.unstubAllGlobals()
vi.restoreAllMocks()
})
describe('pluginService contribution adapter', () => {
it('lists and executes Plugin Commands with scoped wire fields', async () => {
const fetchMock = vi.mocked(fetch)
fetchMock
.mockResolvedValueOnce(jsonResponse({ items: [{ command_id: 'text-tools.uppercase-selection' }] }))
.mockResolvedValueOnce(jsonResponse({
command_id: 'text-tools.uppercase-selection',
status: 'completed',
effect: { type: 'notification', payload: { level: 'success', message: 'HELLO' } },
}))
const commands = await pluginService.listPluginCommands('command_palette')
const result = await pluginService.executePluginCommand(
'text-tools.uppercase-selection',
{},
{ note_id: 'note-1', selection: 'hello' },
)
expect(commands[0].command_id).toBe('text-tools.uppercase-selection')
if (result.effect.type !== 'notification') throw new Error('expected notification effect')
expect(result.effect.payload.message).toBe('HELLO')
expect(fetchMock.mock.calls[0][0]).toBe(
'/api/plugin-contributions/commands?location=command_palette',
)
expect(JSON.parse(String(fetchMock.mock.calls[1][1]?.body))).toEqual({
arguments: {},
context: { note_id: 'note-1', selection: 'hello' },
})
})
it('uses separate Settings and Secret endpoints', async () => {
const fetchMock = vi.mocked(fetch)
fetchMock
.mockResolvedValueOnce(jsonResponse({
plugin_id: 'text-tools', schema_version: 1, fields: [],
values: { result_limit: 10 }, secrets: { api_key: { configured: false } },
}))
.mockResolvedValueOnce(jsonResponse({
plugin_id: 'text-tools', schema_version: 1, fields: [],
values: { result_limit: 20 }, secrets: { api_key: { configured: false } },
}))
.mockResolvedValueOnce(jsonResponse({ plugin_id: 'text-tools', key: 'api_key', configured: true }))
.mockResolvedValueOnce(jsonResponse({ plugin_id: 'text-tools', key: 'api_key', configured: false }))
await pluginService.getPluginSettings('text-tools')
await pluginService.updatePluginSettings('text-tools', 1, { result_limit: 20 })
await pluginService.putPluginSecret('text-tools', 'api_key', 'request-only-secret')
await pluginService.deletePluginSecret('text-tools', 'api_key')
expect(fetchMock.mock.calls.map(([url]) => url)).toEqual([
'/api/plugins/text-tools/settings',
'/api/plugins/text-tools/settings',
'/api/plugins/text-tools/settings/api_key/secret',
'/api/plugins/text-tools/settings/api_key/secret',
])
expect(JSON.parse(String(fetchMock.mock.calls[1][1]?.body))).toEqual({
schema_version: 1,
values: { result_limit: 20 },
})
expect(JSON.parse(String(fetchMock.mock.calls[2][1]?.body))).toEqual({
secret: 'request-only-secret',
})
expect(fetchMock.mock.calls[3][1]?.method).toBe('DELETE')
})
})