Packages
wallaby
0.30.10
0.31.0
0.30.12
0.30.11
0.30.10
0.30.9
0.30.8
0.30.7
0.30.6
0.30.5
0.30.4
0.30.3
0.30.2
0.30.1
0.30.0
0.29.1
0.29.0
0.28.1
0.28.0
0.27.0
0.26.2
0.26.1
0.26.0
0.25.1
0.25.0
0.24.1
0.24.0
0.23.0
0.22.0
0.21.0
0.20.0
0.19.2
0.19.1
0.19.0
0.18.1
0.18.0
0.17.0
0.16.1
0.16.0
0.15.0
0.14.0
0.13.0
0.12.0
0.11.1
0.11.0
0.10.0
0.9.0
0.8.0
0.7.0
0.6.0
0.5.0
0.4.0
0.3.1
0.3.0
0.2.0
0.1.0
0.0.1
Concurrent feature tests for elixir
Current section
Files
Jump to
Current section
Files
lib/event_emitter.ex
defmodule EventEmitter do
@moduledoc false
# This module offers telemetry style event emission for testing purposes.
# If you'd like to emit a message to the event stream, you can call `emit/1` from your
# implementation code. This is macro, and will not result in any AST injection when not being
# compiled in the test env.
# ```elixir
# defmodule ImplMod do
# use EventEmitter, :emitter
# def implementation do
# # some logic
# emit %{
# name: :implementation,
# module: __MODULE__,
# metadata: %{unique_identifier: some_variable}
# }
# end
# end
# ```
# If you'd like to await on a message emitted by implementation code, you can call `await/3` from
# your test code after registering a handler for your test process
# ```elixir
# defmodule TestMod do
# use EventEmitter, :receiver
# test "some test" do
# EventEmitter.add_handler(self())
# # some tricky asynchronous code
# await :implementation, __MODULE__, %{unique_identifier: some_variable}
# end
# end
# ```
# You can use EventEmitter by starting it in your test helper.
# ```elixir
# # test_helper.exs
# EventEmitter.start_link([])
# ExUnit.start()
# ```
use GenServer
@type event :: %{
optional(:metadata) => map(),
required(:name) => String.t()
}
def emitter do
quote do
import EventEmitter, only: [emit: 1]
end
end
def receiver do
quote do
import EventEmitter, only: [await: 3]
end
end
defmacro __using__(which) do
apply(__MODULE__, which, [])
end
defmacro emit(event) do
if Mix.env() == :test do
quote do
EventEmitter.emit_event(unquote(event))
end
else
nil
end
end
def await(name, metadata, module) do
e = {:event, %{metadata: metadata, name: name, module: module}}
receive do
^e -> :ok
end
end
def start_link(args) do
GenServer.start_link(__MODULE__, args, name: __MODULE__)
end
def add_handler(pid), do: GenServer.call(__MODULE__, {:add_handler, pid})
def emit_event(event), do: GenServer.cast(__MODULE__, {:event, event})
@impl GenServer
def init(_) do
{:ok, %{handlers: []}}
end
@impl GenServer
def handle_call({:add_handler, pid}, _, state) do
{:reply, pid, %{state | handlers: [pid | state.handlers]}}
end
@impl GenServer
def handle_cast({:event, event}, %{handlers: handlers} = state) do
for h <- handlers do
send(h, {:event, event})
end
{:noreply, state}
end
end