📄 src/models/test/session.test.ts
D-OPEN SOVEREIGN
1/*
2 * Copyright (c) 2026 DataPond D-Library Pty Ltd. ("The Sanctuary")
3 * Non-Profit Public Library — The World Library
4 *
5 * D-SAFE Certification issued by POND Enterprise.
6 * Published under the D-Open Code Sovereign Licence v1.0 framework
7 * DataPond D-Library All exclusive Right reserved on modifiying the code - CC Attribution to data pond, Non modifiable, Non Commercial.
8 * https://registry.world.bibliotech.com/licence
9 * Source code donated to DataPond D-Library by it's author: data pond.
10 *
11 * Technical Guardian ("The Shield"): Pond Enterprise Pty Ltd. (ACN 694 747 987)
12 * All liability claims about D-SAFE certification issues coming from the published D-Safe direction must be addressed with Pond Enterprise Pty Ltd.
13 * Code Modification automatically voids the certified liability protection provided by Pond Enterprise.
14 */
15import 'fake-indexeddb/auto';
16import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
17import { bootModelsV2, loadLanguage, hasLang, bootstrapSession, resetModelsV2Session, localSidecarUrls, registrySidecarUrls } from '../session.ts';
18import { Book, NewBookWithId } from '../generated-src/Book.ts';
19import * as workerPatchMain from '../worker-patch-main.ts';
20import { clear, configureDb } from '../db.ts';
21
22// Mock the worker methods to avoid spinning up actual workers
23vi.mock('../worker-patch-main.ts', () => {
24 return {
25 InitPatchWorker: async () => ({
26 sidecars: [],
27 patches: { mine: [] }
28 }),
29 LoadLanguageWorkerCmd: async () => ({
30 sidecars: []
31 })
32 };
33});
34
35describe('session.ts', () => {
36 beforeEach(() => {
37 resetModelsV2Session();
38 clear();
39 configureDb({ cacheLimit: 2 });
40 // @ts-ignore
41 globalThis.fetch = vi.fn().mockResolvedValue({
42 ok: true,
43 json: async () => ({
44 objects: {
45 [Book.type]: {
46 tiers: {
47 slim: [{ file: 'eng_slim.bin' }]
48 }
49 }
50 }
51 })
52 });
53 });
54
55 afterEach(() => {
56 vi.restoreAllMocks();
57 });
58
59 it('localSidecarUrls generates correct URLs', () => {
60 const manifest = {
61 objects: {
62 '0': {
63 tiers: {
64 slim: [{ file: 'eng_slim.bin' }],
65 extended: [{ file: 'eng_extended.bin' }],
66 prov: [{ file: 'eng_prov.bin' }]
67 }
68 }
69 }
70 };
71 const urls = localSidecarUrls('/base', manifest, ['eng']);
72 expect(urls.length).toBe(1);
73 expect(urls[0].slimUrl).toBe('/base/eng_slim.bin');
74 expect(urls[0].extendedUrl).toBe('/base/eng_extended.bin');
75 expect(urls[0].provUrl).toBe('/base/eng_prov.bin');
76 });
77
78 it('registrySidecarUrls generates correct URLs', () => {
79 const dataBlock = {
80 objects: {
81 '0': {
82 'eng': {
83 slim: ['tx-slim'],
84 extended: ['tx-ext'],
85 prov: ['tx-prov']
86 }
87 }
88 }
89 };
90 const urls = registrySidecarUrls(dataBlock, ['eng'], 'https://arweave.net');
91 expect(urls.length).toBe(1);
92 expect(urls[0].slimUrl).toBe('https://arweave.net/tx-slim');
93 expect(urls[0].extendedUrl).toBe('https://arweave.net/tx-ext');
94 expect(urls[0].provUrl).toBe('https://arweave.net/tx-prov');
95 });
96
97 it('bootModelsV2 boots correctly in localMode', async () => {
98 const data = await bootModelsV2({
99 userLang: 'eng',
100 localMode: '/corpus_v2',
101 models: [{ type: Book.type, create: NewBookWithId }]
102 });
103
104 expect(data.patches.mine).toBeDefined();
105 expect(hasLang('eng')).toBe(true);
106 });
107
108 it('bootModelsV2 throws if no localMode or registry provided', async () => {
109 await expect(bootModelsV2({
110 userLang: 'eng',
111 models: []
112 } as any)).rejects.toThrow(/provide `localMode`/);
113 });
114
115 it('loadLanguage dynamically loads a new language', async () => {
116 // First boot
117 await bootModelsV2({
118 userLang: 'eng',
119 localMode: '/corpus_v2',
120 models: [{ type: Book.type, create: NewBookWithId }]
121 });
122
123 // Setup mock for fra
124 // @ts-ignore
125 globalThis.fetch.mockResolvedValueOnce({
126 ok: true,
127 json: async () => ({
128 objects: {
129 [Book.type]: {
130 tiers: {
131 slim: [{ file: 'fra_slim.bin' }]
132 }
133 }
134 }
135 })
136 });
137
138 expect(hasLang('fra')).toBe(false);
139 await loadLanguage('fra');
140 expect(hasLang('fra')).toBe(true);
141 });
142
143 it('loadLanguage throws if called before boot', async () => {
144 await expect(loadLanguage('eng')).rejects.toThrow(/before bootModelsV2/);
145 });
146
147 it('bootstrapSession installs reactivity and boots', async () => {
148 const reactivitySpy = vi.fn();
149 const initSpy = vi.fn().mockResolvedValue(undefined);
150
151 await bootstrapSession({
152 userLang: 'eng',
153 models: [],
154 init: initSpy
155 }, reactivitySpy);
156
157 expect(reactivitySpy).toHaveBeenCalled();
158 expect(initSpy).toHaveBeenCalled();
159 });
160});
161