MailglassInbound.MailboxCase (MailglassInbound v1.5.1)

Copy Markdown View Source

The shipped ExUnit.CaseTemplate adopters use to test inbound mailboxes the inbound analog of outbound's Mailglass.MailerCase, and the keystone that ties the inbound Testing helpers together.

use MailglassInbound.MailboxCase injects import MailglassInbound.TestAssertions and the Fixtures/Test aliases, checks out an Ecto sandbox on the adopter's configured repo, sets tenancy, resets the only process-global state the inbound fixtures touch, and tears the sandbox down on exit.

Ships in lib/ (not test/support/)

Like the other inbound Testing helpers, this case template ships in the mailglass_inbound Hex package via the files: ~w(lib …) manifest so adopters can use it from their own suites. Because it ships in lib/ it references ONLY core/runtime modules — never Oban, ExAws, or Plug.Test (Pitfall 6), so it compiles cleanly under mix compile --no-optional-deps --warnings-as-errors.

The adopter's repo is resolved from app-env

The sandbox is checked out on the repo resolved from Application.get_env(:mailglass_inbound, :repo), exactly like the MailglassInbound.Repo facade. The case template NEVER references the package's own test repo literal — the package does not own a repo (Pitfall 1). Adopters configure one in config/test.exs:

config :mailglass_inbound, :repo, MyApp.Repo

If unset, setup raises with that exact instruction. (The package's own self-tests work because config/test.exs points :repo at the support repo under test/support.)

It snapshots NO app-env

Unlike Mailglass.MailerCase (which snapshots/restores its async-mode application-env keys so deliver_later/2 runs inline), this case template writes and restores no application-env key. Inbound achieves synchronous execution structurally: MailglassInbound.Test.Ingress drives MailglassInbound.Execution.execute/2 (SYNC) directly — there is no async-mode app-env key to flip and therefore no leak surface across tests The only teardown is Sandbox.stop_owner/1; the only shared-state hygiene is the per-setup ETS / process-dict reset below.

Default setup

Supported tags

  • @tag tenant: "acme" — override the default "test-tenant"
  • @tag tenant: :unset — disable tenancy stamping
  • @tag async: false — disable async (sandbox checks out in shared mode)

Example

defmodule MyApp.WelcomeMailboxTest do
  use MailglassInbound.MailboxCase, async: false

  test "accepts a welcome message" do
    message = Fixtures.build_inbound_message(subject: "Welcome")

    {:ok, %{outcome: %{outcome: :accept}, route: %{mailbox: MyApp.WelcomeMailbox}}} =
      Test.Ingress.receive_inbound(message, routes: my_routes())

    # ONE assertion per drive: each `assert_inbound_*` reads the captured
    # tuple with `assert_received`, which CONSUMES it from the process
    # mailbox. To run a second assertion, drive a second message (with a
    # distinct `provider_message_id` so it is a fresh receive).
    assert_inbound_received(subject: "Welcome")
  end
end