Remove mox in favour of built-in Req stubs

This commit is contained in:
Claudio Ortolina
2025-02-28 16:38:11 +00:00
parent 8aa283cb84
commit a218942110
16 changed files with 844 additions and 195 deletions
+1 -3
View File
@@ -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,
+6
View File
@@ -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
+8 -6
View File
@@ -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)
@@ -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
-20
View File
@@ -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
+10 -9
View File
@@ -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: []
]
)
-1
View File
@@ -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"},
-2
View File
@@ -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"},
+15 -12
View File
@@ -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" &&
+34 -37
View File
@@ -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)
@@ -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
@@ -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}")
@@ -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
@@ -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
@@ -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"
}
]
}
]
}
-8
View File
@@ -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)