feat(web): connect jobs and audit workspaces
This commit is contained in:
@@ -4,11 +4,15 @@ import userEvent from '@testing-library/user-event';
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { AppShell, type InstanceContext } from './app-shell.js';
|
||||
import type { AuditDataSource } from './audit/audit-page.js';
|
||||
import type { EventStreamClient } from './events/event-stream-client.js';
|
||||
import { type FleetDataSource, type FleetSnapshot } from './fleet/fleet-page.js';
|
||||
import type { JobsDataSource } from './jobs/jobs-page.js';
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
vi.restoreAllMocks();
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
const snapshot: FleetSnapshot = {
|
||||
@@ -52,6 +56,12 @@ function source(load: FleetDataSource['load']): FleetDataSource {
|
||||
return { load };
|
||||
}
|
||||
|
||||
const quietEventStreamClient: EventStreamClient = {
|
||||
subscribe: () => () => undefined,
|
||||
};
|
||||
|
||||
const emptyPage = { items: [], page: { page: 1, pageSize: 25, total: 0 } };
|
||||
|
||||
describe('React AppShell and Fleet vertical slice', () => {
|
||||
it('loads real injected data and renders canonical origins and owner routes without React key warnings', async () => {
|
||||
const consoleError = vi.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||
@@ -197,4 +207,76 @@ describe('React AppShell and Fleet vertical slice', () => {
|
||||
expect(screen.queryByText('Owner modem')).toBeNull();
|
||||
expect(screen.getByText(/Instance context is unavailable/i)).toBeTruthy();
|
||||
});
|
||||
|
||||
it.each([
|
||||
{
|
||||
pathname: '/jobs',
|
||||
endpoint: '/api/v1/jobs?page=1&pageSize=25&sort=createdAt&direction=desc',
|
||||
emptyMessage: /No jobs match the current query/i,
|
||||
},
|
||||
{
|
||||
pathname: '/audit',
|
||||
endpoint: '/api/v1/audit?sort=occurredAt&direction=desc&page=1&pageSize=25',
|
||||
emptyMessage: /No audit events match the current query/i,
|
||||
},
|
||||
])(
|
||||
'uses the default HTTP data source for $pathname',
|
||||
async ({ pathname, endpoint, emptyMessage }) => {
|
||||
const fetcher = vi.fn<typeof fetch>().mockResolvedValue(
|
||||
new Response(JSON.stringify(emptyPage), {
|
||||
status: 200,
|
||||
headers: { 'content-type': 'application/json' },
|
||||
}),
|
||||
);
|
||||
vi.stubGlobal('fetch', fetcher);
|
||||
|
||||
render(<AppShell pathname={pathname} eventStreamClient={quietEventStreamClient} />);
|
||||
|
||||
expect(await screen.findByText(emptyMessage)).toBeTruthy();
|
||||
expect(fetcher).toHaveBeenCalledTimes(1);
|
||||
expect(fetcher).toHaveBeenCalledWith(endpoint, {
|
||||
method: 'GET',
|
||||
credentials: 'same-origin',
|
||||
headers: { accept: 'application/json' },
|
||||
signal: expect.any(AbortSignal),
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it.each([
|
||||
{
|
||||
pathname: '/jobs',
|
||||
sourceProp: 'jobsDataSource' as const,
|
||||
emptyMessage: /No jobs match the current query/i,
|
||||
},
|
||||
{
|
||||
pathname: '/audit',
|
||||
sourceProp: 'auditDataSource' as const,
|
||||
emptyMessage: /No audit events match the current query/i,
|
||||
},
|
||||
])(
|
||||
'uses an explicitly injected data source instead of global fetch for $pathname',
|
||||
async ({ pathname, sourceProp, emptyMessage }) => {
|
||||
const fetcher = vi.fn<typeof fetch>();
|
||||
vi.stubGlobal('fetch', fetcher);
|
||||
const load = vi
|
||||
.fn<JobsDataSource['load'] | AuditDataSource['load']>()
|
||||
.mockResolvedValue(emptyPage);
|
||||
const injectedSource = { load };
|
||||
|
||||
render(
|
||||
<AppShell
|
||||
pathname={pathname}
|
||||
eventStreamClient={quietEventStreamClient}
|
||||
{...(sourceProp === 'jobsDataSource'
|
||||
? { jobsDataSource: injectedSource as JobsDataSource }
|
||||
: { auditDataSource: injectedSource as AuditDataSource })}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(await screen.findByText(emptyMessage)).toBeTruthy();
|
||||
expect(load).toHaveBeenCalledTimes(1);
|
||||
expect(fetcher).not.toHaveBeenCalled();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user