Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion lib/dotcom_web/templates/event/_month.html.heex
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<ul class="list-group list-group-flush">
<ul :if={Enum.any?(@event_teasers)} class="list-group list-group-flush">
<%= if @conn.assigns.date.year == @year and @conn.assigns.date.month == @month_number do %>

<!-- Previous months button. A JS script sets up a listener for button click -->
Expand Down Expand Up @@ -49,3 +49,7 @@
<% end %>
<% end %>
</ul>

<p :if={Enum.empty?(@event_teasers)} class="italic px-6 text-sm sm:text-base">
No events scheduled
</p>
30 changes: 26 additions & 4 deletions lib/dotcom_web/views/event_view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,33 @@ defmodule DotcomWeb.EventView do

@doc "Returns a list of event teasers, grouped/sorted by month"
@spec grouped_by_month([Teaser.t()], number) :: [{number, [Teaser.t()]}]
def grouped_by_month([], _year), do: []

def grouped_by_month(events, year) do
events
|> Enum.filter(&(&1.date.year == year))
|> Enum.group_by(& &1.date.month)
|> Enum.sort_by(&elem(&1, 0))
{earliest_year, latest_year} = events |> Stream.map(& &1.date.year) |> Enum.min_max()
Comment thread
lvachon1 marked this conversation as resolved.

if earliest_year > year || latest_year < year do
[]
else
by_month =
events
|> Stream.filter(&(&1.date.year == year))
|> Enum.group_by(& &1.date.month)

{earliest_month, latest_month} =
by_month
|> Enum.map(fn {month, _} -> month end)
|> case do
[] -> {1, 12}
months -> months |> Enum.min_max()
end

latest_month = if latest_year == year, do: latest_month, else: 12
earliest_month = if earliest_year == year, do: earliest_month, else: 1

earliest_month..latest_month
|> Enum.map(&{&1, Map.get(by_month, &1, [])})
end
end

@doc "Returns a list of event teasers, grouped/sorted by day"
Expand Down
167 changes: 147 additions & 20 deletions test/dotcom_web/views/event_view_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,18 @@ defmodule DotcomWeb.EventViewTest do
import DotcomWeb.EventView
import CMS.Helpers, only: [parse_iso_datetime: 1]
import Phoenix.HTML, only: [safe_to_string: 1]
alias Test.Support.Factories
alias Test.Support.Generators
alias CMS.Page.Event
alias CMS.Page.EventAgenda
alias CMS.Partial.Teaser

setup do
Mox.stub_with(Dotcom.Utils.DateTime.Mock, Dotcom.Utils.DateTime)

:ok
end

describe "show.html" do
test "the notes section is not rendered when the event notes are empty", %{conn: conn} do
event = event_factory(0, notes: nil)
Expand Down Expand Up @@ -155,29 +163,148 @@ defmodule DotcomWeb.EventViewTest do
assert render_event_month(3, 2020) == "March 2020"
end

test "grouped_by_month/2 for a given year" do
events =
for y <- 2018..2020, m <- 1..12, into: [] do
{:ok, date} = Date.new(y, m, 1)
describe "grouped_by_month/2" do
test "groups a given event into the corrent year and month" do
# Setup
date = Generators.Date.random_date()

for t <- 1..(2 * m), into: [] do
%Teaser{
id: "#{y}-#{m}-#{t}",
path: "/#{y}-#{m}/#{t}",
title: "Event #{t} during #{m}/#{y}",
type: :event,
date: date
}
end
end
|> List.flatten()
event = Factories.CMS.Partial.Teaser.build(:event_teaser, date: date)

# Exercise
grouped_events = grouped_by_month([event], date.year)

# Verify
assert grouped_events == [{date.month, [event]}]
end

test "includes an empty month if there are events scheduled before and after that month" do
# Setup
year = Dotcom.Utils.DateTime.now().year + Faker.random_between(-10, 10)
month = Faker.random_between(2, 11)

earlier_event =
Factories.CMS.Partial.Teaser.build(
:event_teaser,
date: Date.new!(year, month - 1, Faker.random_between(1, 28))
)

later_event =
Factories.CMS.Partial.Teaser.build(
:event_teaser,
date: Date.new!(year, month + 1, Faker.random_between(1, 28))
)

# Exercise
grouped_events = grouped_by_month([earlier_event, later_event], year)

# Verify
assert grouped_events == [
{month - 1, [earlier_event]},
{month, []},
{month + 1, [later_event]}
]
end

test "includes empty months later in the year if there is an event the following year" do
# Setup
year = Dotcom.Utils.DateTime.now().year + Faker.random_between(-10, 10)
month = Faker.random_between(1, 11)

event_this_year =
Factories.CMS.Partial.Teaser.build(
:event_teaser,
date: Date.new!(year, month, Faker.random_between(1, 28))
)

event_next_year =
Factories.CMS.Partial.Teaser.build(
:event_teaser,
date: Date.new!(year + 1, Faker.random_between(1, 12), Faker.random_between(1, 28))
)

grouped_2020_events = grouped_by_month(events, 2020)
# Exercise
grouped_events = grouped_by_month([event_this_year, event_next_year], year)

assert grouped_2020_events
assert {1, [january_event, _another_january_event]} = List.first(grouped_2020_events)
assert january_event.date.month == 1
assert january_event.date.year == 2020
# Verify
assert grouped_events ==
[{month, [event_this_year]}] ++
Enum.map((month + 1)..12, &{&1, []})
end

test "includes empty months earlier in the year if there is an event in an earlier year" do
# Setup
year = Dotcom.Utils.DateTime.now().year + Faker.random_between(-10, 10)
month = Faker.random_between(2, 12)

event_this_year =
Factories.CMS.Partial.Teaser.build(
:event_teaser,
date: Date.new!(year, month, Faker.random_between(1, 28))
)

event_last_year =
Factories.CMS.Partial.Teaser.build(
:event_teaser,
date: Date.new!(year - 1, Faker.random_between(1, 12), Faker.random_between(1, 28))
)

# Exercise
grouped_events = grouped_by_month([event_last_year, event_this_year], year)

# Verify
assert grouped_events ==
Enum.map(1..(month - 1), &{&1, []}) ++
[{month, [event_this_year]}]
end

test "doesn't crash if the events list is empty" do
# Setup
year = Dotcom.Utils.DateTime.now().year + Faker.random_between(-10, 10)

# Exercise / Verify
assert grouped_by_month([], year) == []
end

test "returns [] if there are no events for the queried year, but there is in another year" do
# Setup
year = Dotcom.Utils.DateTime.now().year + Faker.random_between(-10, 10)
event_year = year + Faker.Util.pick([-1, 1])

event_in_other_year =
Factories.CMS.Partial.Teaser.build(
:event_teaser,
date: Date.new!(event_year, Faker.random_between(1, 12), Faker.random_between(1, 28))
)

# Exercise
grouped_events = grouped_by_month([event_in_other_year], year)

# Verify
assert grouped_events == []
end

test "returns all months with no events if there are no events for the queried year, but there are on either end" do
# Setup
year = Dotcom.Utils.DateTime.now().year + Faker.random_between(-10, 10)

event_last_year =
Factories.CMS.Partial.Teaser.build(
:event_teaser,
date: Date.new!(year - 1, Faker.random_between(1, 12), Faker.random_between(1, 28))
)

event_next_year =
Factories.CMS.Partial.Teaser.build(
:event_teaser,
date: Date.new!(year + 1, Faker.random_between(1, 12), Faker.random_between(1, 28))
)

# Exercise
grouped_events = grouped_by_month([event_last_year, event_next_year], year)

# Verify
assert grouped_events == Enum.map(1..12, &{&1, []})
end
end

test "grouped_by_day/2 for a given month" do
Expand Down
31 changes: 31 additions & 0 deletions test/support/factories/cms/partial/teaser.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
defmodule Test.Support.Factories.CMS.Partial.Teaser do
@moduledoc """
Generated fake data for %CMS.Partial.Teaser{}
"""

use ExMachina

alias CMS.Partial.Teaser
alias Test.Support.FactoryHelpers
alias Test.Support.Generators

@types [:diversion, :event, :news_entry, :page, :project, :project_update]

def event_teaser_factory do
build(:teaser, type: :event)
end

def teaser_factory do
%Teaser{
id: FactoryHelpers.build(:id),
date: Generators.Date.random_date(),
type: type(),
path: Faker.Internet.url(),
title: Faker.Company.catch_phrase()
}
end

defp type() do
Faker.Util.pick(@types)
end
end
Loading