DraftThis article is currently in draft mode

Blog Content Test (TodoVM Focused)

Adaptations
Original jotai
TXT
Phosphor Team
Cole Lawrence
October 17, 2025

Table of Contents

Blog Content Test#

Interface

export type TodoItemVM = {
  key: string;
  text$: Queryable<string>; 
  completed$: Queryable<boolean>; 
  toggleCompleted: () => void; 
  remove: () => void; 
};

export type TodoListVM = {
  header: {
    newTodoText$: Queryable<string>; 
    updateNewTodoText: (text: string) => void; 
    addTodo: () => void; 
  };
  itemList: {
    items$: Queryable<TodoItemVM[]>; 
  };
  footer: {
    incompleteDisplayText$: Queryable<string>; 
    currentFilter$: Queryable<"all" | "active" | "completed">; 
    showAll: () => void; 
    showActive: () => void; 
    showCompleted: () => void; 
    clearCompleted: () => void; 
  };
  reset: () => void;
};

React Code

Todo List View

const items = liveStore.query(vm.itemList.items$);

// Assert the number of items using toHaveLength for better test errors
expect(items).toHaveLength(1);

// Assert on the first item's text and completed value with expect matchers
expect(liveStore.query(items[0].text$)).toBe("Buy milk");
expect(liveStore.query(items[0].completed$)).toBe(false);

Todo List Full Test
And if you're curious about the full test harness for the Todo List, I've included the source file below.
import { makeInMemoryAdapter } from "@livestore/adapter-web";
import { type Store, createStorePromise } from "@livestore/livestore";
import { LogLevel } from "effect";
import { afterAll, beforeAll, describe, expect, it } from "vitest";
import { schema } from "#sources/view-model-interfaces/todo-vm/livestore/schema.ts";
import { type TodoListVM, createTodoListScope } from "#sources/view-model-interfaces/todo-vm/scope.ts";

// Guided by @docs/vitest-guidelines.md
describe("TodoListVM Integration", () => {
  let liveStore: Store<typeof schema>;
  let vm: TodoListVM;

  beforeAll(async () => {
    liveStore = await createStorePromise({
      schema: schema,
      adapter: makeInMemoryAdapter(),
      storeId: "todo-list-test-store",
      logLevel: LogLevel.Warning,
    });
    vm = createTodoListScope(liveStore);
  });

  afterAll(async () => {
    await liveStore.shutdownPromise();
  });

  it("should return initial todo item values correctly", () => {
    const items = liveStore.query(vm.itemList.items$);

    // Assert the number of items using toHaveLength for better test errors
    expect(items).toHaveLength(1);

    // Assert on the first item's text and completed value with expect matchers
    expect(liveStore.query(items[0].text$)).toBe("Buy milk");
    expect(liveStore.query(items[0].completed$)).toBe(false);
  });
});