mobilizon/test/support/swoosh_assertions.ex
Thomas Citharel 77308a9477
test(notifications): fix testing email notifications
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
2024-02-08 17:23:22 +01:00

92 lines
2.6 KiB
Elixir

# The following module is taken from this issue
# https://github.com/swoosh/swoosh/issues/488#issuecomment-1671224765
defmodule Mobilizon.Tests.SwooshAssertions do
@moduledoc ~S"""
Assertions for emails.
The assertions provided by this module work by pattern matching
against all emails received by the test process against the
`Swoosh.Email` struct. For example:
assert_email_sent %{subject: "You got a message"}
If you want to be additionally explicit, you might:
assert_email_sent %Swoosh.Email{subject: "You got a message"}
If emails are being sent concurrently, you can use `assert_email_sending/2`:
assert_email_sending %{subject: "You got a message"}
Both functions will return the matched email if the assertion succeeds.
You can then perform further matches on it:
email = assert_email_sent %Swoosh.Email{subject: "You got a message"}
assert email.from == {"MyApp", "no-reply@example.com"}
Using pattern matching imposes two limitations. The first one is that you
must match precisely the Swoosh.Email structure. For example, the following
will not work:
assert_email_sent %{to: "foobar@example.com"}
That's because `Swoosh.Email` keeps the field as a list. This will work:
assert_email_sent %{to: [{"FooBar", "foobar@example.com"}]}
You are also not allowed to have interpolations. For example, the following
will not work:
assert_email_sent %{
subject: "You have been invited to #{org.name}",
to: [{user.name, user.email}]
}
However, you can rely on pattern matching and rewrite it as:
email = assert_email_sent %{subject: "You have been invited to " <> org_name}
assert org_name == org.name
assert email.to == [{user.name, user.email}]
"""
@doc """
Matches an email has been sent.
See moduledoc for more information.
"""
defmacro assert_email_sent(pattern) do
quote do
{:email, email} = assert_received({:email, unquote(pattern)})
email
end
end
@doc """
Matches an email is sending (within a timeout).
See moduledoc for more information.
"""
defmacro assert_email_sending(
pattern,
timeout \\ Application.fetch_env!(:ex_unit, :assert_receive_timeout)
) do
quote do
{:email, email} = assert_receive({:email, unquote(pattern)}, unquote(timeout))
email
end
end
@doc """
Refutes an email matching pattern has been sent.
The opposite of `assert_email_sent`.
"""
defmacro refute_email_sent(pattern) do
quote do
refute_received({:email, unquote(pattern)})
end
end
end