berrypod/test/berrypod_web/controllers/favicon_controller_test.exs

138 lines
4.4 KiB
Elixir
Raw Permalink Normal View History

defmodule BerrypodWeb.FaviconControllerTest do
use BerrypodWeb.ConnCase, async: false
alias Berrypod.Media
# Minimal valid PNG (1x1 transparent)
@test_png <<137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 1, 0, 0, 0,
1, 8, 6, 0, 0, 0, 31, 21, 196, 137, 0, 0, 0, 10, 73, 68, 65, 84, 120, 156, 98, 0, 0,
0, 2, 0, 1, 226, 33, 188, 51, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130>>
@test_svg ~s(<svg xmlns="http://www.w3.org/2000/svg"><circle r="10"/></svg>)
defp create_source_image do
{:ok, image} =
Media.upload_image(%{
image_type: "icon",
filename: "icon.svg",
content_type: "image/svg+xml",
file_size: byte_size(@test_svg),
data: @test_svg
})
image
end
defp create_favicon_variants(_context) do
image = create_source_image()
{:ok, variants} =
Media.store_favicon_variants(%{
source_image_id: image.id,
png_32: @test_png,
png_180: @test_png,
png_192: @test_png,
png_512: @test_png,
svg: @test_svg
})
%{variants: variants}
end
describe "favicon routes with variants" do
setup [:create_favicon_variants]
test "serves favicon SVG", %{conn: conn} do
conn = get(conn, ~p"/favicon.svg")
assert response_content_type(conn, :xml) =~ "image/svg+xml"
assert conn.status == 200
assert conn.resp_body =~ "<svg"
assert get_resp_header(conn, "cache-control") == ["public, max-age=86400"]
assert [etag] = get_resp_header(conn, "etag")
assert etag =~ ~r/^"fav-\d+"$/
end
test "serves 32x32 PNG favicon", %{conn: conn} do
conn = get(conn, ~p"/favicon-32x32.png")
assert conn.status == 200
assert response_content_type(conn, :png) =~ "image/png"
assert <<137, 80, 78, 71, _::binary>> = conn.resp_body
end
test "serves apple touch icon", %{conn: conn} do
conn = get(conn, ~p"/apple-touch-icon.png")
assert conn.status == 200
assert response_content_type(conn, :png) =~ "image/png"
end
test "serves 192px icon", %{conn: conn} do
conn = get(conn, ~p"/icon-192.png")
assert conn.status == 200
assert response_content_type(conn, :png) =~ "image/png"
end
test "serves 512px icon", %{conn: conn} do
conn = get(conn, ~p"/icon-512.png")
assert conn.status == 200
assert response_content_type(conn, :png) =~ "image/png"
end
test "returns 304 for matching ETag", %{conn: conn} do
conn1 = get(conn, ~p"/favicon-32x32.png")
[etag] = get_resp_header(conn1, "etag")
conn2 =
conn
|> put_req_header("if-none-match", etag)
|> get(~p"/favicon-32x32.png")
assert conn2.status == 304
end
end
describe "favicon routes without variants" do
test "returns 404 for favicon SVG", %{conn: conn} do
conn = get(conn, ~p"/favicon.svg")
assert conn.status == 404
end
test "returns 404 for PNG variants", %{conn: conn} do
assert get(conn, ~p"/favicon-32x32.png").status == 404
assert get(conn, ~p"/apple-touch-icon.png").status == 404
assert get(conn, ~p"/icon-192.png").status == 404
assert get(conn, ~p"/icon-512.png").status == 404
end
end
describe "webmanifest" do
test "returns valid JSON manifest", %{conn: conn} do
conn = get(conn, ~p"/site.webmanifest")
assert conn.status == 200
assert response_content_type(conn, :json) =~ "application/manifest+json"
manifest = json_response(conn, 200)
assert manifest["name"] == "Store Name"
assert manifest["display"] == "minimal-ui"
assert manifest["start_url"] == "/"
assert is_binary(manifest["theme_color"])
assert is_binary(manifest["background_color"])
assert length(manifest["icons"]) == 2
end
test "manifest icons have correct sizes", %{conn: conn} do
manifest = json_response(get(conn, ~p"/site.webmanifest"), 200)
icons = manifest["icons"]
assert Enum.any?(icons, &(&1["sizes"] == "192x192"))
assert Enum.any?(icons, &(&1["sizes"] == "512x512"))
end
test "manifest uses short name from settings", %{conn: conn} do
manifest = json_response(get(conn, ~p"/site.webmanifest"), 200)
# Default: truncated site_name (no favicon_short_name set)
assert is_binary(manifest["short_name"])
assert String.length(manifest["short_name"]) <= 12
end
end
end