diff --git a/config/test.exs b/config/test.exs index bb516f27..6c5d3451 100644 --- a/config/test.exs +++ b/config/test.exs @@ -31,3 +31,5 @@ config :phoenix_live_view, config :music_library, dev_routes: true config :music_library, LastFm, auto_refresh: false + +config :phoenix_test, :endpoint, MusicLibraryWeb.Endpoint diff --git a/mix.exs b/mix.exs index 131b5389..93025a6c 100644 --- a/mix.exs +++ b/mix.exs @@ -80,6 +80,9 @@ defmodule MusicLibrary.MixProject do # Data validation {:nimble_options, "~> 1.1"}, + + # Test tooling + {:phoenix_test, "~> 0.5.1", only: :test}, {:floki, ">= 0.30.0", only: :test}, {:mox, "~> 1.2", only: :test}, diff --git a/mix.lock b/mix.lock index b4413544..40ccf6c0 100644 --- a/mix.lock +++ b/mix.lock @@ -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_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_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_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"}, "recon": {:hex, :recon, "2.5.6", "9052588e83bfedfd9b72e1034532aee2a5369d9d9343b61aeb7fbce761010741", [:mix, :rebar3], [], "hexpm", "96c6799792d735cc0f0fd0f86267e9d351e63339cbe03df9d162010cefc26bb0"}, diff --git a/test/music_library_web/live/artist_live/show_test.exs b/test/music_library_web/live/artist_live/show_test.exs index fe6d82ad..b772c50e 100644 --- a/test/music_library_web/live/artist_live/show_test.exs +++ b/test/music_library_web/live/artist_live/show_test.exs @@ -43,16 +43,12 @@ defmodule MusicLibraryWeb.ArtistLive.ShowTest do |> Artist.from_api_response()} end) - {:ok, show_live, _html} = live(conn, ~p"/artists/#{artist_musicbrainz_id}") - - render_async(show_live) - - # play count - assert has_element?(show_live, "span", "123") - - assert has_element?(show_live, "summary", "Biography") - - assert element(show_live, "details") + conn + |> visit(~p"/artists/#{artist_musicbrainz_id}") + |> unwrap(&render_async/1) + |> assert_has("span", text: "123") + |> assert_has("summary", text: "Biography") + |> assert_has("details") end test "it gracefully handles errors in fetching bio and play count", %{ @@ -64,16 +60,13 @@ defmodule MusicLibraryWeb.ArtistLive.ShowTest do {:error, :timeout} end) - {:ok, show_live, _html} = live(conn, ~p"/artists/#{artist_musicbrainz_id}") - - render_async(show_live) - - # play count - refute has_element?(show_live, "span", "123") - assert has_element?(show_live, "div", "Error loading play count") - - refute has_element?(show_live, "summary", "Biography") - assert has_element?(show_live, "div", "Error loading biography") + conn + |> visit(~p"/artists/#{artist_musicbrainz_id}") + |> unwrap(&render_async/1) + |> refute_has("span", text: "123") + |> refute_has("summary", text: "Biography") + |> assert_has("div", text: "Error loading play count") + |> assert_has("div", text: "Error loading biography") end test "it shows records from the collection and the wishlist", %{ @@ -96,19 +89,13 @@ defmodule MusicLibraryWeb.ArtistLive.ShowTest do {:error, :timeout} end) - {:ok, show_live, _html} = live(conn, ~p"/artists/#{artist_musicbrainz_id}") - - render_async(show_live) - - # collection records - assert has_element?(show_live, "#collection p", escape(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)) + conn + |> visit(~p"/artists/#{artist_musicbrainz_id}") + |> unwrap(&render_async/1) + |> assert_has("#collection p", text: escape(collection_record.title)) + |> assert_has("#wishlist p", text: escape(wishlist_record.title)) + |> refute_has("#collection p", text: escape(other_collection_record.title)) + |> refute_has("#wishlist p", text: escape(other_collection_record.title)) end end end diff --git a/test/music_library_web/live/collection_live/index_test.exs b/test/music_library_web/live/collection_live/index_test.exs index 77a81eaa..2bc55b12 100644 --- a/test/music_library_web/live/collection_live/index_test.exs +++ b/test/music_library_web/live/collection_live/index_test.exs @@ -29,6 +29,10 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do |> Phoenix.HTML.safe_to_string() end + defp human_datetime(dt) do + "#{dt.day}/#{dt.month}/#{dt.year}" + end + describe "Collection" do setup [:fill_collection, :fill_wishlist] @@ -36,86 +40,100 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do conn: conn, wishlist: wishlist_records } do - {:ok, index_live, _html} = live(conn, ~p"/collection") + session = visit(conn, ~p"/collection") for record <- wishlist_records do - refute has_element?(index_live, "#records-#{record.id}") + refute_has(session, "#records-#{record.id}") end end - test "shows purchased records", %{conn: conn, collection: records} do - {:ok, index_live, html} = live(conn, ~p"/collection") + test "shows purchased records (first page only)", %{conn: conn} do + # 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} = - Enum.split_with(records, fn record -> - html =~ record.id - end) + session = visit(conn, ~p"/collection") - assert length(present) == @default_records_page_size - assert length(absent) == @total_records - @default_records_page_size - - for record <- present do - record_row = - index_live - |> with_target("#records-#{record.id}") - - 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 record <- expected_present do + session + |> assert_has("#records-#{record.id}") + |> assert_has("#records-#{record.id} h2", text: escape(record.title)) + |> assert_has("#records-#{record.id} p", text: record.release) + |> 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_has("#records-#{record.id} span", text: human_datetime(record.purchased_at)) 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 + + 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 describe "Search and pagination" do setup [:fill_collection] - test "uses query string params", %{conn: conn, collection: records} do - {:ok, page_2_live, page_2_html} = live(conn, ~p"/collection?page=2&page_size=10") + test "uses query string params", %{conn: conn} do + # We fetch collection records to maintain consistent order + records = MusicLibrary.Collection.search_records("") + page_size = 10 - {page_2_present, page_2_absent} = - Enum.split_with(records, fn record -> - page_2_html =~ record.id - end) + {page_1_records, rest_of_records} = Enum.split(records, page_size) + {page_2_records, rest_of_records} = Enum.split(rest_of_records, page_size) - assert length(page_2_present) == 10 - assert length(page_2_absent) == @total_records - 10 + page_2_session = + visit(conn, ~p"/collection?page=2&page_size=#{page_size}") - page_2_pagination = page_2_live |> with_target("#pagination") - refute has_element?(page_2_pagination, "a", "2") - assert has_element?(page_2_pagination, "a", "1") - assert has_element?(page_2_pagination, "a", "3") + for record <- page_1_records do + refute_has(page_2_session, "#records-#{record.id}") + end - {: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} = - Enum.split_with(records, fn record -> - page_3_html =~ record.id - end) + for record <- rest_of_records do + refute_has(page_2_session, "#records-#{record.id}") + end - assert length(page_3_present) == 10 - assert length(page_3_absent) == @total_records - 10 + page_2_session + |> 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") - refute has_element?(page_3_pagination, "a", "3") - assert has_element?(page_3_pagination, "a", "1") - assert has_element?(page_3_pagination, "a", "2") + {page_3_records, rest_of_records} = Enum.split(rest_of_records, page_size) - # All records in page 3 were not present in page 2 - assert page_3_present -- page_2_absent == [] - # All records in page 2 are not present in page 3 - assert page_2_present -- page_3_absent == [] + page_3_session = + visit(conn, ~p"/collection?page=3&page_size=#{page_size}") + + 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 @@ -125,23 +143,25 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do test "supports raw queries", %{conn: conn, collection: records} do [record | _rest] = records qs = [query: record.title] - {:ok, index_live, _html} = live(conn, ~p"/collection?#{qs}") - record_row = - index_live - |> with_target("#records-#{record.id}") + session = + visit(conn, ~p"/collection?#{qs}") - 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}" + session + |> assert_has("#records-#{record.id}") + |> assert_has("#records-#{record.id} h2", text: escape(record.title)) + |> assert_has("#records-#{record.id} p", text: record.release) + |> 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_has("#records-#{record.id} span", text: human_datetime(record.purchased_at)) + |> 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 - assert record_row_html =~ escape(artist.name) + assert_has(session, "#records-#{record.id} a", text: escape(artist.name)) end end @@ -165,29 +185,30 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do 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 - record_row = - index_live - |> with_target("#records-#{record.id}") - - 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}" + session + |> assert_has("#records-#{record.id}") + |> assert_has("#records-#{record.id} h2", text: escape(record.title)) + |> assert_has("#records-#{record.id} p", text: record.release) + |> 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_has("#records-#{record.id} span", text: human_datetime(record.purchased_at)) + |> 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 - assert record_row_html =~ escape(artist.name) + assert_has(session, "#records-#{record.id} a", text: escape(artist.name)) end end for record <- absent do - refute has_element?(index_live, "#records-#{record.id}") + refute_has(session, "#records-#{record.id}") end end end @@ -196,79 +217,55 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do test "can navigate to the record edit form", %{conn: conn} do record = record_fixture() - {:ok, index_live, _html} = live(conn, ~p"/collection") - - assert index_live - |> element("#records-#{record.id} a", "Edit") - |> render_click() =~ "Edit" - - assert_patch(index_live, ~p"/collection/#{record}/edit") - - assert index_live |> render() =~ "Edit" + conn + |> visit(~p"/collection") + |> click_link("#records-#{record.id} a", "Edit") + |> assert_has("h1", text: "Edit") + |> assert_path(~p"/collection/#{record}/edit") end test "can change the record cover", %{conn: conn} do 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]) - - assert render_upload(cover_input, cover_metadata.name) =~ "100%" - - list_html = form_live |> element("#record-form") |> render_submit() - - assert list_html =~ "Record updated successfully" + updated_cover = MusicLibrary.Records.get_cover(record.id) + assert updated_cover.cover_hash !== record.cover_hash # We trigger another render to force the list view to update # and display the new cover - list_html = form_live |> render() - - updated_cover = MusicLibrary.Records.get_cover(record.id) - - assert updated_cover.cover_hash !== record.cover_hash - - 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" - } + session + |> unwrap(fn collection_view -> + html = render(collection_view) + assert html =~ ~p"/covers/#{record.id}?vsn=#{updated_cover.cover_hash}" + html + end) end end describe "Importing a new record" do test "it shows the import modal", %{conn: conn} do - {:ok, index_live, _html} = live(conn, ~p"/collection") - - import_dialog = - index_live - |> element("a", "Import") - |> render_click() - - assert import_dialog =~ "Search for a record on MusicBrainz" - assert import_dialog =~ "No results" - - assert_patch(index_live, ~p"/collection/import") + conn + |> visit(~p"/collection") + |> click_link("Import") + |> assert_has("label", text: "Search for a record on MusicBrainz") + |> assert_has("div", text: "No results") + |> assert_path(~p"/collection/import") end 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() expect(APIBehaviourMock, :search_release_group, fn "Marillion Marbles", @@ -277,16 +274,16 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do {:ok, mock_results} end) - assert import_live - |> element("#import_form") - |> render_change(%{mb_query: "Marillion Marbles"}) - - updated_list = import_live |> render() + session = + conn + |> visit(~p"/collection/import") + |> fill_in("Search for a record on MusicBrainz", with: "Marillion Marbles") for result <- mock_results do - assert updated_list =~ result.title - assert updated_list =~ Record.format_release(result.release) - assert updated_list =~ result.artists + session + |> assert_has("h1", text: result.artists) + |> assert_has("h2", text: result.title) + |> assert_has("p", text: Record.format_release(result.release)) end first_result = hd(mock_results) @@ -304,9 +301,9 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do {:ok, cover_data} end) - import_live - |> element("#musicbrainz_#{first_result_id} a", "CD") - |> render_click() + session = + session + |> click_link("#musicbrainz_#{first_result_id} a", "CD") [record] = MusicLibrary.Repo.all(MusicLibrary.Records.Record) @@ -346,7 +343,7 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do musicbrainz_id: "1932f5b6-0b7b-4050-b1df-833ca89e5f44" } = marillion - assert_redirect(import_live, ~p"/collection/#{record.id}") + assert_path(session, ~p"/collection/#{record.id}") end end end diff --git a/test/music_library_web/live/collection_live/show_test.exs b/test/music_library_web/live/collection_live/show_test.exs index be6cca81..3d0ec78d 100644 --- a/test/music_library_web/live/collection_live/show_test.exs +++ b/test/music_library_web/live/collection_live/show_test.exs @@ -19,13 +19,11 @@ defmodule MusicLibraryWeb.CollectionLive.ShowTest do test "can navigate to the record edit form", %{conn: conn} do record = record_fixture() - {:ok, show_live, _html} = live(conn, ~p"/collection/#{record.id}") - - assert show_live - |> element("a", "Edit") - |> render_click() =~ "Edit" - - assert_patch(show_live, ~p"/collection/#{record}/show/edit") + conn + |> visit(~p"/collection/#{record.id}") + |> assert_has("a", text: "Edit") + |> click_link("Edit") + |> assert_path(~p"/collection/#{record}/show/edit") end end @@ -33,19 +31,24 @@ defmodule MusicLibraryWeb.CollectionLive.ShowTest do test "it includes all needed information", %{conn: conn} do record = record_fixture() - {:ok, _show_live, html} = live(conn, ~p"/collection/#{record.id}") - - assert html =~ escape(record.title) - assert html =~ to_string(record.release) - assert html =~ Record.format_long_label(record.format) - assert html =~ record.release - assert html =~ ~p"/covers/#{record.id}?vsn=#{record.cover_hash}" - assert html =~ human_datetime(record.purchased_at) - assert html =~ human_datetime(record.inserted_at) - assert html =~ human_datetime(record.updated_at) + session = + conn + |> visit(~p"/collection/#{record.id}") + |> assert_has("h2", text: escape(record.title)) + |> assert_has("p", text: record.release) + |> assert_has("p", text: Record.format_long_label(record.format)) + |> assert_has("p", text: Record.type_long_label(record.type)) + |> assert_has("dd", text: human_datetime(record.purchased_at)) + |> assert_has("dd", text: human_datetime(record.inserted_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 - assert html =~ escape(artist.name) + assert_has(session, "a", text: escape(artist.name)) end end end diff --git a/test/music_library_web/live/stats_live/index_test.exs b/test/music_library_web/live/stats_live/index_test.exs index b1364413..f7df62b1 100644 --- a/test/music_library_web/live/stats_live/index_test.exs +++ b/test/music_library_web/live/stats_live/index_test.exs @@ -4,7 +4,6 @@ defmodule MusicLibraryWeb.StatsLive.IndexTest do alias MusicLibrary.{Records, Repo, Wishlist} alias MusicLibrary.Records.Record alias MusicBrainz.APIBehaviourMock - import Phoenix.LiveViewTest import MusicLibrary.RecordsFixtures import MusicLibrary.ReleaseGroupsFixtures import Mox @@ -34,43 +33,45 @@ defmodule MusicLibraryWeb.StatsLive.IndexTest do conn: conn, collection: collection } do - {:ok, stats_live, html} = live(conn, "/") - - assert html =~ collection |> length() |> Integer.to_string() + session = + conn + |> visit("/") + |> assert_has("dd", text: collection |> length() |> Integer.to_string()) collection |> Enum.frequencies_by(& &1.format) |> Enum.each(fn {format, count} -> - assert has_element?(stats_live, "a", to_string(count)) - assert has_element?(stats_live, "dt", Record.format_long_label(format)) + assert_has(session, "a", text: to_string(count)) + assert_has(session, "dt", text: Record.format_long_label(format)) end) collection |> Enum.frequencies_by(& &1.type) |> Enum.each(fn {type, count} -> - assert has_element?(stats_live, "a", to_string(count)) - assert has_element?(stats_live, "dt", Record.type_long_label(type)) + assert_has(session, "a", text: to_string(count)) + assert_has(session, "dt", text: Record.type_long_label(type)) end) end test "it shows the latest purchase", %{conn: conn, collection: collection} do # 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) - {:ok, _stats_live, html} = live(conn, "/") - - assert html =~ escape(latest_record.title) + session = + conn + |> visit("/") + |> assert_has("span", text: escape(latest_record.title)) for artist <- latest_record.artists do - assert html =~ escape(artist.name) + assert_has(session, "a", text: escape(artist.name)) end end test "it shows the wishlist total count", %{conn: conn, wishlist: wishlist} do - {:ok, _stats_live, html} = live(conn, "/") - - assert html =~ wishlist |> length() |> Integer.to_string() + conn + |> visit("/") + |> assert_has("dd", text: wishlist |> length() |> Integer.to_string()) end test "it shows the scrobble activity", %{conn: conn} do @@ -155,7 +156,8 @@ defmodule MusicLibraryWeb.StatsLive.IndexTest do 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 = record_fixture(purchased_at: nil) @@ -167,33 +169,21 @@ defmodule MusicLibraryWeb.StatsLive.IndexTest do |> Records.change_record(%{release_ids: ["2157367e-bf73-48bb-8185-41023a54fa08"]}) |> 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?( - 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 + # We now try to import The Mystery of Time. release = release(:mystery_of_time) release_id = release_id(:mystery_of_time) @@ -216,16 +206,17 @@ defmodule MusicLibraryWeb.StatsLive.IndexTest do {:ok, cover_data} end) - stats_live - |> element( - "#track-#{the_mystery_of_time_track.scrobbled_at_uts} a", - "CD" - ) - |> render_click() + assert [] == Wishlist.search_records("mbid:#{release_group_id}") + + session = + session + |> click_link( + "#track-#{the_mystery_of_time_track.scrobbled_at_uts} a", + "CD" + ) assert [wishlisted_record] = Wishlist.search_records("mbid:#{release_group_id}") - - assert_redirected(stats_live, ~p"/wishlist/#{wishlisted_record.id}") + assert_path(session, ~p"/wishlist/#{wishlisted_record.id}") end end end diff --git a/test/music_library_web/live/wishlist_live/index_test.exs b/test/music_library_web/live/wishlist_live/index_test.exs index 65540900..2ed91289 100644 --- a/test/music_library_web/live/wishlist_live/index_test.exs +++ b/test/music_library_web/live/wishlist_live/index_test.exs @@ -1,7 +1,6 @@ defmodule MusicLibraryWeb.WishlistLive.IndexTest do use MusicLibraryWeb.ConnCase - import Phoenix.LiveViewTest import MusicLibrary.RecordsFixtures defp fill_wishlist(_) do @@ -16,13 +15,12 @@ defmodule MusicLibraryWeb.WishlistLive.IndexTest do conn: conn, wishlist: wishlist_records } do - {:ok, index_live, _html} = live(conn, ~p"/wishlist") - record = Enum.random(wishlist_records) - index_live - |> element("#records-#{record.id} a", "Purchase") - |> render_click() =~ "Record updated successfully" + conn + |> visit(~p"/wishlist") + |> click_link("#records-#{record.id} a", "Purchase") + |> assert_has("p", text: "Record updated successfully") purchased_record = MusicLibrary.Records.get_record!(record.id) diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex index 00e29f5b..ac5010c5 100644 --- a/test/support/conn_case.ex +++ b/test/support/conn_case.ex @@ -28,6 +28,7 @@ defmodule MusicLibraryWeb.ConnCase do import Plug.Conn import Phoenix.ConnTest import MusicLibraryWeb.ConnCase + import PhoenixTest end end