julngomz

julngomz

Programming Phoenix LiveView B9: Testing Fails with the provided testing code. (pages 295 - 296)

Hello,

In chapter 10, Testing Your Live Views, the provided code is confusing. (Or I misread this passage)

Example Code

On page 295, when testing ratings by age group, the following code snippet is provided:

test "ratings are filtered by age group",  ...<map>.. do
  ...
  socket =
    update_socket(socket, :age_group_filter, "18 and under")
    |> SurveyResultsLive.assign_age_group_filter()

    assert socket.assigns.age_group_filter == "18 and under"
  ...
end

defp update_socket(socket, key, value) do
  %{socket | assigns: Map.merge(socket.assigns, Map.new([{key, value}]))}
end

Problem

So essentially what this piece of code was suppose to do is update the :age_group_filter to 18 and under, but what the the code provided actually does, is it updates the socket to 18 and under but then it gets piped back through SurveyResultsLive.assign_age_group_filter() reverting it back to all.

The following is the code to update the :age_group_filter in the SurveyResultsLive.assign_age_group_filter() live component function.

def assign_age_group_filter(socket) do
  assign(socket, :age_group_filter, "all")
end

def assign_age_group_filter(socket, age_group_filter) do
  assign(socket, :age_group_filter, age_group_filter)
end

Since we are not passing a second parameter, the first implementation is matched. Assigning all to :age_group_filter once again. Resulting in a failed assertion:

assert socket.assigns.age_group_filter == "18 and under"

Snippet Rewrite

So essentially the testing code should be as the following:

  ...
  socket = SurveyResultsLive.assign_age_group_filter(socket, "18 and under")
  assert socket.assigns.age_group_filter == "18 and under"
  ...

the update_socket helper function is essentially unnecessary and confusing, shouldn’t we leave the socket updates on to implementer not the tester?

Further Changes

If we follow the previous code, then on the next page (page 296), the resulting testing code should be:

 socket
      |> SurveyResultsLive.assign_gender_filter()
      |> SurveyResultsLive.assign_age_group_filter()
      |> assert_keys(:age_group_filter, "all")
      |> SurveyResultsLive.assign_age_group_filter("18 and under")
      |> assert_keys(:age_group_filter, "18 and under")
      |> SurveyResultsLive.assign_age_group_filter()
      |> SurveyResultsLive.assign_products_with_average_ratings()
      |> assert_keys(:products_with_average_ratings, [{"Test Game", 2.0}])

This works as expected and looks much nicer without the update_socket, but this also fails the last assertion test since we are creating two user ratings, the resulting average will change. The simple way to fix this is to change it to from 2.0 to 2.5.

Or you can add a helper function such as the following:

  defp calculate_average_rating(user_ratings) do
    stars = for {_user, stars} <- user_ratings, do: stars
    stars_count = length(stars)
    stars_sum = Enum.sum(stars)
    stars_sum / stars_count
  end
  
  ...using within test...

  user_ratings = [{user, 2}, {user2, 3}]
  avg_rating = calculate_average_rating(user_ratings)

  for {user, stars} <- user_ratings do
    create_rating(stars, user, product)
  end

  ...assertion test...

  |> assert_keys(:products_with_average_ratings, [{"Test Game", avg_rating}])

where user_ratings is a list of user rating tuples [{user, 2}, {user2, 3}] and can be for looped to create multiple ratings

Where Next?

Popular Pragmatic Bookshelf topics Top

jimschubert
In Chapter 3, the source for index introduces Config on page 31, followed by more code including tests; Config isn’t introduced until pag...
New
iPaul
page 37 ANTLRInputStream input = new ANTLRInputStream(is); as of ANTLR 4 .8 should be: CharStream stream = CharStreams.fromStream(i...
New
jamis
The following is cross-posted from the original Ray Tracer Challenge forum, from a post by garfieldnate. I’m cross-posting it so that the...
New
jdufour
Hello! On page xix of the preface, it says there is a community forum "… for help if your’re stuck on one of the exercises in this book… ...
New
raul
Page 28: It implements io.ReaderAt on the store type. Sorry if it’s a dumb question but was the io.ReaderAt supposed to be io.ReadAt? ...
New
brunogirin
When running tox for the first time, I got the following error: ERROR: InterpreterNotFound: python3.10 I realised that I was running ...
New
kolossal
Hi, I need some help, I’m new to rust and was learning through your book. but I got stuck at the last stage of distribution. Whenever I t...
New
mert
AWDWR 7, page 152, page 153: Hello everyone, I’m a little bit lost on the hotwire part. I didn’t fully understand it. On page 152 @rub...
New
mcpierce
@mfazio23 I’ve applied the changes from Chapter 5 of the book and everything builds correctly and runs. But, when I try to start a game,...
New
davetron5000
Hello faithful readers! If you have tried to follow along in the book, you are asked to start up the dev environment via dx/build and ar...
New

Other popular topics Top

Devtalk
Hello Devtalk World! Please let us know a little about who you are and where you’re from :nerd_face:
New
AstonJ
Do the test and post your score :nerd_face: :keyboard: If possible, please add info such as the keyboard you’re using, the layout (Qw...
New
Exadra37
Oh just spent so much time on this to discover now that RancherOS is in end of life but Rancher is refusing to mark the Github repo as su...
New
AstonJ
Continuing the discussion from Thinking about learning Crystal, let’s discuss - I was wondering which languages don’t GC - maybe we can c...
New
Maartz
Hi folks, I don’t know if I saw this here but, here’s a new programming language, called Roc Reminds me a bit of Elm and thus Haskell. ...
New
PragmaticBookshelf
Build efficient applications that exploit the unique benefits of a pure functional language, learning from an engineer who uses Haskell t...
New
husaindevelop
Inside our android webview app, we are trying to paste the copied content from another app eg (notes) using navigator.clipboard.readtext ...
New
New
CommunityNews
A Brief Review of the Minisforum V3 AMD Tablet. Update: I have created an awesome-minisforum-v3 GitHub repository to list information fo...
New
PragmaticBookshelf
A concise guide to MySQL 9 database administration, covering fundamental concepts, techniques, and best practices. Neil Smyth MySQL...
New

Sub Categories: