Files
openmaic/OpenMAIC/tests/persistence/bootstrap.test.ts
2026-08-16 14:58:47 +08:00

121 lines
5.0 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest';
function memoryStorage(): Storage {
const values = new Map<string, string>();
return {
get length() {
return values.size;
},
clear: () => values.clear(),
getItem: (key) => values.get(key) ?? null,
key: (index) => [...values.keys()][index] ?? null,
removeItem: (key) => void values.delete(key),
setItem: (key, value) => void values.set(key, String(value)),
} as Storage;
}
describe('persistence client bootstrap', () => {
beforeEach(() => {
vi.resetModules();
vi.unstubAllEnvs();
vi.unstubAllGlobals();
});
it('leaves all sealed storage seams untouched when the flag is unset', async () => {
vi.stubEnv('NEXT_PUBLIC_PERSISTENCE', '');
const runtime = await import('@/lib/runtime/store');
const documents = await import('@/lib/document-store');
const assets = await import('@/lib/media/asset-pool-config');
expect(runtime.isRuntimeStorageConfigured()).toBe(false);
expect(documents.isDocumentStorageConfigured()).toBe(false);
expect(assets.isAssetPoolStorageConfigured()).toBe(false);
});
it('configures all HTTP stores and passes app validators through', async () => {
vi.stubEnv('NEXT_PUBLIC_PERSISTENCE', '1');
vi.stubEnv('NEXT_PUBLIC_PERSISTENCE_TOKEN', 'test-dev-token');
vi.stubGlobal('window', {});
vi.stubGlobal('localStorage', memoryStorage());
const { HttpAssetStore, HttpDocumentStore } = await import('@openmaic/storage');
const { HttpRuntimeStore } = await import('@openmaic/storage/runtime/http');
// Importing either seam must structurally run bootstrap before the seam can
// resolve its default store.
const runtime = await import('@/lib/runtime/store');
const documents = await import('@/lib/document-store');
const assets = await import('@/lib/media/asset-pool');
expect(runtime.isRuntimeStorageConfigured()).toBe(true);
expect(documents.isDocumentStorageConfigured()).toBe(true);
expect(assets.isAssetPoolStorageConfigured()).toBe(true);
const runtimeStore = runtime.getRuntimeStore();
const documentStore = documents.getDocumentStore();
const assetStore = assets.getAssetPool();
expect(runtimeStore).toBeInstanceOf(HttpRuntimeStore);
expect(documentStore).toBeInstanceOf(HttpDocumentStore);
expect(assetStore).toBeInstanceOf(HttpAssetStore);
const documentInternals = documentStore as unknown as {
validateSceneFn: unknown;
validateStageFn: unknown;
};
expect(documentInternals.validateSceneFn).toBe(documents.validateAppScene);
expect(documentInternals.validateStageFn).toBe(documents.validateAppStage);
const runtimeHeaders = await (
runtimeStore as unknown as {
headersHook: (context: { method: string; path: string }) => Promise<HeadersInit>;
}
).headersHook({ method: 'GET', path: '/runtime/sessions/example' });
expect(new Headers(runtimeHeaders).get('authorization')).toBe('Bearer test-dev-token');
expect(new Headers(runtimeHeaders).get('x-learner-key')).toMatch(/^anon:/);
const assetHeaders = await (
assetStore as unknown as {
headersHook: (context: { method: string; path: string }) => Promise<HeadersInit>;
}
).headersHook({ method: 'GET', path: '/assets/example/content' });
expect(new Headers(assetHeaders).get('authorization')).toBe('Bearer test-dev-token');
expect(new Headers(assetHeaders).get('x-learner-key')).toMatch(/^anon:/);
runtime.resetRuntimeStorageForTests();
documents.resetDocumentStorageForTests();
assets.resetAssetPoolStorageForTests();
expect(runtime.isRuntimeStorageConfigured()).toBe(false);
expect(documents.isDocumentStorageConfigured()).toBe(false);
expect(assets.isAssetPoolStorageConfigured()).toBe(false);
});
it('does not run client configuration during server module evaluation', async () => {
vi.stubEnv('NEXT_PUBLIC_PERSISTENCE', '1');
const runtime = await import('@/lib/runtime/store');
const documents = await import('@/lib/document-store');
const assets = await import('@/lib/media/asset-pool-config');
expect(runtime.isRuntimeStorageConfigured()).toBe(false);
expect(documents.isDocumentStorageConfigured()).toBe(false);
expect(assets.isAssetPoolStorageConfigured()).toBe(false);
});
it('preflights both seams so a failure cannot partially configure bootstrap', async () => {
vi.stubEnv('NEXT_PUBLIC_PERSISTENCE', '1');
vi.stubGlobal('window', {});
const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
const documents = await import('@/lib/document-store/config');
documents.configureDocumentStorage({});
const runtime = await import('@/lib/runtime/store');
const assets = await import('@/lib/media/asset-pool-config');
expect(runtime.isRuntimeStorageConfigured()).toBe(false);
expect(documents.isDocumentStorageConfigured()).toBe(true);
expect(assets.isAssetPoolStorageConfigured()).toBe(false);
expect(errorSpy).toHaveBeenCalledOnce();
expect(errorSpy.mock.calls[0]?.[0]).toContain('FATAL');
});
});