@temporal-contract/testing / activity
activity
Type Aliases
RunActivityHandlerError
type RunActivityHandlerError<TActivity> = TActivity extends object ? ContractErrorUnion<TErrors> | ApplicationFailure : ApplicationFailure;Defined in: activity.ts:154
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, ContractMisuseError — 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:163
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:181 |
env? | MockActivityEnvironment | undefined | Reuse a prepared MockActivityEnvironment — same semantics as RunActivityOptions.env. | activity.ts:186 |
implementation | RunActivityImplementation<TActivity, TOutput, TError> | undefined | The activity implementation under test — the same function you would pass to declareActivitiesHandler. | activity.ts:168 |
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:174 |
payloadConverter? | Pick<typeof defaultPayloadConverter, "fromPayload" | "toPayload"> | defaultPayloadConverter from @temporalio/worker | The payload converter the input, the output and the failure details round-trip through, as they would between a workflow and a worker — pass the one your worker and client are configured with. | activity.ts:194 |
RunActivityImplementation
type RunActivityImplementation<TActivity, TOutput, TError> = (helpers, args) => AsyncResult<TOutput, TError>;Defined in: activity.ts:59
Shape of the implementation accepted by runActivity and runActivityHandler — the same (helpers, args) => AsyncResult<...> shape declareActivitiesHandler expects, 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 | ActivityImplementationHelpers<TActivity> |
args | WorkerInferInput<TActivity> |
Returns
AsyncResult<TOutput, TError>
RunActivityOptions
type RunActivityOptions<TActivity, TOutput, TError> = object;Defined in: activity.ts:67
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:81 |
implementation | RunActivityImplementation<TActivity, TOutput, TError> | The activity implementation under test. | activity.ts:69 |
input | WorkerInferInput<TActivity> | The activity input, in the parsed shape the worker would hand the implementation. | activity.ts:74 |
Functions
runActivity()
function runActivity<TActivity, TOutput, TError>(definition, options): AsyncResult<TOutput, TError>;Defined in: activity.ts:115
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:245
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 input, the output and the failure details round-trip through the payload converter, so a value that does not survive serialization (a
Datebecomes a string under the default JSON converter) fails here as it would in production; - 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, on either side, 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 surfaces the production terminal failure instead of a green test:
ContractMisuseErrorfor an undeclared error name,ContractErrorDataValidationErrorfor error data failing its declared schema; - 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");