Packages
ash_json_api
1.2.0
1.7.1
1.7.0
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0-rc.2
1.6.0-rc.1
1.6.0-rc.0
1.5.1
1.5.0
1.4.45
1.4.44
1.4.43
1.4.42
1.4.41
1.4.40
1.4.39
1.4.38
1.4.37
1.4.36
1.4.35
1.4.34
1.4.33
1.4.32
1.4.31
1.4.30
1.4.29
1.4.28
1.4.27
1.4.26
1.4.25
1.4.24
1.4.23
1.4.22
1.4.21
1.4.20
1.4.19
1.4.18
1.4.17
1.4.16
1.4.15
1.4.13
1.4.12
1.4.11
1.4.10
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.8
1.3.7
1.3.6
1.3.5
1.3.4
retired
1.3.3
1.3.2
1.3.1
1.3.0
1.2.2
1.2.1
1.2.0
1.1.2
1.1.1
1.1.0
1.0.0
1.0.0-rc.6
1.0.0-rc.5
1.0.0-rc.4
1.0.0-rc.3
1.0.0-rc.2
1.0.0-rc.1
1.0.0-rc.0
0.34.2
0.34.1
0.34.0
0.33.1
0.33.0
0.32.1
0.32.0
0.31.3
0.31.2
retired
0.31.1
0.31.0
0.30.1
0.30.0-rc.4
0.30.0-rc.3
0.30.0-rc.2
0.30.0-rc.1
0.30.0-rc.0
0.29.1
0.29.0
0.28.6
0.28.5
0.28.4
0.28.3
0.28.2
0.28.1
0.28.0
0.27.6
0.27.5
0.27.1
0.27.0
0.25.0
0.24.4
0.24.2
0.24.1
0.24.0
0.23.0
0.22.0
0.21.0
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.0
0.14.0
0.13.0
0.12.0
0.11.1
0.10.0
0.9.0
0.8.0
0.6.0
0.5.0
0.4.0
0.3.0
0.2.4
0.2.3
0.2.1
0.2.0
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
The JSON:API extension for the Ash Framework.
Current section
Files
Jump to
Current section
Files
lib/ash_json_api/test/test.ex
defmodule AshJsonApi.Test do
@moduledoc false
use Plug.Test
require ExUnit.Assertions
import ExUnit.Assertions
# This probably won't work for users of ashjsonapi
@schema_file "lib/ash_json_api/test/response_schema"
@external_resource @schema_file
def get(domain, path, opts \\ []) do
result =
:get
|> conn(path)
|> maybe_set_endpoint(opts)
|> set_accept_request_header(opts)
|> AshJsonApi.Domain.Info.router(domain).call(
AshJsonApi.Domain.Info.router(domain).init([])
)
assert result.state == :sent
unless opts[:skip_resp_header_check] do
if 200 <= result.status and result.status <= 300 do
assert_response_header_equals(result, "content-type", "application/vnd.api+json")
end
end
if opts[:status] do
assert result.status == opts[:status]
end
if Keyword.get(opts, :decode?, true) do
%{result | resp_body: Jason.decode!(result.resp_body)}
else
result
end
end
def post(domain, path, body, opts \\ []) do
result =
:post
|> conn(path, Jason.encode!(body))
|> set_content_type_request_header(opts)
|> set_accept_request_header(opts)
|> AshJsonApi.Domain.Info.router(domain).call(
AshJsonApi.Domain.Info.router(domain).init([])
)
assert result.state == :sent
unless opts[:skip_resp_header_check] do
if 200 <= result.status and result.status <= 300 do
assert_response_header_equals(result, "content-type", "application/vnd.api+json")
end
end
if opts[:status] do
assert result.status == opts[:status]
end
if Keyword.get(opts, :decode?, true) do
resp_body = Jason.decode!(result.resp_body)
# JsonXema.validate!(@schema, resp_body)
%{result | resp_body: resp_body}
else
result
end
end
def patch(domain, path, body, opts \\ []) do
result =
:patch
|> conn(path, Jason.encode!(body))
|> set_content_type_request_header(opts)
|> set_accept_request_header(opts)
|> AshJsonApi.Domain.Info.router(domain).call(
AshJsonApi.Domain.Info.router(domain).init([])
)
assert result.state == :sent
unless opts[:skip_resp_header_check] do
if 200 <= result.status and result.status <= 300 do
assert_response_header_equals(result, "content-type", "application/vnd.api+json")
end
end
if opts[:status] do
assert result.status == opts[:status]
end
if Keyword.get(opts, :decode?, true) do
resp_body = Jason.decode!(result.resp_body)
# JsonXema.validate!(@schema, resp_body)
%{result | resp_body: resp_body}
else
result
end
end
def delete(domain, path, opts \\ []) do
result =
:delete
|> conn(path)
|> set_accept_request_header(opts)
|> AshJsonApi.Domain.Info.router(domain).call(
AshJsonApi.Domain.Info.router(domain).init([])
)
assert result.state == :sent
unless opts[:skip_resp_header_check] do
if 200 <= result.status and result.status <= 300 do
assert_response_header_equals(result, "content-type", "application/vnd.api+json")
end
end
if opts[:status] do
assert result.status == opts[:status]
end
if Keyword.get(opts, :decode?, true) do
%{result | resp_body: Jason.decode!(result.resp_body)}
else
result
end
end
defmacro assert_data_equals(conn, expected_data) do
quote bind_quoted: [conn: conn, expected_data: expected_data] do
assert %{"data" => ^expected_data} = conn.resp_body
conn
end
end
defmacro assert_meta_equals(conn, expected_meta) do
quote bind_quoted: [conn: conn, expected_meta: expected_meta] do
assert %{"meta" => ^expected_meta} = conn.resp_body
conn
end
end
def assert_response_header_equals(conn, header, value) do
assert get_resp_header(conn, header) == [value]
conn
end
defmacro assert_attribute_equals(conn, attribute, expected_value) do
quote bind_quoted: [attribute: attribute, expected_value: expected_value, conn: conn] do
assert %{"data" => %{"attributes" => %{^attribute => ^expected_value}}} = conn.resp_body
conn
end
end
defmacro assert_id_equals(conn, expected_value) do
quote bind_quoted: [expected_value: expected_value, conn: conn] do
assert %{"data" => %{"id" => ^expected_value}} = conn.resp_body
conn
end
end
@doc """
Validate the response contains a Resource Object as per 5.2 Specification 1.0
A resource object MUST contain at least the following top-level members:
- id
- type
see: https://jsonapi.org/format/1.0/#document-resource-objects
"""
defmacro assert_valid_resource_object(conn, expected_type, expected_id) do
quote bind_quoted: [conn: conn, expected_type: expected_type, expected_id: expected_id] do
assert %{
"data" => %{
"type" => ^expected_type,
"id" => ^expected_id
}
} = conn.resp_body
conn
end
end
defmacro assert_valid_resource_objects(conn, expected_type, expected_ids) do
quote bind_quoted: [conn: conn, expected_type: expected_type, expected_ids: expected_ids] do
assert %{
"data" => results
} = conn.resp_body
assert Enum.all?(results, fn
%{"type" => ^expected_type, "id" => maybe_known_id} ->
Enum.member?(expected_ids, maybe_known_id)
_ ->
false
end)
conn
end
end
defmacro assert_invalid_resource_objects(conn, expected_type, expected_ids) do
quote bind_quoted: [conn: conn, expected_type: expected_type, expected_ids: expected_ids] do
assert %{
"data" => results
} = conn.resp_body
assert not Enum.any?(results, fn
%{"type" => ^expected_type, "id" => maybe_known_id} ->
Enum.member?(expected_ids, maybe_known_id)
_ ->
false
end)
conn
end
end
defmacro assert_attribute_missing(conn, attribute) do
quote bind_quoted: [conn: conn, attribute: attribute] do
assert %{"data" => %{"attributes" => attributes}} = conn.resp_body
refute Map.has_key?(attributes, attribute)
conn
end
end
defmacro assert_has_error(conn, fields) do
quote do
assert %{"errors" => [_ | _] = errors} = unquote(conn).resp_body
assert Enum.any?(errors, fn error ->
Enum.all?(unquote(fields), fn {key, val} ->
Map.get(error, key) == val
end)
end)
unquote(conn)
end
end
defmacro assert_has_matching_include(conn, function) do
quote do
assert %{"included" => included} = unquote(conn).resp_body
assert is_list(included)
assert Enum.any?(included, fn included ->
unquote(function).(included)
end)
unquote(conn)
end
end
defmacro assert_equal_links(conn, expected_links) do
quote bind_quoted: [expected_links: expected_links, conn: conn] do
%{"links" => resp_links} = conn.resp_body
assert Enum.sort(Map.keys(resp_links)) == Enum.sort(Map.keys(expected_links))
for {key, value} <- expected_links do
assert AshJsonApi.Test.uri_with_query(value) ==
AshJsonApi.Test.uri_with_query(resp_links[key]),
"expected #{key} link to be #{resp_links[key]}, got: #{value}"
end
conn
end
end
def uri_with_query(nil), do: nil
def uri_with_query(value) do
value
|> URI.parse()
|> Map.update!(:query, &URI.decode_query(&1 || %{}))
end
defp set_content_type_request_header(conn, opts) do
cond do
opts[:exclude_req_content_type_header] ->
conn
opts[:req_content_type_header] ->
conn
|> put_req_header("content-type", opts[:req_content_type_header])
true ->
conn
|> put_req_header("content-type", "application/vnd.api+json")
end
end
defp set_accept_request_header(conn, opts) do
cond do
opts[:exclude_req_accept_header] ->
conn
opts[:req_accept_header] ->
conn
|> put_req_header("accept", opts[:req_accept_header])
true ->
conn
|> put_req_header("accept", "application/vnd.api+json")
end
end
defp maybe_set_endpoint(conn, opts) do
if endpoint = opts[:phoenix_endpoint] do
put_private(conn, :phoenix_endpoint, endpoint)
else
conn
end
end
end