96 lines
3.6 KiB
TypeScript
96 lines
3.6 KiB
TypeScript
import { afterEach, expect, it, vi } from 'vitest';
|
|
import { flushSync, mount, unmount } from 'svelte';
|
|
import { writable } from 'svelte/store';
|
|
import UsersPage from '../../src/routes/settings/users/+page.svelte';
|
|
|
|
const page = writable({
|
|
data: { user: { id: 'admin', username: 'administrator', role: 'admin' } }
|
|
});
|
|
vi.mock('$app/stores', () => ({
|
|
page: { subscribe: (run: Parameters<typeof page.subscribe>[0]) => page.subscribe(run) }
|
|
}));
|
|
vi.mock('$app/navigation', () => ({ invalidateAll: vi.fn() }));
|
|
|
|
let component: ReturnType<typeof mount> | undefined;
|
|
afterEach(async () => {
|
|
if (component) await unmount(component);
|
|
component = undefined;
|
|
document.body.replaceChildren();
|
|
vi.unstubAllGlobals();
|
|
});
|
|
|
|
it('describes requests without presenting routes as accounts and preserves their diagnostic evidence', async () => {
|
|
const events = [
|
|
{
|
|
action: 'request',
|
|
targetId: '/api/configs/inspect',
|
|
details: JSON.stringify({ method: 'POST', status: 200, path: '/api/configs/inspect' })
|
|
},
|
|
{
|
|
action: 'request',
|
|
targetId: '/api/servers/[name]',
|
|
details: JSON.stringify({ method: 'DELETE', status: 202, path: '/api/servers/demo' })
|
|
},
|
|
{ action: 'request', targetId: '/api/provisioning', details: '{old malformed details' },
|
|
{ action: 'request', targetId: '/api/future/action', details: 'null' },
|
|
{ action: 'login', targetId: 'admin', details: '{}' }
|
|
].map((event, index) => ({
|
|
...event,
|
|
id: index + 1,
|
|
actorId: 'admin',
|
|
actor: 'administrator',
|
|
createdAt: Date.now()
|
|
}));
|
|
vi.stubGlobal(
|
|
'fetch',
|
|
vi.fn(async (path: string) =>
|
|
Response.json(
|
|
path.endsWith('/audit')
|
|
? { events }
|
|
: {
|
|
users: [
|
|
{
|
|
id: 'admin',
|
|
username: 'administrator',
|
|
displayName: 'Administrator',
|
|
role: 'admin',
|
|
disabled: false,
|
|
mustChangePassword: false,
|
|
lastLoginAt: null
|
|
}
|
|
]
|
|
}
|
|
)
|
|
)
|
|
);
|
|
component = mount(UsersPage, { target: document.body });
|
|
flushSync();
|
|
await vi.waitFor(() => expect(document.querySelectorAll('tbody tr')).toHaveLength(5));
|
|
const rows = Array.from(document.querySelectorAll<HTMLTableRowElement>('tbody tr'));
|
|
expect(rows.map((row) => row.cells[1].textContent)).toEqual([
|
|
'Action requested',
|
|
'Action requested',
|
|
'Action requested',
|
|
'Action requested',
|
|
'Signed in'
|
|
]);
|
|
expect(rows.map((row) => row.cells[3].textContent)).toEqual([
|
|
'Inspect config',
|
|
'Remove server',
|
|
'Manage server operation',
|
|
'Other action',
|
|
'administrator'
|
|
]);
|
|
expect(document.querySelector('thead')?.textContent).toContain('Account or action');
|
|
expect(rows[1].querySelector('details')?.open).toBe(false);
|
|
expect(rows[1].querySelector('summary')?.textContent).toBe('Technical details');
|
|
expect(JSON.parse(rows[1].querySelector('pre')!.textContent!)).toEqual({
|
|
method: 'DELETE',
|
|
status: 202,
|
|
path: '/api/servers/demo',
|
|
routeId: '/api/servers/[name]'
|
|
});
|
|
expect(rows[2].querySelector('pre')?.textContent).toContain('{old malformed details');
|
|
expect(rows[3].querySelector('pre')?.textContent).toContain('/api/future/action');
|
|
});
|