wraith/frontend/tests/composables/useVault.spec.ts
Vantz Stockwell f01e357647 test: frontend test suite — Vitest infrastructure, auth/connection stores, vault composable, admin middleware
28 tests across 4 spec files. Vitest + happy-dom configured with Nuxt auto-import
shims ($$fetch, navigateTo, defineNuxtRouteMiddleware) so stores and composables
resolve cleanly outside the Nuxt runtime.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 19:06:14 -04:00

100 lines
3.6 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest'
import { useVault } from '../../composables/useVault'
const mockFetch = vi.mocked($fetch as ReturnType<typeof vi.fn>)
beforeEach(() => {
vi.clearAllMocks()
})
// ---------------------------------------------------------------------------
// Helper: assert no Authorization header was sent
// ---------------------------------------------------------------------------
function assertNoAuthHeader(callIndex = 0) {
const callArgs = mockFetch.mock.calls[callIndex]
const options = callArgs[1] as Record<string, unknown> | undefined
if (options && options.headers) {
const headers = options.headers as Record<string, unknown>
expect(headers).not.toHaveProperty('Authorization')
}
// If no options object at all — cookie-only, no auth header by definition
}
// ---------------------------------------------------------------------------
// SSH Keys
// ---------------------------------------------------------------------------
describe('listKeys()', () => {
it('fetches /api/ssh-keys without Authorization header', async () => {
mockFetch.mockResolvedValueOnce([])
const { listKeys } = useVault()
await listKeys()
expect(mockFetch).toHaveBeenCalledWith('/api/ssh-keys')
assertNoAuthHeader()
})
})
describe('importKey()', () => {
it('posts key data to /api/ssh-keys', async () => {
mockFetch.mockResolvedValueOnce({ id: 1 })
const { importKey } = useVault()
const payload = { name: 'my-key', privateKey: '-----BEGIN RSA PRIVATE KEY-----' }
await importKey(payload)
expect(mockFetch).toHaveBeenCalledWith('/api/ssh-keys', { method: 'POST', body: payload })
assertNoAuthHeader()
})
})
describe('deleteKey()', () => {
it('sends DELETE to /api/ssh-keys/:id', async () => {
mockFetch.mockResolvedValueOnce(undefined)
const { deleteKey } = useVault()
await deleteKey(7)
expect(mockFetch).toHaveBeenCalledWith('/api/ssh-keys/7', { method: 'DELETE' })
assertNoAuthHeader()
})
})
// ---------------------------------------------------------------------------
// Credentials
// ---------------------------------------------------------------------------
describe('listCredentials()', () => {
it('fetches /api/credentials without Authorization header', async () => {
mockFetch.mockResolvedValueOnce([])
const { listCredentials } = useVault()
await listCredentials()
expect(mockFetch).toHaveBeenCalledWith('/api/credentials')
assertNoAuthHeader()
})
})
describe('createCredential()', () => {
it('posts credential data to /api/credentials', async () => {
const cred = { label: 'prod-db', username: 'admin', password: 'hunter2' }
mockFetch.mockResolvedValueOnce({ id: 5, ...cred })
const { createCredential } = useVault()
await createCredential(cred)
expect(mockFetch).toHaveBeenCalledWith('/api/credentials', { method: 'POST', body: cred })
assertNoAuthHeader()
})
})
describe('updateCredential()', () => {
it('sends PUT to /api/credentials/:id', async () => {
mockFetch.mockResolvedValueOnce(undefined)
const { updateCredential } = useVault()
await updateCredential(5, { password: 'new-pass' })
expect(mockFetch).toHaveBeenCalledWith('/api/credentials/5', { method: 'PUT', body: { password: 'new-pass' } })
assertNoAuthHeader()
})
})
describe('deleteCredential()', () => {
it('sends DELETE to /api/credentials/:id', async () => {
mockFetch.mockResolvedValueOnce(undefined)
const { deleteCredential } = useVault()
await deleteCredential(5)
expect(mockFetch).toHaveBeenCalledWith('/api/credentials/5', { method: 'DELETE' })
assertNoAuthHeader()
})
})