defmodule MicrowavepropWeb.Api.ErrorJSONTest do use ExUnit.Case, async: true import Plug.Conn import Plug.Test alias Ecto.Changeset alias MicrowavepropWeb.Api.ErrorJSON defmodule Dummy do @moduledoc false use Ecto.Schema import Changeset embedded_schema do field :name, :string field :age, :integer end def cs(attrs) do %__MODULE__{} |> cast(attrs, [:name, :age]) |> validate_required([:name]) |> validate_number(:age, greater_than: 0) end end describe "send_problem/4" do test "sets content-type, status, halts, and emits a problem+json body" do conn = conn(:get, "/") conn = ErrorJSON.send_problem(conn, 401, "unauthorized", "Token missing.") assert conn.halted assert conn.status == 401 assert get_resp_header(conn, "content-type") == ["application/problem+json; charset=utf-8"] assert %{ "type" => "about:blank", "title" => "unauthorized", "status" => 401, "detail" => "Token missing." } = Jason.decode!(conn.resp_body) end test "merges extra fields into the body" do conn = ErrorJSON.send_problem(conn(:get, "/"), 422, "x", "y", %{errors: %{a: ["b"]}}) assert %{"errors" => %{"a" => ["b"]}} = Jason.decode!(conn.resp_body) end end describe "send_changeset/2" do test "renders flat field error map at status 422" do cs = Dummy.cs(%{age: -1}) conn = ErrorJSON.send_changeset(conn(:get, "/"), cs) assert conn.status == 422 body = Jason.decode!(conn.resp_body) assert body["title"] == "validation_failed" assert %{"name" => ["can't be blank"], "age" => ["must be greater than 0"]} = body["errors"] end end describe "translate_errors/1" do test "interpolates option placeholders into messages" do cs = %Changeset{} |> Map.put(:errors, name: {"too short %{count}", [count: 3]}) |> Map.put(:types, %{name: :string}) |> Map.put(:data, %{}) assert %{name: ["too short 3"]} = ErrorJSON.translate_errors(cs) end end describe "render/2" do for {tpl, expected_status, expected_title} <- [ {"400.json", 400, "bad_request"}, {"401.json", 401, "unauthorized"}, {"403.json", 403, "forbidden"}, {"404.json", 404, "not_found"}, {"405.json", 405, "method_not_allowed"}, {"415.json", 415, "unsupported_media_type"}, {"429.json", 429, "too_many_requests"}, {"500.json", 500, "internal_server_error"} ] do test "produces a problem map for #{tpl}" do body = ErrorJSON.render(unquote(tpl), %{}) assert body.status == unquote(expected_status) assert body.title == unquote(expected_title) end end test "falls back generically for unknown templates" do body = ErrorJSON.render("418.json", %{}) assert body.status == 418 assert body.title == "im_a_teapot" end end end