home / skills / commontoolsinc / labs / pattern-test

pattern-test skill

/.claude/skills/pattern-test

This skill helps you author and validate pattern tests in TypeScript by guiding test structure, actions, and assertions.

npx playbooks add skill commontoolsinc/labs --skill pattern-test

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
1.8 KB
---
name: pattern-test
description: Write and run pattern tests
user-invocable: false
---

Use `Skill("ct")` for ct CLI documentation when running commands.

# Test Sub-Pattern

## Prerequisite Check
Before writing tests, verify the pattern has:
- `pattern<Input, Output>()` (not single-type `pattern<State>()`)
- Actions typed as `Stream<T>` in Output interface
- Bound handlers returned from the pattern

If missing, fix the pattern first - tests can't call `.send()` without proper Output types.

## Read First
- `docs/common/workflows/pattern-testing.md` - Full test file format and prerequisites

## Test Command
```bash
deno task ct test packages/patterns/[name]/[file].test.tsx
```

## Test File Template

```tsx
import { action, computed, pattern } from "commontools";
import Pattern from "./pattern.tsx";

export default pattern(() => {
  // 1. Instantiate pattern under test
  const instance = Pattern({ /* input */ });

  // 2. Define actions (trigger events)
  const action_do_something = action(() => {
    instance.someAction.send();
  });

  // 3. Define assertions (computed booleans)
  const assert_initial_state = computed(() => instance.someField === expectedValue);
  const assert_after_action = computed(() => instance.someField === newValue);

  // 4. Return tests array
  return {
    tests: [
      { assertion: assert_initial_state },
      { action: action_do_something },
      { assertion: assert_after_action },
    ],
  };
});
```

## Key Points
- Test each sub-pattern BEFORE writing the next one
- Use `.send()` to trigger actions (requires Stream<void> in Output type)
- Use direct property access to read values (not `.get()`)
- Use `computed(() => boolean)` for assertions

## Done When
- Test file exists alongside pattern
- Tests pass
- Ready for next sub-pattern

Overview

This skill helps you write and run pattern tests for TypeScript patterns using the ct test runner. It provides a clear test file template, prerequisite checks, and the exact command to execute tests. Follow the pattern to assert state before and after actions and ensure handlers and types are correct.

How this skill works

It inspects the pattern's shape and generates a minimal test scaffold: instantiate the pattern, define action triggers, create computed boolean assertions, and return an ordered tests array. It requires the pattern to expose Input/Output generics, Stream-typed actions in Output, and bound handlers so tests can call .send(). Use the provided test command to run individual test files.

When to use it

  • When adding or modifying a pattern implementation
  • When implementing a new sub-pattern before composing it into larger workflows
  • When an action must be tested for state transitions
  • When you need deterministic, unit-level verification of pattern handlers

Best practices

  • Verify the pattern signature has pattern<Input, Output>() and not a single-type pattern<State>()
  • Ensure all actions in Output are typed as Stream<T> so tests can call .send()
  • Return bound handlers from the pattern so tests can trigger behavior
  • Write one test file per sub-pattern and complete tests for each sub-pattern before moving on
  • Use direct property access to read instance values and computed(() => boolean) for assertions

Example use cases

  • Test a counter sub-pattern: assert initial count, send increment action, assert new count
  • Test a network-fetch sub-pattern: mock input, trigger fetch action, assert loading and result flags
  • Test a form sub-pattern: set inputs, trigger submit action, assert validation and submission state
  • Test composed patterns by testing each sub-pattern independently before integration tests

FAQ

What command runs a single pattern test file?

Use: deno task ct test packages/patterns/[name]/[file].test.tsx

How should assertions be written?

Wrap boolean checks in computed(() => boolean) and return them as assertion entries in the tests array.

Why won't .send() work in my test?

Ensure Output actions are typed as Stream<T> and the pattern returns bound handlers; otherwise .send() is not available.