Skip to content

Instantly share code, notes, and snippets.

@LostKobrakai
Last active December 22, 2017 19:50
Show Gist options
  • Save LostKobrakai/9077143caacf534f9c4743cfc18a148e to your computer and use it in GitHub Desktop.
Save LostKobrakai/9077143caacf534f9c4743cfc18a148e to your computer and use it in GitHub Desktop.
Swoosh TestAdapter with support for acceptance tests
defmodule MyApp.Swoosh.TestAdapter do
@moduledoc """
Integration Testable Adapter for Swoosh
## Usage
Add `{:ok, _} = MyApp.Swoosh.TestAdapter.start_link` into your
`test_helper.exs` file.
Merge with ecto metadata in the case templates, which need it.
```elixir
sandbox_metadata = Phoenix.Ecto.SQL.Sandbox.metadata_for(MyApp.Repo, self())
swoosh_metadata = MyApp.Swoosh.TestAdapter.metadata_for(self())
metadata = Map.merge(sandbox_metadata, swoosh_metadata)
```
Add the plug to the same place as the ecto sandbox one:
```elixir
if Application.get_env(:my_app, :sql_sandbox) do
plug Phoenix.Ecto.SQL.Sandbox
plug MyApp.Swoosh.TestAdapter
end
```
"""
use Swoosh.Adapter
import Plug.Conn
# Plug
def init(_opts \\ []), do: nil
def call(conn, _) do
:ok =
conn
|> get_req_header("user-agent")
|> List.first()
|> extract_metadata()
|> add_receiver()
conn
end
# Swoosh Adapter
def deliver(email, _) do
send(get_receiver(), {:email, email})
{:ok, %{}}
end
# Registry
def start_link do
Registry.start_link :duplicate, SwooshRegistry
end
def add_receiver(%{email_receiver: receiver}) do
case Registry.register(SwooshRegistry, receiver, :value_not_used) do
{:ok, _} -> :ok
{:error, {:already_registered, _}} -> :err
end
end
def add_receiver(_metadata), do: :ok
def get_receiver do
case Registry.keys(SwooshRegistry, self()) do
[] -> self()
[receiver] -> receiver
[_ | _] -> raise "multiple receivers registered for #{inspect self()}"
end
end
# Metadata
def metadata_for(pid) when is_pid(pid) do
%{email_receiver: pid}
end
defp extract_metadata(user_agent) when is_binary(user_agent) do
ua_last_part = user_agent |> String.split("/") |> List.last
case Regex.run(~r/BeamMetadata \((.*?)\)/, ua_last_part) do
[_, metadata] -> parse_metadata(metadata)
_ -> %{}
end
end
defp extract_metadata(_), do: %{}
defp parse_metadata(encoded_metadata) do
encoded_metadata
|> Base.url_decode64!
|> :erlang.binary_to_term
|> case do
{:v1, metadata} -> metadata
_ -> %{}
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment