Sending top-level JSON in body of request to Phoenix controller in tests

anyone know how to pass a top-level JSON list as the body of the request to a phoenix controller? this is what I have so far:

api_v2_users_path(
            conn,
            :update,
            @user_one_id,
            _json: %{
              0 => %{op: "replace", path: "/firstName", value: "George"},
              1 => %{op: "replace", path: "/lastName", value: "Jungle"}
            }
          )

When I pass it an actual list I get an error:

** (ArgumentError) cannot encode maps inside lists when the map has 0 or more than 1 elements, got: %{op: "replace", path: "/firstName", value: "George"}

this is inside a test
when I pass it

%{
              0 => %{op: "replace", path: "/firstName", value: "George"},
              1 => %{op: "replace", path: "/lastName", value: "Jungle"}
            }

it isn’t converted to a list by the time it reaches the controller function

to give context, I am trying to test my controller which responds to a HTTP Patch request.

How exactly are you trying to test?

    test "can be used to update a field on a user", %{conn: conn} do
      result =
        conn
        |> put_req_header("authorization", @auth_token)
        |> patch(
          api_v2_users_path(
            conn,
            :update,
            @user_one_id,
            _json: %{
                         0 => %{op: "replace", path: "firstName", value: "George of the"},
                        1 => %{op: "replace", path: "lastName", value: "Jungle"}
                      }
          )
        )
        |> json_response(200)

        ... assertions ...
    end

I’m not sure if you should provide that field to the path-helper…

Instead I’d provide the JSON as a string to the body parameter of patch, something like this:

patch(conn, api_v2_users_path(YourApp.Endpoint, :update, @user_one_id), ~s'[{"item": 1}, {"item": 2}]')

But I do not have a project at hand to test it. Its just an aussmption, based on the fact that the path helpers append parameters to the query-part of the URL.

3 Likes

Thank you @NobbZ, that has solved the problem.

Here is my implementation, for others:

      conn
      |> put_req_header("authorization", @user_one_token)
      |> put_req_header("content-type", "application/json")
      |> patch(
        api_v2_users_path(
          conn,
          :update,
          @user_one_id
        ),
        Poison.encode!([%{op: "dunno", path: "/not/sure", value: "x"}])
      )
4 Likes