diff --git a/lib/music_library/records.ex b/lib/music_library/records.ex index 0cfc0bda..4f47fe0b 100644 --- a/lib/music_library/records.ex +++ b/lib/music_library/records.ex @@ -256,7 +256,7 @@ defmodule MusicLibrary.Records do end end - @spec populate_genres(Record.t()) :: {:ok, Record.t()} | {:error, Ecto.Changeset.t()} + @spec populate_genres(Record.t()) :: {:ok, Record.t()} | {:error, Ecto.Changeset.t() | term()} def populate_genres(record) do artists = Enum.map_join(record.artists, ",", fn a -> a.name end) @@ -270,11 +270,11 @@ defmodule MusicLibrary.Records do """ } - {:ok, response} = OpenAI.gpt(completion) - - record - |> Record.add_genres(response["genres"]) - |> Repo.update() + with {:ok, response} <- OpenAI.gpt(completion) do + record + |> Record.add_genres(response["genres"]) + |> Repo.update() + end end @spec populate_genres_async(Record.t()) :: {:ok, Oban.Job.t()} | {:error, Ecto.Changeset.t()} diff --git a/test/music_library/records_test.exs b/test/music_library/records_test.exs index e1260409..ac45413f 100644 --- a/test/music_library/records_test.exs +++ b/test/music_library/records_test.exs @@ -344,4 +344,33 @@ defmodule MusicLibrary.RecordsTest do assert Assets.get(updated_record.cover_hash).content == expected_content end end + + describe "populate_genres/1" do + test "updates record genres from OpenAI response" do + record = record(%{genres: []}) + genres = ["progressive rock", "art rock", "symphonic rock"] + + Req.Test.stub(OpenAI.API, fn conn -> + Req.Test.json(conn, %{ + "choices" => [ + %{"message" => %{"content" => JSON.encode!(%{"genres" => genres})}} + ] + }) + end) + + assert {:ok, updated} = Records.populate_genres(record) + assert updated.genres == genres + end + + @tag :capture_log + test "returns error tuple when OpenAI API fails" do + record = record(%{genres: []}) + + Req.Test.stub(OpenAI.API, fn conn -> + Plug.Conn.send_resp(conn, 500, JSON.encode!(%{"error" => "internal server error"})) + end) + + assert {:error, _reason} = Records.populate_genres(record) + end + end end diff --git a/test/music_library/worker/populate_genres_test.exs b/test/music_library/worker/populate_genres_test.exs new file mode 100644 index 00000000..a187b7dc --- /dev/null +++ b/test/music_library/worker/populate_genres_test.exs @@ -0,0 +1,44 @@ +defmodule MusicLibrary.Worker.PopulateGenresTest do + use MusicLibrary.DataCase + + import MusicLibrary.Fixtures.Records + + alias MusicLibrary.Records + alias MusicLibrary.Worker.PopulateGenres + + describe "perform/1" do + test "populates genres and enqueues embedding generation" do + record = record(%{genres: []}) + genres = ["progressive rock", "art rock", "symphonic rock"] + + Req.Test.stub(OpenAI.API, fn conn -> + Req.Test.json(conn, %{ + "choices" => [ + %{"message" => %{"content" => JSON.encode!(%{"genres" => genres})}} + ] + }) + end) + + assert :ok = perform_job(PopulateGenres, %{"id" => record.id}) + + updated = Records.get_record!(record.id) + assert updated.genres == genres + + assert_enqueued( + worker: MusicLibrary.Worker.GenerateRecordEmbedding, + args: %{"record_id" => record.id} + ) + end + + @tag :capture_log + test "returns error when OpenAI API fails" do + record = record(%{genres: []}) + + Req.Test.stub(OpenAI.API, fn conn -> + Plug.Conn.send_resp(conn, 500, JSON.encode!(%{"error" => "internal server error"})) + end) + + assert {:error, _reason} = perform_job(PopulateGenres, %{"id" => record.id}) + end + end +end