Packages

Collection of functions to test URLs

Current section

Files

Jump to
assert_url lib assert_url.ex
Raw

lib/assert_url.ex

defmodule AssertURL do
@moduledoc ~S"""
AssertURL is a module with semantic helpers to test URLs.
The goal is to provide an explicit way to test the different parts
of a URL without matching string == string.
"""
defmodule ErrorFormatter do
@moduledoc ~S"""
ANSI format error messages.
"""
def format(expected, given) do
to_string(IO.ANSI.format([
:reset,
"Expected ",
:green, :bright,
"#{expected}",
:reset,
", got ",
:red, :bright,
"#{given}",
:reset,
"."
]))
end
def format(key: key, query: query) do
to_string(IO.ANSI.format([
:reset,
"Query key ",
:red, :bright,
"#{key}",
:reset,
" is missing from ",
:yellow, :bright,
query
]))
end
def format(key: key, expected_value: expected_value, value: value, query: query) do
to_string(IO.ANSI.format([
:reset,
"Expected ",
:green, :bright,
"#{key}=#{expected_value}",
:reset,
" but got ",
:red, :bright,
"#{key}=#{value}",
:reset,
" in ",
:yellow, :bright,
query
]))
end
end
defmodule SchemeError do
@moduledoc ~S"""
Represents an error in the expected scheme.
"""
defexception [:message, :expected, :given]
def exception(expected: expected, given: given) do
message = ErrorFormatter.format(expected, given)
%SchemeError{message: message}
end
end
@doc ~S"""
Verifies the scheme of a url.
## Use
assert AssertURL.scheme_equal("http", "http://foo.com")
"""
def scheme_equal(expected, url) do
scheme = URI.parse(url).scheme
if expected != scheme do
raise SchemeError, expected: expected, given: scheme
else
true
end
end
defmodule HostError do
@moduledoc ~S"""
Represents an error in the expected host.
"""
defexception [:message, :expected, :given]
def exception(expected: expected, given: given) do
message = ErrorFormatter.format(expected, given)
%HostError{message: message}
end
end
@doc ~S"""
Verifies the host of a url.
## Use
assert AssertURL.host_equal("foo.com", "http://foo.com")
"""
def host_equal(expected, url) do
host = URI.parse(url).host
if expected != host do
raise HostError, expected: expected, given: host
else
true
end
end
defmodule PortError do
@moduledoc ~S"""
Represents an error in the expected host.
"""
defexception [:message, :expected, :given]
def exception(expected: expected, given: given) do
message = ErrorFormatter.format(expected, given)
%PortError{message: message}
end
end
@doc ~S"""
Verifies the port of a url.
## Use
assert AssertURL.port_equal(80, "http://foo.com")
"""
def port_equal(expected, url) do
port = URI.parse(url).port
if expected != port do
raise PortError, expected: expected, given: port
else
true
end
end
defmodule PathError do
@moduledoc ~S"""
Represents an error in the expected path.
"""
defexception [:message, :expected, :given]
def exception(expected: expected, given: given) do
message = ErrorFormatter.format(expected, given)
%PathError{message: message}
end
end
@doc ~S"""
Verifies the path of a url.
## Use
assert AssertURL.path_equal("/path", "http://foo.com/path")
"""
def path_equal(expected, url) do
path = URI.parse(url).path
if expected != path do
raise PathError, expected: expected, given: path
else
true
end
end
defmodule QueryError do
@moduledoc ~S"""
Represents an error in the expected query.
"""
defexception [:message, :expected, :given]
def exception(expected: expected, given: given) do
message = ErrorFormatter.format(expected, given)
%QueryError{message: message}
end
end
@doc ~S"""
Verifies the query of a url. The order of the query items is relevant for this method.
## Use
assert AssertURL.query_equal("foo=bar", "http://foo.com/path?foo=bar")
"""
def query_equal(expected, url) do
query = URI.parse(url).query
if expected != query do
raise QueryError, expected: expected, given: query
else
true
end
end
defmodule QueryKeyMissingError do
@moduledoc ~S"""
Raised when a key in the expected list is not present in the query:
## Example
# Will raise QueryKeyMissingError
AssertURL.query_include [sorry: "missing"], "http://foo.com/path?foo=bar"
"""
defexception [:message, :expected, :given]
def exception(key: key, query: query) do
message = ErrorFormatter.format(key: key, query: query)
%QueryKeyMissingError{message: message}
end
end
defmodule QueryValueError do
@moduledoc ~S"""
Raised when a key in the query doesn't have the expected value.
## Example
# Will raise QueryValueError
AssertURL.query_include [foo: "not_bar"], "http://foo.com/path?foo=bar"
"""
defexception [:message, :expected, :given]
def exception(key: key, expected_value: expected_value, value: value, query: query) do
message = ErrorFormatter.format(key: key, expected_value: expected_value, value: value, query: query)
%QueryValueError{message: message}
end
end
@doc ~S"""
Verifies that the elements of the keyword list are part of the query. The order of the keyword is irrelevant for this method.
## Use
assert AssertURL.query_equal [foo: "bar"], "http://foo.com/path?foo=bar&very=wow"
assert AssertURL.query_equal [foo: "bar", very: "wow"], "http://foo.com/path?foo=bar&very=wow"
assert AssertURL.query_equal [very: "wow", foo: "bar"], "http://foo.com/path?foo=bar&very=wow"
assert AssertURL.query_equal [], "http://foo.com/path?foo=bar&very=wow"
"""
def query_include(expected_query_items, url) do
query = URI.parse(url).query
query_items = URI.decode_query(query)
for {key, value} <- expected_query_items do
key = to_string(key)
cond do
!Map.has_key?(query_items, key) ->
raise QueryKeyMissingError, key: key, query: query
query_items[key] != value ->
raise QueryValueError, key: key, expected_value: value, value: query_items[key], query: query
true -> true
end
end
end
defmodule FragmentError do
@moduledoc ~S"""
Represents an error in the expected fragment.
"""
defexception [:message, :expected, :given]
def exception(expected: expected, given: given) do
message = ErrorFormatter.format(expected, given)
%FragmentError{message: message}
end
end
@doc ~S"""
Verifies the fragment of a url.
## Use
assert AssertURL.fragment_equal("fragment", "http://foo.com/path#fragment"
"""
def fragment_equal(expected, url) do
fragment = URI.parse(url).fragment
if expected != fragment do
raise FragmentError, expected: expected, given: fragment
else
true
end
end
end