@temporal-contract/testing / activity
activity
Type Aliases
RunActivityHandlerError
type RunActivityHandlerError<TActivity> = TActivity extends object ? ContractErrorUnion<TErrors> | ApplicationFailure : ApplicationFailure;Defined in: activity.ts:166
Error channel surfaced by runActivityHandler: the activity's declared errors rehydrated to their consumer-side (post-transform) shape — exactly what the workflow-side proxy would produce — plus ApplicationFailure for everything else that crossed the boundary (technical failures returned by the implementation, and the worker's terminal validation failures: ActivityInputValidationError, ActivityOutputValidationError, ContractErrorDataValidationError — all ApplicationFailure subclasses, discriminable via failure.type).
Type Parameters
| Type Parameter |
|---|
TActivity extends ActivityDefinition |
RunActivityHandlerOptions
type RunActivityHandlerOptions<TActivity, TOutput, TError> = object;Defined in: activity.ts:175
Options for runActivityHandler.
Type Parameters
| Type Parameter |
|---|
TActivity extends ActivityDefinition |
TOutput |
TError |
Properties
| Property | Type | Default value | Description | Defined in |
|---|---|---|---|---|
activityName? | string | "activity" | Diagnostic name used in validation-error messages (mirrors the flat runtime activity name). | activity.ts:193 |
env? | MockActivityEnvironment | undefined | Reuse a prepared MockActivityEnvironment — same semantics as RunActivityOptions.env. | activity.ts:198 |
implementation | RunActivityImplementation<TActivity, TOutput, TError> | undefined | The activity implementation under test — the same function you would pass to declareActivitiesHandler. | activity.ts:180 |
input | ClientInferInput<TActivity> | undefined | The activity input as a caller would send it (the wire value, in the input schema's pre-transform shape) — the handler parses it, exactly like production. | activity.ts:186 |
RunActivityImplementation
type RunActivityImplementation<TActivity, TOutput, TError> = (helpers, args) => AsyncResult<TOutput, TError>;Defined in: activity.ts:66
Shape of the implementation accepted by runActivity and runActivityHandler — the same (helpers, args) => AsyncResult<...> shape declareActivitiesHandler expects — the input is on the helpers record too, so ({ errors, input }) => ... is the same call in one destructuring — with the output/error channels inferred from the function itself. The context helper is always empty here: implementations relying on middleware-injected context should be exercised through a worker instead.
Type Parameters
| Type Parameter |
|---|
TActivity extends ActivityDefinition |
TOutput |
TError |
Parameters
| Parameter | Type |
|---|---|
helpers | { context: Record<never, never>; errors: ActivityErrorConstructorsOf<TActivity>; input: WorkerInferInput<TActivity>; } |
helpers.context | Record<never, never> |
helpers.errors | ActivityErrorConstructorsOf<TActivity> |
helpers.input | WorkerInferInput<TActivity> |
args | WorkerInferInput<TActivity> |
Returns
AsyncResult<TOutput, TError>
RunActivityOptions
type RunActivityOptions<TActivity, TOutput, TError> = object;Defined in: activity.ts:78
Options for runActivity.
Type Parameters
| Type Parameter |
|---|
TActivity extends ActivityDefinition |
TOutput |
TError |
Properties
| Property | Type | Description | Defined in |
|---|---|---|---|
env? | MockActivityEnvironment | Reuse a prepared MockActivityEnvironment — pass one to observe heartbeats (env.on("heartbeat", ...)), trigger cancellation (env.cancel()), or customize the activity info. A fresh default environment is created when omitted. | activity.ts:92 |
implementation | RunActivityImplementation<TActivity, TOutput, TError> | The activity implementation under test. | activity.ts:80 |
input | WorkerInferInput<TActivity> | The activity input, in the parsed shape the worker would hand the implementation. | activity.ts:85 |
Functions
runActivity()
function runActivity<TActivity, TOutput, TError>(definition, options): AsyncResult<TOutput, TError>;Defined in: activity.ts:126
Execute a single activity implementation against its contract definition inside a MockActivityEnvironment, returning the implementation's AsyncResult untouched: Ok/Err flow through as-is, and an unanticipated throw (including a CancelledFailure from cancellation) surfaces on the defect channel.
This is the pure-logic tier: no input parse, no output validation, no contract-error wire conversion. A test that passes here can still fail at the production boundary (e.g. an Err whose data violates the declared schema) — cover that with runActivityHandler.
Type Parameters
| Type Parameter |
|---|
TActivity extends ActivityDefinition |
TOutput |
TError |
Parameters
| Parameter | Type | Description |
|---|---|---|
definition | TActivity | The activity's contract definition (used to build the typed errors constructors handed to the implementation). |
options | RunActivityOptions<TActivity, TOutput, TError> | See RunActivityOptions. |
Returns
AsyncResult<TOutput, TError>
Example
import { runActivity } from "@temporal-contract/testing/activity";
const result = await runActivity(
orderContract.workflows.processOrder.activities.chargeCard,
{
implementation: chargeCard, // ({ errors, input }) => AsyncResult<...>
input: { amount: 100 },
},
);
await expect(result).toBeOk(); // with @unthrown/vitest matchersrunActivityHandler()
function runActivityHandler<TActivity, TOutput, TError>(definition, options): AsyncResult<ClientInferOutput<TActivity>, RunActivityHandlerError<TActivity>>;Defined in: activity.ts:244
Execute a single activity implementation through the realdeclareActivitiesHandler wrapping inside a MockActivityEnvironment, then classify the outcome the way a workflow-side caller would:
- the wire input is parsed against the contract's input schema (an invalid input surfaces the production
ActivityInputValidationError); - the implementation's
Okoutput is validated on the sending side and parsed on the receiving side, so a transforming output schema applies exactly once — and drift from the schema surfaces the productionActivityOutputValidationError; - a typed
Err(errors.X(data))is converted to itsApplicationFailurewire shape (type= error name,details[0]= data,details[1]= the provenance wire marker) and rehydrated back into the typedContractError— the full wire round-trip; - contract misuse (an undeclared error name, or error data failing its declared schema) surfaces the production terminal
ContractErrorDataValidationErrorinstead of a green test; - an unanticipated throw stays on the
defectchannel.
Use runActivity for pure-logic unit tests of the implementation; use this when the test should be boundary-faithful — passing here means the same call succeeds through a real worker.
Type Parameters
| Type Parameter |
|---|
TActivity extends ActivityDefinition |
TOutput |
TError |
Parameters
| Parameter | Type | Description |
|---|---|---|
definition | TActivity | The activity's contract definition. |
options | RunActivityHandlerOptions<TActivity, TOutput, TError> | See RunActivityHandlerOptions. |
Returns
AsyncResult<ClientInferOutput<TActivity>, RunActivityHandlerError<TActivity>>
Example
import { runActivityHandler } from "@temporal-contract/testing/activity";
const result = await runActivityHandler(
orderContract.workflows.processOrder.activities.chargeCard,
{
implementation: chargeCard,
input: { amount: -1 },
},
);
// The declared error crossed the wire and rehydrated as a typed error.
await expect(result).toBeErrTagged("@temporal-contract/ContractError");