How to test a live_redirect?

I’m writing some tests for a LiveView app: how should I properly/idiomatically create an assertion for a view like the following:

{:live_redirect,
  %{
    flash: "flash",
    kind: :push,
    to: "/xxx/<id>/edit"
  }}}

where the id is not known, but it’s generated by a form submission. Is there a better way than extract the to: path and assert it with a regex?

Thanks!

1 Like

I’m not proficient with live_view, may be there is way to achieve that, but in one project in tests I was using follow_redirect(live, conn, route) and then asserting on some results in there (like the existence of new “flash” message).
Surely without knowing the :id that’s not the case in this scenario…

However, how is that id generated? can’t we either “bypass” that id with some dummy value in the test or reuse the same helper that generates the id?

1 Like

The assert_redirect/2 helper sounds like what you want:

https://hexdocs.pm/phoenix_live_view/Phoenix.LiveViewTest.html#assert_redirect/2

2 Likes

can’t we either “bypass” that id with some dummy value in the test or reuse the same helper that generates the id

nope… the id is a postgresql primary id, I don’t think I can set it without making the code very contrived.

The assert_redirect/2 helper sounds like what you want

I tried it, but I’m getting an error message. Here is the test code:

view
|> element("form")
|> render_submit(%{item: params})
|> assert_redirect()
** (MatchError) no match of right hand side value: {:error, {:live_redirect, %{flash: "flash", kind: :push, to: "/xxx/123/edit"}}}
     code: |> assert_redirect()

I don’t quite understand where is the left hand side of the assertion…

assert_redirect/2 tries to match on a :redirect tuple, so it’s going to fail in this way for a :live_redirect.

If you’re interested in the id you could leverage the ArgumentError thrown by follow_redirect/3 when the to argument doesn’t match:

message =
  catch_error(
    view
    |> element("form")
    |> render_submit(%{item: params})
    |> follow_redirect(conn, "xxx/0/edit")
  )
  |> Exception.message()

%{"id" => id} =
  ~r'expected LiveView to redirect to \"xxx/0/edit\", but got \"/xxx/(?<id>.*)/edit\"'
  |> Regex.named_captures(message)

IO.inspect(id, label: "id")

Or at least assert it raises.

excellent idea, thanks!

1 Like