Test controller who return application/octet-stream

Hello everyone,

I have a controller who return a xlsx file as octet-stream to force the browser to download.

def create(conn, params) do
  buffer = get_buffer_somewhere()
  conn
  |> put_resp_content_type("application/octet-stream")
  |> put_resp_header("Content-disposition", "attachment; filename=spreadsheet.xlsx")
  |> send_resp(200, buffer)
end

I want to test this action.

    test "renders a xlsx document as type application/octet-stream", %{conn: conn} do
      opts = %{
        "type" => "diary",
        "team_id" => team.id,
        "terminal_id" => "",
        "period" => "monthly",
        "period_from" => "",
        "period_to" => ""
      }

      route = Routes.spreadsheet_path(conn, :create, opts)

      build_conn()
      |> put_req_header("accept", "application/octet-stream")
      |> get(route)

    end

I try to add the put_req_header without success even when I add the mime in my config.

     ** (Phoenix.NotAcceptableError) no supported media type in accept header.

     Expected one of ["html"] but got the following formats:

       * "application/octet-stream" with extensions: ["xlsx"]

     To accept custom formats, register them under the :mime library
     in your config/config.exs file:

         config :mime, :types, %{
           "application/xml" => ["xml"]
         }

     And then run `mix deps.clean --build mime` to force it to be recompiled.

Without the put_resp_header I got

test/evoluflor_api_web/controllers/spreadsheet_controller_test.exs:14
     ** (Protocol.UndefinedError) protocol Phoenix.HTML.Safe not implemented for %{errors: %{detail: "Internal Server Error"}} of type Map. This protocol is implemented for the following type(s): Decimal, Phoenix.LiveView.Rendered, Phoenix.LiveView.Comprehension, Phoenix.LiveView.Component, Date, Phoenix.HTML.Form, DateTime, NaiveDateTime, Integer, Atom, List, BitString, Float, Time, Tuple

Thanks for your time.

Since you’re getting a NotAcceptableError take a look at Phoenix.Controller.accepts/2

You were right.
First my header was incorrect it has to be content-disposition no uppercase.
Then in my router I added a new pipeline where I accept the xlsx

plug :accepts, ["xlsx"]

It link to mime type I added in my config

config :mime, :types, %{
 "application/octet-stream" => ["xlsx"]
}

The final test

    test "renders a xlsx document as type application/octet-stream to force browser download", %{conn: conn, team: team} do
      opts = %{
        "type" => "diary",
        "team_id" => team.id,
        "terminal_id" => "",
        "period" => "current_month",
        "period_from" => "",
        "period_to" => ""
      }

      route = Routes.spreadsheet_path(conn, :create, opts)

      conn =
        conn
        |> put_req_header("accept", "application/octet-stream")
        |> get(route)

      assert response_content_type(conn, :xlsx)
      assert response(conn, 200)
    end

Thanks for your help.