lccezinha

lccezinha

Running live view tests that calls get_connect_params raise error

:phoenix, “~> 1.6.2”
:phoenix_live_view, “~> 0.17.5”

I am trying to follow this post [Phoenix LiveView] formatting date/time with local time zone - DEV Community to handle the proper local timezone for my Phoenix Live View app.

The implementation looks fine and working, but I am facing problems when it comes to testing.

Here is what I have in terms of code:

// app.js

const liveSocket = new LiveSocket('/live', Socket, {
  params: {
    _csrf_token: csrfToken,
    timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
  }
})
# my_file.ex

def mount(%{"state" => state, "user_id" => user_id}, session, socket) do
    {:ok, socket} = assign_defaults(session, socket)

    offices = Locations.list_offices_for_state(state)
    time_zone = get_connect_params(socket)["timezone"] || @default_time_zone

    socket =
      socket
      |> assign(:page_title, "Registration - Schedule | Mindful Care")
      |> assign(:state, state)
      |> assign(:user_id, user_id)
      |> assign(:offices, offices)
      |> assign(:time_zone, time_zone)
      |> reset_state()
      |> assign(:step, "select_office")

    {:ok, socket}
  end
# my_file_test.exs

test "loads offices with providers and sets state", %{
      socket: socket,
      user: user,
      office: office,
      provider: provider
    } do
      params = %{"user_id" => user.id, "state" => office.state_abbr}
      {:ok, socket} = Schedule.mount(params, nil, socket)
  
      assert socket.assigns.page_title == "Registration - Schedule | Mindful Care"
      assert socket.assigns.step == "select_office"
      assert [off] = socket.assigns.offices
      assert off.id == office.id
      assert [prov] = off.providers
      assert prov.id == provider.id
    end

user, office, provider are just factories

So I wanna test if calling this mount will return the data I am expecting. My mount function uses another function Phoenix.LiveView — Phoenix LiveView v1.2.5 to get timezone value, but the call to get_connect_params is raising an error that I can not fix to make my test work.

Error:

  1) test mount/3 loads offices with providers and sets state (MindfulWeb.OnboardingLive.ScheduleTest)
     ** (RuntimeError) attempted to read connect_params outside of MindfulWeb.OnboardingLive.Schedule.mount/3.
     
     connect_params only exists while mounting. If you require access to this information
     after mount, store the state in socket assigns.

Is there any way to bypass this, to preset a value, or even a better approach to test if the mount will set the values I am expecting?

Thanks ahead!

Marked As Solved

trisolaran

trisolaran

How are you creating the socket used in your test?

Usually, when I test a live view I don’t try to inspect the content of the socket assigns or test the single functions of the view. Instead I use the Phoenix.LiveViewTest — Phoenix LiveView v1.2.5 function to spawn the view and then I assert that the view correctly rendered its elements.

Also Liked

mcrumm

mcrumm

Phoenix Core Team

You are trying to write a unit test for your LiveView mount, which is not recommended because in your code you do not invoke the mount callback directly. Instead as German points out in the talk you want to test the lifecycle of your LiveView.

For instance, you can use put_connect_params/2 to simulate the client connection with params:

defmodule MyAppWeb.MyFileTest do
  use MyAppWeb.ConnCase

  test "connect params", %{conn: conn} do
    # Simulate client behaviour
    conn = put_connect_params(conn, %{"timezone" => "America/Chicago"})

    {:ok, view, _html} = live(conn, "/")

    # Assert something about the _rendered output_
    assert render(view) =~ "CDT"
  end
end

Note that you can’t trust client-side data without some kind of validation. In the above example I am asserting on a computed timezone value to imply that some validation took place in order to arrive at the rendered output.

Note also that such an assertion only works if you are rendering the value somewhere on the template. Similar to traditional Controller tests, we want to assert on the side effects of the controller request/response flow as opposed to the state of the things directly after invoking the action function.

lccezinha

lccezinha

Socket is defined in the setup:

setup do
  socket = %Phoenix.LiveView.Socket{}
  {:ok, socket: socket}
end

But your suggestion makes sense, the other tests are being done the way you told, basically took from here: https://www.youtube.com/watch?v=h8NURVLysrk

lccezinha

lccezinha

Thanks, both of you @mcrumm and @trisolaran now I know better how to properly test live view code.

Where Next?

Popular in Questions Top

_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lists...
New
JulienCorb
I am trying to implement my new.html.eex file to create new posts on my website. new.html.eex: <h1>Create Post</h1> <%= ...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: The documentation above suggests that while ...
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
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

Other popular topics Top

mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
Lily
In templates/appointment/index.html.eex: <%= for appointment <- @appointments do %> <tr> <td><%= appoi...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New

We're in Beta

About us Mission Statement