jack

jack

About Phoenix LiveView, LiveView Life-Cycle and Testing

So I was taking a look at documentation and other people code as well to understand a bit more about LiveView and specially, how to test it.

I’m still a bit confuse about some things, so those are probably very basic questions but I would appreciate any possible help, tip or advice.

Let’s take this example.

import Plug.Conn
import Phoenix.ConnTest
import Phoenix.LiveViewTest
@endpoint MyEndpoint

test "disconnected and connected mount", %{conn: conn} do
  conn = get(conn, "/my-path")
  assert html_response(conn, 200) =~ "<h1>My Disconnected View</h1>"

  {:ok, view, html} = live(conn)
end

We have this test for “disconnected and connected mount”.
I have a couple of questions about this.
The first one is what the endpoint tag purpose, I still didn’t found about it in the docs (I’m a bit in a hurry so I’m not reading it sequentially, maybe that’s why)

Now, I wonder why would I test “disconnected” and then “connected” mount in the same test case.
But before that, what really does a “disconnected mount” mean? I’ve been searching for this both on Google and on docs, but didn’t found any clarification about it.

As I understand the LiveView Life-Cycle so far is like this:

You receive a regular HTTP Request, it triggers mount/3, then handle_params/3, then render/1, and return a stateless, regular Web Page as HTTP Response.
Then, a WebSocket connection will start triggering mount/3 → handle_params/3 → render/1 again.

What a disconnected mount mean in this cycle?


Just like in this code example above, I’ve found people testing “disconnected mount” in their code as well.

assert html_response(conn, 200) =~ "<h1>My Disconnected View</h1>"

Like this code suggest, I saw people testing it like this: If I render a table, I would test the table empty instead.

My question is how?
If I use mount/3 or handle_params/3 to load the contents of my page, like executing a query to populate a table, how do so I could test for an “empty table” if I’m receiving a page after the complete life-cycle?

Right now I’m prototyping an application to learn and practice LiveView, I have the table as LiveComponents, do I could test successfully passing one valid list to the live component with render_component/2 and asserting the result. This is because I can control the params received in a live component, so I can test it and assert that only one <td> was created if I only passed one element in the list as params.

But if I use the mount/3 function to fetch data testing the liveview page instead of an isolated component, I’ll not be able to ever see this table empty.
Isn’t that what I’m supposed to do? Isn’t mount/3 where I fetch data to prepare the page for the response?

So, what a “disconnected mount” means, and what is the difference to a connected mount?
Can I receive the HTTP response after mount/3 but before handle_params/3?
Can I have a mount/3 for the HTTP response and another mount/3 that will execute only after the WebSocket being stablished?
(Like not fetching data from database in the HTTP request but fetching after a Live Socket start?)

Additionally how can I, in a test, force a failed connection to the database?

Sorry, those are a lot of questions, but I’m still a bit lost about how to test things both on Phoenix as a whole but specially about LiveView. I was wondering for a good bit why people wasn’t using controllers but doing everything on LiveView for example, so is the LiveView supposed to be both Controller, View and Template?
(and possible all three in the same file since you can render a sigil/literal instead of creating a separate template…)

I’m having a lot of fun learning LiveView but I’m not sure on how to do it “right”, I mean, in an organised and well designed way.
Should I call my (context/model) functions directly from LiveView? Or is it a better design to create a Controller, call the Controller from the LiveView, and then this Controller will interact with the Context?
This is not how I’m seeing people use it but I thought that LiveView would only be another type of “View”, I was surprised about it acting as a Controller in a lot of code I’m consuming to learn from.

Thank you for taking your time to read this until the end.

First 2 of 2 Posts Switch mode

cmo

cmo

First mount is disconnected which creates the websocket connection, rest of it happens over websocket (until you redirect etc). You can call connected?(socket) and it will be false for the first mount. You can setup a page with loading placeholders for things here if you like, which will populate either on the connected mount or you could send(self(), {:load_some_thing, ...}) in the mount so you can load the page first or you can do it async and send a message back to the liveview to assign it later.

Should I call my context/module from the LiveView?

Yep. You don’t need much in the way of controllers if your site is all live views. I don’t think of my project in terms of Models, Controllers and Views. I just build a UI in LiveView and call functions in modules :slight_smile:.

To learn about the lifecycle, you might like to watch this talk

This course might be of use to you. They go through the lifecycle and more.

jack

jack OP

Thank you for taking your time to reply cmo!

Your explanation was very helpful, honestly I understood what a disconnect mount is for your reply only.
The docs was not very clear for me, and the talk… I had watched it before and just watch it a second time right now and although it’s entertaining, for someone who is already confused about it showing non-working code it’s not really helpful. I liked the talk and I learned some things but not really about the life cycle itself… :sweat_smile:

I will take a look at the course, thank you!

— All posts loaded —

Where Next?

Trending in Questions Top

jonnycharles
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
spammy
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
silverdr
Using Phoenix.LiveView.TagEngine as an EEx.Engine is deprecated! To compile HEEx, use Phoenix.LiveView.TagEngine.compile/2 instead. Sta...
New
dli
Before I dive in myself, did anyone successfully sprinkle Hologram into their existing LiveView app? Looking for hints regarding: Addi...
New
bottlenecked
Hi all, I wanted to ask how the community is dealing with post-release steps. Today we have Ecto migrations, which make sure that the db...
New
michallepicki
I am using Oban and occasionally, shortly after a deployment, a handful of jobs can fail because of dependency on other parts of the syst...
New
rahultumpala
Hello, I have an Elixir backend that implements a custom protocol over TCP. I want to load test the backend and assess the performance o...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
type1fool
I just stumbled on a newly redesigned elixir-lang.org. :tada: It looks like @Software_Mansion did the work, and I think it is generally a...
New
akoutmos
@hugobarauna and I (Alex Koutmos) have been hard at work on writing a book on Nerves that takes you from simply blinking LEDs to building...
New

We're in Beta

About us Mission Statement