Skip to main content
@craft-ts
LearnLearn with EffectAI agentsGuideReference
@craft-ts/core@craft-ts/component@craft-ts/dev-tools@craft-ts/effect@craft-ts/style@craft-ts/style-testing@craft-ts/i18n@craft-ts/i18n-effect@craft-ts/mcp
ExamplesMigrationEffect compatibility & maturityAdopting CraftTS progressivelyPress kitRoadmapBacklog
Beta
  • Learn
  • Learn with Effect
  • AI agents
  • Guide
  • Reference
  • Packages
  • Resources

i.Learn with Effect

  • Effect users: start here
  • Overview
  • 1. Start with a Craft component
  • 2. Derive UI state
  • 3. Put the domain in Effect
  • 4. Load data with Effect
  • 5. Write data with Effect
  • 6. Provide Layers and route the app
  • 7. Build forms and validate boundaries
  • 8. Test the graph
  • 9. Server functions — POC
  1. Learn with Effect
  2. 8. Test the graph

8. Test the graph#

Goal: test Effect programs, their Layers and the Craft boundary without mocking the whole application.

Test an Effect service with a partial mock#

mockEffectService provides a Layer and makes every unstubbed member fail loudly if the test accidentally uses it:

typescript
import { Effect } from 'effect';
import { mockEffectService } from '@craft-ts/effect';

const register = {
  AccessPolicyService: mockEffectService(AccessPolicyService, {
    decide: () => Effect.succeed(expectedDecision),
  }),
};

For production-like tests, provide the real Layer. For focused tests, stub only the selected members and let UnstubbedEffectMember expose an unexpected read.

Test the Craft service or component by register#

Craft tests still use a register derived from the Craft dependency graph:

typescript
const { sut } = await setupCraftServiceTestingByRegister(
  AccessDecisionService,
  {
    AccessPolicyService: mockEffectService(AccessPolicyService, {
      decide: () => Effect.succeed(expectedDecision),
    }),
  },
);

The exact register also includes regular Craft services, 'real', 'notReached' or provideX() entries when those nodes are reachable. Effect service mocks cover the Effect side; the Craft register proves the full graph is accounted for.

Test the bridge and adapters#

Install and dispose the bridge per test suite:

typescript
let dispose: () => void;

beforeEach(() => {
  dispose = installCraftEffectBridge();
});

afterEach(() => {
  dispose();
});

Cover at least one example of each channel: a typed failure becomes a Craft exception, Effect.die rejects as a technical error, and aborting the owning resource interrupts the Effect.

Architecture checks#

The static graph includes the Effect backend automatically when analyzeDependencyGraph runs. It exposes typed nodes for effect-service, effect-operation and effect-layer, together with requires-service, provided-by-layer and composes-layer relations. You can therefore write rules against Effect concepts just as you do against Craft nodes:

typescript
const effectServices = graph.nodes('effect-service');
const effectOperations = graph.nodes('effect-operation');
const effectLayers = graph.nodes('effect-layer');
const serviceRequirements = graph.edges('requires-service');

The built-in checks can then be kept beside the app's architecture tests:

typescript
assertCraftEffectNoNetwork(graph.graph);
assertCraftEffectNoImperativeSync(graph.graph);
assertDeclarativeArchitecture(graph.graph);

For a project-specific invariant, inspect these typed nodes and relations in a custom assertion and fail the architecture test when the rule is violated. If you need to add concepts that the built-in Effect backend does not model, use the DependencyGraphNodeRegistry and DependencyGraphCollector. The Effect graph is already collected; no extra collector is needed just to apply rules to its services, operations or Layers.

What you gained#

Tests that mirror the real Craft and Effect graphs: real composition by default, narrow mocks at the boundary, and architecture rules for the invariants that types alone cannot keep armed.

← 7. Build forms and validate boundaries

9. Call server functions — POC →

←7. Build forms and validate boundaries9. Server functions — POC→

On this page

  • Test an Effect service with a partial mock
  • Test the Craft service or component by register
  • Test the bridge and adapters
  • Architecture checks
  • What you gained

@craft-ts · MIT licensed

GitHubnpm

Search