Add support for matching swagger content media type when validating pact request and response bodies

Issue #82 new
Mika Kytöjoki created an issue

If I have json type and vendor specific json type in same response on swagger spec file:

  "paths": {
    "/test": {
      "get": {
        "tags": [
          "test"
        ],
        "summary": "Get sample",
        "description": "Gets samples",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Test1"
                }
              },
              "application/vnd.mycompany.myapp.v2+json": {
                "schema": {
                  "$ref": "#/components/schemas/Test2"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Test1": {
        "type": "object",
        "description": "Test Object"
        "properties": {
          "id": {
            "type": "string",
            "description": "Identifier"
          }
        }
      },
      "Test2": {
        "type": "array",
        "items": {
          "type": "object",
          "description": "Test Array"
          "properties": {
            "id": {
              "type": "string",
              "description": "Another Identifier"
            }
          }
        }
      },

And if I try to validate that with this pact interaction:

"interactions": [
    {
      "description": "a GET request for test",
      "providerState": "provider can send test",
      "request": {
        "method": "GET",
        "path": "/test",
        "headers": {
          "Accept": "application/vnd.mycompany.myapp.v2+json"
        }
      },
      "response": {
        "status": 200,
        "headers": {
          "Content-Type": "application/vnd.mycompany.myapp.v2+json"
        },
        "body": [
          {
            "id": "da48fada-7d9d-47e1-9805-ce5270d90380"
          }
        ]
      }
    }
  ],

I’ll have this error:

{ warnings: [],
  errors:
   [ { code: 'response.body.incompatible',
       message:
        'Response body is incompatible with the response body schema in the spec file: should be object',
       mockDetails:
        { interactionDescription: 'a GET request for test',
          interactionState: 'provider can send test',
          location: '[root].interactions[0].response.body',
          mockFile: './pact/pacts/test.json',
          value: [ [Object] ] },
       source: 'spec-mock-validation',
       specDetails:
        { location:
           '[root].paths./test.get.responses.200.content.application/json.schema.type',
          pathMethod: 'get',
          pathName: '/test',
          specFile: './pact/pacts/spec.json',
          value: 'object' },
       type: 'error' } ] }

I cannot validate anything with that vendor specific type because schema for application/json type is always selected. I assume because of these lines: https://bitbucket.org/atlassian/swagger-mock-validator/src/255ba7c9d3dc353bf5d2bd5dcb246b8815ac49e3/dist/swagger-mock-validator/spec-parser/openapi3/openapi3-parser/get-content-schema.js#lines-5,6

Any suggestions to solve this kind of situations?

Comments (3)

  1. Ben Sayers

    @Mika Kytöjoki thanks for raising this. As you have discovered, swagger-mock-validator does not currently support matching the request to the closest media type defined in the swagger file. I’ll change this issue to a feature request instead of a bug as the current behaviour is an intentional design decision. Matching the request to the correct media type has some complexity involved as you can define media type ranges in swagger and the request should match the most specific key. For example, if a swagger contains both application/json and application/*, then a request containing Accept: application/json; charset=utf-8 should match application/json. Since we didn’t need this feature in our use case we decided not spend the engineering effort to add it.

    You are welcome to try and contribute a PR, you might draw some inspiration from the way the Accept and Content-Type headers from the pact file are validated against the produces and consumes from the swagger file - https://bitbucket.org/atlassian/swagger-mock-validator/src/master/lib/swagger-mock-validator/validate-spec-and-mock/content-negotiation.ts

  2. Log in to comment