defmodule Tarakan.Accounts.IdentityTest do
  use ExUnit.Case, async: true

  alias Ecto.Changeset
  alias Tarakan.Accounts.Account
  alias Tarakan.Accounts.Identity

  @profile %{
    provider_uid: 123,
    provider_login: "signal",
    name: "Signal",
    avatar_url: "https://avatars.example.com/u/123",
    profile_url: "https://forge.example.com/signal"
  }

  defp changeset(profile) do
    Identity.provider_changeset(%Identity{}, %Account{id: 1}, :github, profile)
  end

  test "stores absolute http and https provider URLs" do
    changeset = changeset(@profile)

    assert changeset.valid?
    assert Changeset.get_field(changeset, :avatar_url) == @profile.avatar_url
    assert Changeset.get_field(changeset, :profile_url) == @profile.profile_url

    https = changeset(%{@profile | profile_url: "https://forge.example.com/signal"})
    assert Changeset.get_field(https, :profile_url) == "https://forge.example.com/signal"
  end

  test "drops avatar URLs that are not absolute http(s)" do
    for url <- [
          "javascript:alert(1)",
          "data:image/png;base64,AAAA",
          "ftp://example.com/avatar.png",
          "//example.com/avatar.png",
          "/local/path",
          "",
          nil
        ] do
      changeset = changeset(%{@profile | avatar_url: url})

      assert Changeset.get_field(changeset, :avatar_url) == nil
      assert changeset.valid?
    end
  end

  test "rejects identities whose profile URL is not absolute http(s)" do
    changeset = changeset(%{@profile | profile_url: "javascript:alert(1)"})

    assert Changeset.get_field(changeset, :profile_url) == nil
    refute changeset.valid?
    assert %{profile_url: ["can't be blank"]} = Changeset.traverse_errors(changeset, &elem(&1, 0))
  end
end
