Add large battery of tests, primarily workers
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
defmodule MusicLibrary.ArtistChatTest do
|
||||
use ExUnit.Case
|
||||
|
||||
alias MusicLibrary.ArtistChat
|
||||
|
||||
test "implements the Chat behaviour" do
|
||||
Code.ensure_loaded!(ArtistChat)
|
||||
assert function_exported?(ArtistChat, :stream_response, 3)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,38 @@
|
||||
defmodule MusicLibrary.Artists.BatchTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
import MusicLibrary.Fixtures.Records
|
||||
|
||||
alias MusicLibrary.Artists.Batch
|
||||
|
||||
setup do
|
||||
record = record()
|
||||
artist = hd(record.artists)
|
||||
_artist_info = artist_info(artist.musicbrainz_id)
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "refresh_musicbrainz_data/0" do
|
||||
test "enqueues refresh jobs for all artist infos" do
|
||||
assert {:ok, []} = Batch.refresh_musicbrainz_data()
|
||||
end
|
||||
end
|
||||
|
||||
describe "refresh_discogs_data/0" do
|
||||
test "enqueues refresh jobs for all artist infos" do
|
||||
assert {:ok, []} = Batch.refresh_discogs_data()
|
||||
end
|
||||
end
|
||||
|
||||
describe "refresh_wikipedia_data/0" do
|
||||
test "enqueues refresh jobs for all artist infos" do
|
||||
assert {:ok, []} = Batch.refresh_wikipedia_data()
|
||||
end
|
||||
end
|
||||
|
||||
describe "refresh_lastfm_data/0" do
|
||||
test "enqueues refresh jobs for all artist infos" do
|
||||
assert {:ok, []} = Batch.refresh_lastfm_data()
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,68 @@
|
||||
defmodule MusicLibrary.BatchTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
import MusicLibrary.Fixtures.Records
|
||||
|
||||
alias MusicLibrary.Batch
|
||||
alias MusicLibrary.Records.Record
|
||||
|
||||
describe "run_on_all/3" do
|
||||
test "processes all records and returns empty list on success" do
|
||||
_r1 = record()
|
||||
_r2 = record()
|
||||
|
||||
assert {:ok, []} =
|
||||
Batch.run_on_all(Record, "record", fn _record ->
|
||||
:ok
|
||||
end)
|
||||
end
|
||||
|
||||
@tag :capture_log
|
||||
test "collects failed record IDs" do
|
||||
r1 = record()
|
||||
r2 = record()
|
||||
|
||||
assert {:ok, failed_ids} =
|
||||
Batch.run_on_all(Record, "record", fn _record ->
|
||||
{:error, :test_failure}
|
||||
end)
|
||||
|
||||
assert length(failed_ids) == 2
|
||||
assert r1.id in failed_ids
|
||||
assert r2.id in failed_ids
|
||||
end
|
||||
|
||||
@tag :capture_log
|
||||
test "handles mixed success and failure" do
|
||||
r1 = record()
|
||||
_r2 = record()
|
||||
|
||||
assert {:ok, failed_ids} =
|
||||
Batch.run_on_all(Record, "record", fn record ->
|
||||
if record.id == r1.id do
|
||||
{:error, :test_failure}
|
||||
else
|
||||
:ok
|
||||
end
|
||||
end)
|
||||
|
||||
assert failed_ids == [r1.id]
|
||||
end
|
||||
|
||||
test "works with empty table" do
|
||||
assert {:ok, []} =
|
||||
Batch.run_on_all(Record, "record", fn _record ->
|
||||
:ok
|
||||
end)
|
||||
end
|
||||
|
||||
test "accepts {:ok, result} as success" do
|
||||
_r1 = record()
|
||||
|
||||
assert {:ok, []} =
|
||||
Batch.run_on_all(Record, "record", fn _record ->
|
||||
{:ok, :updated}
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,34 @@
|
||||
defmodule MusicLibrary.Colors.ColorFrequencyExtractorTest do
|
||||
use ExUnit.Case
|
||||
|
||||
alias MusicLibrary.Colors.ColorFrequencyExtractor
|
||||
|
||||
@image_data MusicLibrary.Fixtures.Records.marbles_cover_data()
|
||||
|
||||
describe "extract_dominant_colors/1" do
|
||||
@describetag :slow
|
||||
|
||||
test "extracts colors from an image" do
|
||||
assert {:ok, colors} = ColorFrequencyExtractor.extract_dominant_colors(@image_data)
|
||||
|
||||
assert is_list(colors)
|
||||
assert colors == ["#000000", "#C08080", "#400000", "#C0C0C0", "#404000"]
|
||||
end
|
||||
|
||||
test "extracts custom number of colors" do
|
||||
assert {:ok, colors} = ColorFrequencyExtractor.extract_dominant_colors(@image_data, 3)
|
||||
|
||||
assert colors == ["#000000", "#C08080", "#400000"]
|
||||
end
|
||||
end
|
||||
|
||||
describe "extract_dominant_colors!/1" do
|
||||
@describetag :slow
|
||||
|
||||
test "extracts colors or raises" do
|
||||
colors = ColorFrequencyExtractor.extract_dominant_colors!(@image_data)
|
||||
|
||||
assert colors == ["#000000", "#C08080", "#400000", "#C0C0C0", "#404000"]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,32 @@
|
||||
defmodule MusicLibrary.Colors.EdgeWeightedExtractorTest do
|
||||
use ExUnit.Case
|
||||
|
||||
alias MusicLibrary.Colors.EdgeWeightedExtractor
|
||||
|
||||
@image_data MusicLibrary.Fixtures.Records.marbles_cover_data()
|
||||
|
||||
describe "extract_dominant_colors/1" do
|
||||
@describetag :slow
|
||||
test "extracts colors from an image" do
|
||||
assert {:ok, colors} =
|
||||
EdgeWeightedExtractor.extract_dominant_colors(@image_data)
|
||||
|
||||
assert colors == ["#000000", "#A07850", "#785028", "#502828", "#C8A078"]
|
||||
end
|
||||
|
||||
test "extracts custom number of colors" do
|
||||
assert {:ok, colors} = EdgeWeightedExtractor.extract_dominant_colors(@image_data, 3)
|
||||
|
||||
assert colors == ["#000000", "#A07850", "#785028"]
|
||||
end
|
||||
end
|
||||
|
||||
describe "extract_dominant_colors!/1" do
|
||||
@describetag :slow
|
||||
test "extracts colors or raises" do
|
||||
colors = EdgeWeightedExtractor.extract_dominant_colors!(@image_data)
|
||||
|
||||
assert colors == ["#000000", "#A07850", "#785028", "#502828", "#C8A078"]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
defmodule MusicLibrary.RecordChatTest do
|
||||
use ExUnit.Case
|
||||
|
||||
alias MusicLibrary.RecordChat
|
||||
|
||||
test "implements the Chat behaviour" do
|
||||
Code.ensure_loaded!(RecordChat)
|
||||
assert function_exported?(RecordChat, :stream_response, 3)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,31 @@
|
||||
defmodule MusicLibrary.Records.BatchTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
import MusicLibrary.Fixtures.Records
|
||||
|
||||
alias MusicLibrary.Records.Batch
|
||||
|
||||
describe "refresh_musicbrainz_data/0" do
|
||||
test "enqueues refresh jobs for all records" do
|
||||
_record = record()
|
||||
|
||||
assert {:ok, []} = Batch.refresh_musicbrainz_data()
|
||||
end
|
||||
|
||||
test "succeeds with no records" do
|
||||
assert {:ok, []} = Batch.refresh_musicbrainz_data()
|
||||
end
|
||||
end
|
||||
|
||||
describe "generate_embeddings/0" do
|
||||
test "enqueues embedding jobs for all records" do
|
||||
_record = record()
|
||||
|
||||
assert {:ok, []} = Batch.generate_embeddings()
|
||||
end
|
||||
|
||||
test "succeeds with no records" do
|
||||
assert {:ok, []} = Batch.generate_embeddings()
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,50 @@
|
||||
defmodule MusicLibrary.SecretsTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
alias MusicLibrary.Secrets
|
||||
|
||||
describe "store/2" do
|
||||
test "stores a secret" do
|
||||
assert {:ok, secret} = Secrets.store("test_key", "test_value")
|
||||
assert secret.name == "test_key"
|
||||
end
|
||||
|
||||
test "replaces an existing secret" do
|
||||
{:ok, _} = Secrets.store("test_key", "original")
|
||||
{:ok, _} = Secrets.store("test_key", "updated")
|
||||
|
||||
secret = Secrets.get!("test_key")
|
||||
assert secret.value == "updated"
|
||||
end
|
||||
end
|
||||
|
||||
describe "get!/1" do
|
||||
test "retrieves a stored secret" do
|
||||
{:ok, _} = Secrets.store("test_key", "test_value")
|
||||
|
||||
secret = Secrets.get!("test_key")
|
||||
assert secret.name == "test_key"
|
||||
assert secret.value == "test_value"
|
||||
end
|
||||
|
||||
test "raises when secret does not exist" do
|
||||
assert_raise Ecto.NoResultsError, fn ->
|
||||
Secrets.get!("nonexistent")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "get/1" do
|
||||
test "retrieves a stored secret" do
|
||||
{:ok, _} = Secrets.store("test_key", "test_value")
|
||||
|
||||
secret = Secrets.get("test_key")
|
||||
assert secret.name == "test_key"
|
||||
assert secret.value == "test_value"
|
||||
end
|
||||
|
||||
test "returns nil when secret does not exist" do
|
||||
assert Secrets.get("nonexistent") == nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
defmodule MusicLibrary.Worker.ArtistRefreshAllDiscogsDataTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
import MusicLibrary.Fixtures.Records
|
||||
|
||||
alias MusicLibrary.Worker.ArtistRefreshAllDiscogsData
|
||||
|
||||
describe "perform/1" do
|
||||
test "enqueues refresh jobs for all artist infos" do
|
||||
record = record()
|
||||
artist = hd(record.artists)
|
||||
_artist_info = artist_info(artist.musicbrainz_id)
|
||||
|
||||
assert {:ok, []} = perform_job(ArtistRefreshAllDiscogsData, %{})
|
||||
end
|
||||
|
||||
test "succeeds with no artist infos" do
|
||||
assert {:ok, []} = perform_job(ArtistRefreshAllDiscogsData, %{})
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
defmodule MusicLibrary.Worker.ArtistRefreshAllMusicBrainzDataTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
import MusicLibrary.Fixtures.Records
|
||||
|
||||
alias MusicLibrary.Worker.ArtistRefreshAllMusicBrainzData
|
||||
|
||||
describe "perform/1" do
|
||||
test "enqueues refresh jobs for all artist infos" do
|
||||
record = record()
|
||||
artist = hd(record.artists)
|
||||
_artist_info = artist_info(artist.musicbrainz_id)
|
||||
|
||||
assert {:ok, []} = perform_job(ArtistRefreshAllMusicBrainzData, %{})
|
||||
end
|
||||
|
||||
test "succeeds with no artist infos" do
|
||||
assert {:ok, []} = perform_job(ArtistRefreshAllMusicBrainzData, %{})
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
defmodule MusicLibrary.Worker.ArtistRefreshAllWikipediaDataTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
import MusicLibrary.Fixtures.Records
|
||||
|
||||
alias MusicLibrary.Worker.ArtistRefreshAllWikipediaData
|
||||
|
||||
describe "perform/1" do
|
||||
test "enqueues refresh jobs for all artist infos" do
|
||||
record = record()
|
||||
artist = hd(record.artists)
|
||||
_artist_info = artist_info(artist.musicbrainz_id)
|
||||
|
||||
assert {:ok, []} = perform_job(ArtistRefreshAllWikipediaData, %{})
|
||||
end
|
||||
|
||||
test "succeeds with no artist infos" do
|
||||
assert {:ok, []} = perform_job(ArtistRefreshAllWikipediaData, %{})
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,40 @@
|
||||
defmodule MusicLibrary.Worker.ArtistRefreshDiscogsDataTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
import MusicLibrary.Fixtures.Records
|
||||
|
||||
alias Discogs.Fixtures.Artist, as: ArtistFixture
|
||||
alias MusicLibrary.Artists
|
||||
alias MusicLibrary.Worker.ArtistRefreshDiscogsData
|
||||
|
||||
setup do
|
||||
record = record()
|
||||
artist = hd(record.artists)
|
||||
artist_info = artist_info(artist.musicbrainz_id)
|
||||
%{artist_info: artist_info}
|
||||
end
|
||||
|
||||
describe "perform/1" do
|
||||
test "refreshes Discogs data", %{artist_info: artist_info} do
|
||||
Req.Test.stub(Discogs.API, fn conn ->
|
||||
Req.Test.json(conn, ArtistFixture.get_artist())
|
||||
end)
|
||||
|
||||
assert {:ok, _} = perform_job(ArtistRefreshDiscogsData, %{"id" => artist_info.id})
|
||||
|
||||
updated = Artists.get_artist_info!(artist_info.id)
|
||||
assert updated.discogs_data != nil
|
||||
end
|
||||
|
||||
test "returns ok when no discogs data is available" do
|
||||
artist_id = Ecto.UUID.generate()
|
||||
|
||||
Repo.insert!(%Artists.ArtistInfo{
|
||||
id: artist_id,
|
||||
musicbrainz_data: %{"name" => "No Discogs Artist"}
|
||||
})
|
||||
|
||||
assert {:ok, _} = perform_job(ArtistRefreshDiscogsData, %{"id" => artist_id})
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,33 @@
|
||||
defmodule MusicLibrary.Worker.ArtistRefreshMusicBrainzDataTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
alias MusicBrainz.Fixtures.Artist, as: ArtistFixture
|
||||
alias MusicLibrary.Artists
|
||||
alias MusicLibrary.Artists.ArtistInfo
|
||||
alias MusicLibrary.Worker.ArtistRefreshMusicBrainzData
|
||||
|
||||
setup do
|
||||
artist_id = Ecto.UUID.generate()
|
||||
|
||||
Repo.insert!(%ArtistInfo{
|
||||
id: artist_id,
|
||||
musicbrainz_data: %{"name" => "Steven Wilson"}
|
||||
})
|
||||
|
||||
%{artist_id: artist_id}
|
||||
end
|
||||
|
||||
describe "perform/1" do
|
||||
test "refreshes MusicBrainz data for an artist", %{artist_id: artist_id} do
|
||||
Req.Test.stub(MusicBrainz.API, fn conn ->
|
||||
Req.Test.json(conn, ArtistFixture.get_artist())
|
||||
end)
|
||||
|
||||
assert {:ok, %ArtistInfo{}} =
|
||||
perform_job(ArtistRefreshMusicBrainzData, %{"id" => artist_id})
|
||||
|
||||
updated = Artists.get_artist_info!(artist_id)
|
||||
assert updated.musicbrainz_data["name"] == "Steven Wilson"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,53 @@
|
||||
defmodule MusicLibrary.Worker.ArtistRefreshWikipediaDataTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
import MusicLibrary.Fixtures.Records
|
||||
|
||||
alias MusicLibrary.Artists
|
||||
alias MusicLibrary.Worker.ArtistRefreshWikipediaData
|
||||
|
||||
setup do
|
||||
record = record()
|
||||
artist = hd(record.artists)
|
||||
artist_info = artist_info(artist.musicbrainz_id)
|
||||
%{artist_info: artist_info}
|
||||
end
|
||||
|
||||
describe "perform/1" do
|
||||
test "refreshes Wikipedia data", %{artist_info: artist_info} do
|
||||
Req.Test.stub(Wikipedia.API, fn conn ->
|
||||
conn = Plug.Conn.fetch_query_params(conn)
|
||||
|
||||
case conn.params do
|
||||
%{"action" => "wbgetentities"} ->
|
||||
Req.Test.json(conn, Wikipedia.Fixtures.wikidata_response())
|
||||
|
||||
%{"action" => "query"} ->
|
||||
Req.Test.json(conn, Wikipedia.Fixtures.article_extract())
|
||||
|
||||
_ ->
|
||||
Req.Test.json(conn, Wikipedia.Fixtures.article_summary())
|
||||
end
|
||||
end)
|
||||
|
||||
assert {:ok, _} = perform_job(ArtistRefreshWikipediaData, %{"id" => artist_info.id})
|
||||
|
||||
updated = Artists.get_artist_info!(artist_info.id)
|
||||
assert updated.wikipedia_data != nil
|
||||
assert updated.wikipedia_data != %{}
|
||||
end
|
||||
|
||||
test "discards job when no wikidata_id exists in musicbrainz_data" do
|
||||
artist_id = Ecto.UUID.generate()
|
||||
|
||||
Repo.insert!(%Artists.ArtistInfo{
|
||||
id: artist_id,
|
||||
musicbrainz_data: %{"name" => "No Wikipedia Artist"}
|
||||
})
|
||||
|
||||
# No wikidata relation in musicbrainz_data → fetch_wikipedia_data returns {:ok, artist_info}
|
||||
# Worker wraps non-error returns with `with`, so it passes through as :ok
|
||||
assert {:ok, _} = perform_job(ArtistRefreshWikipediaData, %{"id" => artist_id})
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,38 @@
|
||||
defmodule MusicLibrary.Worker.ExtractColorsTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
import MusicLibrary.Fixtures.Records
|
||||
|
||||
alias MusicLibrary.Records
|
||||
alias MusicLibrary.Worker.ExtractColors
|
||||
|
||||
describe "perform/1" do
|
||||
@describetag :slow
|
||||
test "extracts colors using fast method" do
|
||||
record = record()
|
||||
|
||||
assert :ok = perform_job(ExtractColors, %{"id" => record.id, "method" => "fast"})
|
||||
|
||||
updated = Records.get_record!(record.id)
|
||||
assert is_list(updated.dominant_colors)
|
||||
assert updated.dominant_colors != []
|
||||
assert Enum.all?(updated.dominant_colors, &String.starts_with?(&1, "#"))
|
||||
end
|
||||
|
||||
test "extracts colors using slow method" do
|
||||
record = record()
|
||||
|
||||
assert :ok = perform_job(ExtractColors, %{"id" => record.id, "method" => "slow"})
|
||||
|
||||
updated = Records.get_record!(record.id)
|
||||
assert is_list(updated.dominant_colors)
|
||||
assert updated.dominant_colors != []
|
||||
end
|
||||
|
||||
test "raises when record does not exist" do
|
||||
assert_raise Ecto.NoResultsError, fn ->
|
||||
perform_job(ExtractColors, %{"id" => Ecto.UUID.generate(), "method" => "fast"})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,55 @@
|
||||
defmodule MusicLibrary.Worker.FetchArtistImageTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
import MusicLibrary.Fixtures.Records
|
||||
|
||||
alias Discogs.Fixtures.Artist
|
||||
alias MusicLibrary.Artists
|
||||
alias MusicLibrary.Worker.FetchArtistImage
|
||||
|
||||
setup do
|
||||
record = record()
|
||||
artist = hd(record.artists)
|
||||
artist_info = artist_info(artist.musicbrainz_id)
|
||||
%{artist_info: artist_info}
|
||||
end
|
||||
|
||||
describe "perform/1" do
|
||||
test "fetches and stores artist image", %{artist_info: artist_info} do
|
||||
Req.Test.stub(Discogs.API, fn conn ->
|
||||
Plug.Conn.send_resp(conn, 200, Artist.image_data())
|
||||
end)
|
||||
|
||||
assert :ok = perform_job(FetchArtistImage, %{"id" => artist_info.id})
|
||||
|
||||
updated = Artists.get_artist_info!(artist_info.id)
|
||||
assert updated.image_data_hash != nil
|
||||
end
|
||||
|
||||
test "cancels when no discogs data exists" do
|
||||
artist_id = Ecto.UUID.generate()
|
||||
|
||||
Repo.insert!(%Artists.ArtistInfo{
|
||||
id: artist_id,
|
||||
musicbrainz_data: %{"name" => "No Image Artist"},
|
||||
discogs_data: nil
|
||||
})
|
||||
|
||||
assert {:cancel, :no_discogs_data} =
|
||||
perform_job(FetchArtistImage, %{"id" => artist_id})
|
||||
end
|
||||
|
||||
test "cancels when discogs data has no images" do
|
||||
artist_id = Ecto.UUID.generate()
|
||||
|
||||
Repo.insert!(%Artists.ArtistInfo{
|
||||
id: artist_id,
|
||||
musicbrainz_data: %{"name" => "No Image Artist"},
|
||||
discogs_data: %{"id" => 12_345, "images" => []}
|
||||
})
|
||||
|
||||
assert {:cancel, :image_not_found} =
|
||||
perform_job(FetchArtistImage, %{"id" => artist_id})
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,73 @@
|
||||
defmodule MusicLibrary.Worker.FetchArtistInfoTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
import MusicLibrary.Fixtures.Records
|
||||
|
||||
alias MusicLibrary.Artists
|
||||
alias MusicLibrary.Worker.FetchArtistInfo
|
||||
|
||||
# The MusicBrainz fixture for Steven Wilson uses this fixed ID
|
||||
@steven_wilson_mbid "3a51b862-0144-40f6-aa17-6aaeefea29d9"
|
||||
|
||||
describe "perform/1" do
|
||||
test "fetches and stores artist info from all sources" do
|
||||
# Create a record with the artist musicbrainz_id matching the fixture
|
||||
_record =
|
||||
record(%{
|
||||
artists: [
|
||||
%{
|
||||
name: "Steven Wilson",
|
||||
musicbrainz_id: @steven_wilson_mbid,
|
||||
sort_name: "Wilson, Steven",
|
||||
joinphrase: ""
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
Req.Test.stub(MusicBrainz.API, fn conn ->
|
||||
Req.Test.json(conn, MusicBrainz.Fixtures.Artist.get_artist())
|
||||
end)
|
||||
|
||||
Req.Test.stub(Discogs.API, fn conn ->
|
||||
case conn.request_path do
|
||||
"/artists/" <> _ ->
|
||||
Req.Test.json(conn, Discogs.Fixtures.Artist.get_artist())
|
||||
|
||||
_ ->
|
||||
Plug.Conn.send_resp(conn, 200, Discogs.Fixtures.Artist.image_data())
|
||||
end
|
||||
end)
|
||||
|
||||
Req.Test.stub(Wikipedia.API, fn conn ->
|
||||
conn = Plug.Conn.fetch_query_params(conn)
|
||||
|
||||
case conn.params do
|
||||
%{"action" => "wbgetentities"} ->
|
||||
Req.Test.json(conn, Wikipedia.Fixtures.wikidata_response())
|
||||
|
||||
%{"action" => "query"} ->
|
||||
Req.Test.json(conn, Wikipedia.Fixtures.article_extract())
|
||||
|
||||
_ ->
|
||||
Req.Test.json(conn, Wikipedia.Fixtures.article_summary())
|
||||
end
|
||||
end)
|
||||
|
||||
Req.Test.stub(LastFm.API, fn conn ->
|
||||
Req.Test.json(conn, %{
|
||||
"toptags" => %{
|
||||
"tag" => [
|
||||
%{"name" => "progressive rock", "count" => 100}
|
||||
]
|
||||
}
|
||||
})
|
||||
end)
|
||||
|
||||
assert :ok = perform_job(FetchArtistInfo, %{"id" => @steven_wilson_mbid})
|
||||
|
||||
artist_info = Artists.get_artist_info!(@steven_wilson_mbid)
|
||||
assert artist_info.musicbrainz_data != nil
|
||||
assert artist_info.wikipedia_data != nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,35 @@
|
||||
defmodule MusicLibrary.Worker.PruneArtistInfoTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
import MusicLibrary.Fixtures.Records
|
||||
|
||||
alias MusicLibrary.Artists
|
||||
alias MusicLibrary.Worker.PruneArtistInfo
|
||||
|
||||
describe "perform/1" do
|
||||
test "keeps artist info when artist is still referenced by a record" do
|
||||
record = record()
|
||||
artist = hd(record.artists)
|
||||
artist_info = artist_info(artist.musicbrainz_id)
|
||||
|
||||
assert :ok = perform_job(PruneArtistInfo, %{"id" => artist.musicbrainz_id})
|
||||
|
||||
assert Artists.get_artist_info!(artist_info.id)
|
||||
end
|
||||
|
||||
test "deletes artist info when artist is not referenced by any record" do
|
||||
artist_id = Ecto.UUID.generate()
|
||||
|
||||
Repo.insert!(%Artists.ArtistInfo{
|
||||
id: artist_id,
|
||||
musicbrainz_data: %{"name" => "Orphaned Artist"}
|
||||
})
|
||||
|
||||
assert :ok = perform_job(PruneArtistInfo, %{"id" => artist_id})
|
||||
|
||||
assert_raise Ecto.NoResultsError, fn ->
|
||||
Artists.get_artist_info!(artist_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,28 @@
|
||||
defmodule MusicLibrary.Worker.PruneAssetCacheTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
alias MusicLibrary.Assets.Cache
|
||||
alias MusicLibrary.Worker.PruneAssetCache
|
||||
|
||||
describe "perform/1" do
|
||||
@describetag :capture_log
|
||||
|
||||
test "prunes old cache entries" do
|
||||
# Insert a cache entry with an old timestamp
|
||||
old_timestamp = DateTime.utc_now() |> DateTime.add(-8, :day) |> DateTime.to_unix()
|
||||
:ets.insert(Cache, {{"old_payload", "image/jpeg"}, old_timestamp, "old_content"})
|
||||
|
||||
# Insert a recent cache entry
|
||||
Cache.set("recent_payload", "image/jpeg", "recent_content")
|
||||
|
||||
assert :ok = perform_job(PruneAssetCache, %{})
|
||||
|
||||
assert Cache.get("old_payload", "image/jpeg") == :not_found
|
||||
assert {:found, "recent_content"} = Cache.get("recent_payload", "image/jpeg")
|
||||
end
|
||||
|
||||
test "succeeds with empty cache" do
|
||||
assert :ok = perform_job(PruneAssetCache, %{})
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,45 @@
|
||||
defmodule MusicLibrary.Worker.PruneAssetsTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
import MusicLibrary.Fixtures.Records
|
||||
|
||||
alias MusicLibrary.Assets
|
||||
alias MusicLibrary.Worker.PruneAssets
|
||||
|
||||
describe "perform/1" do
|
||||
@describetag :capture_log
|
||||
test "deletes unreferenced assets" do
|
||||
{:ok, orphan} = Assets.store(%{content: "orphan_data", format: "image/jpeg"})
|
||||
|
||||
assert Assets.get(orphan.hash) != nil
|
||||
|
||||
assert :ok = perform_job(PruneAssets, %{})
|
||||
|
||||
assert Assets.get(orphan.hash) == nil
|
||||
end
|
||||
|
||||
test "keeps assets referenced by records" do
|
||||
record = record()
|
||||
|
||||
assert :ok = perform_job(PruneAssets, %{})
|
||||
|
||||
assert Assets.get(record.cover_hash) != nil
|
||||
end
|
||||
|
||||
test "keeps assets referenced by artist info" do
|
||||
record = record()
|
||||
artist = hd(record.artists)
|
||||
_artist_info = artist_info(artist.musicbrainz_id)
|
||||
|
||||
assert :ok = perform_job(PruneAssets, %{})
|
||||
|
||||
# The artist info image data comes from Discogs fixture which stores an asset
|
||||
# The record's cover asset should still be present
|
||||
assert Assets.get(record.cover_hash) != nil
|
||||
end
|
||||
|
||||
test "succeeds with no unreferenced assets" do
|
||||
assert :ok = perform_job(PruneAssets, %{})
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,19 @@
|
||||
defmodule MusicLibrary.Worker.RecordGenerateAllEmbeddingsTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
import MusicLibrary.Fixtures.Records
|
||||
|
||||
alias MusicLibrary.Worker.RecordGenerateAllEmbeddings
|
||||
|
||||
describe "perform/1" do
|
||||
test "enqueues embedding generation jobs for all records" do
|
||||
_record = record()
|
||||
|
||||
assert {:ok, []} = perform_job(RecordGenerateAllEmbeddings, %{})
|
||||
end
|
||||
|
||||
test "succeeds with no records" do
|
||||
assert {:ok, []} = perform_job(RecordGenerateAllEmbeddings, %{})
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,19 @@
|
||||
defmodule MusicLibrary.Worker.RecordRefreshAllMusicBrainzDataTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
import MusicLibrary.Fixtures.Records
|
||||
|
||||
alias MusicLibrary.Worker.RecordRefreshAllMusicBrainzData
|
||||
|
||||
describe "perform/1" do
|
||||
test "enqueues refresh jobs for all records" do
|
||||
_record = record()
|
||||
|
||||
assert {:ok, []} = perform_job(RecordRefreshAllMusicBrainzData, %{})
|
||||
end
|
||||
|
||||
test "succeeds with no records" do
|
||||
assert {:ok, []} = perform_job(RecordRefreshAllMusicBrainzData, %{})
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,36 @@
|
||||
defmodule MusicLibrary.Worker.RecordRefreshMusicBrainzDataTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
import MusicLibrary.Fixtures.Records
|
||||
|
||||
alias MusicBrainz.Fixtures.ReleaseGroup
|
||||
alias MusicLibrary.Records
|
||||
alias MusicLibrary.Worker.RecordRefreshMusicBrainzData
|
||||
|
||||
describe "perform/1" do
|
||||
test "refreshes MusicBrainz data for a record" do
|
||||
record = record()
|
||||
|
||||
Req.Test.stub(MusicBrainz.API, fn conn ->
|
||||
case conn.request_path do
|
||||
"/ws/2/release-group/" <> _ ->
|
||||
Req.Test.json(conn, ReleaseGroup.release_group(:marbles))
|
||||
|
||||
"/ws/2/release" <> _ ->
|
||||
Req.Test.json(conn, %{"releases" => [], "release-count" => 0, "release-offset" => 0})
|
||||
end
|
||||
end)
|
||||
|
||||
assert :ok = perform_job(RecordRefreshMusicBrainzData, %{"id" => record.id})
|
||||
|
||||
updated = Records.get_record!(record.id)
|
||||
assert updated.musicbrainz_data != nil
|
||||
end
|
||||
|
||||
test "raises when record does not exist" do
|
||||
assert_raise Ecto.NoResultsError, fn ->
|
||||
perform_job(RecordRefreshMusicBrainzData, %{"id" => Ecto.UUID.generate()})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,31 @@
|
||||
defmodule MusicLibrary.Worker.RefreshCoverTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
import MusicLibrary.Fixtures.Records
|
||||
|
||||
alias MusicLibrary.Assets
|
||||
alias MusicLibrary.Records
|
||||
alias MusicLibrary.Worker.RefreshCover
|
||||
|
||||
describe "perform/1" do
|
||||
test "refreshes the record cover from MusicBrainz" do
|
||||
record = record()
|
||||
|
||||
Req.Test.stub(MusicBrainz.API, fn conn ->
|
||||
Plug.Conn.send_resp(conn, 200, marbles_cover_data())
|
||||
end)
|
||||
|
||||
assert :ok = perform_job(RefreshCover, %{"id" => record.id})
|
||||
|
||||
updated = Records.get_record!(record.id)
|
||||
assert updated.cover_hash != nil
|
||||
assert Assets.get(updated.cover_hash) != nil
|
||||
end
|
||||
|
||||
test "raises when record does not exist" do
|
||||
assert_raise Ecto.NoResultsError, fn ->
|
||||
perform_job(RefreshCover, %{"id" => Ecto.UUID.generate()})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
defmodule MusicLibrary.Worker.RepoOptimizeTest do
|
||||
use MusicLibrary.DataCase
|
||||
|
||||
alias MusicLibrary.Worker.RepoOptimize
|
||||
|
||||
describe "perform/1" do
|
||||
test "runs optimize on the repo" do
|
||||
assert {:ok, %Exqlite.Result{}} = perform_job(RepoOptimize, %{})
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,3 +1,3 @@
|
||||
ExUnit.start()
|
||||
ExUnit.start(exclude: [:slow])
|
||||
Ecto.Adapters.SQL.Sandbox.mode(MusicLibrary.Repo, :manual)
|
||||
Ecto.Adapters.SQL.Sandbox.mode(MusicLibrary.BackgroundRepo, :manual)
|
||||
|
||||
Reference in New Issue
Block a user