gianthamster
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?
Trending in Questions
Hey guys,
I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly
Do you guys have any suggestions what is the best prac...
New
Hello!
Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app.
I creat...
New
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
Anyone here using Honeybadger?
My Honeybadger account is being overwhelmed with noise from some bots. Seeing a lot of
Bandit.HTTPError...
New
So my question is quite simple and i have found no conclusive answer on forum, google or AI.
Should we use :erlang.float for Integer to ...
New
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
Other Trending Topics
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
New
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
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
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #blog-post
- #elixir-ls
- #elixirconf-us
- #ai
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
crisefd
Are you testing the code in your
*_live.exfile or are you testing a*_view.exfile?gianthamster
In my
*_live.exfile. The tests generally start with{:ok, view, html} = live(conn, "/quiz/")and then anassert render_click.crisefd
Isn’t the socket’s assigns avaiable from
connobject ?gianthamster
Interesting. The
connbefore the{:ok, view, html} = live(conn, "/quiz/")call has emptyassigns, and thelive(conn, "/quiz/")call doesn’t return an updatedconn, just theviewand the renderedhtml, so I was going to say theconnobject wasn’t even available to the test.But if I break up the call to
liveby doing aconn = get(conn, "/quiz")followed by{:ok, view, html} = live(conn), then that intermediateconndoes indeed have the data I’m looking for in itsassigns.Thanks for the poke, I’d been assuming
conn.assignsboth wasn’t available and wasn’t related to thesocket.assignsanyway.I’m still not sure how to access the assigns later on, after they’ve been changed by some
handle_eventcalls, but that doesn’t matter for this test.chrismccord
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 gogianthamster
I do get that the structure of
assignsis 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 ofassigns. But since we’re here, here’s my passing test:The value of
correct_answeris determined by a quiz-generating call during themountand 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.
DavidRawk-Blake
Wouldn’t this violate functional programming. We’d be testing the side-effects of a function not the input output.
Testing a handle_event should take data in and data out. Regardless of the content of the template
sodapopcan
TL;DR,
LiveViewTest’s purpose is to test the simulated effects of network requests.LiveView tests—while not quite end-to-end tests—are meant to test what the user sees, not the internals. We can see this with the
form/3function not allowing us to fill in hidden fields. We also get a good hint with all therender_functions thatLiveViewTestgives us that are always called just before an assertion. At this abstraction level, the fact that the returned compiled templates are the result of side-effects isn’t important.You can even see this with how LV tests are written:
While we know the
lvvariable itself and its value have not been mutated, the process belonging to thepidit holds has! (or like, you know, it’s been “functionally updated” but for all intents and purposes we could say it has been mutated).lccezinha
If you want a hack approach to access assigns I think you can have it by the conn struct or doing:
:sys.get_state(lv.pid).socket.assigns if I am not wrong.
But that is not a good approach since LV test you should follow an approach simulating the user interaction with your app using the render_* functions.
egeersoz
Template changes resulting from an event are not side effects. They are the main effect, i.e. the final action of the live action. The template reflects the changes that occur as a result of the
handle_event. How exactly those changes happen shouldn’t be relevant to your tests.To come at it from a different perspective: When a user clicks a button on the page, they are concerned with what changes they see as a result. They do not care what your assigns are named or what goes on inside the
handle_eventfunction. Therefore, neither should your tests.Suppose you have template that shows a list of ToDo items with their count in the top left corner, and there’s a button that lets you add a todo item with a given name. A proper test would be to call render_click on the ‘create’ button and assert that the ToDo list contains a new item with the given name, and assert that the new count appears somewhere on the page. A brittle test would be to test that
assigns.todo_itemscontains the new todo item andassigns.to_do_countis original + 1. The former is what the user cares about. The latter is an implementation detail, and such a test will break if, for example, the assigns are renamed during a refactor.