Phoenix test controller with custom plug

Hello,
I have a webhook that I would like to test.
In my endpoint.ex I have custom body reader (this) for my paths configured like this

plug Plug.Parsers,
    parsers: [:urlencoded, :multipart, :json],
    pass: ["*/*"],
    body_reader: {MyApp.Plug.CacheBodyReader, :read_body, only: "/webhook"},
    json_decoder: Phoenix.json_library()

And in my controller I have this plug inserted

defmodule MyApp.Webhook.TypeformController do
  use MyApp, :controller

  alias MyApp.Worker.TypeformResponseNotifier

  plug :accepts, ["json"]
  plug MyApp.Plug.TypeformSignatureVerifier

  def process(conn, _) do
    [answers] = get_in(conn.params, ["form_response", "answers"]) |> AtomicMap.convert()
    answers |> TypeformResponseNotifier.new() |> Oban.insert()

    conn
    |> resp(:ok, "")
  end
end

I would like to test in the controller test that the job is actually scheduled, but It seems that it does not go through my custom cache_body_reader.

The test looks like this

test "POST /webhook/typeform", %{conn: conn} do
    conn = build_conn() |> put_req_header("content-type", "application/json") |> put_req_header( "typeform-signature", "secret")|> post("/webhook/typeform", %{
      "event_type" => "form_response",
      "form_response" => %{"answers" => "xxxx"}
    })

    IEx.pry()
  end

and the tests fails inside typeform_signature_verifier plug because the body of the request is not cached, but it should be according to endpoint.ex

Can you guys help me? Why my test is not going through endpoint.ex and through cache_body_reader?

I think you need to pass the payload as a string (e.g. Jason.encode! it), otherwise it’s mostly passed as-is.

1 Like