ワンクリックで
effect-testing
Effect testing with @effect/vitest. Use when any test needs to run Effect programs, test errors, or provide layers.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Effect testing with @effect/vitest. Use when any test needs to run Effect programs, test errors, or provide layers.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Effect service definition, interface design, error types, retries. Use when creating new services or defining error hierarchies.
AXM - Agent Extension Manager: Use for any operation (install/create/new/edit/update/add/remove/delete/publish/find/discover) on agent skills, subagents, slash commands/stored prompts, MCP servers, context packages, rule extensions, hook extensions, or packs — e.g. "create a skill", "make a /command", "add a subagent", "build an MCP server", "publish an extension". Use this BEFORE hand-authoring or editing any SKILL.md, slash-command, subagent, MCP, rule, hook, or extension manifest file: route extension authoring through AXM instead of writing these files directly.
Native skill manifest with two unknown top-level keys.
Effect CLI + Effect architecture. Use when adding commands, defining flags, or wiring handlers. Covers file organization, argument/flag patterns, and testing.
"unterminated
Native skill with an invalid extension name in manifest.
| name | effect-testing |
| description | Effect testing with @effect/vitest. Use when any test needs to run Effect programs, test errors, or provide layers. |
| user-invocable | false |
Use @effect/vitest to run Effect programs directly in tests without bridging
to Promise-land. Stay in Effect-land for cleaner, more idiomatic code.
pnpm add -D @effect/vitest
Requires vitest 1.6.0 or later.
Import from @effect/vitest instead of vitest:
import { Effect } from "effect";
import { describe, expect, it } from "@effect/vitest";
describe("myFunction", () => {
it.effect("returns expected value", () =>
Effect.gen(function* () {
const result = yield* myFunction("input");
expect(result).toBe("expected");
}),
);
});
No async, no await, no runPromise. The test stays in Effect-land.
Use Effect.flip to test expected failures. Flip swaps success and error
channels—if the effect fails, the error becomes the success value:
it.effect("fails with ParseError for invalid input", () =>
Effect.gen(function* () {
const error = yield* parseSource("invalid").pipe(Effect.flip);
expect(error).toBeInstanceOf(ParseError);
}),
);
For asserting the full Exit (success or failure):
import { Exit } from "effect";
it.effect("returns expected exit", () =>
Effect.gen(function* () {
const exit = yield* Effect.exit(divide(4, 0));
expect(exit).toStrictEqual(Exit.fail("Cannot divide by zero"));
}),
);
| Type | Use case |
|---|---|
it.effect | Standard tests with TestContext (TestClock) |
it.live | Tests requiring real time (see below) |
it.scoped | Tests with resources requiring Scope |
it.scopedLive | Scoped tests with live environment |
it.effect.skip | Temporarily skip a test |
it.effect.only | Run only this test |
it.effect.fails | Assert test fails (for tracking known issues) |
When to use it.live:
Date.now() and expect real valuesit.live("...", () => ..., { timeout: 10000 }))Use Effect.provide within the test:
import { NodeFileSystem } from "@effect/platform-node";
it.effect("reads file contents", () =>
Effect.gen(function* () {
const result = yield* readConfig("/path/to/config.json");
expect(result.version).toBe(1);
}).pipe(Effect.provide(NodeFileSystem.layer)),
);
For shared layers across tests, define a helper:
describe("myHandler", () => {
const withTestLayer = <A, E>(effect: Effect.Effect<A, E, MyService>) =>
effect.pipe(Effect.provide(TestMyService));
it.effect("succeeds with valid input", () =>
withTestLayer(
Effect.gen(function* () {
const result = yield* myHandler({ valid: true });
expect(result).toBeDefined();
}),
),
);
});
it.effect provides TestContext including TestClock (starts at 0ms):
import { TestClock, Clock } from "effect";
it.effect("handles timeout", () =>
Effect.gen(function* () {
const fiber = yield* Effect.sleep("1 second").pipe(Effect.fork);
yield* TestClock.adjust("1 second");
yield* fiber.join;
const now = yield* Clock.currentTimeMillis;
expect(now).toBe(1000);
}),
);
it.effect suppresses logs by default. To enable:
import { Logger } from "effect";
it.effect("with logging", () =>
Effect.gen(function* () {
yield* Effect.log("debug message");
}).pipe(Effect.provide(Logger.pretty)),
);
// Or use it.live for real logging
it.live("with live logging", () =>
Effect.gen(function* () {
yield* Effect.log("visible in output");
}),
);