diff --git a/lib/open_api_spex/operation_builder.ex b/lib/open_api_spex/operation_builder.ex index 6802c286..f9c70d6d 100644 --- a/lib/open_api_spex/operation_builder.ex +++ b/lib/open_api_spex/operation_builder.ex @@ -108,6 +108,11 @@ defmodule OpenApiSpex.OperationBuilder do def build_responses(_), do: [] defp status_to_code(:default), do: :default + + defp status_to_code(status) + when status in [:"1XX", "1XX", :"2XX", "2XX", :"3XX", "3XX", :"4XX", "4XX", :"5XX", "5XX"], + do: status + defp status_to_code(status), do: Status.code(status) def build_request_body(%{body: {description, media_type, schema}}) do diff --git a/lib/open_api_spex/test/test_assertions.ex b/lib/open_api_spex/test/test_assertions.ex index 6d089024..809044d6 100644 --- a/lib/open_api_spex/test/test_assertions.ex +++ b/lib/open_api_spex/test/test_assertions.ex @@ -156,10 +156,18 @@ defmodule OpenApiSpex.TestAssertions do defp validate_operation_response(conn, %Operation{operationId: operation_id} = operation, spec) do content_type = Utils.content_type_from_header(conn, :response) + responses = Map.get(operation, :responses, %{}) + code_range = String.first(to_string(conn.status)) <> "XX" + + response = + Map.get(responses, conn.status) || + Map.get(responses, "#{conn.status}") || + Map.get(responses, :"#{conn.status}") || + Map.get(responses, code_range) || + Map.get(responses, :"#{code_range}", %{}) + resolved_schema = - operation - |> Map.get(:responses, %{}) - |> Map.get(conn.status, %{}) + response |> Map.get(:content, %{}) |> Map.get(content_type, %{}) |> Map.get(:schema) diff --git a/test/support/router.ex b/test/support/router.ex index 217f9e70..89cc5b59 100644 --- a/test/support/router.ex +++ b/test/support/router.ex @@ -15,7 +15,9 @@ defmodule OpenApiSpexTest.Router do get "/noapi", OpenApiSpexTest.NoApiController, :noapi get "/noapi_with_struct", OpenApiSpexTest.NoApiControllerWithStructSpecs, :noapi - resources "/users_no_replace", OpenApiSpexTest.UserNoRepalceController, only: [:create, :index] + get "/response_code_ranges", OpenApiSpexTest.ResponseCodeRangesController, :index + + resources "/users_no_replace", OpenApiSpexTest.UserNoReplaceController, only: [:create, :index] # Used by ParamsTest resources "/custom_error_users", OpenApiSpexTest.CustomErrorUserController, only: [:index] diff --git a/test/support/string_response_codes_controller.ex b/test/support/string_response_codes_controller.ex new file mode 100644 index 00000000..49fd8b82 --- /dev/null +++ b/test/support/string_response_codes_controller.ex @@ -0,0 +1,58 @@ +defmodule OpenApiSpexTest.ResponseCodeRangesController do + use Phoenix.Controller + use OpenApiSpex.ControllerSpecs + + alias OpenApiSpex.Operation + + defmodule GenericResponse do + alias OpenApiSpex.Schema + require OpenApiSpex + + OpenApiSpex.schema(%{ + type: :object, + properties: %{ + type: %Schema{ + type: :string, + enum: ["generic"] + } + } + }) + end + + defmodule CreatedResponse do + alias OpenApiSpex.Schema + require OpenApiSpex + + OpenApiSpex.schema(%{ + type: :object, + properties: %{ + type: %Schema{ + type: :string, + enum: ["created"] + } + } + }) + end + + operation :index, + operation_id: "response_code_ranges", + summary: "String response codes index", + responses: [ + created: + Operation.response( + "Created response", + "application/json", + CreatedResponse + ), + "2XX": + Operation.response( + "Generic response", + "application/json", + GenericResponse + ) + ] + + def index(conn, _) do + json(conn, %{type: "generic"}) + end +end diff --git a/test/support/user_no_replace_controller.ex b/test/support/user_no_replace_controller.ex index b74822fe..f3d10b5a 100644 --- a/test/support/user_no_replace_controller.ex +++ b/test/support/user_no_replace_controller.ex @@ -1,4 +1,4 @@ -defmodule OpenApiSpexTest.UserNoRepalceController do +defmodule OpenApiSpexTest.UserNoReplaceController do @moduledoc tags: ["users_no_replace"] use Phoenix.Controller diff --git a/test/test_assertions_test.exs b/test/test_assertions_test.exs index 9174b5e2..db896977 100644 --- a/test/test_assertions_test.exs +++ b/test/test_assertions_test.exs @@ -120,6 +120,18 @@ defmodule OpenApiSpex.TestAssertionsTest do TestAssertions.assert_operation_response(conn) end + test "success with a response code range" do + conn = + :get + |> Plug.Test.conn("/api/response_code_ranges") + |> Plug.Conn.put_req_header("content-type", "application/json") + + conn = OpenApiSpexTest.Router.call(conn, []) + + assert conn.status == 200 + TestAssertions.assert_operation_response(conn, "response_code_ranges") + end + test "missing operation id" do conn = :get