From a2189421106da1c1c3aa04ff4628c75cf568491d Mon Sep 17 00:00:00 2001 From: Claudio Ortolina Date: Fri, 28 Feb 2025 16:38:11 +0000 Subject: [PATCH] Remove mox in favour of built-in Req stubs --- config/config.exs | 4 +- config/test.exs | 6 + lib/music_brainz.ex | 14 +- lib/music_brainz/{api_impl.ex => api.ex} | 12 +- lib/music_brainz/api_behaviour.ex | 20 - lib/music_brainz/config.ex | 19 +- mix.exs | 1 - mix.lock | 2 - test/music_brainz_test.exs | 27 +- test/music_library/records_test.exs | 71 +- .../live/collection_live/index_test.exs | 97 ++- .../live/stats_live/index_test.exs | 33 +- test/support/fixtures/music_brainz/release.ex | 2 - .../fixtures/music_brainz/release_group.ex | 21 +- ...up_search_results - marillion marbles.json | 702 ++++++++++++++++++ test/test_helper.exs | 8 - 16 files changed, 844 insertions(+), 195 deletions(-) rename lib/music_brainz/{api_impl.ex => api.ex} (99%) delete mode 100644 lib/music_brainz/api_behaviour.ex create mode 100644 test/support/fixtures/music_brainz/release_group_search_results - marillion marbles.json diff --git a/config/config.exs b/config/config.exs index 9fce067a..1e439c62 100644 --- a/config/config.exs +++ b/config/config.exs @@ -33,9 +33,7 @@ config :music_library, LastFm, api_key: "change me", user_agent: user_agent -config :music_library, MusicBrainz, - api: MusicBrainz.APIImpl, - user_agent: user_agent +config :music_library, MusicBrainz, user_agent: user_agent # Configure esbuild (the version is required) config :esbuild, diff --git a/config/test.exs b/config/test.exs index bc373bfd..8b5d2bfd 100644 --- a/config/test.exs +++ b/config/test.exs @@ -42,4 +42,10 @@ config :music_library, LastFm, max_retries: 0 ] +config :music_library, MusicBrainz, + req_options: [ + plug: {Req.Test, MusicBrainz.API}, + max_retries: 0 + ] + config :phoenix_test, :endpoint, MusicLibraryWeb.Endpoint diff --git a/lib/music_brainz.ex b/lib/music_brainz.ex index c6d45534..586d6478 100644 --- a/lib/music_brainz.ex +++ b/lib/music_brainz.ex @@ -1,9 +1,11 @@ defmodule MusicBrainz do + alias MusicBrainz.API + def search_release_group(query, opts \\ []) do limit = Keyword.get(opts, :limit, 20) offset = Keyword.get(opts, :offset, 0) - music_brainz_config().api.search_release_group( + API.search_release_group( query, [limit: limit, offset: offset], music_brainz_config() @@ -11,23 +13,23 @@ defmodule MusicBrainz do end def get_release_group(musicbrainz_id) do - music_brainz_config().api.get_release_group(musicbrainz_id, music_brainz_config()) + API.get_release_group(musicbrainz_id, music_brainz_config()) end def get_releases(musicbrainz_id, opts) do - music_brainz_config().api.get_releases(musicbrainz_id, opts, music_brainz_config()) + API.get_releases(musicbrainz_id, opts, music_brainz_config()) end def get_release(musicbrainz_id) do - music_brainz_config().api.get_release(musicbrainz_id, music_brainz_config()) + API.get_release(musicbrainz_id, music_brainz_config()) end def search_release_by_barcode(barcode) do - music_brainz_config().api.search_release_by_barcode(barcode, music_brainz_config()) + API.search_release_by_barcode(barcode, music_brainz_config()) end def get_cover_art(id_or_url) do - music_brainz_config().api.get_cover_art(id_or_url, music_brainz_config()) + API.get_cover_art(id_or_url, music_brainz_config()) end defp music_brainz_config, do: MusicBrainz.Config.resolve(:music_library) diff --git a/lib/music_brainz/api_impl.ex b/lib/music_brainz/api.ex similarity index 99% rename from lib/music_brainz/api_impl.ex rename to lib/music_brainz/api.ex index 61aa2d47..b1097120 100644 --- a/lib/music_brainz/api_impl.ex +++ b/lib/music_brainz/api.ex @@ -1,4 +1,4 @@ -defmodule MusicBrainz.APIImpl do +defmodule MusicBrainz.API do @moduledoc """ The original data from Obsidian maps records to MusicBrainz release groups, so we can leverage the MusicBrainz API to: @@ -6,8 +6,6 @@ defmodule MusicBrainz.APIImpl do - Extend the metadata associated with existing records """ - @behaviour MusicBrainz.APIBehaviour - require Logger alias MusicBrainz.{ReleaseGroupSearchResult, ReleaseSearchResult} @@ -208,7 +206,6 @@ defmodule MusicBrainz.APIImpl do } """ - @impl true def get_release_group(id, config) do config |> new_request() @@ -285,7 +282,6 @@ defmodule MusicBrainz.APIImpl do "title": "Clark (Soundtrack From the Netflix Series)" } """ - @impl true def get_release(id, config) do config |> new_request() @@ -299,7 +295,6 @@ defmodule MusicBrainz.APIImpl do |> get_request() end - @impl true def get_releases(release_group_id, opts, config) do Keyword.validate!(opts, [:limit, :offset]) @@ -319,7 +314,6 @@ defmodule MusicBrainz.APIImpl do |> get_request() end - @impl true def search_release_by_barcode(barcode, config) do config |> new_request() @@ -436,7 +430,6 @@ defmodule MusicBrainz.APIImpl do ] } """ - @impl true def search_release_group(query, opts, config) do Keyword.validate!(opts, [:limit, :offset]) @@ -461,7 +454,6 @@ defmodule MusicBrainz.APIImpl do @doc """ Uses the [cover art](https://musicbrainz.org/doc/Cover_Art_Archive/API) endpoint with the release group id to get the cover image. """ - @impl true def get_cover_art({:musicbrainz_id, musicbrainz_id}, config) do url = "https://coverartarchive.org/release-group/#{musicbrainz_id}/front" @@ -470,6 +462,7 @@ defmodule MusicBrainz.APIImpl do def get_cover_art({:url, url}, config) do case Req.new(url: url, max_retries: 1, user_agent: config.user_agent) + |> Req.Request.merge_options(config.req_options) |> Req.Request.append_request_steps(log_attempt: &log_attempt/1) |> Req.Request.append_response_steps(log_error: &log_error/1) |> get_request() do @@ -484,6 +477,7 @@ defmodule MusicBrainz.APIImpl do max_retries: 1, user_agent: config.user_agent ) + |> Req.Request.merge_options(config.req_options) |> Req.Request.append_request_steps(log_attempt: &log_attempt/1) end diff --git a/lib/music_brainz/api_behaviour.ex b/lib/music_brainz/api_behaviour.ex deleted file mode 100644 index 43b97916..00000000 --- a/lib/music_brainz/api_behaviour.ex +++ /dev/null @@ -1,20 +0,0 @@ -defmodule MusicBrainz.APIBehaviour do - @type musicbrainz_id :: String.t() - @type config :: MusicBrainz.Config.t() - @type limit :: pos_integer() - @type barcode :: String.t() - - @callback get_release_group(musicbrainz_id, config) :: {:ok, map()} | {:error, String.t()} - - @callback get_releases(musicbrainz_id, limit, config) :: {:ok, map()} | {:error, String.t()} - - @callback get_release(musicbrainz_id, config) :: {:ok, map()} | {:error, String.t()} - - @callback search_release_group(String.t(), Keyword.t(), config) :: - {:ok, [map()]} | {:error, String.t()} - - @callback search_release_by_barcode(barcode, config) :: {:ok, [map()]} | {:error, String.t()} - - @callback get_cover_art({:musicbrainz_id, musicbrainz_id()} | {:url, String.t()}, config) :: - {:ok, binary()} | {:error, String.t()} -end diff --git a/lib/music_brainz/config.ex b/lib/music_brainz/config.ex index 4ba13487..f758aac3 100644 --- a/lib/music_brainz/config.ex +++ b/lib/music_brainz/config.ex @@ -1,22 +1,23 @@ defmodule MusicBrainz.Config do @type t :: %__MODULE__{ - api: module(), - user_agent: String.t() + user_agent: String.t(), + req_options: Keyword.t() } - @enforce_keys [:api, :user_agent] - defstruct api: MusicBrainz.APIImpl, - user_agent: "change me" + @enforce_keys [:user_agent] + defstruct user_agent: "change me", + req_options: [] @schema NimbleOptions.new!( - api: [ - type: :atom, - required: true - ], user_agent: [ type: :string, required: false, default: "change me" + ], + req_options: [ + type: :keyword_list, + required: false, + default: [] ] ) diff --git a/mix.exs b/mix.exs index 3400d00d..5de5bf50 100644 --- a/mix.exs +++ b/mix.exs @@ -85,7 +85,6 @@ defmodule MusicLibrary.MixProject do # Test tooling {:phoenix_test, "~> 0.5.1", only: :test}, {:floki, ">= 0.30.0", only: :test}, - {:mox, "~> 1.2", only: :test}, # Prod error/perf tooling {:phoenix_live_dashboard, "~> 0.8.3"}, diff --git a/mix.lock b/mix.lock index 6fdd6aae..b26cb3ec 100644 --- a/mix.lock +++ b/mix.lock @@ -26,9 +26,7 @@ "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"}, "mint": {:hex, :mint, "1.7.1", "113fdb2b2f3b59e47c7955971854641c61f378549d73e829e1768de90fc1abf1", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "fceba0a4d0f24301ddee3024ae116df1c3f4bb7a563a731f45fdfeb9d39a231b"}, - "mox": {:hex, :mox, "1.2.0", "a2cd96b4b80a3883e3100a221e8adc1b98e4c3a332a8fc434c39526babafd5b3", [:mix], [{:nimble_ownership, "~> 1.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}], "hexpm", "c7b92b3cc69ee24a7eeeaf944cd7be22013c52fcb580c1f33f50845ec821089a"}, "nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"}, - "nimble_ownership": {:hex, :nimble_ownership, "1.0.1", "f69fae0cdd451b1614364013544e66e4f5d25f36a2056a9698b793305c5aa3a6", [:mix], [], "hexpm", "3825e461025464f519f3f3e4a1f9b68c47dc151369611629ad08b636b73bb22d"}, "nimble_parsec": {:hex, :nimble_parsec, "1.4.2", "8efba0122db06df95bfaa78f791344a89352ba04baedd3849593bfce4d0dc1c6", [:mix], [], "hexpm", "4b21398942dda052b403bbe1da991ccd03a053668d147d53fb8c4e0efe09c973"}, "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"}, "phoenix": {:hex, :phoenix, "1.7.20", "6bababaf27d59f5628f9b608de902a021be2cecefb8231e1dbdc0a2e2e480e9b", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, 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.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "6be2ab98302e8784a31829e0d50d8bdfa81a23cd912c395bafd8b8bfb5a086c2"}, diff --git a/test/music_brainz_test.exs b/test/music_brainz_test.exs index 308ce7e4..c182e072 100644 --- a/test/music_brainz_test.exs +++ b/test/music_brainz_test.exs @@ -1,22 +1,22 @@ defmodule MusicBrainzTest do use ExUnit.Case, async: true - alias MusicBrainz.{APIMock, ReleaseSearchResult} + alias MusicBrainz.ReleaseGroupSearchResult import MusicBrainz.Fixtures.Release import MusicBrainz.Fixtures.ReleaseGroup - import Mox - - setup :verify_on_exit! describe "search_release_group/2" do test "it returns results with correct limit and offset" do - mock_results = release_group_search_results() + results = release_group_search_results() - expect(APIMock, :search_release_group, fn "Marillion", [limit: 20, offset: 10], _config -> - {:ok, mock_results} + expected_results = + Enum.map(results["release-groups"], &ReleaseGroupSearchResult.from_api_response/1) + + Req.Test.stub(MusicBrainz.API, fn conn -> + Req.Test.json(conn, results) end) - assert {:ok, mock_results} == + assert {:ok, expected_results} == MusicBrainz.search_release_group("Marillion", limit: 20, offset: 10) end end @@ -24,13 +24,16 @@ defmodule MusicBrainzTest do describe "search_release_by_barcode/1" do test "it returns releases belonging to the same release group" do barcode = "5052205070023" - releases = releases(:queen_greatest_hits) - expect(APIMock, :search_release_by_barcode, fn ^barcode, _config -> - {:ok, Enum.map(releases, &ReleaseSearchResult.from_api_response/1)} + releases = + releases(:queen_greatest_hits) + + Req.Test.stub(MusicBrainz.API, fn conn -> + Req.Test.json(conn, releases) end) - assert {:ok, results} = MusicBrainz.search_release_by_barcode(barcode) + assert {:ok, results} = + MusicBrainz.search_release_by_barcode(barcode) assert Enum.all?(results, fn result -> result.release_group.id == "69ce61c8-127f-3809-95d8-62fdf3ae1347" && diff --git a/test/music_library/records_test.exs b/test/music_library/records_test.exs index da8102b6..077f478d 100644 --- a/test/music_library/records_test.exs +++ b/test/music_library/records_test.exs @@ -1,15 +1,11 @@ defmodule MusicLibrary.RecordsTest do use MusicLibrary.DataCase - alias MusicBrainz.APIMock alias MusicLibrary.Records alias MusicLibrary.Records.SearchIndex import MusicLibrary.Fixtures.Records import MusicBrainz.Fixtures.ReleaseGroup import MusicBrainz.Fixtures.Release - import Mox - - setup :verify_on_exit! defp create_records(_) do records = [ @@ -63,12 +59,14 @@ defmodule MusicLibrary.RecordsTest do assert record.release_ids == [] assert record.included_release_group_ids == [] - expect(APIMock, :get_release_group, fn ^release_group_id, _config -> - {:ok, release_group(:lockdown_trilogy)} - end) + Req.Test.stub(MusicBrainz.API, fn conn -> + case conn.path_info do + [_ws, _version, "release-group", ^release_group_id] -> + Req.Test.json(conn, release_group(:lockdown_trilogy)) - expect(APIMock, :get_releases, fn ^release_group_id, _opts, _config -> - {:ok, %{"releases" => release_group(:lockdown_trilogy)["releases"]}} + [_ws, _version, "release"] -> + Req.Test.json(conn, %{"releases" => release_group(:lockdown_trilogy)["releases"]}) + end end) {:ok, updated_record} = Records.refresh_musicbrainz_data(record) @@ -189,18 +187,19 @@ defmodule MusicLibrary.RecordsTest do release_group = release_group(:marbles) release_group_id = release_group_id(:marbles) - expect(APIMock, :get_release_group, fn ^release_group_id, _config -> - {:ok, release_group} - end) - - expect(APIMock, :get_releases, fn ^release_group_id, _opts, _config -> - {:ok, %{"releases" => release_group["releases"]}} - end) - cover_data = File.read!(marbles_cover_fixture()) - expect(APIMock, :get_cover_art, fn {:musicbrainz_id, ^release_group_id}, _config -> - {:ok, cover_data} + Req.Test.stub(MusicBrainz.API, fn conn -> + case conn.path_info do + [_ws, _version, "release-group", ^release_group_id] -> + Req.Test.json(conn, release_group) + + [_ws, _version, "release"] -> + Req.Test.json(conn, %{"releases" => release_group["releases"]}) + + [_release_group, ^release_group_id, "front"] -> + Plug.Conn.send_resp(conn, 200, cover_data) + end end) assert {:ok, record} = @@ -243,22 +242,22 @@ defmodule MusicLibrary.RecordsTest do release_group = release_group(:marbles) release_group_id = release_group_id(:marbles) - expect(APIMock, :get_release, fn ^release_id, _config -> - {:ok, release} - end) - - expect(APIMock, :get_release_group, fn ^release_group_id, _config -> - {:ok, release_group} - end) - - expect(APIMock, :get_releases, fn ^release_group_id, _opts, _config -> - {:ok, %{"releases" => release_group["releases"]}} - end) - cover_data = File.read!(marbles_cover_fixture()) - expect(APIMock, :get_cover_art, fn {:musicbrainz_id, ^release_group_id}, _config -> - {:ok, cover_data} + Req.Test.stub(MusicBrainz.API, fn conn -> + case conn.path_info do + [_ws, _version, "release-group", ^release_group_id] -> + Req.Test.json(conn, release_group) + + [_ws, _version, "release", ^release_id] -> + Req.Test.json(conn, release) + + [_ws, _version, "release"] -> + Req.Test.json(conn, %{"releases" => release_group["releases"]}) + + [_release_group, ^release_group_id, "front"] -> + Plug.Conn.send_resp(conn, 200, cover_data) + end end) assert {:ok, record} = @@ -297,10 +296,8 @@ defmodule MusicLibrary.RecordsTest do raven_cover_data = File.read!(raven_cover_fixture()) - cover_url = record.cover_url - - expect(APIMock, :get_cover_art, fn {:url, ^cover_url}, _config -> - {:ok, raven_cover_data} + Req.Test.stub(MusicBrainz.API, fn conn -> + Plug.Conn.send_resp(conn, 200, raven_cover_data) end) assert {:ok, updated_record} = Records.refresh_cover(record) 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 90880cb5..0ab8b7c0 100644 --- a/test/music_library_web/live/collection_live/index_test.exs +++ b/test/music_library_web/live/collection_live/index_test.exs @@ -5,12 +5,9 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do import MusicBrainz.Fixtures.ReleaseGroup import MusicBrainz.Fixtures.Release import MusicLibraryWeb.RecordComponents, only: [format_label: 1, type_label: 1] - import Mox - alias MusicBrainz.{APIMock, ReleaseSearchResult} + alias MusicBrainz.ReleaseGroupSearchResult alias MusicLibrary.Records.{Cover, Record} - setup :verify_on_exit! - @default_records_page_size 20 @total_records @default_records_page_size + 10 @@ -243,12 +240,29 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do end test "it imports a record when selected", %{conn: conn} do - mock_results = release_group_search_results() + release_group_search_results = Map.get(release_group_search_results(), "release-groups") - expect(APIMock, :search_release_group, fn "Marillion Marbles", - [limit: 10, offset: 0], - _config -> - {:ok, mock_results} + first_release_group_search_result = hd(release_group_search_results) + first_release_group_search_result_id = first_release_group_search_result["id"] + + release_group = release_group(:marbles) + + cover_data = File.read!(marbles_cover_fixture()) + + Req.Test.stub(MusicBrainz.API, fn conn -> + case conn.path_info do + [_ws, _version, "release-group", ^first_release_group_search_result_id] -> + Req.Test.json(conn, release_group) + + [_ws, _version, "release-group"] -> + Req.Test.json(conn, release_group_search_results()) + + [_ws, _version, "release"] -> + Req.Test.json(conn, %{"releases" => release_group["releases"]}) + + [_release_group, ^first_release_group_search_result_id, "front"] -> + Plug.Conn.send_resp(conn, 200, cover_data) + end end) session = @@ -256,39 +270,22 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do |> visit(~p"/collection/import") |> fill_in("Search for a record on MusicBrainz", with: "Marillion Marbles") - for result <- mock_results do + for release_group_search_result <- release_group_search_results do + result = ReleaseGroupSearchResult.from_api_response(release_group_search_result) + 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) - first_result_id = first_result.id - - release_group = release_group(:marbles) - - expect(APIMock, :get_release_group, fn ^first_result_id, _config -> - {:ok, release_group} - end) - - expect(APIMock, :get_releases, fn ^first_result_id, _opts, _config -> - {:ok, %{"releases" => release_group["releases"]}} - end) - - cover_data = File.read!(marbles_cover_fixture()) - - expect(APIMock, :get_cover_art, fn {:musicbrainz_id, ^first_result_id}, _config -> - {:ok, cover_data} - end) - session = session - |> click_link("#musicbrainz_#{first_result_id} a", "CD") + |> click_link("#musicbrainz_#{first_release_group_search_result_id} a", "CD") [record] = MusicLibrary.Repo.all(MusicLibrary.Records.Record) - assert record.musicbrainz_id == first_result_id + assert record.musicbrainz_id == first_release_group_search_result_id assert record.title == "Marbles" assert record.release == "2004-05-03" assert record.format == :cd @@ -352,32 +349,34 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do barcode = "5037300650128" releases = releases(:marbles) - expect(APIMock, :search_release_by_barcode, fn ^barcode, _config -> - {:ok, Enum.map(releases, &ReleaseSearchResult.from_api_response/1)} - end) - release = release(:marbles) release_id = release_id(:marbles) - expect(APIMock, :get_release, fn ^release_id, _config -> - {:ok, release} - end) - release_group = release_group(:marbles) release_group_id = release_group["id"] - expect(APIMock, :get_release_group, fn ^release_group_id, _config -> - {:ok, release_group} - end) - - expect(APIMock, :get_releases, fn ^release_group_id, _opts, _config -> - {:ok, %{"releases" => release_group["releases"]}} - end) - cover_data = File.read!(marbles_cover_fixture()) - expect(APIMock, :get_cover_art, fn {:musicbrainz_id, ^release_group_id}, _config -> - {:ok, cover_data} + Req.Test.stub(MusicBrainz.API, fn conn -> + case conn.path_info do + [_ws, _version, "release-group", ^release_group_id] -> + Req.Test.json(conn, release_group) + + [_ws, _version, "release", ^release_id] -> + Req.Test.json(conn, release) + + [_ws, _version, "release"] -> + if conn.params["query"] do + # barcode scan + Req.Test.json(conn, releases) + else + # Search by release group ID + Req.Test.json(conn, %{"releases" => release_group["releases"]}) + end + + [_release_group, ^release_group_id, "front"] -> + Plug.Conn.send_resp(conn, 200, cover_data) + end end) conn 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 7f924516..0f0cd5ac 100644 --- a/test/music_library_web/live/stats_live/index_test.exs +++ b/test/music_library_web/live/stats_live/index_test.exs @@ -1,15 +1,11 @@ defmodule MusicLibraryWeb.StatsLive.IndexTest do use MusicLibraryWeb.ConnCase - alias MusicBrainz.APIMock alias MusicLibrary.{Records, Repo, Wishlist} import MusicLibraryWeb.RecordComponents, only: [format_label: 1, type_label: 1] import MusicLibrary.Fixtures.Records import MusicBrainz.Fixtures.ReleaseGroup import MusicBrainz.Fixtures.Release - import Mox - - setup :verify_on_exit! defp fill_collection(_) do records = Enum.map(1..19, fn _ -> record() end) @@ -186,23 +182,22 @@ defmodule MusicLibraryWeb.StatsLive.IndexTest do release_group = release_group(:mystery_of_time) release_group_id = release_group_id(:mystery_of_time) - expect(APIMock, :get_release, fn ^release_id, _config -> - {:ok, release} - end) - - expect(APIMock, :get_release_group, fn ^release_group_id, _config -> - {:ok, release_group} - end) - - expect(APIMock, :get_releases, fn ^release_group_id, _opts, _config -> - {:ok, %{"releases" => release_group["releases"]}} - end) - - # Doesn't matter if we use a different cover cover_data = File.read!(marbles_cover_fixture()) - expect(APIMock, :get_cover_art, fn {:musicbrainz_id, ^release_group_id}, _config -> - {:ok, cover_data} + Req.Test.stub(MusicBrainz.API, fn conn -> + case conn.path_info do + [_ws, _version, "release-group", ^release_group_id] -> + Req.Test.json(conn, release_group) + + [_ws, _version, "release", ^release_id] -> + Req.Test.json(conn, release) + + [_ws, _version, "release"] -> + Req.Test.json(conn, %{"releases" => release_group["releases"]}) + + [_release_group, ^release_group_id, "front"] -> + Plug.Conn.send_resp(conn, 200, cover_data) + end end) assert [] == Wishlist.search_records("mbid:#{release_group_id}") diff --git a/test/support/fixtures/music_brainz/release.ex b/test/support/fixtures/music_brainz/release.ex index c67cbe93..aa65b0fa 100644 --- a/test/support/fixtures/music_brainz/release.ex +++ b/test/support/fixtures/music_brainz/release.ex @@ -5,14 +5,12 @@ defmodule MusicBrainz.Fixtures.Release do Path.join([@fixtures_folder, "releases - queen - greatest hits.json"]) |> File.read!() |> Jason.decode!() - |> Map.get("releases") end def releases(:marbles) do Path.join([@fixtures_folder, "releases - marillion - marbles.json"]) |> File.read!() |> Jason.decode!() - |> Map.get("releases") end def release(:mystery_of_time) do diff --git a/test/support/fixtures/music_brainz/release_group.ex b/test/support/fixtures/music_brainz/release_group.ex index 19d901ba..b1c3bf6e 100644 --- a/test/support/fixtures/music_brainz/release_group.ex +++ b/test/support/fixtures/music_brainz/release_group.ex @@ -1,25 +1,10 @@ defmodule MusicBrainz.Fixtures.ReleaseGroup do @fixtures_folder Path.join([File.cwd!(), "test/support/fixtures/music_brainz"]) - alias MusicBrainz.ReleaseGroupSearchResult - def release_group_search_results do - [ - %ReleaseGroupSearchResult{ - id: "20790e26-98e4-3ad3-a67f-b674758b942d", - type: :album, - title: "Marbles", - artists: "Marillion", - release: "2004-05-03" - }, - %ReleaseGroupSearchResult{ - id: "bf20ac32-a793-3bb4-beff-f7b9bffaca38", - type: :album, - title: "Marbles Live", - artists: "Marillion", - release: "2005-10-24" - } - ] + Path.join([@fixtures_folder, "release_group_search_results - marillion marbles.json"]) + |> File.read!() + |> JSON.decode!() end def release_group(:mystery_of_time) do diff --git a/test/support/fixtures/music_brainz/release_group_search_results - marillion marbles.json b/test/support/fixtures/music_brainz/release_group_search_results - marillion marbles.json new file mode 100644 index 00000000..e45b781c --- /dev/null +++ b/test/support/fixtures/music_brainz/release_group_search_results - marillion marbles.json @@ -0,0 +1,702 @@ +{ + "created": "2025-02-28T11:35:03.807Z", + "count": 437, + "offset": 0, + "release-groups": [ + { + "id": "20790e26-98e4-3ad3-a67f-b674758b942d", + "type-id": "f529b476-6e62-324f-b0aa-1f3e33d313fc", + "score": 100, + "primary-type-id": "f529b476-6e62-324f-b0aa-1f3e33d313fc", + "count": 10, + "title": "Marbles", + "first-release-date": "2004-05-03", + "primary-type": "Album", + "artist-credit": [ + { + "name": "Marillion", + "artist": { + "id": "1932f5b6-0b7b-4050-b1df-833ca89e5f44", + "name": "Marillion", + "sort-name": "Marillion", + "disambiguation": "British progressive rock band", + "aliases": [ + { + "sort-name": "Trios Marillos, Los", + "name": "Los Trios Marillos", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + }, + { + "sort-name": "Skyline Drifters", + "name": "Skyline Drifters", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + }, + { + "sort-name": "Low Fat Yoghurts", + "name": "Low Fat Yoghurts", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + } + ] + } + } + ], + "releases": [ + { + "id": "3f89357a-eeb3-4040-af34-a27b7c2aea2b", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles", + "status": "Official" + }, + { + "id": "0e290154-5375-4f4f-a658-4a92bf02faa5", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles", + "status": "Official" + }, + { + "id": "f3937bc5-b99f-443a-9609-a404201f21ca", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles", + "status": "Official" + }, + { + "id": "d3f9b9e2-73f5-4b47-a2a7-2c2199aad608", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles", + "status": "Official" + }, + { + "id": "4b9fe13b-4837-4c02-9368-e97ba6f5a086", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles", + "status": "Official" + }, + { + "id": "3f1cc80f-4507-48a9-899c-c1bda83280c2", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles", + "status": "Official" + }, + { + "id": "a4b02377-0b5e-448e-9cd6-5500c0378523", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles", + "status": "Official" + }, + { + "id": "ab151aa6-7538-4e93-be60-eded52b5b7b7", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles", + "status": "Official" + }, + { + "id": "b94bbd1f-ae5d-4e7b-98ff-28bfe135f20c", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles", + "status": "Official" + }, + { + "id": "2c4ecd84-7a84-4f42-a600-2f00ed8978c9", + "status-id": "1156806e-d06a-38bd-83f0-cf2284a808b9", + "title": "Marbles", + "status": "Bootleg" + } + ], + "tags": [ + { + "count": 2, + "name": "rock" + }, + { + "count": 1, + "name": "alternative rock" + }, + { + "count": 2, + "name": "progressive rock" + }, + { + "count": 1, + "name": "art rock" + }, + { + "count": 1, + "name": "baroque pop" + }, + { + "count": 1, + "name": "psychedelic pop" + }, + { + "count": 1, + "name": "pop rock" + } + ] + }, + { + "id": "bf20ac32-a793-3bb4-beff-f7b9bffaca38", + "type-id": "6fd474e2-6b58-3102-9d17-d6f7eb7da0a0", + "score": 90, + "primary-type-id": "f529b476-6e62-324f-b0aa-1f3e33d313fc", + "count": 1, + "title": "Marbles Live", + "first-release-date": "2005-10-24", + "primary-type": "Album", + "secondary-types": [ + "Live" + ], + "secondary-type-ids": [ + "6fd474e2-6b58-3102-9d17-d6f7eb7da0a0" + ], + "artist-credit": [ + { + "name": "Marillion", + "artist": { + "id": "1932f5b6-0b7b-4050-b1df-833ca89e5f44", + "name": "Marillion", + "sort-name": "Marillion", + "disambiguation": "British progressive rock band", + "aliases": [ + { + "sort-name": "Skyline Drifters", + "name": "Skyline Drifters", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + }, + { + "sort-name": "Low Fat Yoghurts", + "name": "Low Fat Yoghurts", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + }, + { + "sort-name": "Trios Marillos, Los", + "name": "Los Trios Marillos", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + } + ] + } + } + ], + "releases": [ + { + "id": "bdc6ee20-edd8-4a74-8666-f6f90a67a36a", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles Live", + "status": "Official" + } + ], + "tags": [ + { + "count": 1, + "name": "rock" + } + ] + }, + { + "id": "ea42b213-0502-391b-bb51-e2ef6315b300", + "type-id": "dd2a21e1-0c00-3729-a7a0-de60b84eb5d1", + "score": 77, + "primary-type-id": "f529b476-6e62-324f-b0aa-1f3e33d313fc", + "count": 1, + "title": "A Handful of Marbles", + "first-release-date": "2005-06", + "primary-type": "Album", + "secondary-types": [ + "Compilation" + ], + "secondary-type-ids": [ + "dd2a21e1-0c00-3729-a7a0-de60b84eb5d1" + ], + "artist-credit": [ + { + "name": "Marillion", + "artist": { + "id": "1932f5b6-0b7b-4050-b1df-833ca89e5f44", + "name": "Marillion", + "sort-name": "Marillion", + "disambiguation": "British progressive rock band", + "aliases": [ + { + "sort-name": "Low Fat Yoghurts", + "name": "Low Fat Yoghurts", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + }, + { + "sort-name": "Skyline Drifters", + "name": "Skyline Drifters", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + }, + { + "sort-name": "Trios Marillos, Los", + "name": "Los Trios Marillos", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + } + ] + } + } + ], + "releases": [ + { + "id": "09bbc223-0c47-4074-ac8e-a619407d1ab2", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "A Handful of Marbles", + "status": "Official" + } + ], + "tags": [ + { + "count": 1, + "name": "rock" + }, + { + "count": 1, + "name": "alternative rock" + } + ] + }, + { + "id": "134154a8-4c48-4185-b515-831b01164a68", + "type-id": "6fd474e2-6b58-3102-9d17-d6f7eb7da0a0", + "score": 77, + "primary-type-id": "f529b476-6e62-324f-b0aa-1f3e33d313fc", + "count": 2, + "title": "Marbles on the Road", + "first-release-date": "2004", + "primary-type": "Album", + "secondary-types": [ + "Live" + ], + "secondary-type-ids": [ + "6fd474e2-6b58-3102-9d17-d6f7eb7da0a0" + ], + "artist-credit": [ + { + "name": "Marillion", + "artist": { + "id": "1932f5b6-0b7b-4050-b1df-833ca89e5f44", + "name": "Marillion", + "sort-name": "Marillion", + "disambiguation": "British progressive rock band", + "aliases": [ + { + "sort-name": "Trios Marillos, Los", + "name": "Los Trios Marillos", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + }, + { + "sort-name": "Skyline Drifters", + "name": "Skyline Drifters", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + }, + { + "sort-name": "Low Fat Yoghurts", + "name": "Low Fat Yoghurts", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + } + ] + } + } + ], + "releases": [ + { + "id": "f23430e9-cc04-42e0-a697-92f0b802c9c1", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles on the Road", + "status": "Official" + }, + { + "id": "480ec2f0-d567-4814-aee2-c2f9a2367da8", + "status-id": "1156806e-d06a-38bd-83f0-cf2284a808b9", + "title": "Marbles on the Road", + "status": "Bootleg" + } + ] + }, + { + "id": "5fb9fdb0-cd94-412c-b4d1-f0354128e4c2", + "type-id": "6fd474e2-6b58-3102-9d17-d6f7eb7da0a0", + "score": 77, + "primary-type-id": "f529b476-6e62-324f-b0aa-1f3e33d313fc", + "count": 4, + "title": "Marbles in the Park", + "first-release-date": "2016-11-06", + "primary-type": "Album", + "secondary-types": [ + "Live" + ], + "secondary-type-ids": [ + "6fd474e2-6b58-3102-9d17-d6f7eb7da0a0" + ], + "artist-credit": [ + { + "name": "Marillion", + "artist": { + "id": "1932f5b6-0b7b-4050-b1df-833ca89e5f44", + "name": "Marillion", + "sort-name": "Marillion", + "disambiguation": "British progressive rock band", + "aliases": [ + { + "sort-name": "Trios Marillos, Los", + "name": "Los Trios Marillos", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + }, + { + "sort-name": "Skyline Drifters", + "name": "Skyline Drifters", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + }, + { + "sort-name": "Low Fat Yoghurts", + "name": "Low Fat Yoghurts", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + } + ] + } + } + ], + "releases": [ + { + "id": "f5db4db0-1b60-492a-a4c1-b286dda4e03a", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles in the Park", + "status": "Official" + }, + { + "id": "a8a70e02-828f-46a3-ba0e-7e97ee5b9d02", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles in the Park", + "status": "Official" + }, + { + "id": "53a08c1a-a9a1-48f2-b5ae-7ac8a75f3f21", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles in the Park", + "status": "Official" + }, + { + "id": "f7151d70-64d9-4520-97a0-0d2747b514fc", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles in the Park", + "status": "Official" + } + ], + "tags": [ + { + "count": 1, + "name": "rock" + }, + { + "count": 1, + "name": "pop" + }, + { + "count": 1, + "name": "art rock" + } + ] + }, + { + "id": "84ad8315-f7fe-3988-962f-440307682dd6", + "type-id": "6fd474e2-6b58-3102-9d17-d6f7eb7da0a0", + "score": 77, + "primary-type-id": "f529b476-6e62-324f-b0aa-1f3e33d313fc", + "count": 2, + "title": "Marbles by the Sea", + "first-release-date": "2005-10", + "primary-type": "Album", + "secondary-types": [ + "Live" + ], + "secondary-type-ids": [ + "6fd474e2-6b58-3102-9d17-d6f7eb7da0a0" + ], + "artist-credit": [ + { + "name": "Marillion", + "artist": { + "id": "1932f5b6-0b7b-4050-b1df-833ca89e5f44", + "name": "Marillion", + "sort-name": "Marillion", + "disambiguation": "British progressive rock band", + "aliases": [ + { + "sort-name": "Trios Marillos, Los", + "name": "Los Trios Marillos", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + }, + { + "sort-name": "Skyline Drifters", + "name": "Skyline Drifters", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + }, + { + "sort-name": "Low Fat Yoghurts", + "name": "Low Fat Yoghurts", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + } + ] + } + } + ], + "releases": [ + { + "id": "2a4dd3a3-e63f-4f6d-8035-34da48670593", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles by the Sea", + "status": "Official" + }, + { + "id": "0c724b38-216e-4a33-931e-f23c7f175792", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles by the Sea", + "status": "Official" + } + ], + "tags": [ + { + "count": 1, + "name": "rock" + } + ] + }, + { + "id": "56286106-d546-4a3a-9304-242ca7715453", + "type-id": "4fc3be2b-de1e-396b-a933-beb8f1607a22", + "score": 69, + "primary-type-id": "4fc3be2b-de1e-396b-a933-beb8f1607a22", + "count": 2, + "title": "Glass Half Full: Making of Marbles", + "first-release-date": "2015", + "primary-type": "Other", + "artist-credit": [ + { + "name": "Marillion", + "artist": { + "id": "1932f5b6-0b7b-4050-b1df-833ca89e5f44", + "name": "Marillion", + "sort-name": "Marillion", + "disambiguation": "British progressive rock band", + "aliases": [ + { + "sort-name": "Trios Marillos, Los", + "name": "Los Trios Marillos", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + }, + { + "sort-name": "Skyline Drifters", + "name": "Skyline Drifters", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + }, + { + "sort-name": "Low Fat Yoghurts", + "name": "Low Fat Yoghurts", + "locale": null, + "type": null, + "primary": null, + "begin-date": null, + "end-date": null + } + ] + } + } + ], + "releases": [ + { + "id": "a2459015-e3e6-4f1c-b765-2d8ec3a0564f", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Glass Half Full – The Making of Marbles", + "status": "Official" + }, + { + "id": "68351699-e4d8-4650-850f-d40460c76b7b", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Glass Half Full: Making of Marbles", + "status": "Official" + } + ], + "tags": [ + { + "count": 1, + "name": "rock" + } + ] + }, + { + "id": "9006f9e9-207e-4741-8c99-562f94c87fe1", + "type-id": "6d0c5bf6-7a33-3420-a519-44fc63eedebf", + "score": 68, + "primary-type-id": "6d0c5bf6-7a33-3420-a519-44fc63eedebf", + "count": 1, + "title": "MARBLES", + "first-release-date": "2024-03-13", + "primary-type": "EP", + "artist-credit": [ + { + "name": "THE ORAL CIGARETTES", + "artist": { + "id": "7974fd3f-b3e7-4607-a1ad-9d85c07ac3b9", + "name": "THE ORAL CIGARETTES", + "sort-name": "ORAL CIGARETTES, THE" + } + } + ], + "releases": [ + { + "id": "7495379e-fa66-411a-9092-a1bf634352d3", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "MARBLES", + "status": "Official" + } + ] + }, + { + "id": "765278d7-1c6d-4f02-8642-d3d4120ad765", + "score": 68, + "count": 1, + "title": "Marbles", + "first-release-date": "2021-02-22", + "artist-credit": [ + { + "name": "slowbomb", + "artist": { + "id": "1dc4d526-7896-4309-9814-1399d5451fb9", + "name": "slowbomb", + "sort-name": "slowbomb" + } + } + ], + "releases": [ + { + "id": "b45fec65-b17b-4c74-87d2-11a62d9ee456", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles", + "status": "Official" + } + ] + }, + { + "id": "fdfdbd61-6b9b-360e-96a3-efd2f95d2169", + "type-id": "f529b476-6e62-324f-b0aa-1f3e33d313fc", + "score": 68, + "primary-type-id": "f529b476-6e62-324f-b0aa-1f3e33d313fc", + "count": 2, + "title": "Marbles", + "first-release-date": "1993", + "primary-type": "Album", + "artist-credit": [ + { + "name": "King Apparatus", + "artist": { + "id": "cc97c476-5587-42cc-814b-7ccb4005fd4e", + "name": "King Apparatus", + "sort-name": "King Apparatus" + } + } + ], + "releases": [ + { + "id": "04548253-77bc-4d92-abe7-c8f8f0640f3b", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles", + "status": "Official" + }, + { + "id": "dc7bc259-7e05-4ae4-a126-98ec0599b1e6", + "status-id": "4e304316-386d-3409-af2e-78857eec5cfe", + "title": "Marbles", + "status": "Official" + } + ], + "tags": [ + { + "count": 1, + "name": "rock" + }, + { + "count": 1, + "name": "ska" + } + ] + } + ] +} diff --git a/test/test_helper.exs b/test/test_helper.exs index 4eac347f..bc8763ae 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -1,10 +1,2 @@ -Mox.defmock(MusicBrainz.APIMock, for: MusicBrainz.APIBehaviour) - -music_brainz_config = - Application.get_env(:music_library, MusicBrainz) - |> Keyword.put(:api, MusicBrainz.APIMock) - -Application.put_env(:music_library, MusicBrainz, music_brainz_config) - ExUnit.start() Ecto.Adapters.SQL.Sandbox.mode(MusicLibrary.Repo, :manual)