More webui layout, navigation, preparations of user/roles/groups/security

This commit is contained in:
2026-07-16 22:00:02 +02:00
parent 324367abd7
commit 63deb02d39
13 changed files with 1352 additions and 31 deletions
+142 -1
View File
@@ -1,5 +1,12 @@
import { afterEach, describe, expect, it, vi } from 'vitest'
import { fetchHealth, fetchStatus, getApiBaseUrl } from './client'
import {
deleteGroup,
fetchGroups,
fetchHealth,
fetchStatus,
getApiBaseUrl,
upsertGroup,
} from './client'
describe('getApiBaseUrl', () => {
it('defaults to localhost:8080 when unset', () => {
@@ -68,3 +75,137 @@ describe('fetchStatus', () => {
)
})
})
describe('fetchGroups', () => {
afterEach(() => {
vi.restoreAllMocks()
})
it('returns parsed groups payload', async () => {
const fetchMock = vi.fn().mockResolvedValue({
ok: true,
json: async () => ({
groups: [
{
name: 'Admins',
scope_kind: 'node',
scope_name: 'node-1',
permissions: ['nodes.read'],
},
],
}),
})
const payload = await fetchGroups(fetchMock)
expect(fetchMock).toHaveBeenCalledWith('http://localhost:8080/api/v1/groups')
expect(payload.groups).toEqual([
{
name: 'Admins',
scope_kind: 'node',
scope_name: 'node-1',
permissions: ['nodes.read'],
},
])
})
it('throws when the response is not ok', async () => {
const fetchMock = vi.fn().mockResolvedValue({
ok: false,
status: 503,
json: async () => ({}),
})
await expect(fetchGroups(fetchMock)).rejects.toThrow(
'groups fetch failed: 503',
)
})
})
describe('upsertGroup', () => {
afterEach(() => {
vi.restoreAllMocks()
})
it('sends JSON body and returns parsed groups', async () => {
const fetchMock = vi.fn().mockResolvedValue({
ok: true,
json: async () => ({ groups: [] }),
})
await upsertGroup(
{
name: 'Admins',
scope_kind: 'node',
scope_name: 'node-1',
permissions: ['nodes.read'],
},
fetchMock,
)
expect(fetchMock).toHaveBeenCalledWith('http://localhost:8080/api/v1/groups', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
group: {
name: 'Admins',
scope_kind: 'node',
scope_name: 'node-1',
permissions: ['nodes.read'],
},
}),
})
})
it('throws when the response is not ok', async () => {
const fetchMock = vi.fn().mockResolvedValue({
ok: false,
status: 400,
json: async () => ({}),
})
await expect(
upsertGroup(
{
name: 'Admins',
scope_kind: 'node',
scope_name: 'node-1',
permissions: ['nodes.read'],
},
fetchMock,
),
).rejects.toThrow('groups upsert failed: 400')
})
})
describe('deleteGroup', () => {
afterEach(() => {
vi.restoreAllMocks()
})
it('sends DELETE and returns parsed groups', async () => {
const fetchMock = vi.fn().mockResolvedValue({
ok: true,
json: async () => ({ groups: [] }),
})
await deleteGroup('Admins', fetchMock)
expect(fetchMock).toHaveBeenCalledWith(
'http://localhost:8080/api/v1/groups?name=Admins',
{ method: 'DELETE' },
)
})
it('throws when the response is not ok', async () => {
const fetchMock = vi.fn().mockResolvedValue({
ok: false,
status: 404,
json: async () => ({}),
})
await expect(deleteGroup('Admins', fetchMock)).rejects.toThrow(
'groups delete failed: 404',
)
})
})