LemonPlatformTest.EventsFixtures (lemon_platform_test v0.1.0)

View Source

Builders for valid typed LemonCore.Events.* payloads, for use in tests.

Tests that publish onto LemonCore.Bus used to hand-construct raw payload maps:

LemonCore.Bus.broadcast(
  LemonCore.Bus.run_topic(run_id),
  LemonCore.Event.new(:run_completed, %{completed: %{ok: true, answer: "Done"}}, meta)
)

A raw map drifts from the contract the moment a field is added, renamed, or made mandatory — and it silently omits enforced keys (the %{seq: 1, text: "..."} delta map above is missing its run_id, which the typed Delta requires). These builders produce the real struct instead, so a test payload is exactly as valid as a production one:

LemonCore.Bus.broadcast(
  LemonCore.Bus.run_topic(run_id),
  LemonCore.Event.new(:run_completed, EventsFixtures.run_completed(answer: "Done"), meta)
)

Defaults and overrides

Every builder fills the payload's enforced keys with sensible sample values and leaves optional keys at their struct default, so a no-argument call is always a valid payload. Pass a keyword list or map to override any field:

EventsFixtures.delta(text: "chunk two", seq: 2)
EventsFixtures.run_started(run_id: "run_42", engine: "native")

Unknown keys raise, because each builder ends in the payload's strict new/1 — a typo in a test fixture should fail at the fixture, not surface as a nil field three assertions later.

Nested payloads

Payloads that wrap another payload accept shorthand: fields belonging to the nested struct can be passed at the top level and are routed inward. For run_completed the nested LemonCore.Events.Completion fields (:ok, :answer, :error, :usage, …) are lifted automatically:

EventsFixtures.run_completed(ok: false, error: :timeout, duration_ms: 30)

Pass :completed (a Completion struct or an attrs map) explicitly to build it yourself; an explicit :completed wins over any shorthand. The nested builders (completion/1, action/1, approval_pending/1) are public so you can compose them directly.

This module is the fixture companion to LemonPlatformTest.EventsCase, which asserts the payload contract. Like that case, it needs :lemon_core (the EventsCase -> lemon_core row in the kit's dep table); anyone building event payloads already has it.

Summary

Types

Field overrides for a builder, as a keyword list or map.

Types

overrides()

@type overrides() :: Enumerable.t()

Field overrides for a builder, as a keyword list or map.

Functions

action(overrides \\ [])

@spec action(overrides()) :: LemonCore.Events.Action.t()

A LemonCore.Events.Action — the nested record inside engine_action.

Enforced: :id (default "act_1"), :kind (default :tool), :title (default "Example action").

approval_pending(overrides \\ [])

@spec approval_pending(overrides()) :: LemonCore.Events.ApprovalPending.t()

A LemonCore.Events.ApprovalPending — the nested record inside the approval events.

Enforced: :id (default "appr_1"), :tool (default "bash").

approval_requested(overrides \\ [])

@spec approval_requested(overrides()) :: LemonCore.Events.ApprovalRequested.t()

A LemonCore.Events.ApprovalRequested.

Enforced: :approval_id (default "appr_1") and :pending (default approval_pending/1). Pass :pending as an ApprovalPending struct or an attrs map.

approval_resolved(overrides \\ [])

@spec approval_resolved(overrides()) :: LemonCore.Events.ApprovalResolved.t()

A LemonCore.Events.ApprovalResolved.

Enforced: :approval_id (default "appr_1") and :decision (default :approve_once; see LemonCore.Events.ApprovalResolved.decisions/0). :pending is optional; pass an ApprovalPending struct or an attrs map to include it.

completion(overrides \\ [])

@spec completion(overrides()) :: LemonCore.Events.Completion.t()

A LemonCore.Events.Completion — the terminal result nested in run_completed.

Enforced: :ok (default true). Defaults :answer to "ok".

cron_job_changed(overrides \\ [])

@spec cron_job_changed(overrides()) :: LemonCore.Events.CronJobChanged.t()

A LemonCore.Events.CronJobChanged (the cron_job_created/updated/deleted payload).

Enforced: :action (default :created), :job_id (default "job_1").

cron_run_completed(overrides \\ [])

@spec cron_run_completed(overrides()) :: LemonCore.Events.CronRunCompleted.t()

A LemonCore.Events.CronRunCompleted.

Enforced: :cron_run_id (default "cron_run_1"), :job_id (default "job_1"). Defaults :status to :ok.

cron_run_started(overrides \\ [])

@spec cron_run_started(overrides()) :: LemonCore.Events.CronRunStarted.t()

A LemonCore.Events.CronRunStarted.

Enforced: :cron_run_id (default "cron_run_1"), :job_id (default "job_1").

cron_tick(overrides \\ [])

@spec cron_tick(overrides()) :: LemonCore.Events.CronTick.t()

A LemonCore.Events.CronTick. Enforced: :timestamp_ms (default a fixed sample).

delta(overrides \\ [])

@spec delta(overrides()) :: LemonCore.Events.Delta.t()

A LemonCore.Events.Delta — a chunk of streamed text.

Enforced: :run_id (default "run_test"), :seq (default 0), :text (default "delta"). Unlike the legacy raw map, run_id lives in the payload where the typed contract requires it.

run_completed(overrides \\ [])

@spec run_completed(overrides()) :: LemonCore.Events.RunCompleted.t()

A LemonCore.Events.RunCompleted wrapping a Completion.

The nested completion is built from :completed when given, otherwise from any Completion shorthand fields passed at the top level (:ok, :answer, :error, :usage, …). Everything else (:duration_ms) is a RunCompleted field.

EventsFixtures.run_completed()                      # ok: true, answer: "ok"
EventsFixtures.run_completed(answer: "Done", duration_ms: 100)
EventsFixtures.run_completed(ok: false, error: :timeout)
EventsFixtures.run_completed(completed: EventsFixtures.completion(ok: false))

run_failed(overrides \\ [])

@spec run_failed(overrides()) :: LemonCore.Events.RunFailed.t()

A LemonCore.Events.RunFailed.

Enforced: :run_id (default "run_test"), :reason (default :test_failure).

run_started(overrides \\ [])

@spec run_started(overrides()) :: LemonCore.Events.RunStarted.t()

A LemonCore.Events.RunStarted. Enforced: :run_id (default "run_test").