Skip to content

Commit

Permalink
test duplicate id / component errors
Browse files Browse the repository at this point in the history
  • Loading branch information
SteffenDE committed Jan 26, 2025
1 parent ee3218e commit ed990cd
Show file tree
Hide file tree
Showing 6 changed files with 322 additions and 12 deletions.
14 changes: 7 additions & 7 deletions lib/phoenix_live_view/test/client_proxy.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ defmodule Phoenix.LiveViewTest.ClientProxy do
uri: nil,
connect_params: %{},
connect_info: %{},
handle_errors: :raise
on_error: :raise

alias Plug.Conn.Query
alias Phoenix.LiveViewTest.{ClientProxy, DOM, Element, View, Upload}
Expand Down Expand Up @@ -84,7 +84,7 @@ defmodule Phoenix.LiveViewTest.ClientProxy do
session: session,
url: url,
test_supervisor: test_supervisor,
handle_errors: handle_errors
on_error: on_error
} = opts

# We can assume there is at least one LiveView
Expand Down Expand Up @@ -114,9 +114,9 @@ defmodule Phoenix.LiveViewTest.ClientProxy do
uri: URI.parse(url),
child_statics: Map.delete(DOM.find_static_views(root_html), id),
topic: "lv:#{id}",
# we store handle_errors in the view ClientProxy struct as well
# we store on_error in the view ClientProxy struct as well
# to pass it when live_redirecting
handle_errors: handle_errors
on_error: on_error
}

# We build an absolute path to any relative
Expand Down Expand Up @@ -149,7 +149,7 @@ defmodule Phoenix.LiveViewTest.ClientProxy do
test_supervisor: test_supervisor,
url: url,
page_title: :unset,
handle_errors: handle_errors
on_error: on_error
}

try do
Expand Down Expand Up @@ -481,12 +481,12 @@ defmodule Phoenix.LiveViewTest.ClientProxy do
end

def handle_info({:test_error, error}, state) do
case state.handle_errors do
case state.on_error do
:raise ->
raise """
#{String.trim(error)}
You can prevent this from raising by passing `handle_errors: :warn` to
You can prevent this from raising by passing `on_error: :warn` to
`Phoenix.LiveViewTest.live/3` or `Phoenix.LiveViewTest.live_isolated/3`.
"""

Expand Down
10 changes: 5 additions & 5 deletions lib/phoenix_live_view/test/live_view_test.ex
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ defmodule Phoenix.LiveViewTest do
## Options
* `:handle_errors` - Can be either `:raise` or `:warn` to control whether
* `:on_error` - Can be either `:raise` or `:warn` to control whether
detected errors like duplicate IDs or live components fail the test or just log
a warning. Defaults to `:raise`.
Expand Down Expand Up @@ -244,7 +244,7 @@ defmodule Phoenix.LiveViewTest do
## Options
* `:session` - the session to be given to the LiveView
* `:handle_errors` - Can be either `:raise` or `:warn` to control whether
* `:on_error` - Can be either `:raise` or `:warn` to control whether
detected errors like duplicate IDs or live components fail the test or just log
a warning. Defaults to `:raise`.
Expand Down Expand Up @@ -347,7 +347,7 @@ defmodule Phoenix.LiveViewTest do
endpoint: Phoenix.Controller.endpoint_module(conn),
session: maybe_get_session(conn),
url: Plug.Conn.request_url(conn),
handle_errors: opts[:handle_errors] || :raise
on_error: opts[:on_error] || :raise
})
end

Expand Down Expand Up @@ -394,7 +394,7 @@ defmodule Phoenix.LiveViewTest do
session: opts.session,
url: opts.url,
test_supervisor: fetch_test_supervisor!(),
handle_errors: opts.handle_errors
on_error: opts.on_error
})

case ClientProxy.start_link(opts) do
Expand Down Expand Up @@ -1815,7 +1815,7 @@ defmodule Phoenix.LiveViewTest do
router: root.router,
session: session,
url: url,
handle_errors: root.handle_errors
on_error: root.on_error
})
end

Expand Down
111 changes: 111 additions & 0 deletions test/phoenix_live_view/integrations/live_view_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,52 @@ defmodule Phoenix.LiveView.LiveViewTest do
{:ok, _view, html} = live(conn, "/classlist")
assert html =~ ~s|class="foo bar"|
end

test "raises for duplicate ids by default", %{conn: conn} do
Process.flag(:trap_exit, true)

{:ok, view, _html} = live(conn, "/duplicate-id")
{{exception, _}, _} = catch_exit(render(view))
assert Exception.message(exception) =~ "Duplicate id found while testing LiveView: a"
assert_receive {:EXIT, _, _}
end

test "raises for duplicate ids when on_error: :raise", %{conn: conn} do
Process.flag(:trap_exit, true)

{:ok, view, _html} = live(conn, "/duplicate-id", on_error: :raise)
{{exception, _}, _} = catch_exit(render(view))
assert Exception.message(exception) =~ "Duplicate id found while testing LiveView: a"
assert_receive {:EXIT, _, _}
end

test "raises for duplicate components by default", %{conn: conn} do
Process.flag(:trap_exit, true)

{:ok, view, _html} = live(conn, "/dynamic-duplicate-component", on_error: :raise)
view |> element("button", "Toggle duplicate LC") |> render_click() =~ "I am LiveComponent2"

{{exception, _}, _} = catch_exit(render(view))

assert Exception.message(exception) =~
"Duplicate live component found while testing LiveView:"

assert_receive {:EXIT, _, _}
end

test "raises for duplicate components when on_error: :raise", %{conn: conn} do
Process.flag(:trap_exit, true)

{:ok, view, _html} = live(conn, "/dynamic-duplicate-component", on_error: :raise)
view |> element("button", "Toggle duplicate LC") |> render_click() =~ "I am LiveComponent2"

{{exception, _}, _} = catch_exit(render(view))

assert Exception.message(exception) =~
"Duplicate live component found while testing LiveView:"

assert_receive {:EXIT, _, _}
end
end

describe "render_*" do
Expand Down Expand Up @@ -388,6 +434,71 @@ defmodule Phoenix.LiveView.LiveViewTest do
)
end
end

test "raises for duplicate ids by default" do
Process.flag(:trap_exit, true)

{:ok, view, _html} =
live_isolated(Phoenix.ConnTest.build_conn(), Phoenix.LiveViewTest.Support.DuplicateIdLive)

# errors are detected asynchronously, so we need to render again for the message to be processed
{{exception, _}, _} = catch_exit(render(view))
assert Exception.message(exception) =~ "Duplicate id found while testing LiveView: a"
assert_receive {:EXIT, _, _}
end

test "raises for duplicate ids when on_error: raise" do
Process.flag(:trap_exit, true)

{:ok, view, _html} =
live_isolated(Phoenix.ConnTest.build_conn(), Phoenix.LiveViewTest.Support.DuplicateIdLive,
on_error: :raise
)

{{exception, _}, _} = catch_exit(render(view))
assert Exception.message(exception) =~ "Duplicate id found while testing LiveView: a"
assert_receive {:EXIT, _, _}
end

test "raises for duplicate components by default" do
Process.flag(:trap_exit, true)

{:ok, view, _html} =
live_isolated(
Phoenix.ConnTest.build_conn(),
Phoenix.LiveViewTest.Support.DynamicDuplicateComponentLive
)

view |> element("button", "Toggle duplicate LC") |> render_click() =~ "I am LiveComponent2"

# errors are detected asynchronously, so we need to render again for the message to be processed
{{exception, _}, _} = catch_exit(render(view))

assert Exception.message(exception) =~
"Duplicate live component found while testing LiveView:"

assert_receive {:EXIT, _, _}
end

test "raises for duplicate components when on_error: raise" do
Process.flag(:trap_exit, true)

{:ok, view, _html} =
live_isolated(
Phoenix.ConnTest.build_conn(),
Phoenix.LiveViewTest.Support.DynamicDuplicateComponentLive,
on_error: :raise
)

view |> element("button", "Toggle duplicate LC") |> render_click() =~ "I am LiveComponent2"

{{exception, _}, _} = catch_exit(render(view))

assert Exception.message(exception) =~
"Duplicate live component found while testing LiveView:"

assert_receive {:EXIT, _, _}
end
end

describe "format_status/2" do
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
defmodule Phoenix.LiveView.LiveViewTestWarningsTest do
use ExUnit.Case, async: false

import ExUnit.CaptureIO

import Phoenix.ConnTest
import Phoenix.LiveViewTest

alias Phoenix.LiveViewTest.Support.Endpoint

@endpoint Endpoint

describe "live" do
test "warns for duplicate ids when on_error: warn" do
conn = Plug.Test.init_test_session(Phoenix.ConnTest.build_conn(), %{})
conn = get(conn, "/duplicate-id")

Process.flag(:trap_exit, true)

assert capture_io(:stderr, fn ->
{:ok, view, _html} = live(conn, nil, on_error: :warn)
render(view)
end) =~
"Duplicate id found while testing LiveView: a"

refute_receive {:EXIT, _, _}
end

test "warns for duplicate component when on_error: warn" do
conn = Plug.Test.init_test_session(Phoenix.ConnTest.build_conn(), %{})
conn = get(conn, "/dynamic-duplicate-component")

Process.flag(:trap_exit, true)

assert capture_io(:stderr, fn ->
{:ok, view, _html} = live(conn, nil, on_error: :warn)

view |> element("button", "Toggle duplicate LC") |> render_click() =~
"I am LiveComponent2"

render(view)
end) =~
"Duplicate live component found while testing LiveView:"

refute_receive {:EXIT, _, _}
end
end

describe "live_isolated" do
test "warns for duplicate ids when on_error: warn" do
Process.flag(:trap_exit, true)

assert capture_io(:stderr, fn ->
{:ok, view, _html} =
live_isolated(
Phoenix.ConnTest.build_conn(),
Phoenix.LiveViewTest.Support.DuplicateIdLive,
on_error: :warn
)

render(view)
end) =~
"Duplicate id found while testing LiveView: a"

refute_receive {:EXIT, _, _}
end

test "warns for duplicate component when on_error: warn" do
Process.flag(:trap_exit, true)

assert capture_io(:stderr, fn ->
{:ok, view, _html} =
live_isolated(
Phoenix.ConnTest.build_conn(),
Phoenix.LiveViewTest.Support.DynamicDuplicateComponentLive,
on_error: :warn
)

view |> element("button", "Toggle duplicate LC") |> render_click() =~
"I am LiveComponent2"

render(view)
end) =~
"Duplicate live component found while testing LiveView:"

refute_receive {:EXIT, _, _}
end
end
end
Loading

0 comments on commit ed990cd

Please sign in to comment.