germsvel

germsvel

PhoenixTest - a unified way of writing feature tests for LiveView and static pages

PhoenixTest provides a unified way of writing feature tests – regardless of whether you’re testing LiveView pages or static pages.

It also handles navigation between LiveView and static pages seamlessly. You don’t have to worry about what type of page you’re visiting or navigating to. So, you can test a flow going from static to LiveView pages and back without having to worry about the underlying implementation.

Just write your tests from the user’s perspective. :sparkles:

Why create PhoenixTest?

With the advent of LiveView, I find myself writing less and less JavaScript.

Sure, there are sprinkles of it here and there, and there’s always the occasional need for something more.

But for the most part, if I’m going to build a page that needs interactivity, I use LiveView. If I’m going to write a static page, I use regular controllers + views/HTML modules.

The problem is that LiveView pages and static pages have vastly different testing strategies.

If I use LiveView, I can write my tests like this:

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

html =
  view
  |> element("#greet-guest")
  |> render_click()

assert html =~ "Hello, guest!"

But if I want to test a static page, we have to resort to controller testing:

conn = get(conn, ~p"/greet_page")

assert html_response(conn, 200) =~ "Hello, guest!"

That means I don’t have ways of interacting with static pages at all!

What if I want to submit a form or click a link? And what if a click takes me from a LiveView to a static view or vice versa?

A Unified way of writing feature tests

So, I wanted a unified way of writing feature tests – regardless of whether or not you’re testing LiveView pages or static pages.

And that’s what PhoenixTest does!

Imagine having a workflow that starts on a static page. We click a link and are taken to a LiveView page. Then, we fill a LiveView form (which could even have its phx-change triggered), and then we submit the form. Finally, we assert that what we expect to see is present.

All of that in a succinct, pipe-friendly way!

test "can create a user", %{conn: conn} do
  conn
  |> visit("/")  # <- could be LiveView or static page
  |> click_link("Users") # <- navigate between LiveViews and static pages
  |> fill_form("#user-form", name: "Aragorn", email: "aragorn@dunedain.com")
    # ^ will trigger `phx-change` if present
  |> click_button("Create") # <- submits LiveView forms and regular forms
  |> assert_has(".user", "Aragorn") # <- provides better error messages
end

Improving assertions

Then there’s the problem of assertions.

Because LiveView and controller tests use =~ for assertions, the error messages aren’t very helpful when assertions fail.

After all, we’re just comparing two blobs of text – and trust me, HTML pages can get very large and hard to read as a blob of text in your terminal.

LiveView tries to help with the has_element?/3 helper, which allows us to target elements by CSS selectors and text.

But, unfortunately, it still doesn’t provide the best errors.

has_element?/3 only tells us what was passed into the function. It doesn’t give us a clue as to what else might’ve been on the page – maybe we just made a small typo and we have no idea!

With PhoenixTest.assert_has/3 and PhoenixTest.refute_has/3, we can provide better errors when assertions fail.

How did you write feature tests before?

In the past, I would’ve used Wallaby to write feature tests.

But since I’m not writing as much JavaScript, I don’t feel the need for something so heavy – requiring chromedriver and slowing down our tests.

Instead, I’d like to have something more akin to what LiveView tests brought us – tests that act as though there’s a driver, but they mostly parse HTML and allows us to make assertions about it.

That’s where PhoenixTest shines.

Of course, without something like chromedriver, we cannot test JavaScript. So, PhoenixTest remains blissfully ignorant of it. If you need that, check Wallaby.

But if you’re looking for something to write fast feature tests for your LiveView pages and static pages – and something that is (hopefully) a pleasure to write – check out PhoenixTest!

Links

Most Liked

germsvel

germsvel

The library has been consistently improving since its introduction.

Today I published the biggest change (from an API perspective) on how we fill form.

PhoenixTest v0.2.13 deprecates two form helpers :disappointed_face: but introduces new ones to help us fill forms with labels. :star_struck:

I know it’s a pain to change this (I don’t change APIs lightly), but I think the changes improve our tests.

Change this: :backhand_index_pointing_down:

session
|> fill_form("form", user: %{
  name: "Aragorn",
  admin: true,
  country: "Arnor"
})

To this: :backhand_index_pointing_down:

session
|> fill_in("Name", with: "Aragorn")
|> check("Admin")
|> select("Arnor", from: "Countries")

Read the full upgrade guide: Upgrade Guides — PhoenixTest v0.11.1

germsvel

germsvel

PhoenixTest v0.3.0 is now out! :megaphone:

  • Removes deprecated code

  • Adds unwrap for an escape hatch :hatching_chick:

  • Handles buttons submitting forms when not nested in the form

  • and more!

Grab it while it’s hot :fire:

:gear: phoenix_test | Hex

:books: PhoenixTest — PhoenixTest v0.11.1

soyjeansoy

soyjeansoy

Wish they’d consider that idea

Where Next?

Popular in Announcing Top

maltoe
Hello! Came here to announce ChromicPDF, a pet project PDF generator I’ve been working on for the past few months. Why another PDF gener...
New
bluzky
You may know https://ui.shadcn.com/, a UI component library for React. I really love it’s design style and components. I’ve built some co...
384 14136 119
New
Crowdhailer
Experimenting with this code. OK.try do user &lt;- fetch_user(1) cart &lt;- fetch_cart(1) order = checkout(cart, user) save_orde...
New
RobertDober
Earmark is a pure-Elixir Markdown converter. It is intended to be used as a library (just call Earmark.as_html), but can also be used as...
239 12645 134
New
sbs
Only 650 LOC, wrote for fun :slight_smile: https://github.com/sunboshan/qrcode
New
Azolo
Hey everyone, I just released WebSockex which is a Elixir WebSocket client. WebSockex strives to work as a OTP special process, be RFC6...
New
archan937
It is a well-know topic within the Elixir community: “To mock or not to mock? :)” Every alchemist probably has his / her own opinion con...
New
handnot2
Samly can be used to enable SAML 2.0 Single Sign On in a Plug/Phoenix application. This library uses Erlang esaml to provide plug enabl...
New
wfgilman
I’ve cleaned up and open sourced three financial libraries I was using for my company. They are bindings for the APIs of these three comp...
New
mattludwigs
Grizzly is a library for working with Z-Wave devices. Z-Wave is a low-frequency radio protocol for controlling smart home devices on a me...
New

Other popular topics Top

New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
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
johnnyicon
Hi all, I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I’m trying to use Postgres...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 39467 209
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
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
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement