-module(aion@testing@mock). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/aion/testing/mock.gleam"). -export([activity/3]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC( " Typed activity mock registry for `aion/testing`.\n" "\n" " Tests register mocks against an `Activity(i, o)` value so the handler is\n" " statically checked against the same input and output types that\n" " `workflow.run` will use. The test-only FFI double stores a type-erased\n" " wrapper in process-scoped state and intercepts activity dispatch by name.\n" ). -file("src/aion/testing/mock.gleam", 42). -spec activity_error_to_raw(aion@error:activity_error()) -> binary(). activity_error_to_raw(Activity_error) -> case Activity_error of {retryable, Message, _} -> <<"retryable:"/utf8, Message/binary>>; {terminal, Message@1, _} -> <<"terminal:"/utf8, Message@1/binary>>; {activity_decode_failed, Decode_error} -> <<"terminal:activity decode failed: "/utf8, (erlang:element(2, Decode_error))/binary>>; {activity_timed_out, {timed_out, Message@2}} -> <<"timeout:"/utf8, Message@2/binary>>; {activity_cancelled, {cancelled, Reason}} -> <<"cancelled:"/utf8, Reason/binary>>; {activity_non_deterministic, {non_determinism_violation, Message@3}} -> <<"non_determinism:"/utf8, Message@3/binary>>; {activity_engine_failure, Message@4} -> Message@4 end. -file("src/aion/testing/mock.gleam", 16). ?DOC( " Register a typed activity mock for the current process.\n" "\n" " A handler whose input or output type does not match the supplied activity will\n" " fail at `gleam build`, before the workflow test can run.\n" ). -spec activity( EJW, aion@activity:activity(EJX, EJY), fun((EJX) -> {ok, EJY} | {error, aion@error:activity_error()}) ) -> {ok, EJW} | {error, aion@error:engine_error()}. activity(Env, Activity_value, Handler) -> Input_codec = aion@activity:input_codec(Activity_value), Output_codec = aion@activity:output_codec(Activity_value), Name = aion@activity:name(Activity_value), Raw_handler = fun(Raw_input) -> case (erlang:element(3, Input_codec))(Raw_input) of {ok, Typed_input} -> case Handler(Typed_input) of {ok, Typed_output} -> {ok, (erlang:element(2, Output_codec))(Typed_output)}; {error, Activity_error} -> {error, activity_error_to_raw(Activity_error)} end; {error, Decode_error} -> {error, <<"terminal:mock input decode failed: "/utf8, (erlang:element(2, Decode_error))/binary>>} end end, case aion_flow_ffi:testing_register_activity_mock(Name, Raw_handler) of {ok, _} -> {ok, Env}; {error, Raw_error} -> {error, {engine_failure, Raw_error}} end.