open-api-spex / open_api_spex

Open API Specifications for Elixir Plug applications
Mozilla Public License 2.0
681 stars 177 forks source link

Confusion around reading YAML into ApiSpec #582

Open mengelseatz opened 7 months ago

mengelseatz commented 7 months ago

The documentation implies that you can use either Elixir code to create your OpenAPI schema or parse and read a YAML( or JSON) OpenAPI schema. I need to do the former and I have this in my code and it parses and reads the file without an error. I also have configured the SwaggerUI and it renders the API documentation correctly which to me implies this is configured correctly:

  defmodule MyApiWeb.ApiSpec do
    @moduledoc false

    alias OpenApiSpex.{Components, Info, OpenApi, Paths, Server}
    alias MyApiWeb.{Endpoint, Router}
    @behaviour OpenApi

    @impl OpenApi
    def spec do
      open_api_spec_from_yaml =
        "openapi/v1/car.yaml"
        |> YamlElixir.read_all_from_file!()
        |> List.first()
        |> OpenApiSpex.OpenApi.Decode.decode()

      # IO.inspect(open_api_spec_from_yaml)
      # Discover request/response schemas from path specs
      open_api_spec_from_yaml |> OpenApiSpex.resolve_schema_modules()
    end
  end

But when I'm trying to use the functionality described in the documentation it doesn't appear that the data structures are created correctly in the modules used by the documentation. e.g. the README section "Validate Responses" has a test like this which I modified to use my module

    use ExUnit.Case
    import OpenApiSpex.TestAssertions

    test "MyOffersRequest example matches schema" do
      api_spec = MyApiWeb.ApiSpec.spec()
      schema = MyApiWeb.Schemas. MyOffersRequest.schema()
      assert_schema(schema.example, "MyOffersRequest, api_spec)
    end

And if I run the test I get the following error

 ** (UndefinedFunctionError) function MyApiWeb.Schemas.MyOffersRequest.schema/0 is undefined (module MyApiWeb.Schemas.MyOffersRequest is not available)
 code: schema = MyApiWeb.Schemas.MyOffersRequest.schema()
 stacktrace:
   MyApiWeb.Schemas.MyOffersRequest.schema()

So in effect MyApiWeb.Schemas is empty and I saw this while trying to do request validation in my Phoenix controllers as well. I know there is a PutApiSpec that's mentioned in doing validation which I have setup in my router.ex (see comment above about the swagger ui working correctly which I believe relies on this) but I get the same error there as if the module created doesn't get populated with the data from my OpenAPI schema YAML file even though it parses it and can render the docs. Note I did a quick test with the Ruby on Rails committee gem to confirm if this was something wrong with my schema that maybe OpenApiSpex didn't like and it worked fine without any issues.

If someone could steer me in the right direction I'd appreciate it.

mengelseatz commented 7 months ago

So as to not confuse this with my specific API I moved to a new phoenix application and am using the OpenAPI 3 petstore.yaml and still running into similar issues. The documentation doesn't describe this use case where the operation that is used in the controller comes from an already parsed API schema. I'm trying things like this but it's not working operation(:create, PetstoreApiWeb.ApiSpec.spec().paths()["/pets"].post)