Skip to content

Commit 4c8d39c

Browse files
committed
Test calendar component
1 parent 92332f0 commit 4c8d39c

File tree

8 files changed

+142
-3
lines changed

8 files changed

+142
-3
lines changed

lib/components_guide_web.ex

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ defmodule ComponentsGuideWeb do
4343
end
4444
end
4545

46+
def component do
47+
quote do
48+
use Phoenix.Component
49+
50+
unquote(view_helpers())
51+
end
52+
end
53+
4654
def live_view(opts \\ []) do
4755
quote do
4856
@opts Keyword.merge(
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
defmodule ComponentsGuideWeb.CalendarComponent do
2+
use ComponentsGuideWeb, :component
3+
4+
def calendar_grid(assigns) do
5+
%{year: year, month: month, day: day} = today = assigns[:date]
6+
start_date = Date.beginning_of_month(today)
7+
end_date = Date.end_of_month(today)
8+
date_range = Date.range(start_date, end_date)
9+
10+
day_offset = 1 - Date.day_of_week(start_date)
11+
12+
assigns =
13+
assigns
14+
|> Map.merge(%{
15+
date_range: date_range,
16+
year: year,
17+
month: month,
18+
day: day,
19+
day_offset: day_offset
20+
})
21+
22+
~H"""
23+
<h2><%= @year %> <%= @month %> <%= Gettext.dgettext(ComponentsGuideWeb.Gettext, "months", "april") %></h2>
24+
<table class="text-center">
25+
<thead>
26+
<tr>
27+
<th abbr="Monday">Mon</th>
28+
<th abbr="Tuesday">Tue</th>
29+
<th abbr="Wednesday">Wed</th>
30+
<th abbr="Thursday">Thu</th>
31+
<th abbr="Friday">Fri</th>
32+
<th abbr="Saturday">Sat</th>
33+
<th abbr="Sunday">Sun</th>
34+
</tr>
35+
</thead>
36+
<tbody>
37+
<%= for week_n <- 1..6 do %>
38+
<tr>
39+
<%= for day_n <- 1..7 do %>
40+
<% day = day_n + day_offset + ((week_n - 1) * 7) %>
41+
<%= if day in @date_range.first.day..@date_range.last.day do %>
42+
<% current = day == @day %>
43+
<td aria-current={if current, do: "date", else: "false"} class={if current, do: "bg-red-900", else: ""}>
44+
<%= day %>
45+
</td>
46+
<% else %>
47+
<td class="bg-black"></td>
48+
<% end %>
49+
<% end %>
50+
</tr>
51+
<% end %>
52+
</tbody>
53+
</table>
54+
"""
55+
end
56+
end

lib/components_guide_web/controllers/calendar_controller.ex

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,13 @@ defmodule ComponentsGuideWeb.CalendarController do
8686
jest28: "https://jestjs.io/blog/2022/04/25/jest-28"
8787
}
8888

89+
today = Date.utc_today()
90+
8991
assigns = [
9092
page_title:
9193
"Calendar of when important tools are released, become LTS, and reach end-of-life",
92-
current_week: iso_week_number(Date.utc_today() |> Date.to_erl()),
94+
today: today,
95+
current_week: today |> Date.to_erl() |> iso_week_number(),
9396
list: create_list(groups, links)
9497
]
9598

@@ -150,6 +153,8 @@ end
150153
defmodule ComponentsGuideWeb.CalendarView do
151154
use ComponentsGuideWeb, :view
152155

156+
alias ComponentsGuideWeb.CalendarComponent
157+
153158
def present_item({id, {date, type, meta}}) do
154159
options = %{
155160
what: pretty_name(id),

lib/components_guide_web/templates/calendar/index.html.heex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<label><input type="checkbox" name="released" checked class="rounded text-sky-500"> Released</label>
66
<label><input type="checkbox" name="lts_starts" checked class="rounded text-sky-500"> LTS</label>
77
</form>
8+
<CalendarComponent.calendar_grid date={@today} />
89
<article>
910
<%= for item <- @list do %>
1011
<%= present_item(item) %>

mix.exs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ defmodule ComponentsGuide.MixProject do
5555
{:tesla, "~> 1.3.0"},
5656
{:mojito, "~> 0.6.1"},
5757
{:mint, "~> 1.0"},
58-
{:floki, "~> 0.26.0"},
58+
{:floki, "~> 0.32.0"},
59+
{:html5ever, "~> 0.12.0"},
5960
{:plug_cowboy, "~> 2.0"},
6061
{:earmark, "~> 1.4.15"},
6162
{:paredown, "~> 0.1.0"},

mix.lock

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616
"ex_doc": {:hex, :ex_doc, "0.23.0", "a069bc9b0bf8efe323ecde8c0d62afc13d308b1fa3d228b65bca5cf8703a529d", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "f5e2c4702468b2fd11b10d39416ddadd2fcdd173ba2a0285ebd92c39827a5a16"},
1717
"ex_image_info": {:hex, :ex_image_info, "0.2.4", "610002acba43520a9b1cf1421d55812bde5b8a8aeaf1fe7b1f8823e84e762adb", [:mix], [], "hexpm", "fd1a7e02664e3b14dfd3b231d22fdd48bd3dd694c4773e6272b3a6228f1106bc"},
1818
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
19-
"floki": {:hex, :floki, "0.26.0", "4df88977e2e357c6720e1b650f613444bfb48c5acfc6a0c646ab007d08ad13bf", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "e7b66ce7feef5518a9cd9fc7b52dd62a64028bd9cb6d6ad282a0f0fc90a4ae52"},
19+
"floki": {:hex, :floki, "0.32.1", "dfe3b8db3b793939c264e6f785bca01753d17318d144bd44b407fb3493acaa87", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "d4b91c713e4a784a3f7b1e3cc016eefc619f6b1c3898464222867cafd3c681a3"},
2020
"gettext": {:hex, :gettext, "0.19.1", "564953fd21f29358e68b91634799d9d26989f8d039d7512622efb3c3b1c97892", [:mix], [], "hexpm", "10c656c0912b8299adba9b061c06947511e3f109ab0d18b44a866a4498e77222"},
2121
"hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"},
2222
"hpax": {:hex, :hpax, "0.1.1", "2396c313683ada39e98c20a75a82911592b47e5c24391363343bde74f82396ca", [:mix], [], "hexpm", "0ae7d5a0b04a8a60caf7a39fcf3ec476f35cc2cc16c05abea730d3ce6ac6c826"},
23+
"html5ever": {:hex, :html5ever, "0.12.0", "b2a33306d5cf5f96a9967ae311215d31b30eb1b8e990f1439535d4323505d8ee", [:mix], [{:rustler_precompiled, "~> 0.2", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "115d66cf44f6eabad6a2ee41392daea12fb35598b5b79d8bffa83bbead258e7b"},
2324
"html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"},
2425
"httpoison": {:hex, :httpoison, "1.8.1", "df030d96de89dad2e9983f92b0c506a642d4b1f4a819c96ff77d12796189c63e", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "35156a6d678d6d516b9229e208942c405cf21232edd632327ecfaf4fd03e79e0"},
2526
"httpotion": {:hex, :httpotion, "3.1.3", "fdaf1e16b9318dcb722de57e75ac368c93d4c6e3c9125f93e960f953a750fb77", [:mix], [{:ibrowse, "== 4.4.0", [hex: :ibrowse, repo: "hexpm", optional: false]}], "hexpm", "e420172ef697a0f1f4dc40f89a319d5a3aad90ec51fa424f08c115f04192ae43"},
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
defmodule ComponentsGuideWeb.CalendarComponentTest do
2+
# use ExUnit.Case
3+
# import Phoenix.LiveViewTest
4+
use ComponentsGuideWeb.ComponentCase
5+
alias ComponentsGuideWeb.CalendarComponent
6+
7+
describe "CalendarComponent.calendar_grid" do
8+
setup context do
9+
assigns = context[:assigns]
10+
el = render_fragment(&CalendarComponent.calendar_grid/1, assigns)
11+
{:ok, el: el}
12+
end
13+
14+
@tag assigns: [date: ~D[2022-04-01]]
15+
test "April 1 2022", %{el: el} do
16+
current_date = el |> find("td[aria-current=date]")
17+
assert "1" == current_date |> text() |> String.trim()
18+
assert current_date |> Enum.count() == 1
19+
20+
assert 7 == count(el, "thead th")
21+
assert 6 == count(el, "tbody tr")
22+
end
23+
24+
@tag assigns: [date: ~D[2022-04-15]]
25+
test "April 15 2022", %{el: el} do
26+
current_date = el |> find("td[aria-current=date]")
27+
assert "15" == current_date |> text() |> String.trim()
28+
end
29+
30+
@tag assigns: [date: ~D[2022-01-03]]
31+
test "January 3 2022", %{el: el} do
32+
current_date = el |> find("td[aria-current=date]")
33+
assert "3" == current_date |> text() |> String.trim()
34+
end
35+
end
36+
end

test/support/component_case.ex

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
defmodule ComponentsGuideWeb.ComponentCase do
2+
@moduledoc """
3+
This module defines the test case to be used by
4+
component tests.
5+
"""
6+
7+
use ExUnit.CaseTemplate
8+
9+
using do
10+
quote do
11+
import Phoenix.LiveViewTest
12+
13+
defdelegate find(el, selector), to: Floki
14+
defdelegate text(html), to: Floki
15+
16+
def render_fragment(component, assigns) do
17+
html = render_component(component, assigns)
18+
{:ok, el} = Floki.parse_fragment(html)
19+
el
20+
end
21+
22+
def count(el, selector) do
23+
find(el, selector) |> Enum.count()
24+
end
25+
end
26+
end
27+
28+
setup _tags do
29+
:ok
30+
end
31+
end

0 commit comments

Comments
 (0)