Testing
Syncraft Labs stores state in IndexedDB, which doesn’t exist in Node.js test environments. This guide shows how to set up your test environment and write effective tests.
Test Environment Setup
Section titled “Test Environment Setup”1. Install fake-indexeddb
Section titled “1. Install fake-indexeddb”This polyfill provides an in-memory IndexedDB implementation for Node.js:
npm install -D fake-indexeddb2. Configure Vitest
Section titled “2. Configure Vitest”import { defineConfig } from "vitest/config";
export default defineConfig({ test: { environment: "jsdom", setupFiles: ["./src/__tests__/setup.ts"], },});3. Create Setup File
Section titled “3. Create Setup File”import "fake-indexeddb/auto";
// fake-indexeddb/auto sets up global indexedDB, IDBKeyRange, etc.Testing React Components
Section titled “Testing React Components”Wrapping with Provider
Section titled “Wrapping with Provider”Every test must wrap the rendered component in <SyncraftProvider>:
import { render, screen, fireEvent, waitFor } from "@testing-library/react";import { SyncraftProvider, useSync } from "@syncraft-labs/react";import { describe, it, expect } from "vitest";
interface TodoState { todos: Array<{ id: string; text: string }>;}
function TestApp() { const { data, update, isHydrating } = useSync<TodoState>("test-todos", { initialState: { todos: [] }, });
if (isHydrating) return <div>Loading…</div>;
return ( <div> <button onClick={() => update((draft) => { draft.todos.push({ id: "1", text: "Buy milk" }); }) } > Add </button> <ul> {data?.todos.map((t) => ( <li key={t.id}>{t.text}</li> ))} </ul> </div> );}
describe("TestApp", () => { it("adds a todo item optimistic update", async () => { render( <SyncraftProvider> <TestApp /> </SyncraftProvider> );
// Wait for hydration await waitFor(() => { expect(screen.queryByText("Loading…")).toBeNull(); });
// Trigger update fireEvent.click(screen.getByText("Add"));
// Verify optimistic UI update expect(screen.getByText("Buy milk")).toBeDefined(); });});Testing Vue Components
Section titled “Testing Vue Components”Use @vue/test-utils and mount with createSyncraft() plugin:
import { mount } from "@vue/test-utils";import { createSyncraft } from "@syncraft-labs/vue";import { describe, it, expect } from "vitest";import TodoComponent from "./TodoComponent.vue";
describe("TodoComponent", () => { it("renders correctly", async () => { const wrapper = mount(TodoComponent, { global: { plugins: [createSyncraft()], }, });
await wrapper.vm.$nextTick(); expect(wrapper.text()).toContain("Add Todo"); });});Resetting Registries Between Tests
Section titled “Resetting Registries Between Tests”To ensure test isolation, clean up stores between test runs:
import { beforeEach } from "vitest";import { _resetRegistry } from "@syncraft-labs/react";
beforeEach(() => { // Clear any existing store singletons // When using <SyncraftProvider>, a fresh registry is created automatically per render});