Temporalex.Testing (Temporalex v0.2.0)

Copy Markdown View Source

Test executor for Temporalex workflows.

Implements the same GenServer.call protocol as the production executor, but operates in step-by-step mode. Workflow code can't tell the difference.

Usage

test "checkout charges then sends receipt" do
  {:ok, exec} = Temporalex.Testing.start_workflow(MyWorkflow, %{"id" => "123"})

  assert {:activity, call} = Temporalex.Testing.next(exec)
  assert call.type == "MyApp.Activities.Payment.charge"

  assert {:activity, call} = Temporalex.Testing.resolve(exec, {:ok, "charge_123"})
  assert call.type == "MyApp.Activities.Email.send_receipt"

  assert {:ok, result} = Temporalex.Testing.resolve(exec, {:ok, :sent})
  assert result == %{charge_id: "charge_123"}
end

Summary

Functions

Set the workflow's cancelled flag.

Mark a patch id as "seen in history" — mirrors what a notify_has_patch job would do during replay. After this, patched?(id) returns true.

Returns what the workflow is currently blocked on.

Query the workflow's published state.

Provide a result for the current blocking call and advance to the next one. Returns the same values as next/1.

Run an activity function directly for testing.

Run a workflow with a pre-loaded operation log. Convenience wrapper that feeds results automatically and returns the final workflow result.

Send a signal into the workflow. Works both inside and outside receive.

Send an update into the workflow. Only works inside receive with a matching handler.

Flip the executor into replay mode. Subsequent patched? calls that haven't seen the patch id (via mark_patch_seen/2) will return false.

Start a workflow in test mode. Returns {:ok, executor_pid}.

Functions

cancel(exec)

Set the workflow's cancelled flag.

mark_patch_seen(exec, patch_id)

Mark a patch id as "seen in history" — mirrors what a notify_has_patch job would do during replay. After this, patched?(id) returns true.

next(exec)

Returns what the workflow is currently blocked on.

Possible returns:

  • {:activity, %{type, input, opts}} — waiting for an activity result
  • {:sleep, duration_ms} — waiting for a timer
  • {:signal, name} — waiting for a signal (via wait_for_signal)
  • {:side_effect, fun} — waiting for side effect resolution
  • {:receive, %{signals: [...], updates: [...], timeout: ...}} — in a receive loop
  • {:ok, result} — workflow completed successfully
  • {:error, reason} — workflow failed
  • {:continue_as_new, args} — workflow wants to restart

query(exec, name, args \\ nil)

Query the workflow's published state.

resolve(exec, result)

Provide a result for the current blocking call and advance to the next one. Returns the same values as next/1.

run_activity(module, function, args \\ [])

Run an activity function directly for testing.

Example

{:ok, result} = Temporalex.Testing.run_activity(MyActivities, :charge, [100])

run_workflow(module, args, opts \\ [])

Run a workflow with a pre-loaded operation log. Convenience wrapper that feeds results automatically and returns the final workflow result.

Example

{:ok, result} = Temporalex.Testing.run_workflow(MyWorkflow, %{"id" => "123"},
  log: [
    {:activity, "MyApp.Activities.Payment.charge", {:ok, "charge_123"}},
    {:activity, "MyApp.Activities.Email.send_receipt", {:ok, :sent}}
  ]
)

send_signal(exec, name, payload \\ nil)

Send a signal into the workflow. Works both inside and outside receive.

send_update(exec, name, args \\ [])

Send an update into the workflow. Only works inside receive with a matching handler.

Returns the handler's reply value, or {:error, reason} if validation fails.

set_replaying(exec)

Flip the executor into replay mode. Subsequent patched? calls that haven't seen the patch id (via mark_patch_seen/2) will return false.

start_workflow(module, args \\ %{}, opts \\ [])

Start a workflow in test mode. Returns {:ok, executor_pid}.

Options:

  • :is_replaying — when true, patched?/1 returns false for patches that haven't been marked as seen (via :seen_patches or mark_patch_seen/2). Models a Temporal replay activation.
  • :seen_patches — a list of patch ids to pre-populate as "seen", mirroring notify_has_patch jobs from an activation's history.