jazz-testing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Jazz Testing

Jazz 测试

When to Use This Skill

何时使用该技能

  • Writing unit or integration tests for apps using Jazz
  • Simulating synchronisation for testing purposes
  • Verifying permissions and security logic
  • Testing UI components in various application states (Guest/Anonymous/Authenticated/Online/Offline)
  • Debugging failing tests
  • 为使用Jazz的应用编写单元测试或集成测试
  • 出于测试目的模拟同步功能
  • 验证权限和安全逻辑
  • 在多种应用状态(访客/匿名/已认证/在线/离线)下测试UI组件
  • 调试运行失败的测试

Do NOT Use This Skill For

请勿将该技能用于

  • Designing the initial data schema (use
    jazz-schema-design
  • General React/Svelte UI layout questions unrelated to Jazz (for questions on Jazz integration with React/Svelte, use the
    jazz-ui-development
    skill)
  • 设计初始数据schema(请使用
    jazz-schema-design
    技能)
  • 与Jazz无关的通用React/Svelte UI布局问题(关于Jazz与React/Svelte集成的问题,请使用
    jazz-ui-development
    技能)

Key Heuristic for Agents

Agent的关键启发规则

If you are about to suggest "mocking" any part of the data layer in the user's application, STOP and invoke this skill instead. This skill enforces the use of the official in-memory test sync node.
如果你打算建议对用户应用的数据层的任何部分进行「模拟(mocking)」,请立即停止并调用本技能。该技能要求使用官方的内存测试同步节点。

Core Concepts

核心概念

Testing in Jazz requires understanding identity-based context and authentic synchronization. The framework's collaborative nature means tests must simulate real multi-user scenarios rather than mocking the sync layer.
Jazz中的测试需要理解基于身份的上下文和真实同步机制。该框架的协作特性意味着测试必须模拟真实的多用户场景,而不是模拟同步层。

Fundamental Principles

基本原则

  • NEVER Mock the Sync Layer: Avoid using generic mocking libraries (like Jest/Vitest mocks) for 'jazz-tools'
  • In-Memory Synchronization: Always use a real in-memory sync node via
    setupJazzTestSync()
    to allow authentic data flow between test identities
  • Identity-Based Context: Testing in Jazz is about "who" is performing the action. Manage the "Active Account" explicitly to verify permissions and ownership
  • 永远不要模拟同步层:避免为
    jazz-tools
    使用通用模拟库(比如Jest/Vitest模拟能力)
  • 内存同步:始终通过
    setupJazzTestSync()
    使用真实的内存同步节点,以实现测试身份之间的真实数据流
  • 基于身份的上下文:Jazz中的测试核心是「谁」在执行操作。显式管理「活跃账户」以验证权限和所有权

Test Environment Setup

测试环境设置

The virtual sync node must be initialized before tests run. It handles data synchronization in-memory and requires no manual cleanup between runs.
Example Setup:
ts
import { setupJazzTestSync } from "jazz-tools/testing";
import { beforeEach, describe } from "vitest";

describe("Jazz Feature Test", () => {
  beforeEach(async () => {
    await setupJazzTestSync();
  });
});
虚拟同步节点必须在测试运行前初始化。它会在内存中处理数据同步,测试运行之间无需手动清理。
设置示例:
ts
import { setupJazzTestSync } from "jazz-tools/testing";
import { beforeEach, describe } from "vitest";

describe("Jazz Feature Test", () => {
  beforeEach(async () => {
    await setupJazzTestSync();
  });
});

Identity & Account Management

身份与账户管理

Testing in Jazz requires simulating multiple users to verify synchronization and security.
Jazz中的测试需要模拟多个用户,以验证同步逻辑和安全性。

createJazzTestAccount

createJazzTestAccount

Used to create user accounts linked to the sync node.
  • AccountSchema
    : Pass your custom co.account schema
  • isCurrentActiveAccount
    : Set to true to automatically log the test runner into this account
  • creationProps
    : Data passed to the account's migration function on creation if required
用于创建绑定到同步节点的用户账户。
  • AccountSchema
    :传入你自定义的co.account schema
  • isCurrentActiveAccount
    :设置为true可自动将测试运行器登录到该账户
  • creationProps
    :如果需要,可传入账户创建时迁移函数所需的数据

setActiveAccount

setActiveAccount

Used to switch between different users within a single test.
  • Pattern: Create Account A -> Create Data -> Switch to Account B -> Attempt to Load/Modify Data
  • Note: Once a CoValue is loaded, the permission context for that CoValue instance is fixed. Always use
    .load(id)
    after switching accounts to load a new CoValue instance with the new permission context for that specific user
用于在单条测试中切换不同用户身份。
  • 模式:创建账户A -> 创建数据 -> 切换到账户B -> 尝试加载/修改数据
  • 注意: 一旦CoValue被加载,该CoValue实例的权限上下文就固定了。切换账户后请始终使用
    .load(id)
    加载新的CoValue实例,以获取对应用户的新权限上下文

UI & Context Testing

UI与上下文测试

UI tests must render components and hooks inside a Jazz-aware test harness (e.g. framework-specific render utilities that inject account, connection state, and sync context). In UI tests, assert observable loading state transitions, not internal CoValue mechanics.
UI测试必须在支持Jazz的测试工具中渲染组件和钩子(例如框架专属的渲染工具,可注入账户、连接状态和同步上下文)。在UI测试中,应当断言可观测的加载状态转换,而非内部CoValue的运行机制。

React

React

  • Refer to the React provider and the context provided to it to see how to create a suitable harness for React tests.
参考React provider注入的上下文,了解如何为React测试创建合适的测试工具。

Svelte

Svelte

  • Refer to the Svelte provider and the context provided to it to see how to create a suitable harness for Svelte tests.
Use the
jazz-ui-development
skill for questions on Jazz integration with React/Svelte.
参考Svelte provider注入的上下文,了解如何为Svelte测试创建合适的测试工具。
关于Jazz与React/Svelte集成的问题,请使用
jazz-ui-development
技能。

Common Testing Patterns

常见测试模式

Verifying Unauthorized Writes

验证未授权写入行为

ts
const account1 = await createJazzTestAccount({ isCurrentActiveAccount: true });
const account2 = await createJazzTestAccount();

// Setup restricted group
const group = co.group().create();
group.addMember(account2, "reader");

const myMap = MyMap.create({ text: "Hi" }, { owner: group });
const mapId = myMap.$jazz.id;

// Switch to reader
setActiveAccount(account2);
// You *must* reload the CoValue with the new active account
const mapAsReader = await MyMap.load(mapId);

// Verify enforcement
expect(() => mapAsReader.$jazz.set("text", "some text")).toThrow();

// Note: myMap.$jazz.set() would *not* throw, as it was loaded with account1 as the active account
ts
const account1 = await createJazzTestAccount({ isCurrentActiveAccount: true });
const account2 = await createJazzTestAccount();

// 设置受限用户组
const group = co.group().create();
group.addMember(account2, "reader");

const myMap = MyMap.create({ text: "Hi" }, { owner: group });
const mapId = myMap.$jazz.id;

// 切换到读者身份
setActiveAccount(account2);
// 你*必须*使用新的活跃账户重新加载CoValue
const mapAsReader = await MyMap.load(mapId);

// 验证权限校验生效
expect(() => mapAsReader.$jazz.set("text", "some text")).toThrow();

// 注意:myMap.$jazz.set() *不会*抛出异常,因为它是在账户1为活跃账户时加载的

Testing Behavior without an Active Account

测试无活跃账户时的行为

ts
runWithoutActiveAccount(() => {
  // Verify that protected actions fail when no account is active
  expect(() => co.group().create()).toThrow();
});
ts
runWithoutActiveAccount(() => {
  // 验证无活跃账户时受保护的操作会失败
  expect(() => co.group().create()).toThrow();
});

Common Pitfalls to Avoid

需要避免的常见陷阱

  • CoValues not reloaded when active account changes: CoValues are always loaded with the active account at the time the CoValue is loaded, and this does not change even if the active account changes. CoValues loaded while
    account1
    is the currently active account do not update their local permissions when
    setActiveAccount(account2)
    is called; you MUST
    .load()
    a new instance of the CoValue
  • Missing Sync Setup: Ensure
    setupJazzTestSync()
    is called
  • Attempting to test UI components outside of a Jazz context: Components relying on Jazz must have access to a Jazz context. Patterns for creating test contexts can be found in the framework-specific tests links
  • 活跃账户变更时未重新加载CoValue:CoValue始终是在加载时的活跃账户上下文下加载的,即便后续活跃账户变更也不会改变。当
    account1
    为活跃账户时加载的CoValue,在调用
    setActiveAccount(account2)
    后不会更新本地权限,你必须调用
    .load()
    获取新的CoValue实例
  • 缺少同步节点初始化:确保已经调用了
    setupJazzTestSync()
  • 尝试在Jazz上下文外测试UI组件:依赖Jazz的组件必须能访问Jazz上下文。创建测试上下文的模式可以在框架专属的测试链接中找到

Quick Reference

快速参考

Account switching: Always reload CoValues after
setActiveAccount()
to get new permission context.
Sync setup: Call
setupJazzTestSync()
in
beforeEach
for all Jazz tests.
UI testing: Use a framework-specific Jazz test harness built on
TestJazzContextManager
.
账户切换: 调用
setActiveAccount()
后始终要重新加载CoValue,以获取新的权限上下文。
同步节点设置: 所有Jazz测试的
beforeEach
钩子中都要调用
setupJazzTestSync()
UI测试: 使用基于
TestJazzContextManager
构建的框架专属Jazz测试工具。

References

参考资料

Load these on demand, based on need:
When using an online reference via a skill, cite the specific URL to the user to build trust.
按需加载以下资源:
通过技能调用在线参考资料时,请向用户提供具体的URL以建立信任。