Skip to content

TestClock

In most cases, we want our unit tests to run as quickly as possible. Waiting for real time to pass can slow down our tests significantly. Effect provides a handy tool called TestClock that allows us to control time during testing. This means we can efficiently and predictably test code that involves time without having to wait for the actual time to pass.

The TestClock in Effect allows us to control time for testing purposes. It lets us schedule effects to run at specific times, making it ideal for testing time-related functionality.

Instead of waiting for real time to pass, we use the TestClock to set the clock time to a specific point. Any effects scheduled to run at or before that time will be executed in order.

Imagine TestClock as a wall clock, but with a twist—it doesn’t tick on its own. Instead, it only changes when we manually adjust it using the TestClock.adjust and TestClock.setTime functions. The clock time never progresses on its own.

When we adjust the clock time, any effects scheduled to run at or before the new time will be executed. This allows us to simulate the passage of time in our tests without waiting for real time.

Let’s look at an example of how to test Effect.timeout using the TestClock:

1
import {
import Effect
Effect
,
import TestClock
TestClock
,
import Fiber
Fiber
,
import Option
Option
,
import TestContext
TestContext
} from "effect"
2
import * as
(alias) function assert(value: unknown, message?: string | Error): asserts value (alias) namespace assert import assert

An alias of {@link ok } .

assert
from "node:assert"
3
4
const
const test: Effect.Effect<void, never, never>
test
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
5
// Create a fiber that sleeps for 5 minutes and then times out
6
// after 1 minute
7
const
const fiber: Fiber.RuntimeFiber<Option.Option<void>, never>
fiber
= yield*
import Effect
Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Returns an effect that suspends for the specified duration. This method is asynchronous, and does not actually block the fiber executing the effect.

sleep
("5 minutes").
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<Option.Option<void>, never, never>, Effect.Effect<Fiber.RuntimeFiber<Option.Option<void>, never>, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<...>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
8
import Effect
Effect
.
const timeoutTo: <void, Option.Option<void>, Option.Option<void>>(options: { readonly onTimeout: LazyArg<Option.Option<void>>; readonly onSuccess: (a: void) => Option.Option<void>; readonly duration: DurationInput; }) => <E, R>(self: Effect.Effect<...>) => Effect.Effect<...> (+1 overload)

Returns an effect that will timeout this effect, returning either the default value if the timeout elapses before the effect has produced a value or returning the result of applying the function `onSuccess` to the success value of the effect. If the timeout elapses without producing a value, the running effect will be safely interrupted.

timeoutTo
({
9
(property) duration: DurationInput
duration
: "1 minute",
10
(property) onSuccess: (a: void) => Option.Option<void>
onSuccess
:
import Option
Option
.
const some: <A>(value: A) => Option.Option<A>

Creates a new `Option` that wraps the given value.

some
,
11
(property) onTimeout: LazyArg<Option.Option<void>>
onTimeout
: () =>
import Option
Option
.
const none: <void>() => Option.Option<void>

Creates a new `Option` that represents the absence of a value.

none
<void>()
12
}),
13
import Effect
Effect
.
const fork: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R>

Returns an effect that forks this effect into its own separate fiber, returning the fiber immediately, without waiting for it to begin executing the effect. You can use the `fork` method whenever you want to execute an effect in a new fiber, concurrently and without "blocking" the fiber executing other effects. Using fibers can be tricky, so instead of using this method directly, consider other higher-level methods, such as `raceWith`, `zipPar`, and so forth. The fiber returned by this method has methods to interrupt the fiber and to wait for it to finish executing the effect. See `Fiber` for more information. Whenever you use this method to launch a new fiber, the new fiber is attached to the parent fiber's scope. This means when the parent fiber terminates, the child fiber will be terminated as well, ensuring that no fibers leak. This behavior is called "auto supervision", and if this behavior is not desired, you may use the `forkDaemon` or `forkIn` methods.

fork
14
)
15
16
// Adjust the TestClock by 1 minute to simulate the passage of time
17
yield*
import TestClock
TestClock
.
const adjust: (durationInput: DurationInput) => Effect.Effect<void>

Accesses a `TestClock` instance in the context and increments the time by the specified duration, running any actions scheduled for on or before the new time in order.

adjust
("1 minute")
18
19
// Get the result of the fiber
20
const
const result: Option.Option<void>
result
= yield*
import Fiber
Fiber
.
const join: <Option.Option<void>, never>(self: Fiber.Fiber<Option.Option<void>, never>) => Effect.Effect<Option.Option<void>, never, never>

Joins the fiber, which suspends the joining fiber until the result of the fiber has been determined. Attempting to join a fiber that has erred will result in a catchable error. Joining an interrupted fiber will result in an "inner interruption" of this fiber, unlike interruption triggered by another fiber, "inner interruption" can be caught and recovered.

join
(
const fiber: Fiber.RuntimeFiber<Option.Option<void>, never>
fiber
)
21
22
// Check if the result is None, indicating a timeout
23
(alias) function assert(value: unknown, message?: string | Error): asserts value (alias) namespace assert import assert

An alias of {@link ok } .

assert
.
function assert.ok(value: unknown, message?: string | Error): asserts value

Tests if `value` is truthy. It is equivalent to `assert.equal(!!value, true, message)`. If `value` is not truthy, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is `undefined`, a default error message is assigned. If the `message` parameter is an instance of an `Error` then it will be thrown instead of the `AssertionError`. If no arguments are passed in at all `message` will be set to the string:`` 'No value argument passed to `assert.ok()`' ``. Be aware that in the `repl` the error message will be different to the one thrown in a file! See below for further details. ```js import assert from 'node:assert/strict'; assert.ok(true); // OK assert.ok(1); // OK assert.ok(); // AssertionError: No value argument passed to `assert.ok()` assert.ok(false, 'it\'s false'); // AssertionError: it's false // In the repl: assert.ok(typeof 123 === 'string'); // AssertionError: false == true // In a file (e.g. test.js): assert.ok(typeof 123 === 'string'); // AssertionError: The expression evaluated to a falsy value: // // assert.ok(typeof 123 === 'string') assert.ok(false); // AssertionError: The expression evaluated to a falsy value: // // assert.ok(false) assert.ok(0); // AssertionError: The expression evaluated to a falsy value: // // assert.ok(0) ``` ```js import assert from 'node:assert/strict'; // Using `assert()` works the same: assert(0); // AssertionError: The expression evaluated to a falsy value: // // assert(0) ```

ok
(
import Option
Option
.
const isNone: <void>(self: Option.Option<void>) => self is Option.None<void>

Determine if a `Option` is a `None`.

isNone
(
const result: Option.Option<void>
result
))
24
}).
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const provide: <TestServices, never, never>(layer: Layer<TestServices, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<...> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder `R0`

provide
(
import TestContext
TestContext
.
const TestContext: Layer<TestServices, never, never>
TestContext
))
25
26
import Effect
Effect
.
const runPromise: <void, never>(effect: Effect.Effect<void, never, never>, options?: { readonly signal?: AbortSignal; } | undefined) => Promise<void>

Runs an `Effect` workflow, returning a `Promise` which resolves with the result of the workflow or rejects with an error.

runPromise
(
const test: Effect.Effect<void, never, never>
test
)

In this example, we create a test scenario involving a fiber that sleeps for 5 minutes and then times out after 1 minute. Instead of waiting for the full 5 minutes to elapse in real time, we utilize the TestClock to instantly advance time by 1 minute.

A critical point to note is the forking of the fiber where Effect.sleep is invoked. Calls to Effect.sleep and related methods wait until the clock time matches or surpasses the scheduled time for their execution. By forking the fiber, we ensure that we have control over the clock time adjustment.

Let’s explore an example demonstrating how to test an effect that runs at fixed intervals using the TestClock:

1
import {
import Effect
Effect
,
import Queue
Queue
,
import TestClock
TestClock
,
import Option
Option
,
import TestContext
TestContext
} from "effect"
2
import * as
(alias) function assert(value: unknown, message?: string | Error): asserts value (alias) namespace assert import assert

An alias of {@link ok } .

assert
from "node:assert"
3
4
const
const test: Effect.Effect<void, never, never>
test
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
5
const
const q: Queue.Queue<unknown>
q
= yield*
import Queue
Queue
.
const unbounded: <unknown>() => Effect.Effect<Queue.Queue<unknown>, never, never>

Creates a new unbounded `Queue`.

unbounded
()
6
7
yield*
import Queue
Queue
.
const offer: <unknown>(self: Queue.Enqueue<unknown>, value: unknown) => Effect.Effect<boolean> (+1 overload)

Places one value in the queue.

offer
(
const q: Queue.Queue<unknown>
q
,
var undefined
undefined
).
(method) Pipeable.pipe<Effect.Effect<boolean, never, never>, Effect.Effect<boolean, never, never>, Effect.Effect<never, never, never>, Effect.Effect<RuntimeFiber<never, never>, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<...>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>, cd: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
8
// Delay the effect for 60 minutes and repeat it forever
9
import Effect
Effect
.
const delay: (duration: DurationInput) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

Returns an effect that is delayed from this effect by the specified `Duration`.

delay
("60 minutes"),
10
import Effect
Effect
.
const forever: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<never, E, R>

Repeats this effect forever (until the first error).

forever
,
11
import Effect
Effect
.
const fork: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<RuntimeFiber<A, E>, never, R>

Returns an effect that forks this effect into its own separate fiber, returning the fiber immediately, without waiting for it to begin executing the effect. You can use the `fork` method whenever you want to execute an effect in a new fiber, concurrently and without "blocking" the fiber executing other effects. Using fibers can be tricky, so instead of using this method directly, consider other higher-level methods, such as `raceWith`, `zipPar`, and so forth. The fiber returned by this method has methods to interrupt the fiber and to wait for it to finish executing the effect. See `Fiber` for more information. Whenever you use this method to launch a new fiber, the new fiber is attached to the parent fiber's scope. This means when the parent fiber terminates, the child fiber will be terminated as well, ensuring that no fibers leak. This behavior is called "auto supervision", and if this behavior is not desired, you may use the `forkDaemon` or `forkIn` methods.

fork
12
)
13
14
// Check if no effect is performed before the recurrence period
15
const
const a: boolean
a
= yield*
import Queue
Queue
.
const poll: <unknown>(self: Queue.Dequeue<unknown>) => Effect.Effect<Option.Option<unknown>, never, never>

Returns the first value in the `Queue` as a `Some<A>`, or `None` if the queue is empty.

poll
(
const q: Queue.Queue<unknown>
q
).
(method) Pipeable.pipe<Effect.Effect<Option.Option<unknown>, never, never>, Effect.Effect<boolean, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<Option.Option<unknown>, never, never>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const andThen: <Option.Option<unknown>, boolean>(f: (a: Option.Option<unknown>) => boolean) => <E, R>(self: Effect.Effect<Option.Option<unknown>, E, R>) => Effect.Effect<boolean, E, R> (+3 overloads)

Executes a sequence of two actions, typically two `Effect`s, where the second action can depend on the result of the first action. The `that` action can take various forms: - a value - a function returning a value - a promise - a function returning a promise - an effect - a function returning an effect

andThen
(
import Option
Option
.
const isNone: <A>(self: Option.Option<A>) => self is Option.None<A>

Determine if a `Option` is a `None`.

isNone
))
16
17
// Adjust the TestClock by 60 minutes to simulate the passage of time
18
yield*
import TestClock
TestClock
.
const adjust: (durationInput: DurationInput) => Effect.Effect<void>

Accesses a `TestClock` instance in the context and increments the time by the specified duration, running any actions scheduled for on or before the new time in order.

adjust
("60 minutes")
19
20
// Check if an effect is performed after the recurrence period
21
const
const b: boolean
b
= yield*
import Queue
Queue
.
const take: <unknown>(self: Queue.Dequeue<unknown>) => Effect.Effect<unknown, never, never>

Takes the oldest value in the queue. If the queue is empty, this will return a computation that resumes when an item has been added to the queue.

take
(
const q: Queue.Queue<unknown>
q
).
(method) Pipeable.pipe<Effect.Effect<unknown, never, never>, Effect.Effect<boolean, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<unknown, never, never>) => Effect.Effect<boolean, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const as: <boolean>(value: boolean) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<boolean, E, R> (+1 overload)

This function maps the success value of an `Effect` value to a specified constant value.

as
(true))
22
23
// Check if the effect is performed exactly once
24
const
const c: boolean
c
= yield*
import Queue
Queue
.
const poll: <unknown>(self: Queue.Dequeue<unknown>) => Effect.Effect<Option.Option<unknown>, never, never>

Returns the first value in the `Queue` as a `Some<A>`, or `None` if the queue is empty.

poll
(
const q: Queue.Queue<unknown>
q
).
(method) Pipeable.pipe<Effect.Effect<Option.Option<unknown>, never, never>, Effect.Effect<boolean, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<Option.Option<unknown>, never, never>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const andThen: <Option.Option<unknown>, boolean>(f: (a: Option.Option<unknown>) => boolean) => <E, R>(self: Effect.Effect<Option.Option<unknown>, E, R>) => Effect.Effect<boolean, E, R> (+3 overloads)

Executes a sequence of two actions, typically two `Effect`s, where the second action can depend on the result of the first action. The `that` action can take various forms: - a value - a function returning a value - a promise - a function returning a promise - an effect - a function returning an effect

andThen
(
import Option
Option
.
const isNone: <A>(self: Option.Option<A>) => self is Option.None<A>

Determine if a `Option` is a `None`.

isNone
))
25
26
// Adjust the TestClock by another 60 minutes
27
yield*
import TestClock
TestClock
.
const adjust: (durationInput: DurationInput) => Effect.Effect<void>

Accesses a `TestClock` instance in the context and increments the time by the specified duration, running any actions scheduled for on or before the new time in order.

adjust
("60 minutes")
28
29
// Check if another effect is performed
30
const
const d: boolean
d
= yield*
import Queue
Queue
.
const take: <unknown>(self: Queue.Dequeue<unknown>) => Effect.Effect<unknown, never, never>

Takes the oldest value in the queue. If the queue is empty, this will return a computation that resumes when an item has been added to the queue.

take
(
const q: Queue.Queue<unknown>
q
).
(method) Pipeable.pipe<Effect.Effect<unknown, never, never>, Effect.Effect<boolean, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<unknown, never, never>) => Effect.Effect<boolean, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const as: <boolean>(value: boolean) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<boolean, E, R> (+1 overload)

This function maps the success value of an `Effect` value to a specified constant value.

as
(true))
31
const
const e: boolean
e
= yield*
import Queue
Queue
.
const poll: <unknown>(self: Queue.Dequeue<unknown>) => Effect.Effect<Option.Option<unknown>, never, never>

Returns the first value in the `Queue` as a `Some<A>`, or `None` if the queue is empty.

poll
(
const q: Queue.Queue<unknown>
q
).
(method) Pipeable.pipe<Effect.Effect<Option.Option<unknown>, never, never>, Effect.Effect<boolean, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<Option.Option<unknown>, never, never>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const andThen: <Option.Option<unknown>, boolean>(f: (a: Option.Option<unknown>) => boolean) => <E, R>(self: Effect.Effect<Option.Option<unknown>, E, R>) => Effect.Effect<boolean, E, R> (+3 overloads)

Executes a sequence of two actions, typically two `Effect`s, where the second action can depend on the result of the first action. The `that` action can take various forms: - a value - a function returning a value - a promise - a function returning a promise - an effect - a function returning an effect

andThen
(
import Option
Option
.
const isNone: <A>(self: Option.Option<A>) => self is Option.None<A>

Determine if a `Option` is a `None`.

isNone
))
32
33
// Ensure that all conditions are met
34
(alias) function assert(value: unknown, message?: string | Error): asserts value (alias) namespace assert import assert

An alias of {@link ok } .

assert
.
function assert.ok(value: unknown, message?: string | Error): asserts value

Tests if `value` is truthy. It is equivalent to `assert.equal(!!value, true, message)`. If `value` is not truthy, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is `undefined`, a default error message is assigned. If the `message` parameter is an instance of an `Error` then it will be thrown instead of the `AssertionError`. If no arguments are passed in at all `message` will be set to the string:`` 'No value argument passed to `assert.ok()`' ``. Be aware that in the `repl` the error message will be different to the one thrown in a file! See below for further details. ```js import assert from 'node:assert/strict'; assert.ok(true); // OK assert.ok(1); // OK assert.ok(); // AssertionError: No value argument passed to `assert.ok()` assert.ok(false, 'it\'s false'); // AssertionError: it's false // In the repl: assert.ok(typeof 123 === 'string'); // AssertionError: false == true // In a file (e.g. test.js): assert.ok(typeof 123 === 'string'); // AssertionError: The expression evaluated to a falsy value: // // assert.ok(typeof 123 === 'string') assert.ok(false); // AssertionError: The expression evaluated to a falsy value: // // assert.ok(false) assert.ok(0); // AssertionError: The expression evaluated to a falsy value: // // assert.ok(0) ``` ```js import assert from 'node:assert/strict'; // Using `assert()` works the same: assert(0); // AssertionError: The expression evaluated to a falsy value: // // assert(0) ```

ok
(
const a: boolean
a
&&
const b: boolean
b
&&
const c: boolean
c
&&
const d: boolean
d
&&
const e: boolean
e
)
35
}).
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const provide: <TestServices, never, never>(layer: Layer<TestServices, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<...> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder `R0`

provide
(
import TestContext
TestContext
.
const TestContext: Layer<TestServices, never, never>
TestContext
))
36
37
import Effect
Effect
.
const runPromise: <void, never>(effect: Effect.Effect<void, never, never>, options?: { readonly signal?: AbortSignal; } | undefined) => Promise<void>

Runs an `Effect` workflow, returning a `Promise` which resolves with the result of the workflow or rejects with an error.

runPromise
(
const test: Effect.Effect<void, never, never>
test
)

In this example, we aim to test an effect that runs at regular intervals. We use an unbounded queue to manage the effects. We verify that:

  1. No effect is performed before the specified recurrence period.
  2. An effect is performed after the recurrence period.
  3. The effect is executed exactly once.

It’s crucial to note that after each recurrence, the next occurrence is scheduled to happen at the appropriate time in the future. When we adjust the clock by 60 minutes, precisely one value is placed in the queue, and when we adjust the clock by another 60 minutes, another value is added to the queue.

Let’s explore an example that demonstrates how to test the behavior of the Clock using the TestClock:

1
import {
import Effect
Effect
,
import Clock
Clock
,
import TestClock
TestClock
,
import TestContext
TestContext
} from "effect"
2
import * as
(alias) function assert(value: unknown, message?: string | Error): asserts value (alias) namespace assert import assert

An alias of {@link ok } .

assert
from "node:assert"
3
4
const
const test: Effect.Effect<void, never, never>
test
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
5
// Get the current time using the Clock
6
const
const startTime: number
startTime
= yield*
import Clock
Clock
.
const currentTimeMillis: Effect.Effect<number, never, never>
currentTimeMillis
7
8
// Adjust the TestClock by 1 minute to simulate the passage of time
9
yield*
import TestClock
TestClock
.
const adjust: (durationInput: DurationInput) => Effect.Effect<void>

Accesses a `TestClock` instance in the context and increments the time by the specified duration, running any actions scheduled for on or before the new time in order.

adjust
("1 minute")
10
11
// Get the current time again
12
const
const endTime: number
endTime
= yield*
import Clock
Clock
.
const currentTimeMillis: Effect.Effect<number, never, never>
currentTimeMillis
13
14
// Check if the time difference is at least
15
// 60,000 milliseconds (1 minute)
16
(alias) function assert(value: unknown, message?: string | Error): asserts value (alias) namespace assert import assert

An alias of {@link ok } .

assert
.
function assert.ok(value: unknown, message?: string | Error): asserts value

Tests if `value` is truthy. It is equivalent to `assert.equal(!!value, true, message)`. If `value` is not truthy, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is `undefined`, a default error message is assigned. If the `message` parameter is an instance of an `Error` then it will be thrown instead of the `AssertionError`. If no arguments are passed in at all `message` will be set to the string:`` 'No value argument passed to `assert.ok()`' ``. Be aware that in the `repl` the error message will be different to the one thrown in a file! See below for further details. ```js import assert from 'node:assert/strict'; assert.ok(true); // OK assert.ok(1); // OK assert.ok(); // AssertionError: No value argument passed to `assert.ok()` assert.ok(false, 'it\'s false'); // AssertionError: it's false // In the repl: assert.ok(typeof 123 === 'string'); // AssertionError: false == true // In a file (e.g. test.js): assert.ok(typeof 123 === 'string'); // AssertionError: The expression evaluated to a falsy value: // // assert.ok(typeof 123 === 'string') assert.ok(false); // AssertionError: The expression evaluated to a falsy value: // // assert.ok(false) assert.ok(0); // AssertionError: The expression evaluated to a falsy value: // // assert.ok(0) ``` ```js import assert from 'node:assert/strict'; // Using `assert()` works the same: assert(0); // AssertionError: The expression evaluated to a falsy value: // // assert(0) ```

ok
(
const endTime: number
endTime
-
const startTime: number
startTime
>= 60_000)
17
}).
(method) Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const provide: <TestServices, never, never>(layer: Layer<TestServices, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<...> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder `R0`

provide
(
import TestContext
TestContext
.
const TestContext: Layer<TestServices, never, never>
TestContext
))
18
19
import Effect
Effect
.
const runPromise: <void, never>(effect: Effect.Effect<void, never, never>, options?: { readonly signal?: AbortSignal; } | undefined) => Promise<void>

Runs an `Effect` workflow, returning a `Promise` which resolves with the result of the workflow or rejects with an error.

runPromise
(
const test: Effect.Effect<void, never, never>
test
)

TestClock also affects asynchronous code scheduled to run after a certain time:

1
import {
import Effect
Effect
,
import Deferred
Deferred
,
import TestClock
TestClock
,
import TestContext
TestContext
} from "effect"
2
import * as
(alias) function assert(value: unknown, message?: string | Error): asserts value (alias) namespace assert import assert

An alias of {@link ok } .

assert
from "node:assert"
3
4
const
const test: Effect.Effect<void, void, never>
test
=
import Effect
Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>> | YieldWrap<Effect.Effect<number, void, never>>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)
gen
(function* () {
5
// Create a deferred value
6
const
const deferred: Deferred.Deferred<number, void>
deferred
= yield*
import Deferred
Deferred
.
const make: <number, void>() => Effect.Effect<Deferred.Deferred<number, void>, never, never>

Creates a new `Deferred`.

make
<number, void>()
7
8
// Run two effects concurrently: sleep for 10 seconds and succeed
9
// the deferred with a value of 1
10
yield*
import Effect
Effect
.
const all: <readonly [Effect.Effect<void, never, never>, Effect.Effect<boolean, never, never>], { concurrency: "unbounded"; }>(arg: readonly [Effect.Effect<void, never, never>, Effect.Effect<...>], options?: { ...; } | undefined) => Effect.Effect<...>

Runs all the provided effects in sequence respecting the structure provided in input. Supports multiple arguments, a single argument tuple / array or record / struct.

all
(
11
[
import Effect
Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Returns an effect that suspends for the specified duration. This method is asynchronous, and does not actually block the fiber executing the effect.

sleep
("10 seconds"),
import Deferred
Deferred
.
const succeed: <number, void>(self: Deferred.Deferred<number, void>, value: number) => Effect.Effect<boolean> (+1 overload)

Completes the `Deferred` with the specified value.

succeed
(
const deferred: Deferred.Deferred<number, void>
deferred
, 1)],
12
{
(property) concurrency: "unbounded"
concurrency
: "unbounded" }
13
).
(method) Pipeable.pipe<Effect.Effect<[void, boolean], never, never>, Effect.Effect<RuntimeFiber<[void, boolean], never>, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<[void, boolean], never, never>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const fork: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<RuntimeFiber<A, E>, never, R>

Returns an effect that forks this effect into its own separate fiber, returning the fiber immediately, without waiting for it to begin executing the effect. You can use the `fork` method whenever you want to execute an effect in a new fiber, concurrently and without "blocking" the fiber executing other effects. Using fibers can be tricky, so instead of using this method directly, consider other higher-level methods, such as `raceWith`, `zipPar`, and so forth. The fiber returned by this method has methods to interrupt the fiber and to wait for it to finish executing the effect. See `Fiber` for more information. Whenever you use this method to launch a new fiber, the new fiber is attached to the parent fiber's scope. This means when the parent fiber terminates, the child fiber will be terminated as well, ensuring that no fibers leak. This behavior is called "auto supervision", and if this behavior is not desired, you may use the `forkDaemon` or `forkIn` methods.

fork
)
14
15
// Adjust the TestClock by 10 seconds
16
yield*
import TestClock
TestClock
.
const adjust: (durationInput: DurationInput) => Effect.Effect<void>

Accesses a `TestClock` instance in the context and increments the time by the specified duration, running any actions scheduled for on or before the new time in order.

adjust
("10 seconds")
17
18
// Await the value from the deferred
19
const
const readRef: number
readRef
= yield*
import Deferred
Deferred
.
(alias) await<number, void>(self: Deferred.Deferred<number, void>): Effect.Effect<number, void, never> export await

Retrieves the value of the `Deferred`, suspending the fiber running the workflow until the result is available.

await
(
const deferred: Deferred.Deferred<number, void>
deferred
)
20
21
(alias) function assert(value: unknown, message?: string | Error): asserts value (alias) namespace assert import assert

An alias of {@link ok } .

assert
.
function assert.ok(value: unknown, message?: string | Error): asserts value

Tests if `value` is truthy. It is equivalent to `assert.equal(!!value, true, message)`. If `value` is not truthy, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is `undefined`, a default error message is assigned. If the `message` parameter is an instance of an `Error` then it will be thrown instead of the `AssertionError`. If no arguments are passed in at all `message` will be set to the string:`` 'No value argument passed to `assert.ok()`' ``. Be aware that in the `repl` the error message will be different to the one thrown in a file! See below for further details. ```js import assert from 'node:assert/strict'; assert.ok(true); // OK assert.ok(1); // OK assert.ok(); // AssertionError: No value argument passed to `assert.ok()` assert.ok(false, 'it\'s false'); // AssertionError: it's false // In the repl: assert.ok(typeof 123 === 'string'); // AssertionError: false == true // In a file (e.g. test.js): assert.ok(typeof 123 === 'string'); // AssertionError: The expression evaluated to a falsy value: // // assert.ok(typeof 123 === 'string') assert.ok(false); // AssertionError: The expression evaluated to a falsy value: // // assert.ok(false) assert.ok(0); // AssertionError: The expression evaluated to a falsy value: // // assert.ok(0) ``` ```js import assert from 'node:assert/strict'; // Using `assert()` works the same: assert(0); // AssertionError: The expression evaluated to a falsy value: // // assert(0) ```

ok
(1 ===
const readRef: number
readRef
)
22
}).
(method) Pipeable.pipe<Effect.Effect<void, void, never>, Effect.Effect<void, void, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, void, never>) => Effect.Effect<void, void, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect
Effect
.
const provide: <TestServices, never, never>(layer: Layer<TestServices, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<...> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder `R0`

provide
(
import TestContext
TestContext
.
const TestContext: Layer<TestServices, never, never>
TestContext
))
23
24
import Effect
Effect
.
const runPromise: <void, void>(effect: Effect.Effect<void, void, never>, options?: { readonly signal?: AbortSignal; } | undefined) => Promise<void>

Runs an `Effect` workflow, returning a `Promise` which resolves with the result of the workflow or rejects with an error.

runPromise
(
const test: Effect.Effect<void, void, never>
test
)

In this code, we create a scenario where a value is set in a Deferred after 10 seconds asynchronously. We use Effect.fork to run this asynchronously. By adjusting the TestClock by 10 seconds, we can simulate the passage of time and test the code without waiting for the actual 10 seconds to elapse.