96 lines
3.1 KiB
TypeScript
96 lines
3.1 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest'
|
|
import { runEsRequest } from '../../../src/tools/request.js'
|
|
|
|
const fakeManaged = (readonly: boolean, calls: unknown[]) =>
|
|
({
|
|
config: { name: 'c', readonly, type: 'elasticsearch' },
|
|
backend: {
|
|
request: async (method: string, path: string, opts?: unknown) => {
|
|
calls.push({ method, path, opts })
|
|
return { status: 200, body: { hits: { total: 1 } } }
|
|
},
|
|
dispose: async () => {}
|
|
}
|
|
}) as never
|
|
|
|
describe('runEsRequest', () => {
|
|
it('blocks a mutating method on a readonly connection before calling backend', async () => {
|
|
const calls: unknown[] = []
|
|
const res = await runEsRequest(
|
|
fakeManaged(true, calls),
|
|
'DELETE',
|
|
'/idx/_doc/1',
|
|
undefined,
|
|
undefined,
|
|
1_000_000
|
|
)
|
|
expect(res.status).toBeUndefined()
|
|
expect(res.error).toMatch(/readonly/)
|
|
expect(calls).toHaveLength(0)
|
|
})
|
|
it('allows a read POST on a readonly connection', async () => {
|
|
const calls: unknown[] = []
|
|
const res = await runEsRequest(
|
|
fakeManaged(true, calls),
|
|
'POST',
|
|
'/idx/_search',
|
|
{ query: {} },
|
|
undefined,
|
|
1_000_000
|
|
)
|
|
expect(res.status).toBe(200)
|
|
expect(calls).toHaveLength(1)
|
|
})
|
|
it('passes through and returns status+body when allowed', async () => {
|
|
const calls: unknown[] = []
|
|
const res = await runEsRequest(
|
|
fakeManaged(false, calls),
|
|
'POST',
|
|
'/idx/_doc',
|
|
{ a: 1 },
|
|
undefined,
|
|
1_000_000
|
|
)
|
|
expect(res.status).toBe(200)
|
|
expect(calls).toHaveLength(1)
|
|
})
|
|
it('truncates an over-budget body', async () => {
|
|
const calls: unknown[] = []
|
|
const managed = fakeManaged(false, calls) as { backend: { request: unknown } }
|
|
managed.backend.request = async () => ({ status: 200, body: { big: 'x'.repeat(5000) } })
|
|
const res = await runEsRequest(
|
|
managed as never,
|
|
'GET',
|
|
'/idx/_search',
|
|
undefined,
|
|
undefined,
|
|
100
|
|
)
|
|
expect(res.truncated).toBe(true)
|
|
})
|
|
it('rethrows a non-guard error from the readonly check', async () => {
|
|
const calls: unknown[] = []
|
|
vi.resetModules()
|
|
vi.doMock('../../../src/es/guard.js', () => ({
|
|
EsGuardError: class EsGuardError extends Error {},
|
|
assertReadAllowed: () => {
|
|
throw new Error('boom')
|
|
}
|
|
}))
|
|
const { runEsRequest: mocked } = await import('../../../src/tools/request.js')
|
|
await expect(
|
|
mocked(
|
|
fakeManaged(true, calls),
|
|
'POST',
|
|
'/idx/_search',
|
|
undefined,
|
|
undefined,
|
|
1_000_000
|
|
)
|
|
).rejects.toThrow('boom')
|
|
expect(calls).toHaveLength(0)
|
|
vi.doUnmock('../../../src/es/guard.js')
|
|
vi.resetModules()
|
|
})
|
|
})
|