Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: assert_operation_response header lookup #584

Merged
Merged
Changes from 3 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
@@ -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(";")
19 changes: 9 additions & 10 deletions lib/open_api_spex/test/test_assertions.ex
Original file line number Diff line number Diff line change
@@ -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 ->
@@ -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

23 changes: 22 additions & 1 deletion test/test_assertions_test.exs
Original file line number Diff line number Diff line change
@@ -135,7 +135,7 @@ defmodule OpenApiSpex.TestAssertionsTest do
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"
"Failed to resolve a response schema for operation_id: not_a_real_operation_id for status code: 200"
end
end

@@ -158,5 +158,26 @@ defmodule OpenApiSpex.TestAssertionsTest do
"Value does not conform to schema PetResponse: Failed to cast value to one of: no schemas validate at"
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

try do
TestAssertions.assert_operation_response(conn, "showPetById")
raise RuntimeError, "Should flunk"
rescue
e in ExUnit.AssertionError ->
assert e.message =~
"Failed to resolve a response schema for operation_id: showPetById for status code: 200 and content type: unexpected-content-type"
end
end
end
end