Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accept timeout option in test helpers #605

Merged
merged 1 commit into from
May 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 43 additions & 25 deletions lib/bamboo/test.ex
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,17 @@ 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) do
defmacro assert_delivered_email(email, opts \\ []) do
quote do
import ExUnit.Assertions
email = Bamboo.Test.normalize_for_testing(unquote(email))
assert_receive({:delivered_email, ^email}, 100, Bamboo.Test.flunk_with_email_list(email))
timeout = Bamboo.Test.get_timeout(unquote(opts))

assert_receive(
{:delivered_email, ^email},
timeout,
Bamboo.Test.flunk_with_email_list(email)
)
end
end

Expand All @@ -181,10 +187,11 @@ defmodule Bamboo.Test do
assert text_body =~ "Welcome to MyApp, #\{user_name}"
assert text_body =~ "You can sign up at https://my_app.com/users/#\{user_name}"
"""
defmacro assert_delivered_email_matches(email_pattern) do
defmacro assert_delivered_email_matches(email_pattern, opts \\ []) do
quote do
import ExUnit.Assertions
ExUnit.Assertions.assert_receive({:delivered_email, unquote(email_pattern)})
timeout = Bamboo.Test.get_timeout(unquote(opts))
ExUnit.Assertions.assert_receive({:delivered_email, unquote(email_pattern)}, timeout)
end
end

Expand Down Expand Up @@ -220,10 +227,11 @@ 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) do
quote bind_quoted: [email_params: email_params] do
defmacro assert_email_delivered_with(email_params, opts \\ []) do
quote bind_quoted: [email_params: email_params, opts: opts] do
import ExUnit.Assertions
assert_receive({:delivered_email, email}, 100, Bamboo.Test.flunk_no_emails_received())
timeout = Bamboo.Test.get_timeout(opts)
assert_receive({:delivered_email, email}, timeout, Bamboo.Test.flunk_no_emails_received())

received_email_params = email |> Map.from_struct()

Expand All @@ -233,11 +241,23 @@ defmodule Bamboo.Test do
end

@doc """
Check that no email was sent with the given parameters
Check that no email was sent with the given parameters.

Similar to `assert_email_delivered_with/1`, but it checks that an email with
those parameters wasn't sent.

Note that this assertion helper will grab the email out of the process
mailbox. So if you want to make other assertions about the same email after
this assertion, you need to send the email again.

## Examples

Bamboo.Email.new_email(subject: "something") |> MyApp.Mailer.deliver()
refute_email_delivered_with(subject: "something else") # Will pass

Bamboo.Email.new_email(subject: "something") |> MyApp.Mailer.deliver()
refute_email_delivered_with(subject: ~r/some/) # Will fail

If `Bamboo.Test` is used with shared mode, you must also configure a timeout
in your test config.

Expand All @@ -247,27 +267,22 @@ defmodule Bamboo.Test do
The value you set is up to you. Lower values may result in faster tests, but
your tests may incorrectly pass if an email is delivered *after* the timeout.

Note that this assertion helper will grab the email out of the process
mailbox. So if you want to make other assertions about the same email after
this assertion, you need to send the email again.
You can also pass a timeout for a given refutation:

## Examples

Bamboo.Email.new_email(subject: "something") |> MyApp.Mailer.deliver
refute_email_delivered_with(subject: "something else") # Will pass

Bamboo.Email.new_email(subject: "something") |> MyApp.Mailer.deliver
refute_email_delivered_with(subject: ~r/some/) # Will fail
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) do
quote bind_quoted: [email_params: email_params] do
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() -> []
Bamboo.Test.refute_timeout(opts) -> []
end

if is_nil(received_email_params) do
Expand Down Expand Up @@ -388,11 +403,11 @@ defmodule Bamboo.Test do
but may incorrectly pass if an email is delivered *after* the timeout. Often
times 1ms is enough.
"""
def assert_no_emails_delivered do
def assert_no_emails_delivered(opts \\ []) do
receive do
{:delivered_email, email} -> flunk_with_unexpected_email(email)
after
refute_timeout() -> true
refute_timeout(opts) -> true
end
end

Expand Down Expand Up @@ -427,13 +442,13 @@ defmodule Bamboo.Test do
but may incorrectly pass if an email is delivered *after* the timeout. Often
times 1ms is enough.
"""
def refute_delivered_email(%Bamboo.Email{} = email) do
def refute_delivered_email(%Bamboo.Email{} = email, opts \\ []) do
email = normalize_for_testing(email)

receive do
{:delivered_email, ^email} -> flunk_with_unexpected_matching_email(email)
after
refute_timeout() -> true
refute_timeout(opts) -> true
end
end

Expand All @@ -448,7 +463,7 @@ defmodule Bamboo.Test do
end

@doc false
def refute_timeout do
def refute_timeout(opts \\ []) do
if using_shared_mode?() do
Application.get_env(:bamboo, :refute_timeout) ||
raise """
Expand All @@ -462,7 +477,7 @@ defmodule Bamboo.Test do
but may incorrectly pass if an email is delivered *after* the timeout.
"""
else
100
Keyword.get(opts, :timeout, 100)
end
end

Expand All @@ -476,4 +491,7 @@ defmodule Bamboo.Test do
|> Bamboo.Mailer.normalize_addresses()
|> Bamboo.TestAdapter.clean_assigns()
end

@doc false
def get_timeout(opts), do: Keyword.get(opts, :timeout, 1000)
end
47 changes: 47 additions & 0 deletions test/lib/bamboo/adapters/test_adapter_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,14 @@ defmodule Bamboo.TestAdapterTest do

assert_delivered_email(%{email | assigns: :assigns_removed_for_testing})
end

test "accepts timeout" do
email = new_email(from: "foo@bar.com", to: "bar@baz.com")

email |> TestMailer.deliver_now()

assert_delivered_email(email, timeout: 1)
end
end

describe "refute_delivered_email/1" do
Expand Down Expand Up @@ -142,6 +150,12 @@ defmodule Bamboo.TestAdapterTest do
refute_delivered_email(sent_email)
end
end

test "accepts a timeout configuration" do
unsent_email = new_email(from: "foo@bar.com")

refute_delivered_email(unsent_email, timeout: 1)
end
end

describe "assert_email_delivered_with/1" do
Expand Down Expand Up @@ -216,6 +230,14 @@ defmodule Bamboo.TestAdapterTest do
assert_email_delivered_with(text_body: ~r/tea/)
end
end

test "accepts timeout" do
email = new_email(from: "foo@bar.com", to: "bar@baz.com")

email |> TestMailer.deliver_now()

assert_email_delivered_with([from: "foo@bar.com"], timeout: 1)
end
end

describe "refute_email_delivered_with/1" do
Expand Down Expand Up @@ -259,6 +281,14 @@ defmodule Bamboo.TestAdapterTest do
refute_email_delivered_with(text_body: ~r/coffee/)
end
end

test "accepts a timeout configuration" do
mail = new_email(to: [nil: "foo@bar.com"], from: {nil, "baz@bar.com"})

TestMailer.deliver_now(mail)

refute_email_delivered_with([to: [nil: "something@else.com"]], timeout: 1)
end
end

describe "assert_no_emails_sent/0" do
Expand Down Expand Up @@ -296,6 +326,15 @@ defmodule Bamboo.TestAdapterTest do
assert_no_emails_delivered()
end
end

test "accepts a timeout configuration" do
sent_email = new_email(from: "foo@bar.com", to: "whoever")
sent_email |> TestMailer.deliver_now()

assert_raise ExUnit.AssertionError, fn ->
assert_no_emails_delivered(timeout: 1)
end
end
end

describe "assert_delivered_email_matches/1" do
Expand All @@ -312,5 +351,13 @@ defmodule Bamboo.TestAdapterTest do
assert_delivered_email_matches(%{to: [{nil, email}]})
assert email == "foo@bar.com"
end

test "accepts timeout" do
sent_email = new_email(from: "foo@bar.com", to: ["foo@bar.com"])

TestMailer.deliver_now(sent_email)

assert_delivered_email_matches(%{to: [{nil, "foo@bar.com"}]}, timeout: 1)
end
end
end