Testing your integration
selfstore is designed to be tested without a browser and without mocking any of its internals.
The simple store just runs
Where there is no IndexedDB (vitest, SSR), selfstore(app) lands on an
in-memory cache automatically. So this is a real test, no setup, no mocks:
import { describe, expect, it } from 'vitest';
import { selfstore } from 'selfstore';
it('persists and reads back', async () => {
type Todo = { id: string; text: string };
const store = await selfstore<{ todos: Todo }>('test-app');
await store.put('todos', { id: 't1', text: 'write tests' });
expect(store.all('todos')).toEqual([{ id: 't1', text: 'write tests' }]);
store.dispose();
});
It exercises the real save path, the real snapshot plumbing and the real status machine, not stand-ins. This is how selfstore tests itself (234 tests, including seeded fuzz tests on the merge).
An in-memory durable home
A BackupTarget is about fifteen lines, which turns “does my app survive backup
and restore” into a plain unit test. On the advanced surface:
import { createLocalStore, memoryCache } from 'selfstore/advanced';
import type { BackupTarget } from 'selfstore/advanced';
function memoryTarget() {
let stored: Blob | null = null;
let version = 0;
const target: BackupTarget = {
kind: 'memory',
label: 'in-memory (tests)',
async save(blob) { stored = blob; return String(++version); },
async load() { return stored; },
async stat() { return stored ? String(version) : null; },
async isReady() { return true; },
async reconnect() { return true; },
async disconnect() {},
};
return target;
}
Attach it to a simple store with store.connectTarget(memoryTarget()), or to a
createLocalStore store with attachTarget, then assert on the full loop. Two
devices in one test: two stores over two memoryCache() instances, pointed at
the same memoryTarget(), each calling sync(). That is a complete
multi-device convergence test in plain vitest, milliseconds to run.
The format layer needs no store at all
backup(...), restore(...), changePassword(...) take and return blobs, so
testing an import/export feature is just calling them. If you need reference
files, the
canonical vectors
in the library repository are maintained for exactly that.