Skip to content

Commit b813785

Browse files
Copilothotlong
andcommitted
test: add WASM driver tests for environment detection and driver metadata
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 44a00db commit b813785

2 files changed

Lines changed: 418 additions & 0 deletions

File tree

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
/**
2+
* ObjectQL
3+
* Copyright (c) 2026-present ObjectStack Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
import { describe, it, expect, vi, afterEach } from 'vitest';
10+
import { checkWebAssembly, checkIndexedDB, checkOPFS, detectStorageBackend } from './environment.js';
11+
import { PgWasmDriver } from './index.js';
12+
13+
// ---------------------------------------------------------------------------
14+
// Environment Detection Utilities
15+
// ---------------------------------------------------------------------------
16+
17+
describe('pg-wasm / environment', () => {
18+
describe('checkWebAssembly', () => {
19+
afterEach(() => {
20+
vi.restoreAllMocks();
21+
});
22+
23+
it('should not throw when WebAssembly is available', () => {
24+
// Node.js ships with WebAssembly support
25+
expect(() => checkWebAssembly()).not.toThrow();
26+
});
27+
28+
it('should throw ObjectQLError when WebAssembly is unavailable', () => {
29+
const original = globalThis.WebAssembly;
30+
try {
31+
Object.defineProperty(globalThis, 'WebAssembly', {
32+
value: undefined,
33+
configurable: true,
34+
});
35+
expect(() => checkWebAssembly()).toThrowError('WebAssembly is not supported');
36+
} finally {
37+
Object.defineProperty(globalThis, 'WebAssembly', {
38+
value: original,
39+
configurable: true,
40+
});
41+
}
42+
});
43+
44+
it('should throw an error with code ENVIRONMENT_ERROR', () => {
45+
const original = globalThis.WebAssembly;
46+
try {
47+
Object.defineProperty(globalThis, 'WebAssembly', {
48+
value: undefined,
49+
configurable: true,
50+
});
51+
try {
52+
checkWebAssembly();
53+
} catch (err: any) {
54+
expect(err.code).toBe('ENVIRONMENT_ERROR');
55+
}
56+
} finally {
57+
Object.defineProperty(globalThis, 'WebAssembly', {
58+
value: original,
59+
configurable: true,
60+
});
61+
}
62+
});
63+
});
64+
65+
describe('checkIndexedDB', () => {
66+
it('should return false in Node.js (no indexedDB global)', async () => {
67+
const result = await checkIndexedDB();
68+
expect(result).toBe(false);
69+
});
70+
71+
it('should return a boolean value', async () => {
72+
const result = await checkIndexedDB();
73+
expect(typeof result).toBe('boolean');
74+
});
75+
});
76+
77+
describe('checkOPFS', () => {
78+
it('should return false in Node.js (no navigator)', async () => {
79+
const result = await checkOPFS();
80+
expect(result).toBe(false);
81+
});
82+
83+
it('should return a boolean value', async () => {
84+
const result = await checkOPFS();
85+
expect(typeof result).toBe('boolean');
86+
});
87+
});
88+
89+
describe('detectStorageBackend', () => {
90+
it('should return "memory" in Node.js (no browser APIs)', async () => {
91+
const backend = await detectStorageBackend();
92+
expect(backend).toBe('memory');
93+
});
94+
95+
it('should return a valid storage type', async () => {
96+
const backend = await detectStorageBackend();
97+
expect(['idb', 'opfs', 'memory']).toContain(backend);
98+
});
99+
});
100+
});
101+
102+
// ---------------------------------------------------------------------------
103+
// PgWasmDriver — Metadata & Capabilities
104+
// ---------------------------------------------------------------------------
105+
106+
describe('PgWasmDriver', () => {
107+
describe('instantiation', () => {
108+
it('should instantiate with default config', () => {
109+
const driver = new PgWasmDriver();
110+
expect(driver).toBeDefined();
111+
});
112+
113+
it('should accept custom configuration', () => {
114+
const driver = new PgWasmDriver({
115+
storage: 'memory',
116+
database: 'testdb',
117+
extensions: ['vector'],
118+
});
119+
expect(driver).toBeDefined();
120+
});
121+
122+
it('should accept partial configuration', () => {
123+
const driver = new PgWasmDriver({ database: 'custom' });
124+
expect(driver).toBeDefined();
125+
});
126+
});
127+
128+
describe('metadata', () => {
129+
const driver = new PgWasmDriver({ storage: 'memory' });
130+
131+
it('should expose driver name', () => {
132+
expect(driver.name).toBe('PgWasmDriver');
133+
});
134+
135+
it('should expose driver version', () => {
136+
expect(driver.version).toBe('4.2.0');
137+
});
138+
139+
it('should expose a supports/capabilities object', () => {
140+
expect(driver.supports).toBeDefined();
141+
expect(typeof driver.supports).toBe('object');
142+
});
143+
});
144+
145+
describe('capabilities', () => {
146+
const driver = new PgWasmDriver({ storage: 'memory' });
147+
const caps = driver.supports;
148+
149+
it('should support basic CRUD operations', () => {
150+
expect(caps.create).toBe(true);
151+
expect(caps.read).toBe(true);
152+
expect(caps.update).toBe(true);
153+
expect(caps.delete).toBe(true);
154+
});
155+
156+
it('should support bulk operations', () => {
157+
expect(caps.bulkCreate).toBe(true);
158+
expect(caps.bulkUpdate).toBe(true);
159+
expect(caps.bulkDelete).toBe(true);
160+
});
161+
162+
it('should support transactions and savepoints', () => {
163+
expect(caps.transactions).toBe(true);
164+
expect(caps.savepoints).toBe(true);
165+
});
166+
167+
it('should support isolation levels', () => {
168+
expect(caps.isolationLevels).toBeDefined();
169+
expect(Array.isArray(caps.isolationLevels)).toBe(true);
170+
expect(caps.isolationLevels).toContain('serializable');
171+
expect(caps.isolationLevels).toContain('read_committed');
172+
});
173+
174+
it('should support JSON query and JSON fields', () => {
175+
expect(caps.jsonQuery).toBe(true);
176+
expect(caps.jsonFields).toBe(true);
177+
});
178+
179+
it('should support array fields', () => {
180+
expect(caps.arrayFields).toBe(true);
181+
});
182+
183+
it('should NOT support streaming', () => {
184+
expect(caps.streaming).toBe(false);
185+
});
186+
187+
it('should support query features', () => {
188+
expect(caps.queryFilters).toBe(true);
189+
expect(caps.queryAggregations).toBe(true);
190+
expect(caps.querySorting).toBe(true);
191+
expect(caps.queryPagination).toBe(true);
192+
});
193+
194+
it('should support advanced SQL features', () => {
195+
expect(caps.queryWindowFunctions).toBe(true);
196+
expect(caps.querySubqueries).toBe(true);
197+
expect(caps.queryCTE).toBe(true);
198+
expect(caps.joins).toBe(true);
199+
});
200+
201+
it('should support full-text search', () => {
202+
expect(caps.fullTextSearch).toBe(true);
203+
});
204+
205+
it('should support schema management', () => {
206+
expect(caps.schemaSync).toBe(true);
207+
expect(caps.migrations).toBe(true);
208+
expect(caps.indexes).toBe(true);
209+
});
210+
211+
it('should support prepared statements but not connection pooling', () => {
212+
expect(caps.preparedStatements).toBe(true);
213+
expect(caps.connectionPooling).toBe(false);
214+
});
215+
216+
it('should NOT support query cache', () => {
217+
expect(caps.queryCache).toBe(false);
218+
});
219+
});
220+
});

0 commit comments

Comments
 (0)