gianthamster

gianthamster

Accessing assigns in LiveView test?

I’m working on a multiple-choice quiz application that uses LiveView for its interface. The questions are randomly selected from a larger set, and then stored in the socket’s assigns, along with their answers.

When testing the LiveView, I’d like to look at a question contained in the assigns (and along with it, its answer), so I can then test what happens when a right answer or wrong answer is selected by the user. However, I don’t see an easy way to access the socket and its assigns from the test case itself – just the HTML of the rendered view.

Am I missing a simple way to get at socket.assigns in a Phoenix.LiveViewTest, or will I need to mock the quiz interface so it always returns something non-random in the test environment?

Marked As Solved

crisefd

crisefd

Isn’t the socket’s assigns avaiable from conn object ?

https://hexdocs.pm/phoenix/plug.html

Also Liked

chrismccord

chrismccord

Creator of Phoenix

Note that you should test the results of the LV rendered content rather than the assigns. Reaching into the assigns is internal state and will lead to a brittle test. So using the render_* functions and asserting on the expected side effects is the way to go :slight_smile:

13
Post #6
gianthamster

gianthamster

Interesting. The conn before the {:ok, view, html} = live(conn, "/quiz/") call has empty assigns, and the live(conn, "/quiz/") call doesn’t return an updated conn, just the view and the rendered html, so I was going to say the conn object wasn’t even available to the test.

But if I break up the call to live by doing a conn = get(conn, "/quiz") followed by {:ok, view, html} = live(conn), then that intermediate conn does indeed have the data I’m looking for in its assigns.

Thanks for the poke, I’d been assuming conn.assigns both wasn’t available and wasn’t related to the socket.assigns anyway.

I’m still not sure how to access the assigns later on, after they’ve been changed by some handle_event calls, but that doesn’t matter for this test.

gianthamster

gianthamster

I do get that the structure of assigns is a lot more likely to change than the contents of the view, and that other people working on the same code might not expect the tests to depend on the structure of assigns. But since we’re here, here’s my passing test:

  test "correct answer clicked", %{conn: conn} do
    conn = get(conn, "/quiz")
    {:ok, view, _html} = live(conn) 

    correct_answer = conn.assigns.correct_answer
    expected = "Congratulations! You got it right!"

    assert render_click(view, :answer, %{option: correct_answer}) =~ expected
  end

The value of correct_answer is determined by a quiz-generating call during the mount and is completely random – while the answer to ‘What sound does a cat make?’ will always be ‘Meow’, sometimes that’ll be the first answer, sometimes that’ll be the second answer, etc.

I don’t consider myself particularly skilled here, so this is my chance to learn something – instead of doing what I’ve done, how would you test something like this? Mock the quiz-generating function? Pass an anonymous answer-sorting function to the quiz-generating function as a variable, and use a deterministic one in test? Click on every link, add up the results, and assert that the ‘correct answer’ result happened once and only once? Change the implementation so the correct answer isn’t in the assigns at all, but fetched from the backend after every answer? I considered all of these instead of dipping into the assigns, but didn’t love any of them – the increased complexity didn’t seem worth it.

Where Next?

Popular in Questions Top

sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
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
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
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
Lily
In templates/appointment/index.html.eex: <%= for appointment <- @appointments do %> <tr> <td><%= appoi...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
nobody
Hi! In PHP: $SERVER['SERVERADDR'] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
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
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
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 fore...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
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
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
hariharasudhan94
Lets say i have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => "XX...
New

We're in Beta

About us Mission Statement