Skip to content

Commit

Permalink
fix: Revising section 8 of readme. #54
Browse files Browse the repository at this point in the history
  • Loading branch information
LuchoTurtle committed Dec 6, 2022
1 parent 32acb54 commit bbaa6ca
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 25 deletions.
90 changes: 71 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1166,8 +1166,45 @@ e.g: 0 to 1 and 1 to 0.
2. `toggle/2` the handler function for HTTP requests
to toggle the status of an item.

Open the `test/app_web/controllers/item_controller_test.exs` file
and append the following code to the end:
Open the `test/app_web/controllers/item_controller_test.exs` file.
We are going to make some changes here
so we can add tests to the functions we
mentioned prior.
We are going to import `App.Todo`
inside `item_controller_test.exs`
and fix create and attribute constants
to create mock items.
Make sure the beginning of the
file looks like so.

```elixir
defmodule AppWeb.ItemControllerTest do
use AppWeb.ConnCase
alias App.Todo

import App.TodoFixtures

@create_attrs %{person_id: 42, status: 0, text: "some text"}
@update_attrs %{person_id: 43, status: 1, text: "some updated text"}
@invalid_attrs %{person_id: nil, status: nil, text: nil}
```

After this, locate `defp create_item()/1`
function inside the same file.
Change it so it looks like so.

```elixir
defp create_item(_) do
item = item_fixture(@create_attrs)
%{item: item}
end
```

We are going to be using this function
to create `Item` objects
to use in the tests we are going to add.
Speaking of which, let's do that!
Add the following snippet to the file.

```elixir
describe "toggle updates the status of an item 0 > 1 | 1 > 0" do
Expand All @@ -1184,7 +1221,7 @@ describe "toggle updates the status of an item 0 > 1 | 1 > 0" do

test "toggle/2 updates an item.status 0 > 1", %{conn: conn, item: item} do
assert item.status == 0
get(conn, Routes.item_path(conn, :toggle, item.id))
get(conn, ~p'/items/toggle/#{item.id}')
toggled_item = Todo.get_item!(item.id)
assert toggled_item.status == 1
end
Expand All @@ -1203,18 +1240,19 @@ Open the
file and add the following functions to it:

```elixir
def toggle_status(item) do
case item.status do
1 -> 0
0 -> 1
def toggle_status(item) do
case item.status do
1 -> 0
0 -> 1
end
end
end

def toggle(conn, %{"id" => id}) do
item = Todo.get_item!(id)
Todo.update_item(item, %{status: toggle_status(item)})
redirect(conn, to: Routes.item_path(conn, :index))
end
def toggle(conn, %{"id" => id}) do
item = Todo.get_item!(id)
Todo.update_item(item, %{status: toggle_status(item)})
conn
|> redirect(to: ~p"/items")
end
```

e.g:
Expand Down Expand Up @@ -1262,18 +1300,31 @@ Finished in 0.5 seconds
Now that our tests are passing,
it's time actually _use_ all this functionality we have been building
in the UI.
Open the `/lib/app_web/templates/item/index.html.eex` file
Open the `/lib/app_web/controllers/item_html/index.html.eex` file
and locate the line:

```html
<input <%= checked(item) %> class="toggle" type="checkbox">
<%= if item.status == 1 do %>
...
<% else %>
...
<% end %>
```

Replace it with the following:

```html
<a href="<%= Routes.item_path(@conn, :toggle, item.id) %>"
class="toggle <%= checked(item) %>"></a>
<%= if item.status == 1 do %>
<.link href={~p"/items/toggle/#{item.id}"}
class="toggle checked">
type="checkbox"
</.link>
<% else %>
<.link href={~p"/items/toggle/#{item.id}"}
type="checkbox"
class="toggle">
</.link>
<% end %>
```

When this link is clicked
Expand All @@ -1292,7 +1343,8 @@ we defined above.
### 7.5 Add a `.checked` CSS to `app.scss`


Unfortunately, `<a>` tags cannot have a `:checked` pseudo selector,
Unfortunately, `<a>` tags (that are generated with `<.link>`)
cannot have a `:checked` pseudo selector,
so the default TodoMVC styles that worked on the `<input>` tag
will not work for the link.
So we need to add a couple of lines of CSS to our `app.scss`.
Expand All @@ -1312,7 +1364,7 @@ After saving the file you should have:
And when you view the app,
the Toggle functionality is working as expected:

![todo-app-toggle](https://user-images.githubusercontent.com/194400/82806639-1c888b80-9e7e-11ea-8053-8dd6a770a923.gif)
![todo-app-toggle](https://user-images.githubusercontent.com/17494745/205961019-141d4488-3856-4c1e-b846-6ef52252c7d1.gif)


**Implementation Note**: we are very deliberately
Expand Down
5 changes: 5 additions & 0 deletions assets/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,8 @@
@import "./todomvc-app.css";

/* This file is for your main application CSS */

.todo-list li .checked + label {
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');
background-repeat: no-repeat;
}
9 changes: 8 additions & 1 deletion lib/app/todo.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,14 @@ defmodule App.Todo do
"""
def list_items do
Repo.all(Item)
query =
from(
i in Item,
select: i,
order_by: [asc: i.id]
)

Repo.all(query)
end

@doc """
Expand Down
14 changes: 14 additions & 0 deletions lib/app_web/controllers/item_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,18 @@ defmodule AppWeb.ItemController do
|> put_flash(:info, "Item deleted successfully.")
|> redirect(to: ~p"/items")
end

def toggle_status(item) do
case item.status do
1 -> 0
0 -> 1
end
end

def toggle(conn, %{"id" => id}) do
item = Todo.get_item!(id)
Todo.update_item(item, %{status: toggle_status(item)})
conn
|> redirect(to: ~p"/items")
end
end
10 changes: 8 additions & 2 deletions lib/app_web/controllers/item_html/index.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,15 @@
<li data-id={item.id} class={complete(item)}>
<div class="view">
<%= if item.status == 1 do %>
<input class="toggle" type="checkbox" checked/>
<.link href={~p"/items/toggle/#{item.id}"}
class="toggle checked">
type="checkbox"
</.link>
<% else %>
<input class="toggle" type="checkbox"/>
<.link href={~p"/items/toggle/#{item.id}"}
type="checkbox"
class="toggle">
</.link>
<% end %>
<label><%= item.text %></label>
<.link
Expand Down
1 change: 1 addition & 0 deletions lib/app_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ defmodule AppWeb.Router do
pipe_through :browser

get "/", PageController, :home
get "/items/toggle/:id", ItemController, :toggle
resources "/items", ItemController
end

Expand Down
27 changes: 24 additions & 3 deletions test/app_web/controllers/item_controller_test.exs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
defmodule AppWeb.ItemControllerTest do
use AppWeb.ConnCase
alias App.Todo

import App.TodoFixtures

@create_attrs %{person_id: 42, status: 42, text: "some text"}
@update_attrs %{person_id: 43, status: 43, text: "some updated text"}
@create_attrs %{person_id: 42, status: 0, text: "some text"}
@update_attrs %{person_id: 43, status: 1, text: "some updated text"}
@invalid_attrs %{person_id: nil, status: nil, text: nil}

describe "index" do
Expand Down Expand Up @@ -69,8 +70,28 @@ defmodule AppWeb.ItemControllerTest do
end
end

describe "toggle updates the status of an item 0 > 1 | 1 > 0" do
setup [:create_item]

test "toggle_status/1 item.status 1 > 0", %{item: item} do
assert item.status == 0
# first toggle
toggled_item = %{item | status: AppWeb.ItemController.toggle_status(item)}
assert toggled_item.status == 1
# second toggle sets status back to 0
assert AppWeb.ItemController.toggle_status(toggled_item) == 0
end

test "toggle/2 updates an item.status 0 > 1", %{conn: conn, item: item} do
assert item.status == 0
get(conn, ~p'/items/toggle/#{item.id}')
toggled_item = Todo.get_item!(item.id)
assert toggled_item.status == 1
end
end

defp create_item(_) do
item = item_fixture()
item = item_fixture(@create_attrs)
%{item: item}
end
end

0 comments on commit bbaa6ca

Please sign in to comment.