Search selfstore
v1.8.21

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.