Generate URLs for Libravatar and Gravatar avatars
at master 155 lines 3.8 kB view raw
1# SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev> 2# 3# SPDX-License-Identifier: MPL-2.0 4 5defmodule AwwTest do 6 use ExUnit.Case, async: true 7 use ExUnitProperties 8 9 @subject Aww 10 11 doctest @subject 12 13 test "by default there is no query" do 14 url = @subject.avatar_url("foo@example.com") 15 16 assert "" == url.query 17 end 18 19 test "by default HTTPS is used" do 20 url = @subject.avatar_url("foo@example.com") 21 22 assert "https" == url.scheme 23 end 24 25 test "can opt out to insecure HTTP query" do 26 url = @subject.avatar_url("foo@example.com", service_opts: [secure?: false]) 27 28 assert "http" == url.scheme 29 end 30 31 test "default can be changed" do 32 url = @subject.avatar_url("foo@example.com", default: "monster") 33 34 assert url.query =~ "d=monster" 35 end 36 37 test "size can be defined" do 38 url = @subject.avatar_url("foo@example.com", size: 2137) 39 40 assert url.query =~ "s=2137" 41 end 42 43 test "enforce default" do 44 url = @subject.avatar_url("foo@example.com", forcedefault?: true) 45 46 assert url.query =~ "f=y" 47 end 48 49 test "select rating" do 50 url = @subject.avatar_url("foo@example.com", rating: "R") 51 52 assert url.query =~ "r=R" 53 end 54 55 property "email is case insensitive" do 56 check all( 57 local_part <- string(:ascii, min_length: 1), 58 domain <- string(:ascii, min_length: 1) 59 ) do 60 input = "#{local_part}@#{domain}" 61 downcased = String.downcase(input) 62 63 assert @subject.avatar_url(input) == @subject.avatar_url(downcased) 64 end 65 end 66 67 property "custom host contains that host" do 68 check all(host <- string(:ascii, min_length: 1)) do 69 url = @subject.avatar_url("foo@example.com", service_opts: [host: host]) 70 71 assert host == url.host 72 end 73 end 74 75 property "custom host as URI contains that host" do 76 check all(host <- string(:ascii, min_length: 1), port <- integer(0..0xFFFF)) do 77 uri = %URI{ 78 host: host, 79 port: port 80 } 81 82 url = @subject.avatar_url("foo@example.com", service_opts: [host: uri]) 83 84 assert host == url.host 85 assert port == url.port 86 end 87 end 88 89 defp domain do 90 part = string([?a..?z, ?A..?Z, ?0..?9, ?-], min_length: 1, max_length: 10) 91 92 gen( 93 all( 94 parts <- list_of(part, min_length: 1, max_length: 4), 95 do: Enum.join(parts, ".") 96 ) 97 ) 98 end 99 100 defp open_id_uri do 101 gen all( 102 scheme <- one_of([constant("http"), constant("https")]), 103 host <- domain(), 104 port <- integer(0..0xFFFF), 105 segment = string(:alphanumeric, min_length: 1), 106 path <- list_of(segment), 107 user <- string(:alphanumeric, min_length: 1), 108 pass <- string(:alphanumeric, min_length: 1) 109 ) do 110 %URI{ 111 scheme: scheme, 112 host: host, 113 port: port, 114 path: "/" <> Enum.join(path, "/"), 115 userinfo: "#{user}:#{pass}" 116 } 117 end 118 end 119 120 property "normalizes OpenID addresses" do 121 check all(url <- open_id_uri()) do 122 input = URI.to_string(url) 123 124 downcased = 125 URI.to_string(%URI{ 126 url 127 | host: String.downcase(url.host) 128 }) 129 130 assert @subject.avatar_url(input) == @subject.avatar_url(downcased) 131 end 132 end 133 134 describe "function as a host provider" do 135 def host_func(host, _opts), do: "test.#{host}" 136 137 test "passed as MFA" do 138 url = 139 @subject.avatar_url("hello@example.com", 140 service_opts: [host: {__MODULE__, :host_func, []}] 141 ) 142 143 assert url.host == "test.example.com" 144 end 145 146 test "passed as capture" do 147 url = 148 @subject.avatar_url("hello@example.com", 149 service_opts: [host: &host_func/2] 150 ) 151 152 assert url.host == "test.example.com" 153 end 154 end 155end