import { createPinia, setActivePinia } from 'pinia'; import { createRouter, createMemoryHistory } from 'vue-router'; import { LocalizedConcept } from 'glossarist'; import type { Manifest, ConceptSummary, SearchHit } from '../adapters/types'; import { ReferenceResolver } from '../adapters/ReferenceResolver'; import { UriRouter } from '../adapters/UriRouter'; // ── Manifest Factory ────────────────────────────────────────────────── const STUB_COMPONENT = { template: '
' }; export function makeManifest(overrides: Partial = {}): Manifest { return { id: 'test', datasetUri: 'https://glossarist.org/test/concept', title: 'Test Dataset', description: 'A test dataset', owner: 'ISO', baseUrl: '/data/test', languages: ['eng'], conceptCount: 10, conceptUrlTemplate: '/data/test/concepts/{id}.json', indexUrl: '/data/test/index.json', contextUrl: '/data/test/context.json', uriBase: 'https://glossarist.org', status: 'published', schemaVersion: '1.0', tags: [], lastUpdated: '2025-01-01', sourceRepo: 'https://example.com/repo', chunkSize: 1000, color: '#3366ff', ...overrides, }; } // ── Adapter Stub ────────────────────────────────────────────────────── export interface AdapterStubOptions { concepts?: ConceptSummary[]; manifest?: Manifest | null; search?: () => SearchHit[]; fetchConcept?: () => Promise; getAdjacentConcepts?: () => { prev: string | null; next: string | null }; getConceptPosition?: () => number; isRangeLoaded?: () => boolean; ensureChunksForRange?: () => Promise; ensureAllChunksLoaded?: () => Promise; extractEdges?: () => any[]; extractDomainEdges?: () => any[]; getIndexEntry?: () => any; loadEdgeIndex?: () => Promise; loadDomainNodes?: () => Promise; } export function makeAdapterStub(options: AdapterStubOptions = {}): any { return { index: options.concepts ?? [], manifest: options.manifest ?? makeManifest(), registerId: 'test', getConceptCount: () => (options.concepts ?? []).length, getConcepts: () => options.concepts ?? [], search: options.search ?? (() => []), fetchConcept: options.fetchConcept ?? (() => Promise.resolve(null)), getAdjacentConcepts: options.getAdjacentConcepts ?? (() => ({ prev: null, next: null })), getConceptPosition: options.getConceptPosition ?? (() => -1), isRangeLoaded: options.isRangeLoaded ?? (() => true), ensureChunksForRange: options.ensureChunksForRange ?? (() => Promise.resolve()), ensureAllChunksLoaded: options.ensureAllChunksLoaded ?? (() => Promise.resolve()), extractEdges: options.extractEdges ?? (() => []), extractDomainEdges: options.extractDomainEdges ?? (() => []), getIndexEntry: options.getIndexEntry ?? (() => null), loadEdgeIndex: options.loadEdgeIndex ?? (() => Promise.resolve([])), loadDomainNodes: options.loadDomainNodes ?? (() => Promise.resolve([])), }; } // ── Concept Data Factories ──────────────────────────────────────────── export function makeLocalizedConcept(overrides: Record = {}): LocalizedConcept { return LocalizedConcept.fromJSON({ language_code: 'eng', entry_status: 'valid', terms: [{ type: 'expression', designation: 'test term' }], ...overrides, }); } export function makeConceptSummary(overrides: Partial = {}): ConceptSummary { return { id: '1', designations: { eng: 'test concept' }, eng: 'test concept', status: 'valid', ...overrides, }; } export function makeSearchHit(overrides: Partial = {}): SearchHit { return { conceptId: '1', registerId: 'test', designation: 'test', language: 'eng', matchField: 'designation', ...overrides, }; } // ── Router Factory ──────────────────────────────────────────────────── export type RouteSet = 'minimal' | 'search' | 'dataset' | 'full' | 'resolve' | 'news' | 'pages' | 'contributors' | 'graph'; const ROUTE_SETS: Record = { minimal: [{ path: '/', name: 'home', component: STUB_COMPONENT }], search: [ { path: '/', name: 'home', component: STUB_COMPONENT }, { path: '/search', name: 'search', component: STUB_COMPONENT }, ], dataset: [ { path: '/', name: 'home', component: STUB_COMPONENT }, { path: '/dataset/:registerId', name: 'dataset', component: STUB_COMPONENT }, { path: '/dataset/:registerId/concept/:conceptId', name: 'concept', component: STUB_COMPONENT }, { path: '/dataset/:registerId/stats', name: 'stats', component: STUB_COMPONENT }, { path: '/dataset/:registerId/about', name: 'about', component: STUB_COMPONENT }, ], full: [ { path: '/', name: 'home', component: STUB_COMPONENT }, { path: '/dataset/:registerId', name: 'dataset', component: STUB_COMPONENT }, { path: '/dataset/:registerId/concept/:conceptId', name: 'concept', component: STUB_COMPONENT }, { path: '/dataset/:registerId/stats', name: 'stats', component: STUB_COMPONENT }, { path: '/dataset/:registerId/about', name: 'about', component: STUB_COMPONENT }, { path: '/search', name: 'search', component: STUB_COMPONENT }, { path: '/graph', name: 'graph', component: STUB_COMPONENT }, ], resolve: [ { path: '/', name: 'home', component: STUB_COMPONENT }, { path: '/dataset/:registerId/concept/:conceptId', name: 'concept', component: STUB_COMPONENT }, { path: '/resolve/:uri(.*)', name: 'resolve', component: STUB_COMPONENT }, ], news: [ { path: '/', name: 'home', component: STUB_COMPONENT }, { path: '/news', name: 'news', component: STUB_COMPONENT }, ], pages: [ { path: '/', name: 'home', component: STUB_COMPONENT }, { path: '/pages/:slug', name: 'page', component: STUB_COMPONENT }, ], contributors: [ { path: '/', name: 'home', component: STUB_COMPONENT }, { path: '/contributors', name: 'contributors', component: STUB_COMPONENT }, ], graph: [ { path: '/', name: 'home', component: STUB_COMPONENT }, { path: '/graph', name: 'graph', component: STUB_COMPONENT }, ], }; export async function createTestRouter( routeSet: RouteSet = 'minimal', initialPath = '/', ) { const router = createRouter({ history: createMemoryHistory(), routes: ROUTE_SETS[routeSet], }); router.push(initialPath); await router.isReady(); return router; } // ── Pinia Setup ─────────────────────────────────────────────────────── export function setupPinia() { const pinia = createPinia(); setActivePinia(pinia); return pinia; } // ── ReferenceResolver Setup ────────────────────────────────────────── export interface ResolverPair { uriRouter: UriRouter; resolver: ReferenceResolver; } /** * Create a UriRouter + ReferenceResolver pair for testing. * Use `pair.uriRouter.registerDataset()` to register URI patterns, * then use `pair.resolver` for reference resolution. */ export function createResolverPair(): ResolverPair { const uriRouter = new UriRouter(); const resolver = new ReferenceResolver(uriRouter); return { uriRouter, resolver }; }