coen.bakker
Testing `attach_hook/4` raises ** (KeyError) key :lifecycle not found in: %{__temp__: %{}}`
I wanted to test this server-side hook.
def on_mount(:default, _params, _session, socket) do
socket =
socket
|> assign(dialog_open: false)
|> assign(dialog_inner_block: nil)
|> assign(dialog_history: [])
|> attach_hook(:dialog_hook, :handle_event, &handle_event/3) # Causes error
{:cont, socket}
end
def handle_event("reset_dialog", _, socket) do
...
end
With this test.
setup %{conn: conn} do
%{conn: init_test_session(conn, %{})}
end
describe "on_mount: default" do
test "assigns dialog_open: false", %{conn: conn} do
session = get_session(conn)
{:cont, updated_socket} = Dialog.DialogHook.on_mount(:default, %{}, session, %LiveView.Socket{})
assert updated_socket.assigns.dialog_open == false
end
end
But I ran into this error.
1) test on_mount: default assigns dialog_open: false (MyAppWeb.DialogTest)
test/my_app_web/dialog_test.exs:26
** (KeyError) key :lifecycle not found in: %{__temp__: %{}}
code: {:cont, updated_socket} = Dialog.DialogHook.on_mount(:default, %{}, session, %LiveView.Socket{})
stacktrace:
:erlang.map_get(:lifecycle, %{__temp__: %{}})
(phoenix_live_view 0.19.5) lib/phoenix_live_view/lifecycle.ex:92: Phoenix.LiveView.Lifecycle.lifecycle/2
(phoenix_live_view 0.19.5) lib/phoenix_live_view/lifecycle.ex:45: Phoenix.LiveView.Lifecycle.attach_hook/4
(my_app 0.1.0) lib/my_app_web/dialog/dialog_hook.ex:11: MyAppWeb.Dialog.DialogHook.on_mount/4
test/my_app_web/dialog_test.exs:29: (test)
The socket.private doesn’t contain the key :lifecycle.
%LiveView.Socket{}
|> Map.get(:private)
|> IO.inspect()
=> %{__temp__: %{}}
I have been reading docs and searching around online, but cannot seem to find how to test this scenario.
How would I go about this? Any ideas?
Most Liked
LostKobrakai
I don’t think you can test those callbacks in isolation due to missing simple constructors for that state involved.
Instead I’d suggest creating a full LV module within the test and interact with that one to assert the hooks functionality.
sodapopcan
With LiveView tests you can only assert on behaviour, ie, on the outputted HTML. Well, ok, you can use :sys.get_state to look at a process’ state, but I realllllly wouldn’t recommend it.
Harking back to your recent post regarding testing, these are the types of unit tests I don’t bother with. Dialogs are very simple so there is really nothing to be gained from unit testing them in that way. So long as they open, display the correct contents, and all the buttons do what they are supposed to, then the desin of the internal state really doesn’t matter. It also means you could rejig the internals later on without changing the test. That is to say, a LiveViewTest asserting on HTML in a LiveView test is perfectly adequate here. Just my opinion, of course.
coen.bakker
And I started reading the “Testing Elixir” book. Have good hope I’ll learn some valuable lessons from it. Want to demystify testing…
Last Post!
sodapopcan
I’ve seen people say they prefer to use hooks. I haven’t studied the livebook example you shared, but in general it can be simpler to use hooks over a component if the LiveView needs to know any state, that way you can avoid having to notify_parent. But if all the state can be encapsulated then I feel a LiveComponent is a little clearer, but honestly both are pretty good, ha. I’m actually still not super comfortable with LiveComponents because I do try and avoid them, but for things like this where there are clear boundaries I use them.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex









