Files
music_library/test/music_library_web/controllers/collection_controller_test.exs
T
2026-05-10 14:52:01 +01:00

186 lines
6.1 KiB
Elixir

defmodule MusicLibraryWeb.CollectionControllerTest do
use MusicLibraryWeb.ConnCase
import MusicLibrary.Fixtures.Records
defp create_record(_) do
%{record: record_with_artist("Steven Wilson", %{release_date: "2025-06-21"})}
end
defp api_token do
Application.get_env(:music_library, MusicLibraryWeb)
|> Keyword.fetch!(:api_token)
end
describe "authentication" do
test "all API endpoints require a bearer token", %{conn: conn} do
for path <- [
~p"/api/v1/collection/latest",
~p"/api/v1/collection/random",
~p"/api/v1/collection",
~p"/api/v1/collection/on_this_day"
] do
assert get(conn, path).status == 401,
"expected 401 for unauthenticated GET #{path}"
end
end
end
describe "GET /api/v1/collection/latest" do
setup [:create_record]
test "returns the latest record", %{conn: conn, record: record} do
conn =
conn
|> put_req_header("authorization", "Bearer #{api_token()}")
|> get(~p"/api/v1/collection/latest")
assert json_response(conn, 200) == expected_record_json(record)
end
end
describe "GET /api/v1/collection/random" do
setup [:create_record]
# We're not testing random here - the query is solid enough
test "returns a random record", %{conn: conn, record: record} do
conn =
conn
|> put_req_header("authorization", "Bearer #{api_token()}")
|> get(~p"/api/v1/collection/random")
assert json_response(conn, 200) == expected_record_json(record)
end
end
describe "GET /api/v1/collection" do
setup [:create_record]
test "returns a paginated list of records", %{conn: conn, record: record} do
conn =
conn
|> put_req_header("authorization", "Bearer #{api_token()}")
|> get(~p"/api/v1/collection")
assert json_response(conn, 200) == %{
"total" => 1,
"limit" => 20,
"offset" => 0,
"records" => [expected_record_json(record)]
}
end
test "filters records when q param matches", %{conn: conn} do
beatles = record_with_artist("The Beatles", %{title: "Abbey Road"})
conn =
conn
|> put_req_header("authorization", "Bearer #{api_token()}")
|> get(~p"/api/v1/collection?q=beatles")
assert json_response(conn, 200) == %{
"total" => 1,
"limit" => 20,
"offset" => 0,
"records" => [expected_record_json(beatles)]
}
end
test "returns all records when q is empty string", %{conn: conn, record: record} do
conn =
conn
|> put_req_header("authorization", "Bearer #{api_token()}")
|> get(~p"/api/v1/collection?q=")
assert json_response(conn, 200) == %{
"total" => 1,
"limit" => 20,
"offset" => 0,
"records" => [expected_record_json(record)]
}
end
test "returns empty results when q matches nothing", %{conn: conn} do
conn =
conn
|> put_req_header("authorization", "Bearer #{api_token()}")
|> get(~p"/api/v1/collection?q=nonexistentxyz")
assert json_response(conn, 200) == %{
"total" => 0,
"limit" => 20,
"offset" => 0,
"records" => []
}
end
test "respects pagination with search query", %{conn: conn} do
_a = record_with_artist("The Beatles", %{title: "Abbey Road"})
b = record_with_artist("The Beatles", %{title: "Revolver"})
_c = record_with_artist("The Beatles", %{title: "Sgt Pepper"})
conn =
conn
|> put_req_header("authorization", "Bearer #{api_token()}")
|> get(~p"/api/v1/collection?q=beatles&limit=1&offset=1")
assert json_response(conn, 200) == %{
"total" => 3,
"limit" => 1,
"offset" => 1,
"records" => [expected_record_json(b)]
}
end
test "response shape is unchanged when searching", %{conn: conn} do
beatles = record_with_artist("The Beatles", %{title: "Abbey Road"})
conn =
conn
|> put_req_header("authorization", "Bearer #{api_token()}")
|> get(~p"/api/v1/collection?q=beatles")
response = json_response(conn, 200)
assert %{"total" => 1, "limit" => 20, "offset" => 0, "records" => [record_json]} = response
assert record_json == expected_record_json(beatles)
end
end
describe "GET /api/v1/collection/on_this_day" do
setup [:create_record]
test "returns a list of records", %{conn: conn, record: record} do
conn =
conn
|> put_req_header("authorization", "Bearer #{api_token()}")
|> get(~p"/api/v1/collection/on_this_day?date=2025-06-21")
assert json_response(conn, 200) == %{
"records" => [expected_record_json(record)]
}
end
end
defp expected_record_json(record) do
%{
"id" => record.id,
"type" => record.type |> to_string(),
"format" => record.format |> to_string(),
"musicbrainz_id" => record.musicbrainz_id,
"genres" => record.genres,
"release_date" => record.release_date,
"purchased_at" => record.purchased_at |> DateTime.to_iso8601(),
"artists" => Enum.map(record.artists, & &1.name),
"title" => record.title,
"cover_url" =>
"http://localhost:4002/api/v1/assets/eyJoYXNoIjoiNTk5NDA3RERGNjk5MDdENEE2MEZFMTNDQ0FBODI0RDI1Q0YwOERDMTI0RkQ2QUEzRThFN0VDRDk4Qzg4NUZGRSIsIndpZHRoIjpudWxsfQ",
"thumb_url" =>
"http://localhost:4002/api/v1/assets/eyJoYXNoIjoiNTk5NDA3RERGNjk5MDdENEE2MEZFMTNDQ0FBODI0RDI1Q0YwOERDMTI0RkQ2QUEzRThFN0VDRDk4Qzg4NUZGRSIsIndpZHRoIjo0ODB9",
"mini_cover_url" =>
"http://localhost:4002/api/v1/assets/eyJoYXNoIjoiNTk5NDA3RERGNjk5MDdENEE2MEZFMTNDQ0FBODI0RDI1Q0YwOERDMTI0RkQ2QUEzRThFN0VDRDk4Qzg4NUZGRSIsIndpZHRoIjoxNTB9",
"micro_cover_url" =>
"http://localhost:4002/api/v1/assets/eyJoYXNoIjoiNTk5NDA3RERGNjk5MDdENEE2MEZFMTNDQ0FBODI0RDI1Q0YwOERDMTI0RkQ2QUEzRThFN0VDRDk4Qzg4NUZGRSIsIndpZHRoIjo0MH0"
}
end
end