4.6 KiB · text History b868907
defmodule GitGudWeb.BadgeControllerTest do
  use GitGudWeb.ConnCase, async: false

  import GitGud.ForgeFixtures

  alias GitGud.Repositories.Storage

  defp base(repo) do
    repo = GitGud.Repo.preload(repo, [:owner, :organization])
    "/r/#{Storage.repo_handle(repo)}/#{repo.name}/badge"
  end

  test "a public repository's badge is anyone's", %{conn: conn} do
    {_user, repo} = repository_fixture(%{visibility: "public"})
    conn = get(conn, base(repo) <> "/ci/dot/gg/forest.svg")

    assert response(conn, 200) =~ ~s(aria-label="ci: none")
    assert get_resp_header(conn, "content-type") == ["image/svg+xml"]
    assert get_resp_header(conn, "cache-control") == ["public, max-age=120"]
    assert [_] = get_resp_header(conn, "etag")
  end

  test "a PNG", %{conn: conn} do
    {_user, repo} = repository_fixture(%{visibility: "public"})
    conn = get(conn, base(repo) <> "/coverage/2.5x/light.png")

    assert <<137, 80, 78, 71, _::binary>> = response(conn, 200)
    assert get_resp_header(conn, "content-type") == ["image/png"]
  end

  test "an unchanged badge revalidates as 304", %{conn: conn} do
    {_user, repo} = repository_fixture(%{visibility: "public"})
    [etag] = conn |> get(base(repo) <> "/mark.svg") |> get_resp_header("etag")

    conn =
      conn |> recycle() |> put_req_header("if-none-match", etag) |> get(base(repo) <> "/mark.svg")

    assert response(conn, 304) == ""
  end

  test "a private repository's badge is 404 to a stranger", %{conn: conn} do
    {_user, repo} = repository_fixture(%{visibility: "private"})
    assert conn |> get(base(repo) <> "/ci.svg") |> response(404)
  end

  test "a private repository's badge is there for its owner", %{conn: conn} do
    {user, repo} = repository_fixture(%{visibility: "private"})
    conn = conn |> log_in_user(user) |> get(base(repo) <> "/ci.svg")

    assert response(conn, 200)
    assert get_resp_header(conn, "cache-control") == ["private, max-age=120"]
  end

  test "a path that isn't a badge is 404", %{conn: conn} do
    {_user, repo} = repository_fixture(%{visibility: "public"})
    assert conn |> get(base(repo) <> "/ci/sparkly.svg") |> response(404)
    assert conn |> get(base(repo) <> "/ci.gif") |> response(404)
  end

  test "a workflow's badge", %{conn: conn} do
    {_user, repo} = repository_fixture(%{visibility: "public"})
    conn = get(conn, base(repo) <> "/workflow/audit/outline.svg")
    assert response(conn, 200) =~ ~s(aria-label="audit: none")
    assert conn |> recycle() |> get(base(repo) <> "/workflow.svg") |> response(404)
  end

  test "counts", %{conn: conn} do
    {_user, repo} = repository_fixture(%{visibility: "public"})

    assert conn |> get(base(repo) <> "/issues.svg") |> response(200) =~
             ~s(aria-label="issues: 0 open")

    assert conn |> recycle() |> get(base(repo) <> "/commits/dot.svg") |> response(200) =~
             "commits"
  end

  describe "package badges" do
    test "a public repository's", %{conn: conn} do
      {_user, repo} = repository_fixture(%{visibility: "public"})
      conn = get(conn, base(repo) <> "/package/cargo/gitgud-cli.svg")

      assert response(conn, 200) =~ ~s(aria-label="install with cargo: none")
      assert get_resp_header(conn, "cache-control") == ["public, max-age=120"]
    end

    test "a private repository's follow the registry: hidden, unless its format is public",
         %{conn: conn} do
      {_user, repo} = repository_fixture(%{visibility: "private"})
      assert conn |> get(base(repo) <> "/package/cargo/x.svg") |> response(404)
      assert conn |> recycle() |> get(base(repo) <> "/ci.svg") |> response(404)

      repo
      |> Ecto.Changeset.change(public_package_formats: ["cargo"])
      |> GitGud.Repo.update!()

      conn = conn |> recycle() |> get(base(repo) <> "/package/cargo/x.svg")
      assert response(conn, 200)
      assert get_resp_header(conn, "cache-control") == ["public, max-age=120"]
      # The rest of the repository stays private.
      assert conn |> recycle() |> get(base(repo) <> "/ci.svg") |> response(404)
      assert conn |> recycle() |> get(base(repo) <> "/package/pypi/x.svg") |> response(404)
    end
  end

  test "samples need no repository and cache for a day", %{conn: conn} do
    conn = get(conn, "/badges/sample/ci/failing/outline/her.svg")
    assert response(conn, 200) =~ ~s(aria-label="ci: failing")
    assert get_resp_header(conn, "cache-control") == ["public, max-age=86400"]

    assert conn |> recycle() |> get("/badges/sample/ci/exploded/auto.svg") |> response(404)

    assert conn
           |> recycle()
           |> get("/badges/sample/workflow/warning/dot/sky.svg")
           |> response(200) =~
             ~s(aria-label="audit: 1 no fix")
  end
end