Rewrite LV tests using PhoenixTest
This commit is contained in:
@@ -31,3 +31,5 @@ config :phoenix_live_view,
|
|||||||
config :music_library, dev_routes: true
|
config :music_library, dev_routes: true
|
||||||
|
|
||||||
config :music_library, LastFm, auto_refresh: false
|
config :music_library, LastFm, auto_refresh: false
|
||||||
|
|
||||||
|
config :phoenix_test, :endpoint, MusicLibraryWeb.Endpoint
|
||||||
|
|||||||
@@ -80,6 +80,9 @@ defmodule MusicLibrary.MixProject do
|
|||||||
|
|
||||||
# Data validation
|
# Data validation
|
||||||
{:nimble_options, "~> 1.1"},
|
{:nimble_options, "~> 1.1"},
|
||||||
|
|
||||||
|
# Test tooling
|
||||||
|
{:phoenix_test, "~> 0.5.1", only: :test},
|
||||||
{:floki, ">= 0.30.0", only: :test},
|
{:floki, ">= 0.30.0", only: :test},
|
||||||
{:mox, "~> 1.2", only: :test},
|
{:mox, "~> 1.2", only: :test},
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
"phoenix_live_view": {:hex, :phoenix_live_view, "1.0.1", "5389a30658176c0de816636ce276567478bffd063c082515a6e8368b8fc9a0db", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c0f517e6f290f10dbb94343ac22e0109437fb1fa6f0696e7c73967b789c1c285"},
|
"phoenix_live_view": {:hex, :phoenix_live_view, "1.0.1", "5389a30658176c0de816636ce276567478bffd063c082515a6e8368b8fc9a0db", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c0f517e6f290f10dbb94343ac22e0109437fb1fa6f0696e7c73967b789c1c285"},
|
||||||
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"},
|
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"},
|
||||||
"phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
|
"phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
|
||||||
|
"phoenix_test": {:hex, :phoenix_test, "0.5.1", "9d3e27f47d15ed0cda1a4afaf79eec4177162ed6d50b32276e122bc97dc00214", [:mix], [{:floki, ">= 0.30.0", [hex: :floki, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, ">= 1.0.0", [hex: :mime, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.7.10", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.20 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "9bcaf413296f7a7f7f9ddade2177b2d0e4f650b05c517a7922a48843d7e456f7"},
|
||||||
"plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"},
|
"plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"},
|
||||||
"plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"},
|
"plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"},
|
||||||
"recon": {:hex, :recon, "2.5.6", "9052588e83bfedfd9b72e1034532aee2a5369d9d9343b61aeb7fbce761010741", [:mix, :rebar3], [], "hexpm", "96c6799792d735cc0f0fd0f86267e9d351e63339cbe03df9d162010cefc26bb0"},
|
"recon": {:hex, :recon, "2.5.6", "9052588e83bfedfd9b72e1034532aee2a5369d9d9343b61aeb7fbce761010741", [:mix, :rebar3], [], "hexpm", "96c6799792d735cc0f0fd0f86267e9d351e63339cbe03df9d162010cefc26bb0"},
|
||||||
|
|||||||
@@ -43,16 +43,12 @@ defmodule MusicLibraryWeb.ArtistLive.ShowTest do
|
|||||||
|> Artist.from_api_response()}
|
|> Artist.from_api_response()}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
{:ok, show_live, _html} = live(conn, ~p"/artists/#{artist_musicbrainz_id}")
|
conn
|
||||||
|
|> visit(~p"/artists/#{artist_musicbrainz_id}")
|
||||||
render_async(show_live)
|
|> unwrap(&render_async/1)
|
||||||
|
|> assert_has("span", text: "123")
|
||||||
# play count
|
|> assert_has("summary", text: "Biography")
|
||||||
assert has_element?(show_live, "span", "123")
|
|> assert_has("details")
|
||||||
|
|
||||||
assert has_element?(show_live, "summary", "Biography")
|
|
||||||
|
|
||||||
assert element(show_live, "details")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it gracefully handles errors in fetching bio and play count", %{
|
test "it gracefully handles errors in fetching bio and play count", %{
|
||||||
@@ -64,16 +60,13 @@ defmodule MusicLibraryWeb.ArtistLive.ShowTest do
|
|||||||
{:error, :timeout}
|
{:error, :timeout}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
{:ok, show_live, _html} = live(conn, ~p"/artists/#{artist_musicbrainz_id}")
|
conn
|
||||||
|
|> visit(~p"/artists/#{artist_musicbrainz_id}")
|
||||||
render_async(show_live)
|
|> unwrap(&render_async/1)
|
||||||
|
|> refute_has("span", text: "123")
|
||||||
# play count
|
|> refute_has("summary", text: "Biography")
|
||||||
refute has_element?(show_live, "span", "123")
|
|> assert_has("div", text: "Error loading play count")
|
||||||
assert has_element?(show_live, "div", "Error loading play count")
|
|> assert_has("div", text: "Error loading biography")
|
||||||
|
|
||||||
refute has_element?(show_live, "summary", "Biography")
|
|
||||||
assert has_element?(show_live, "div", "Error loading biography")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it shows records from the collection and the wishlist", %{
|
test "it shows records from the collection and the wishlist", %{
|
||||||
@@ -96,19 +89,13 @@ defmodule MusicLibraryWeb.ArtistLive.ShowTest do
|
|||||||
{:error, :timeout}
|
{:error, :timeout}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
{:ok, show_live, _html} = live(conn, ~p"/artists/#{artist_musicbrainz_id}")
|
conn
|
||||||
|
|> visit(~p"/artists/#{artist_musicbrainz_id}")
|
||||||
render_async(show_live)
|
|> unwrap(&render_async/1)
|
||||||
|
|> assert_has("#collection p", text: escape(collection_record.title))
|
||||||
# collection records
|
|> assert_has("#wishlist p", text: escape(wishlist_record.title))
|
||||||
assert has_element?(show_live, "#collection p", escape(collection_record.title))
|
|> refute_has("#collection p", text: escape(other_collection_record.title))
|
||||||
|
|> refute_has("#wishlist p", text: escape(other_collection_record.title))
|
||||||
# wishlist records
|
|
||||||
assert has_element?(show_live, "#wishlist p", escape(wishlist_record.title))
|
|
||||||
|
|
||||||
# other records
|
|
||||||
refute has_element?(show_live, "#collection p", escape(other_collection_record.title))
|
|
||||||
refute has_element?(show_live, "#wishlist p", escape(other_collection_record.title))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do
|
|||||||
|> Phoenix.HTML.safe_to_string()
|
|> Phoenix.HTML.safe_to_string()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp human_datetime(dt) do
|
||||||
|
"#{dt.day}/#{dt.month}/#{dt.year}"
|
||||||
|
end
|
||||||
|
|
||||||
describe "Collection" do
|
describe "Collection" do
|
||||||
setup [:fill_collection, :fill_wishlist]
|
setup [:fill_collection, :fill_wishlist]
|
||||||
|
|
||||||
@@ -36,86 +40,100 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do
|
|||||||
conn: conn,
|
conn: conn,
|
||||||
wishlist: wishlist_records
|
wishlist: wishlist_records
|
||||||
} do
|
} do
|
||||||
{:ok, index_live, _html} = live(conn, ~p"/collection")
|
session = visit(conn, ~p"/collection")
|
||||||
|
|
||||||
for record <- wishlist_records do
|
for record <- wishlist_records do
|
||||||
refute has_element?(index_live, "#records-#{record.id}")
|
refute_has(session, "#records-#{record.id}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "shows purchased records", %{conn: conn, collection: records} do
|
test "shows purchased records (first page only)", %{conn: conn} do
|
||||||
{:ok, index_live, html} = live(conn, ~p"/collection")
|
# We fetch collection records to maintain consistent order
|
||||||
|
records = MusicLibrary.Collection.search_records("")
|
||||||
|
|
||||||
assert html =~ "Collection"
|
{expected_present, expected_absent} = Enum.split(records, @default_records_page_size)
|
||||||
|
|
||||||
{present, absent} =
|
session = visit(conn, ~p"/collection")
|
||||||
Enum.split_with(records, fn record ->
|
|
||||||
html =~ record.id
|
|
||||||
end)
|
|
||||||
|
|
||||||
assert length(present) == @default_records_page_size
|
for record <- expected_present do
|
||||||
assert length(absent) == @total_records - @default_records_page_size
|
session
|
||||||
|
|> assert_has("#records-#{record.id}")
|
||||||
for record <- present do
|
|> assert_has("#records-#{record.id} h2", text: escape(record.title))
|
||||||
record_row =
|
|> assert_has("#records-#{record.id} p", text: record.release)
|
||||||
index_live
|
|> assert_has("#records-#{record.id} p", text: Record.format_long_label(record.format))
|
||||||
|> with_target("#records-#{record.id}")
|
|> assert_has("#records-#{record.id} p", text: Record.type_long_label(record.type))
|
||||||
|
|> assert_has("#records-#{record.id} span", text: human_datetime(record.purchased_at))
|
||||||
record_row_html = record_row |> render()
|
|
||||||
|
|
||||||
assert record_row_html =~ escape(record.title)
|
|
||||||
assert record_row_html =~ to_string(record.release)
|
|
||||||
assert record_row_html =~ Record.format_long_label(record.format)
|
|
||||||
assert record_row_html =~ Record.type_long_label(record.type)
|
|
||||||
assert record_row_html =~ record.release
|
|
||||||
assert record_row_html =~ ~p"/covers/#{record.id}?vsn=#{record.cover_hash}"
|
|
||||||
assert record_row_html =~ Record.format_purchased_at(record.purchased_at)
|
|
||||||
|
|
||||||
for artist <- record.artists do
|
for artist <- record.artists do
|
||||||
assert record_row_html =~ escape(artist.name)
|
assert_has(session, "#records-#{record.id} a", text: escape(artist.name))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
session
|
||||||
|
|> unwrap(fn collection_view ->
|
||||||
|
html = render(collection_view)
|
||||||
|
|
||||||
|
for record <- expected_present do
|
||||||
|
assert html =~ ~p"/covers/#{record.id}?vsn=#{record.cover_hash}"
|
||||||
|
end
|
||||||
|
|
||||||
|
html
|
||||||
|
end)
|
||||||
|
|
||||||
|
for record <- expected_absent do
|
||||||
|
refute_has(session, "#records-#{record.id}")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "Search and pagination" do
|
describe "Search and pagination" do
|
||||||
setup [:fill_collection]
|
setup [:fill_collection]
|
||||||
|
|
||||||
test "uses query string params", %{conn: conn, collection: records} do
|
test "uses query string params", %{conn: conn} do
|
||||||
{:ok, page_2_live, page_2_html} = live(conn, ~p"/collection?page=2&page_size=10")
|
# We fetch collection records to maintain consistent order
|
||||||
|
records = MusicLibrary.Collection.search_records("")
|
||||||
|
page_size = 10
|
||||||
|
|
||||||
{page_2_present, page_2_absent} =
|
{page_1_records, rest_of_records} = Enum.split(records, page_size)
|
||||||
Enum.split_with(records, fn record ->
|
{page_2_records, rest_of_records} = Enum.split(rest_of_records, page_size)
|
||||||
page_2_html =~ record.id
|
|
||||||
end)
|
|
||||||
|
|
||||||
assert length(page_2_present) == 10
|
page_2_session =
|
||||||
assert length(page_2_absent) == @total_records - 10
|
visit(conn, ~p"/collection?page=2&page_size=#{page_size}")
|
||||||
|
|
||||||
page_2_pagination = page_2_live |> with_target("#pagination")
|
for record <- page_1_records do
|
||||||
refute has_element?(page_2_pagination, "a", "2")
|
refute_has(page_2_session, "#records-#{record.id}")
|
||||||
assert has_element?(page_2_pagination, "a", "1")
|
end
|
||||||
assert has_element?(page_2_pagination, "a", "3")
|
|
||||||
|
|
||||||
{:ok, page_3_live, page_3_html} = live(conn, ~p"/collection?page=3&page_size=10")
|
for record <- page_2_records do
|
||||||
|
assert_has(page_2_session, "#records-#{record.id}")
|
||||||
|
end
|
||||||
|
|
||||||
{page_3_present, page_3_absent} =
|
for record <- rest_of_records do
|
||||||
Enum.split_with(records, fn record ->
|
refute_has(page_2_session, "#records-#{record.id}")
|
||||||
page_3_html =~ record.id
|
end
|
||||||
end)
|
|
||||||
|
|
||||||
assert length(page_3_present) == 10
|
page_2_session
|
||||||
assert length(page_3_absent) == @total_records - 10
|
|> assert_has("#bottom_pagination a", text: "1")
|
||||||
|
|> refute_has("#bottom_pagination a", text: "2")
|
||||||
|
|> assert_has("#bottom_pagination a", text: "3")
|
||||||
|
|
||||||
page_3_pagination = page_3_live |> with_target("#pagination")
|
{page_3_records, rest_of_records} = Enum.split(rest_of_records, page_size)
|
||||||
refute has_element?(page_3_pagination, "a", "3")
|
|
||||||
assert has_element?(page_3_pagination, "a", "1")
|
|
||||||
assert has_element?(page_3_pagination, "a", "2")
|
|
||||||
|
|
||||||
# All records in page 3 were not present in page 2
|
page_3_session =
|
||||||
assert page_3_present -- page_2_absent == []
|
visit(conn, ~p"/collection?page=3&page_size=#{page_size}")
|
||||||
# All records in page 2 are not present in page 3
|
|
||||||
assert page_2_present -- page_3_absent == []
|
for record <- page_3_records do
|
||||||
|
assert_has(page_3_session, "#records-#{record.id}")
|
||||||
|
end
|
||||||
|
|
||||||
|
for record <- rest_of_records do
|
||||||
|
refute_has(page_3_session, "#records-#{record.id}")
|
||||||
|
end
|
||||||
|
|
||||||
|
page_3_session
|
||||||
|
|> assert_has("#bottom_pagination a", text: "1")
|
||||||
|
|> assert_has("#bottom_pagination a", text: "2")
|
||||||
|
|> refute_has("#bottom_pagination a", text: "3")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -125,23 +143,25 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do
|
|||||||
test "supports raw queries", %{conn: conn, collection: records} do
|
test "supports raw queries", %{conn: conn, collection: records} do
|
||||||
[record | _rest] = records
|
[record | _rest] = records
|
||||||
qs = [query: record.title]
|
qs = [query: record.title]
|
||||||
{:ok, index_live, _html} = live(conn, ~p"/collection?#{qs}")
|
|
||||||
|
|
||||||
record_row =
|
session =
|
||||||
index_live
|
visit(conn, ~p"/collection?#{qs}")
|
||||||
|> with_target("#records-#{record.id}")
|
|
||||||
|
|
||||||
record_row_html = record_row |> render()
|
session
|
||||||
|
|> assert_has("#records-#{record.id}")
|
||||||
assert record_row_html =~ escape(record.title)
|
|> assert_has("#records-#{record.id} h2", text: escape(record.title))
|
||||||
assert record_row_html =~ to_string(record.release)
|
|> assert_has("#records-#{record.id} p", text: record.release)
|
||||||
assert record_row_html =~ Record.format_long_label(record.format)
|
|> assert_has("#records-#{record.id} p", text: Record.format_long_label(record.format))
|
||||||
assert record_row_html =~ Record.type_long_label(record.type)
|
|> assert_has("#records-#{record.id} p", text: Record.type_long_label(record.type))
|
||||||
assert record_row_html =~ record.release
|
|> assert_has("#records-#{record.id} span", text: human_datetime(record.purchased_at))
|
||||||
assert record_row_html =~ ~p"/covers/#{record.id}?vsn=#{record.cover_hash}"
|
|> unwrap(fn collection_view ->
|
||||||
|
html = render(collection_view)
|
||||||
|
assert html =~ ~p"/covers/#{record.id}?vsn=#{record.cover_hash}"
|
||||||
|
html
|
||||||
|
end)
|
||||||
|
|
||||||
for artist <- record.artists do
|
for artist <- record.artists do
|
||||||
assert record_row_html =~ escape(artist.name)
|
assert_has(session, "#records-#{record.id} a", text: escape(artist.name))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -165,29 +185,30 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do
|
|||||||
page_size: @default_records_page_size
|
page_size: @default_records_page_size
|
||||||
]
|
]
|
||||||
|
|
||||||
{:ok, index_live, _html} = live(conn, ~p"/collection?#{qs}")
|
session =
|
||||||
|
visit(conn, ~p"/collection?#{qs}")
|
||||||
|
|
||||||
for record <- present do
|
for record <- present do
|
||||||
record_row =
|
session
|
||||||
index_live
|
|> assert_has("#records-#{record.id}")
|
||||||
|> with_target("#records-#{record.id}")
|
|> assert_has("#records-#{record.id} h2", text: escape(record.title))
|
||||||
|
|> assert_has("#records-#{record.id} p", text: record.release)
|
||||||
record_row_html = record_row |> render()
|
|> assert_has("#records-#{record.id} p", text: Record.format_long_label(record.format))
|
||||||
|
|> assert_has("#records-#{record.id} p", text: Record.type_long_label(record.type))
|
||||||
assert record_row_html =~ escape(record.title)
|
|> assert_has("#records-#{record.id} span", text: human_datetime(record.purchased_at))
|
||||||
assert record_row_html =~ to_string(record.release)
|
|> unwrap(fn collection_view ->
|
||||||
assert record_row_html =~ Record.format_long_label(record.format)
|
html = render(collection_view)
|
||||||
assert record_row_html =~ Record.type_long_label(record.type)
|
assert html =~ ~p"/covers/#{record.id}?vsn=#{record.cover_hash}"
|
||||||
assert record_row_html =~ record.release
|
html
|
||||||
assert record_row_html =~ ~p"/covers/#{record.id}?vsn=#{record.cover_hash}"
|
end)
|
||||||
|
|
||||||
for artist <- record.artists do
|
for artist <- record.artists do
|
||||||
assert record_row_html =~ escape(artist.name)
|
assert_has(session, "#records-#{record.id} a", text: escape(artist.name))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for record <- absent do
|
for record <- absent do
|
||||||
refute has_element?(index_live, "#records-#{record.id}")
|
refute_has(session, "#records-#{record.id}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -196,79 +217,55 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do
|
|||||||
test "can navigate to the record edit form", %{conn: conn} do
|
test "can navigate to the record edit form", %{conn: conn} do
|
||||||
record = record_fixture()
|
record = record_fixture()
|
||||||
|
|
||||||
{:ok, index_live, _html} = live(conn, ~p"/collection")
|
conn
|
||||||
|
|> visit(~p"/collection")
|
||||||
assert index_live
|
|> click_link("#records-#{record.id} a", "Edit")
|
||||||
|> element("#records-#{record.id} a", "Edit")
|
|> assert_has("h1", text: "Edit")
|
||||||
|> render_click() =~ "Edit"
|
|> assert_path(~p"/collection/#{record}/edit")
|
||||||
|
|
||||||
assert_patch(index_live, ~p"/collection/#{record}/edit")
|
|
||||||
|
|
||||||
assert index_live |> render() =~ "Edit"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "can change the record cover", %{conn: conn} do
|
test "can change the record cover", %{conn: conn} do
|
||||||
record = record_fixture(cover_data: File.read!(marbles_cover_fixture()))
|
record = record_fixture(cover_data: File.read!(marbles_cover_fixture()))
|
||||||
{:ok, form_live, html} = live(conn, ~p"/collection/#{record.id}/edit")
|
session = visit(conn, ~p"/collection/#{record.id}/edit")
|
||||||
|
|
||||||
assert html =~ ~p"/covers/#{record.id}?vsn=#{record.cover_hash}"
|
session
|
||||||
|
|> unwrap(fn edit_view ->
|
||||||
|
html = render(edit_view)
|
||||||
|
assert html =~ ~p"/covers/#{record.id}?vsn=#{record.cover_hash}"
|
||||||
|
html
|
||||||
|
end)
|
||||||
|
|
||||||
cover_metadata = cover_metadata(raven_cover_fixture())
|
session =
|
||||||
|
session
|
||||||
|
|> upload("Cover art", raven_cover_fixture())
|
||||||
|
|> click_button("Save")
|
||||||
|
|> assert_has("p", text: "Record updated successfully")
|
||||||
|
|
||||||
cover_input = file_input(form_live, "#record-form", :cover_data, [cover_metadata])
|
updated_cover = MusicLibrary.Records.get_cover(record.id)
|
||||||
|
assert updated_cover.cover_hash !== record.cover_hash
|
||||||
assert render_upload(cover_input, cover_metadata.name) =~ "100%"
|
|
||||||
|
|
||||||
list_html = form_live |> element("#record-form") |> render_submit()
|
|
||||||
|
|
||||||
assert list_html =~ "Record updated successfully"
|
|
||||||
|
|
||||||
# We trigger another render to force the list view to update
|
# We trigger another render to force the list view to update
|
||||||
# and display the new cover
|
# and display the new cover
|
||||||
list_html = form_live |> render()
|
session
|
||||||
|
|> unwrap(fn collection_view ->
|
||||||
updated_cover = MusicLibrary.Records.get_cover(record.id)
|
html = render(collection_view)
|
||||||
|
assert html =~ ~p"/covers/#{record.id}?vsn=#{updated_cover.cover_hash}"
|
||||||
assert updated_cover.cover_hash !== record.cover_hash
|
html
|
||||||
|
end)
|
||||||
assert list_html =~ ~p"/covers/#{record.id}?vsn=#{updated_cover.cover_hash}"
|
|
||||||
end
|
|
||||||
|
|
||||||
defp cover_metadata(path) do
|
|
||||||
stat = File.stat!(path)
|
|
||||||
|
|
||||||
%{
|
|
||||||
last_modified:
|
|
||||||
stat.mtime
|
|
||||||
|> NaiveDateTime.from_erl!()
|
|
||||||
|> DateTime.from_naive!("Etc/UTC")
|
|
||||||
|> DateTime.to_unix(),
|
|
||||||
name: Path.basename(path),
|
|
||||||
content: File.read!(path),
|
|
||||||
size: stat.size,
|
|
||||||
type: "image/jpeg"
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "Importing a new record" do
|
describe "Importing a new record" do
|
||||||
test "it shows the import modal", %{conn: conn} do
|
test "it shows the import modal", %{conn: conn} do
|
||||||
{:ok, index_live, _html} = live(conn, ~p"/collection")
|
conn
|
||||||
|
|> visit(~p"/collection")
|
||||||
import_dialog =
|
|> click_link("Import")
|
||||||
index_live
|
|> assert_has("label", text: "Search for a record on MusicBrainz")
|
||||||
|> element("a", "Import")
|
|> assert_has("div", text: "No results")
|
||||||
|> render_click()
|
|> assert_path(~p"/collection/import")
|
||||||
|
|
||||||
assert import_dialog =~ "Search for a record on MusicBrainz"
|
|
||||||
assert import_dialog =~ "No results"
|
|
||||||
|
|
||||||
assert_patch(index_live, ~p"/collection/import")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it imports a record when selected", %{conn: conn} do
|
test "it imports a record when selected", %{conn: conn} do
|
||||||
{:ok, import_live, _html} = live(conn, ~p"/collection/import")
|
|
||||||
|
|
||||||
mock_results = release_group_search_results()
|
mock_results = release_group_search_results()
|
||||||
|
|
||||||
expect(APIBehaviourMock, :search_release_group, fn "Marillion Marbles",
|
expect(APIBehaviourMock, :search_release_group, fn "Marillion Marbles",
|
||||||
@@ -277,16 +274,16 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do
|
|||||||
{:ok, mock_results}
|
{:ok, mock_results}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
assert import_live
|
session =
|
||||||
|> element("#import_form")
|
conn
|
||||||
|> render_change(%{mb_query: "Marillion Marbles"})
|
|> visit(~p"/collection/import")
|
||||||
|
|> fill_in("Search for a record on MusicBrainz", with: "Marillion Marbles")
|
||||||
updated_list = import_live |> render()
|
|
||||||
|
|
||||||
for result <- mock_results do
|
for result <- mock_results do
|
||||||
assert updated_list =~ result.title
|
session
|
||||||
assert updated_list =~ Record.format_release(result.release)
|
|> assert_has("h1", text: result.artists)
|
||||||
assert updated_list =~ result.artists
|
|> assert_has("h2", text: result.title)
|
||||||
|
|> assert_has("p", text: Record.format_release(result.release))
|
||||||
end
|
end
|
||||||
|
|
||||||
first_result = hd(mock_results)
|
first_result = hd(mock_results)
|
||||||
@@ -304,9 +301,9 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do
|
|||||||
{:ok, cover_data}
|
{:ok, cover_data}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
import_live
|
session =
|
||||||
|> element("#musicbrainz_#{first_result_id} a", "CD")
|
session
|
||||||
|> render_click()
|
|> click_link("#musicbrainz_#{first_result_id} a", "CD")
|
||||||
|
|
||||||
[record] = MusicLibrary.Repo.all(MusicLibrary.Records.Record)
|
[record] = MusicLibrary.Repo.all(MusicLibrary.Records.Record)
|
||||||
|
|
||||||
@@ -346,7 +343,7 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do
|
|||||||
musicbrainz_id: "1932f5b6-0b7b-4050-b1df-833ca89e5f44"
|
musicbrainz_id: "1932f5b6-0b7b-4050-b1df-833ca89e5f44"
|
||||||
} = marillion
|
} = marillion
|
||||||
|
|
||||||
assert_redirect(import_live, ~p"/collection/#{record.id}")
|
assert_path(session, ~p"/collection/#{record.id}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -19,13 +19,11 @@ defmodule MusicLibraryWeb.CollectionLive.ShowTest do
|
|||||||
test "can navigate to the record edit form", %{conn: conn} do
|
test "can navigate to the record edit form", %{conn: conn} do
|
||||||
record = record_fixture()
|
record = record_fixture()
|
||||||
|
|
||||||
{:ok, show_live, _html} = live(conn, ~p"/collection/#{record.id}")
|
conn
|
||||||
|
|> visit(~p"/collection/#{record.id}")
|
||||||
assert show_live
|
|> assert_has("a", text: "Edit")
|
||||||
|> element("a", "Edit")
|
|> click_link("Edit")
|
||||||
|> render_click() =~ "Edit"
|
|> assert_path(~p"/collection/#{record}/show/edit")
|
||||||
|
|
||||||
assert_patch(show_live, ~p"/collection/#{record}/show/edit")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -33,19 +31,24 @@ defmodule MusicLibraryWeb.CollectionLive.ShowTest do
|
|||||||
test "it includes all needed information", %{conn: conn} do
|
test "it includes all needed information", %{conn: conn} do
|
||||||
record = record_fixture()
|
record = record_fixture()
|
||||||
|
|
||||||
{:ok, _show_live, html} = live(conn, ~p"/collection/#{record.id}")
|
session =
|
||||||
|
conn
|
||||||
assert html =~ escape(record.title)
|
|> visit(~p"/collection/#{record.id}")
|
||||||
assert html =~ to_string(record.release)
|
|> assert_has("h2", text: escape(record.title))
|
||||||
assert html =~ Record.format_long_label(record.format)
|
|> assert_has("p", text: record.release)
|
||||||
assert html =~ record.release
|
|> assert_has("p", text: Record.format_long_label(record.format))
|
||||||
assert html =~ ~p"/covers/#{record.id}?vsn=#{record.cover_hash}"
|
|> assert_has("p", text: Record.type_long_label(record.type))
|
||||||
assert html =~ human_datetime(record.purchased_at)
|
|> assert_has("dd", text: human_datetime(record.purchased_at))
|
||||||
assert html =~ human_datetime(record.inserted_at)
|
|> assert_has("dd", text: human_datetime(record.inserted_at))
|
||||||
assert html =~ human_datetime(record.updated_at)
|
|> assert_has("dd", text: human_datetime(record.updated_at))
|
||||||
|
|> unwrap(fn show_view ->
|
||||||
|
html = render(show_view)
|
||||||
|
assert html =~ ~p"/covers/#{record.id}?vsn=#{record.cover_hash}"
|
||||||
|
html
|
||||||
|
end)
|
||||||
|
|
||||||
for artist <- record.artists do
|
for artist <- record.artists do
|
||||||
assert html =~ escape(artist.name)
|
assert_has(session, "a", text: escape(artist.name))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ defmodule MusicLibraryWeb.StatsLive.IndexTest do
|
|||||||
alias MusicLibrary.{Records, Repo, Wishlist}
|
alias MusicLibrary.{Records, Repo, Wishlist}
|
||||||
alias MusicLibrary.Records.Record
|
alias MusicLibrary.Records.Record
|
||||||
alias MusicBrainz.APIBehaviourMock
|
alias MusicBrainz.APIBehaviourMock
|
||||||
import Phoenix.LiveViewTest
|
|
||||||
import MusicLibrary.RecordsFixtures
|
import MusicLibrary.RecordsFixtures
|
||||||
import MusicLibrary.ReleaseGroupsFixtures
|
import MusicLibrary.ReleaseGroupsFixtures
|
||||||
import Mox
|
import Mox
|
||||||
@@ -34,43 +33,45 @@ defmodule MusicLibraryWeb.StatsLive.IndexTest do
|
|||||||
conn: conn,
|
conn: conn,
|
||||||
collection: collection
|
collection: collection
|
||||||
} do
|
} do
|
||||||
{:ok, stats_live, html} = live(conn, "/")
|
session =
|
||||||
|
conn
|
||||||
assert html =~ collection |> length() |> Integer.to_string()
|
|> visit("/")
|
||||||
|
|> assert_has("dd", text: collection |> length() |> Integer.to_string())
|
||||||
|
|
||||||
collection
|
collection
|
||||||
|> Enum.frequencies_by(& &1.format)
|
|> Enum.frequencies_by(& &1.format)
|
||||||
|> Enum.each(fn {format, count} ->
|
|> Enum.each(fn {format, count} ->
|
||||||
assert has_element?(stats_live, "a", to_string(count))
|
assert_has(session, "a", text: to_string(count))
|
||||||
assert has_element?(stats_live, "dt", Record.format_long_label(format))
|
assert_has(session, "dt", text: Record.format_long_label(format))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
collection
|
collection
|
||||||
|> Enum.frequencies_by(& &1.type)
|
|> Enum.frequencies_by(& &1.type)
|
||||||
|> Enum.each(fn {type, count} ->
|
|> Enum.each(fn {type, count} ->
|
||||||
assert has_element?(stats_live, "a", to_string(count))
|
assert_has(session, "a", text: to_string(count))
|
||||||
assert has_element?(stats_live, "dt", Record.type_long_label(type))
|
assert_has(session, "dt", text: Record.type_long_label(type))
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it shows the latest purchase", %{conn: conn, collection: collection} do
|
test "it shows the latest purchase", %{conn: conn, collection: collection} do
|
||||||
# purchased_at has second precision, so finding the latest purchased using then
|
# purchased_at has second precision, so finding the latest purchased using then
|
||||||
# highest purchsed_at value doesn't work, as it picks the wrong value.
|
# highest purchased_at value doesn't work, as it picks the wrong value.
|
||||||
latest_record = List.last(collection)
|
latest_record = List.last(collection)
|
||||||
|
|
||||||
{:ok, _stats_live, html} = live(conn, "/")
|
session =
|
||||||
|
conn
|
||||||
assert html =~ escape(latest_record.title)
|
|> visit("/")
|
||||||
|
|> assert_has("span", text: escape(latest_record.title))
|
||||||
|
|
||||||
for artist <- latest_record.artists do
|
for artist <- latest_record.artists do
|
||||||
assert html =~ escape(artist.name)
|
assert_has(session, "a", text: escape(artist.name))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it shows the wishlist total count", %{conn: conn, wishlist: wishlist} do
|
test "it shows the wishlist total count", %{conn: conn, wishlist: wishlist} do
|
||||||
{:ok, _stats_live, html} = live(conn, "/")
|
conn
|
||||||
|
|> visit("/")
|
||||||
assert html =~ wishlist |> length() |> Integer.to_string()
|
|> assert_has("dd", text: wishlist |> length() |> Integer.to_string())
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it shows the scrobble activity", %{conn: conn} do
|
test "it shows the scrobble activity", %{conn: conn} do
|
||||||
@@ -155,7 +156,8 @@ defmodule MusicLibraryWeb.StatsLive.IndexTest do
|
|||||||
in_murmuration_track
|
in_murmuration_track
|
||||||
])
|
])
|
||||||
|
|
||||||
# We add one album to the wishlist, and one to the collection.
|
# We add one album to the wishlist, and one to the collection so that
|
||||||
|
# their status in the scrobble activity changes.
|
||||||
|
|
||||||
_machinarium_soundtrack =
|
_machinarium_soundtrack =
|
||||||
record_fixture(purchased_at: nil)
|
record_fixture(purchased_at: nil)
|
||||||
@@ -167,33 +169,21 @@ defmodule MusicLibraryWeb.StatsLive.IndexTest do
|
|||||||
|> Records.change_record(%{release_ids: ["2157367e-bf73-48bb-8185-41023a54fa08"]})
|
|> Records.change_record(%{release_ids: ["2157367e-bf73-48bb-8185-41023a54fa08"]})
|
||||||
|> Repo.update!()
|
|> Repo.update!()
|
||||||
|
|
||||||
{:ok, stats_live, _html} = live(conn, "/")
|
session =
|
||||||
|
conn
|
||||||
|
|> visit("/")
|
||||||
|
|> assert_has("#track-#{machinarium_soundtrack_track.scrobbled_at_uts}",
|
||||||
|
text: "Wishlisted"
|
||||||
|
)
|
||||||
|
|> assert_has("#track-#{the_last_flight_track.scrobbled_at_uts}", text: "Collected")
|
||||||
|
|> assert_has("#track-#{the_mystery_of_time_track.scrobbled_at_uts}",
|
||||||
|
text: "Choose which format to import"
|
||||||
|
)
|
||||||
|
|> assert_has("#track-#{in_murmuration_track.scrobbled_at_uts}",
|
||||||
|
text: "No MB ID"
|
||||||
|
)
|
||||||
|
|
||||||
assert has_element?(
|
# We now try to import The Mystery of Time.
|
||||||
stats_live,
|
|
||||||
"#track-#{machinarium_soundtrack_track.scrobbled_at_uts}",
|
|
||||||
"Wishlisted"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert has_element?(
|
|
||||||
stats_live,
|
|
||||||
"#track-#{the_last_flight_track.scrobbled_at_uts}",
|
|
||||||
"Collected"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert has_element?(
|
|
||||||
stats_live,
|
|
||||||
"#track-#{the_mystery_of_time_track.scrobbled_at_uts}",
|
|
||||||
"Choose which format to import"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert has_element?(
|
|
||||||
stats_live,
|
|
||||||
"#track-#{in_murmuration_track.scrobbled_at_uts}",
|
|
||||||
"No MB ID"
|
|
||||||
)
|
|
||||||
|
|
||||||
# We now try to import The Mystery of Time
|
|
||||||
|
|
||||||
release = release(:mystery_of_time)
|
release = release(:mystery_of_time)
|
||||||
release_id = release_id(:mystery_of_time)
|
release_id = release_id(:mystery_of_time)
|
||||||
@@ -216,16 +206,17 @@ defmodule MusicLibraryWeb.StatsLive.IndexTest do
|
|||||||
{:ok, cover_data}
|
{:ok, cover_data}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
stats_live
|
assert [] == Wishlist.search_records("mbid:#{release_group_id}")
|
||||||
|> element(
|
|
||||||
"#track-#{the_mystery_of_time_track.scrobbled_at_uts} a",
|
session =
|
||||||
"CD"
|
session
|
||||||
)
|
|> click_link(
|
||||||
|> render_click()
|
"#track-#{the_mystery_of_time_track.scrobbled_at_uts} a",
|
||||||
|
"CD"
|
||||||
|
)
|
||||||
|
|
||||||
assert [wishlisted_record] = Wishlist.search_records("mbid:#{release_group_id}")
|
assert [wishlisted_record] = Wishlist.search_records("mbid:#{release_group_id}")
|
||||||
|
assert_path(session, ~p"/wishlist/#{wishlisted_record.id}")
|
||||||
assert_redirected(stats_live, ~p"/wishlist/#{wishlisted_record.id}")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
defmodule MusicLibraryWeb.WishlistLive.IndexTest do
|
defmodule MusicLibraryWeb.WishlistLive.IndexTest do
|
||||||
use MusicLibraryWeb.ConnCase
|
use MusicLibraryWeb.ConnCase
|
||||||
|
|
||||||
import Phoenix.LiveViewTest
|
|
||||||
import MusicLibrary.RecordsFixtures
|
import MusicLibrary.RecordsFixtures
|
||||||
|
|
||||||
defp fill_wishlist(_) do
|
defp fill_wishlist(_) do
|
||||||
@@ -16,13 +15,12 @@ defmodule MusicLibraryWeb.WishlistLive.IndexTest do
|
|||||||
conn: conn,
|
conn: conn,
|
||||||
wishlist: wishlist_records
|
wishlist: wishlist_records
|
||||||
} do
|
} do
|
||||||
{:ok, index_live, _html} = live(conn, ~p"/wishlist")
|
|
||||||
|
|
||||||
record = Enum.random(wishlist_records)
|
record = Enum.random(wishlist_records)
|
||||||
|
|
||||||
index_live
|
conn
|
||||||
|> element("#records-#{record.id} a", "Purchase")
|
|> visit(~p"/wishlist")
|
||||||
|> render_click() =~ "Record updated successfully"
|
|> click_link("#records-#{record.id} a", "Purchase")
|
||||||
|
|> assert_has("p", text: "Record updated successfully")
|
||||||
|
|
||||||
purchased_record = MusicLibrary.Records.get_record!(record.id)
|
purchased_record = MusicLibrary.Records.get_record!(record.id)
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ defmodule MusicLibraryWeb.ConnCase do
|
|||||||
import Plug.Conn
|
import Plug.Conn
|
||||||
import Phoenix.ConnTest
|
import Phoenix.ConnTest
|
||||||
import MusicLibraryWeb.ConnCase
|
import MusicLibraryWeb.ConnCase
|
||||||
|
import PhoenixTest
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user