Phoenix route helpers are behaving inconsistently in tests

So I’m working through some tests from a generated chunk of Phoenix bits, and oddly enough the route helper functions are not behaving consistently.

The generated tests worked fine until I forced auth on certain endpoints, which I was able to work through for most things, but in this particular test I’m getting stuck with the following error:

     ** (ArgumentError) PxblogWeb.Router.Helpers.post_path/3 called with invalid params.
     The last argument to this function should be a keyword list or a map.
     For example:
         post_path(conn, :index, page: 5, per_page: 10)
     It is possible you have called this function without defining the proper
     number of path segments in your router.
     code: conn = get(conn, Routes.post_path(conn, :show, my_post))

The confusing part is that the code looks like this:

      my_post = Content.get_post!(id)
      assert redirected_to(conn) == Routes.post_path(conn, :show, my_post)

      conn = get(conn, Routes.post_path(conn, :show, my_post))
      assert html_response(conn, 200) =~ "Show Post"

You can see that I get a %Post{} struct, then call Routes.post_path/3 to generate a string like /posts/71. This works just fine. But then very next line makes the very same call to the same function, and it throws the above error.

The error message is… odd, at best. It says that the final argument must be a map or keyword list, which I am indeed passing. But then if I try any sort of keyword list, it bails with the same error, which is extra weird.

Any pointers? I know I can just build the path I want, but it seems silly to need to do so when it worked one line above. :slight_smile:

To add to the weirdness, this fails in the exact same way:

      my_post = Content.get_post!(id)
      redirect_path = Routes.post_path(conn, :show, my_post)
      assert redirected_to(conn) == redirect_path

      new_conn = get(conn, redirect_path)
      assert html_response(new_conn, 200) =~ "Show Post"

I was under the impression that Elixir doesn’t do full-on lazy evaluation of expressions, yea?

Also, still weird that it’s totally fine in the first assert, but the new_conn complains. I’m very lost!

(Forgot to mention earlier, too, this doesn’t seem to happen in normal usage of the app, only in test contexts.)

I think you might need to recycle the conn, see

I can’t remember the exact reasons why and I’m not 100% sure it will help but worth a try.

1 Like

Oh, neat! I hadn’t seen that particular function.

That said, it sadly didn’t help. :frowning:

I also tried creating an entirely new conn and initializing it the same way as the first one, but it still bails.

I’m missing something in how these helpers work, I think.

Aha! I figured it out - I wasn’t paying close enough attention to the stacktrace it was giving me. I didn’t copy the whole thing into the first post because, well, I’m silly like that. :slight_smile:

The second line here was the clincher - lib/pxblog_web/templates/show.html.eex:18

       (phoenix) lib/phoenix/router/helpers.ex:358: Phoenix.Router.Helpers.invalid_param_error/5
       (pxblog) lib/pxblog_web/templates/post/show.html.eex:18: PxblogWeb.PostView."show.html"/1
       (pxblog) lib/pxblog_web/templates/layout/app.html.eex:35: PxblogWeb.LayoutView."app.html"/1
       (phoenix) lib/phoenix/view.ex:410: Phoenix.View.render_to_iodata/3

The call to post_path/3 that was failing was not at all in my test code - it was in the template! I had made a change to nest a particular path (/posts) under /users/:id, which meant I had to update my post_path calls to user_post_path, and include the user ID in those calls. I later reverted that change because I didn’t care for that URL pathing, and I apparently missed that particular template - because I wasn’t using the “Back” link that was in it, and was calling post_path with an extra argument.

Whew! No magic involved, and no reason I couldn’t have found it more quickly if I had paid more attention to the stacktrace I was so conveniently handed. :slight_smile:

1 Like