Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions lib/open_api_spex/cast/utils.ex
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,19 @@ defmodule OpenApiSpex.Cast.Utils do
- If multiple `content-type` headers are found, the function will only return the value of the first one.

"""
@spec content_type_from_header(Plug.Conn.t()) :: String.t() | nil
def content_type_from_header(conn = %Plug.Conn{}) do
case Plug.Conn.get_req_header(conn, "content-type") do
@spec content_type_from_header(Plug.Conn.t(), :request | :response) ::
String.t() | nil
def content_type_from_header(conn = %Plug.Conn{}, header_location \\ :request) do
content_type =
case header_location do
:request ->
Plug.Conn.get_req_header(conn, "content-type")

:response ->
Plug.Conn.get_resp_header(conn, "content-type")
end

case content_type do
[header_value | _] ->
header_value
|> String.split(";")
Expand Down
19 changes: 9 additions & 10 deletions lib/open_api_spex/test/test_assertions.ex
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ defmodule OpenApiSpex.TestAssertions do
case operation_lookup[operation_id] do
nil ->
flunk(
"Failed to resolve schema. Unable to find a response for operation_id: #{operation_id} for response status code: #{conn.status}"
"Failed to resolve a response schema for operation_id: #{operation_id} for status code: #{conn.status}"
)

operation ->
Expand All @@ -154,20 +154,19 @@ defmodule OpenApiSpex.TestAssertions do
) ::
term | no_return
defp validate_operation_response(conn, %Operation{operationId: operation_id} = operation, spec) do
content_type = Utils.content_type_from_header(conn)
content_type = Utils.content_type_from_header(conn, :response)

resolved_schema =
get_in(operation, [
Access.key!(:responses),
Access.key!(conn.status),
Access.key!(:content),
content_type,
Access.key!(:schema)
])
operation
|> Map.get(:responses, %{})
|> Map.get(conn.status, %{})
|> Map.get(:content, %{})
|> Map.get(content_type, %{})
|> Map.get(:schema)

if is_nil(resolved_schema) do
flunk(
"Failed to resolve schema! Unable to find a response for operation_id: #{operation_id} for response status code: #{conn.status} and content type #{content_type}"
"Failed to resolve a response schema for operation_id: #{operation_id} for status code: #{conn.status} and content type: #{content_type}"
)
end

Expand Down
44 changes: 28 additions & 16 deletions test/test_assertions_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,11 @@ defmodule OpenApiSpex.TestAssertionsTest do
conn = OpenApiSpexTest.Router.call(conn, [])
assert conn.status == 200

try do
TestAssertions.assert_operation_response(conn, "not_a_real_operation_id")
raise RuntimeError, "Should flunk"
rescue
e in ExUnit.AssertionError ->
assert e.message =~
"Failed to resolve schema. Unable to find a response for operation_id: not_a_real_operation_id for response status code: 200"
end
assert_raise(
ExUnit.AssertionError,
~r/Failed to resolve a response schema for operation_id: not_a_real_operation_id for status code: 200/,
fn -> TestAssertions.assert_operation_response(conn, "not_a_real_operation_id") end
)
end

test "invalid schema" do
Expand All @@ -149,14 +146,29 @@ defmodule OpenApiSpex.TestAssertionsTest do

assert conn.status == 200

try do
TestAssertions.assert_operation_response(conn, "showPetById")
raise RuntimeError, "Should flunk"
rescue
e in ExUnit.AssertionError ->
assert e.message =~
"Value does not conform to schema PetResponse: Failed to cast value to one of: no schemas validate at"
end
assert_raise(
ExUnit.AssertionError,
~r/Value does not conform to schema PetResponse: Failed to cast value to one of: no schemas validate at/,
fn -> TestAssertions.assert_operation_response(conn, "showPetById") end
)
end

test "returns an error when the response content-type does not match the schema" do
conn =
:get
|> Plug.Test.conn("/api/pets")
|> Plug.Conn.put_req_header("content-type", "application/json")
|> Plug.Conn.put_resp_header("content-type", "unexpected-content-type")

conn = OpenApiSpexTest.Router.call(conn, [])

assert conn.status == 200

assert_raise(
ExUnit.AssertionError,
~r/Failed to resolve a response schema for operation_id: showPetById for status code: 200 and content type: unexpected-content-type/,
fn -> TestAssertions.assert_operation_response(conn, "showPetById") end
)
end
end
end