Skip to content

Commit

Permalink
Turn some test helpers from macros -> functions (#604)
Browse files Browse the repository at this point in the history
What changed?
============

We change three test helpers in `Bamboo.Test` from macros into regular
functions:

- `assert_delivered_email/1`
- `assert_delivered_email_with/1`
- `refute_email_delivered_with/1`

There are other helpers that are already functions:

- `assert_no_emails_delivered/0`
- `refute_delivered_email/1`

The only macro we leave as a macro (because it needs to be one) is
`assert_delivered_email_matches/1`

Why?
----

There seems no reason for those functions to be macros, and they only
add extra complexity.

> Macros should only be used as a last resort

- from Elixir's [getting started
  docs](https://elixir-lang.org/getting-started/meta/macros.html)

A side benefit
-------------

A side benefit of doing this is that we can make most of the private
functions truly private with `defp`. With the macros, we had to make
them public (to access them from the macros), and we set `@doc false` so
they wouldn't show up in docs.
  • Loading branch information
germsvel committed May 27, 2021
1 parent dbc9203 commit 6aa74c3
Showing 1 changed file with 29 additions and 52 deletions.
81 changes: 29 additions & 52 deletions lib/bamboo/test.ex
Original file line number Diff line number Diff line change
Expand Up @@ -157,18 +157,10 @@ defmodule Bamboo.Test do
unsent_email = Bamboo.Email.new_email(subject: "something else")
assert_delivered_email(unsent_email) # Will fail
"""
defmacro assert_delivered_email(email, opts \\ []) do
quote do
import ExUnit.Assertions
email = Bamboo.Test.normalize_for_testing(unquote(email))
timeout = Bamboo.Test.get_timeout(unquote(opts))

assert_receive(
{:delivered_email, ^email},
timeout,
Bamboo.Test.flunk_with_email_list(email)
)
end
def assert_delivered_email(email, opts \\ []) do
email = normalize_for_testing(email)
timeout = get_timeout(opts)
assert_receive({:delivered_email, ^email}, timeout, flunk_with_email_list(email))
end

@doc """
Expand Down Expand Up @@ -227,17 +219,14 @@ defmodule Bamboo.Test do
assert_email_delivered_with(text_body: ~r/love/) # Will pass
assert_email_delivered_with(text_body: ~r/like/) # Will fail
"""
defmacro assert_email_delivered_with(email_params, opts \\ []) do
quote bind_quoted: [email_params: email_params, opts: opts] do
import ExUnit.Assertions
timeout = Bamboo.Test.get_timeout(opts)
assert_receive({:delivered_email, email}, timeout, Bamboo.Test.flunk_no_emails_received())
def assert_email_delivered_with(email_params, opts \\ []) do
timeout = get_timeout(opts)
assert_receive({:delivered_email, email}, timeout, flunk_no_emails_received())

received_email_params = email |> Map.from_struct()
received_email_params = email |> Map.from_struct()

assert Enum.all?(email_params, fn {k, v} -> do_match(received_email_params[k], v, k) end),
Bamboo.Test.flunk_attributes_do_not_match(email_params, received_email_params)
end
assert Enum.all?(email_params, fn {k, v} -> do_match(received_email_params[k], v, k) end),
flunk_attributes_do_not_match(email_params, received_email_params)
end

@doc """
Expand Down Expand Up @@ -274,43 +263,35 @@ defmodule Bamboo.Test do
Bamboo.Email.new_email(subject: "something") |> MyApp.Mailer.deliver()
refute_email_delivered_with([subject: "something else"], timeout: 100)
"""
defmacro refute_email_delivered_with(email_params, opts \\ []) do
quote bind_quoted: [email_params: email_params, opts: opts] do
import ExUnit.Assertions

received_email_params =
receive do
{:delivered_email, email} -> Map.from_struct(email)
after
Bamboo.Test.refute_timeout(opts) -> []
end

if is_nil(received_email_params) do
refute false
else
refute Enum.any?(email_params, fn {k, v} -> do_match(received_email_params[k], v, k) end),
Bamboo.Test.flunk_attributes_match(email_params, received_email_params)
def refute_email_delivered_with(email_params, opts \\ []) do
received_email_params =
receive do
{:delivered_email, email} -> Map.from_struct(email)
after
refute_timeout(opts) -> []
end

if is_nil(received_email_params) do
refute false
else
refute Enum.any?(email_params, fn {k, v} -> do_match(received_email_params[k], v, k) end),
flunk_attributes_match(email_params, received_email_params)
end
end

@doc false
def do_match(value1, value2 = %Regex{}, _type) do
defp do_match(value1, value2 = %Regex{}, _type) do
Regex.match?(value2, value1)
end

@doc false
def do_match(value1, value2, type) do
defp do_match(value1, value2, type) do
value1 == value2 || value1 == format(value2, type)
end

@doc false
defp format(record, type) do
Bamboo.Formatter.format_email_address(record, %{type: type})
end

@doc false
def flunk_with_email_list(email) do
defp flunk_with_email_list(email) do
if Enum.empty?(delivered_emails()) do
flunk_no_emails_received()
else
Expand All @@ -328,8 +309,7 @@ defmodule Bamboo.Test do
end
end

@doc false
def flunk_no_emails_received do
defp flunk_no_emails_received do
flunk("""
There were 0 emails delivered to this process.
Expand All @@ -344,8 +324,7 @@ defmodule Bamboo.Test do
""")
end

@doc false
def flunk_attributes_do_not_match(params_given, params_received) do
defp flunk_attributes_do_not_match(params_given, params_received) do
"""
The parameters given do not match.
Expand All @@ -359,8 +338,7 @@ defmodule Bamboo.Test do
"""
end

@doc false
def flunk_attributes_match(params_given, params_received) do
defp flunk_attributes_match(params_given, params_received) do
"""
The parameters given match.
Expand Down Expand Up @@ -485,8 +463,7 @@ defmodule Bamboo.Test do
!!Application.get_env(:bamboo, :shared_test_process)
end

@doc false
def normalize_for_testing(email) do
defp normalize_for_testing(email) do
email
|> Bamboo.Mailer.normalize_addresses()
|> Bamboo.TestAdapter.clean_assigns()
Expand Down

0 comments on commit 6aa74c3

Please sign in to comment.