openapi-library / OpenAPIValidators

Use Jest or Chai to assert that HTTP responses satisfy an OpenAPI spec
MIT License
189 stars 35 forks source link

Invalid OpenAPI spec #268

Open ghost opened 2 years ago

ghost commented 2 years ago

Are you using jest or chai? Jest

Are you using OpenAPI 2, 3.0.X, or 3.1.0? Openapi 3.0

Describe the bug clearly I'm using swaggerJSDoc and swagger-ui as interface to access the documentation in my express server. That works fine. Here's how I generate the documentation from all the .yaml file in my project:

const swaggerJsdoc = require("swagger-jsdoc");

const options = {
    definition: {
        openapi: "3.0.0",
        info: {
            title: "Public API",
            version: "1.0.0",
        },
    },
    apis: ["./src/**/docs/*.yaml"],
    explorer: true,
};

const openapiSpecification = swaggerJsdoc(options);
console.log(JSON.stringify(openapiSpecification, null, 2));

export default openapiSpecification;

Now, the problem is that when I use jestOpenAPI for my tests it only works if I copy the console.log of openapiSpecification. If I import the file it doesn't.

So, if I run the script to generate the configuration and I copy the result of the console.log and I paste it directly in the test file:

const test = {
    "openapi": "3.0.0",
    "info": {
      "title": "Public API",
      "version": "1.0.0"
    },
    "paths": {
   ...}
}

jestOpenAPI(test)

Then the test work. But if I import the script instead of copying the output it doesn't:

const jestOpenAPI = require('jest-openapi').default;
const swaggerFile = require('../../docs/swaggerConfig')

jestOpenAPI(swaggerFile)

This returns the following error:

  ● Test suite failed to run

    Invalid OpenAPI spec: [
      {
        instancePath: '',
        schemaPath: '#/required',
        keyword: 'required',
        params: { missingProperty: 'swagger' },
        message: "must have required property 'swagger'"
      },
      {
        instancePath: '',
        schemaPath: '#/required',
        keyword: 'required',
        params: { missingProperty: 'info' },
        message: "must have required property 'info'"
      },
      {
        instancePath: '',
        schemaPath: '#/required',
        keyword: 'required',
        params: { missingProperty: 'paths' },
        message: "must have required property 'paths'"
      },
      {
        instancePath: '',
        schemaPath: '#/additionalProperties',
        keyword: 'additionalProperties',
        params: { additionalProperty: 'default' },
        message: 'must NOT have additional properties'
      }
    ]

The weird thing is that the file is exactly the same but if I import the file that generates the config I get the invalid specification error, if I copy the output of that file in the test file then it runs fine. How can I fix this?

rwalle61 commented 2 years ago

Hi @Stedelie , thanks for raising this!

If I understand you correctly, jestOpenAPI(swaggerJsdoc(options)) throws the error, but jestOpenAPI({ openapi: '3.0.0', info: ... }) doesn't.

I haven't used swagger-jsdoc before. What is the value of swaggerJsdoc(options).swagger? If it's truthy, then jestOpenAPI will treat the doc as an an OpenAPI 2 spec, not OpenAPI 3.

By the way, swagger-jsdoc's docs says:

The resulting openapiSpecification will be a swagger tools-compatible (and validated) specification.

Is openapiSpecification a normal JavaScript object, or does it have extra helper methods and properties? jestOpenAPI expects to receive a normal JS object reflecting the JSON structure of the document. I think that's why when you paste the output of console.log(JSON.stringify(swaggerJsdoc(options))), jestOpenAPI behaves as you expect

Let me know if that resolves your problem 🙂