Files
openmaic/OpenMAIC/tests/lib/ops/api-fetch.test.ts

93 lines
3.2 KiB
TypeScript

// @vitest-environment jsdom
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { installOpsBrowserBoundary } from '@/lib/ops/api-fetch';
const AUTH_STORAGE_KEY = 'works-square.operations.auth.v1';
describe('installOpsBrowserBoundary', () => {
let nativeFetch: ReturnType<typeof vi.fn>;
let cleanup: (() => void) | undefined;
beforeEach(() => {
vi.stubEnv('NEXT_PUBLIC_OPENMAIC_DEPLOYMENT_ROLE', 'ops');
vi.stubEnv('NEXT_PUBLIC_OPENMAIC_BASE_PATH', '/learning-ops');
window.localStorage.clear();
nativeFetch = vi.fn(async () => new Response(null, { status: 204 }));
window.fetch = nativeFetch as unknown as typeof window.fetch;
});
afterEach(() => {
cleanup?.();
cleanup = undefined;
window.localStorage.clear();
vi.unstubAllEnvs();
vi.restoreAllMocks();
});
it('maps root-relative API requests to the Ops basePath and adds the Works bearer token', async () => {
window.localStorage.setItem(
AUTH_STORAGE_KEY,
JSON.stringify({
accessToken: 'works-access-token',
expiresAt: Date.now() + 60_000,
}),
);
cleanup = installOpsBrowserBoundary();
await window.fetch('/api/server-providers', {
method: 'POST',
headers: { 'X-Request-Id': 'request-1' },
});
expect(nativeFetch).toHaveBeenCalledTimes(1);
const [input, init] = nativeFetch.mock.calls[0] as [RequestInfo | URL, RequestInit];
expect(input).toBe('/learning-ops/api/server-providers');
expect(init.method).toBe('POST');
const headers = new Headers(init.headers);
expect(headers.get('Authorization')).toBe('Bearer works-access-token');
expect(headers.get('X-Request-Id')).toBe('request-1');
});
it('leaves external URLs and unrelated root-relative paths unchanged', async () => {
cleanup = installOpsBrowserBoundary();
await window.fetch('https://example.test/api/courses');
await window.fetch('/courses/course-1', { method: 'GET' });
expect(nativeFetch).toHaveBeenNthCalledWith(1, 'https://example.test/api/courses', {});
expect(nativeFetch).toHaveBeenNthCalledWith(2, '/courses/course-1', { method: 'GET' });
});
it('restores unwrapped fetch behavior when cleaned up', async () => {
cleanup = installOpsBrowserBoundary();
const wrappedFetch = window.fetch;
cleanup();
cleanup = undefined;
expect(window.fetch).not.toBe(wrappedFetch);
await window.fetch('/api/server-providers');
expect(nativeFetch).toHaveBeenCalledTimes(1);
expect(nativeFetch.mock.calls[0]?.[0]).toBe('/api/server-providers');
});
it.each([
{
label: 'expired session',
value: JSON.stringify({ accessToken: 'expired-token', expiresAt: Date.now() - 1 }),
},
{ label: 'malformed session JSON', value: '{not-json' },
{ label: 'session without a string token', value: JSON.stringify({ accessToken: 123 }) },
])('does not add Authorization for a $label', async ({ value }) => {
window.localStorage.setItem(AUTH_STORAGE_KEY, value);
cleanup = installOpsBrowserBoundary();
await window.fetch('/api/server-providers');
const [, init] = nativeFetch.mock.calls[0] as [RequestInfo | URL, RequestInit];
expect(new Headers(init.headers).has('Authorization')).toBe(false);
});
});