coen.bakker

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

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

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

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

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.

Where Next?

Popular in Questions Top

electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New

Other popular topics Top

minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 55125 245
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
274 42716 114
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

We're in Beta

About us Mission Statement