civisanalytics / swagger-diff

Utility for comparing two Swagger specifications.
BSD 3-Clause "New" or "Revised" License
264 stars 32 forks source link

Show differences for similar Swagger Docs #43

Closed SelAnt closed 6 years ago

SelAnt commented 7 years ago

Hi,

I have 2 Swagger docs. One was created manually, one - automatically. Swagger-diff shows a lot of discrepancies between documents. However in Swagger Editor both documents looks similar. Please see swagger-diff output and documents below.

Thank you in advance for help,

Swagger-diff output:

- incompatible response attributes
  - get /internal/v0/orgs/{}/facs
    - missing attribute from 200 response: data[]/orgId (in: body, type: integer)
    - missing attribute from 200 response: data[]/facId (in: body, type: integer)
    - missing attribute from 200 response: data[]/facilityName (in: body, type: string)
    - missing attribute from 200 response: data[]/country (in: body, type: string)
    - missing attribute from 200 response: data[]/addressLine1 (in: body, type: string)
    - missing attribute from 200 response: data[]/addressLine2 (in: body, type: string)
    - missing attribute from 200 response: data[]/postalCode (in: body, type: string)
    - missing attribute from 200 response: data[]/phone (in: body, type: string)
    - missing attribute from 200 response: data[]/city (in: body, type: string)
    - missing attribute from 200 response: data[]/state (in: body, type: string)
    - missing attribute from 200 response: data[]/fax (in: body, type: string)
    - missing attribute from 200 response: data[]/emailAddress (in: body, type: string)
    - missing attribute from 200 response: data[]/inactiveDate (in: body, type: string)
    - missing attribute from 200 response: data[]/bedCount (in: body, type: integer)
    - missing attribute from 200 response: data[]/lineOfBusiness/shortDesc (in: body, type: string)
    - missing attribute from 200 response: data[]/lineOfBusiness/longDesc (in: body, type: string)
    - missing attribute from 200 response: data[]/healthType (in: body, type: string)
    - missing attribute from 200 response: data[]/facilityCode (in: body, type: string)
    - missing attribute from 200 response: data[]/billingStyleCountry (in: body, type: string)
    - missing attribute from 200 response: data[]/timeZone (in: body, type: string)
    - missing attribute from 200 response: data[]/active (in: body, type: boolean)
    - missing attribute from 200 response: data[]/headOffice (in: body, type: boolean)
    - missing attribute from 200 response: paging/page (in: body, type: integer)
    - missing attribute from 200 response: paging/pageSize (in: body, type: integer)
    - missing attribute from 200 response: paging/hasMore (in: body, type: boolean)

---------------------Document 1----------------------------------

{
    "swagger": "2.0",
    "info": {
        "version": "1.0.0",
        "title": "API",
        "contact": {
            "name": "Dev Relations",
            "url": "https://developer.XXX.com",
            "email": "devrelations@XXX.com"
        }
    },
    "host": "connect.XXX.com",
    "basePath": "/api",
    "schemes": [
        "https"
    ],
    "consumes": [
        "application/json"
    ],
    "produces": [
        "application/json"
    ],
    "paths": {
        "/internal/v0/orgs/{orgId}/facs": {
            "get": {
                "tags": [
                    "Facilities"
                ],
                "summary": "List of facilities within an organization.",
                "description": "",
                "operationId": "Facility List (Internal)",
                "produces": [
                    "application/json"
                ],
                "parameters": [
                    {
                        "name": "healthType",
                        "in": "query",
                        "description": "If provided, return only facilities with a matching health type.",
                        "required": false,
                        "type": "string",
                        "x-example": "false"
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "The limit used in the execution of the query; default is 50.",
                        "required": false,
                        "type": "integer",
                        "x-example": "false"
                    },
                    {
                        "name": "offset",
                        "in": "query",
                        "description": "The offset used in the execution of the query; default is 0.",
                        "required": false,
                        "type": "integer",
                        "x-example": "false"
                    },
                    {
                        "name": "orgId",
                        "in": "path",
                        "description": "XXX's unique identifier for the organization.",
                        "required": true,
                        "type": "integer",
                        "x-example": 10000003
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/FacilityList"
                        }
                    },
                    "400": {
                        "description": "Bad Request"
                    },
                    "401": {
                        "description": "Unauthorized"
                    },
                    "500": {
                        "description": "Internal Server Error"
                    }
                },
                "x-authorization": {
                    "name": "2-legged",
                    "description": "This API requires a 2-legged OAuth access token."
                }
            }
        }
    },
    "definitions": {
        "PagingResponseByPage": {
            "type": "object",
            "properties": {
                "page": {
                    "type": "integer",
                    "format": "int32",
                    "description": "Represents the current page number for which the records are returned."
                },
                "pageSize": {
                    "type": "integer",
                    "format": "int32",
                    "description": "Represents the number of records returned in the response."
                },
                "hasMore": {
                    "type": "boolean",
                    "description": "Identifies if there are further records in the list. Possible responses are 'true' or 'false'.",
                    "default": false
                }
            },
            "example": {
                "page": 1,
                "pageSize": 50,
                "hasMore": false
            }
        },
        "FacilityList": {
            "type": "object",
            "properties": {
                "data": {
                    "type": "array",
                    "description": "List of facilities",
                    "items": {
                        "$ref": "#/definitions/Facility"
                    }
                },
                "paging": {
                    "$ref": "#/definitions/PagingResponseByPage"
                }
            },
        },
        "FacilityLineOfBusiness": {
            "type": "object",
            "properties": {
                "shortDesc": {
                    "type": "string",
                    "description": "A short description of the facility's line of business"
                },
                "longDesc": {
                    "type": "string",
                    "description": "A long description of the facility's line of business"
                }
            },
            "example": {
                "shortDesc": "Short Description",
                "longDesc": "Long Description"
            }
        },
        "Facility": {
            "type": "object",
            "required": [
                "addressLine1",
                "addressLine2",
                "city",
                "emailAddress",
                "facilityName",
                "fax",
                "healthType",
                "phone",
                "postalCode",
                "state"
            ],
            "properties": {
                "orgId": {
                    "type": "integer",
                    "format": "int32",
                    "description": "XXX's unique identifier for the organization. "
                },
                "facId": {
                    "type": "integer",
                    "format": "int32",
                    "description": "XXX's unique identifier for a facility within the organization. "
                },
                "facilityName": {
                    "type": "string",
                    "description": "The name of the facility. ",
                    "minLength": 1,
                    "maxLength": 2147483647
                },
                "country": {
                    "type": "string",
                    "description": "The ISO 3166 3 letter code for the country the facility resides in. (Example: USA for United States and CAN for Canada). ",
                    "enum": [
                        "USA",
                        "CAN"
                    ]
                },
                "addressLine1": {
                    "type": "string",
                    "description": "The address of the facility. ",
                    "minLength": 1,
                    "maxLength": 2147483647
                },
                "addressLine2": {
                    "type": "string",
                    "description": "Additional address information for the facility. ",
                    "minLength": 1,
                    "maxLength": 2147483647
                },
                "postalCode": {
                    "type": "string",
                    "description": "The postal/zip code of the facility. ",
                    "minLength": 1,
                    "maxLength": 2147483647
                },
                "phone": {
                    "type": "string",
                    "description": "The phone number of the facility, if available. ",
                    "minLength": 1,
                    "maxLength": 2147483647
                },
                "city": {
                    "type": "string",
                    "description": "The city of the facility. ",
                    "minLength": 1,
                    "maxLength": 2147483647
                },
                "state": {
                    "type": "string",
                    "description": "The state/province/territory of the facility. ",
                    "minLength": 1,
                    "maxLength": 2147483647
                },
                "fax": {
                    "type": "string",
                    "description": "The fax number of the facility, if available. ",
                    "minLength": 1,
                    "maxLength": 2147483647
                },
                "emailAddress": {
                    "type": "string",
                    "description": "The contact email address of the facility, if available. ",
                    "minLength": 1,
                    "maxLength": 2147483647
                },
                "inactiveDate": {
                    "type": "string",
                    "format": "date",
                    "description": "Represents the date at which a facility became inactive. The date format is YYYY-MM-DD. "
                },
                "bedCount": {
                    "type": "integer",
                    "format": "int32",
                    "description": "The number of beds the facility offers, if available. "
                },
                "lineOfBusiness": {
                    "$ref": "#/definitions/FacilityLineOfBusiness"
                },
                "healthType": {
                    "type": "string",
                    "description": "The health type of the facility (Example: XXX).",
                    "minLength": 1,
                    "maxLength": 2147483647
                },
                "facilityCode": {
                    "type": "string",
                    "description": "Another unique identifier for the facility. Facility code can be configured by an organization in the XXX application."
                },
                "billingStyleCountry": {
                    "type": "string",
                    "description": "The ISO 3166 3 letter code for the country whose billing style the facility uses. (Example: USA for United States and CAN for Canada). ",
                    "enum": [
                        "USA",
                        "CAN"
                    ]
                },
                "timeZone": {
                    "type": "string",
                    "description": "Represents the timezone the facility operates in."
                },
                "active": {
                    "type": "boolean",
                    "description": "Represents whether if the facility is active or inactive. Possible responses are 'true' or 'false'. ",
                    "default": false
                },
                "headOffice": {
                    "type": "boolean",
                    "description": "Represents whether if the facility is the head office.  Some organizations have a concept of a 'head office' facility which is usually for administrative purposes only and this facility would not contain actual patients. Possible responses are 'true' or 'false'. ",
                    "default": false
                }
            }
        }
    }
}

----------------------Document 2---------------------------------

{
    "swagger": "2.0",
    "info": {
        "description": "API Documentation",
        "version": "1.0.0",
        "title": "API Documentation",
        "termsOfService": "http://XXX.com",
        "contact": {
            "url": "http://XXX.com",
            "name": "XXX",
            "email": "XXX@XXX.com"
        }
    },
    "host": "apiqa.XXX.com",
    "basePath": "/api",
    "schemes": [
        "http",
        "https"
    ],
    "tags": [
        {
            "name": "Others",
            "description": "Others"
        }
    ],
    "paths": {
        "/internal/v0/orgs/{orgId}/facs": {
            "get": {
                "tags": [
                    "Others"
                ],
                "summary": "",
                "description": "",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "parameters": [
                    {
                        "name": "orgId",
                        "in": "path",
                        "required": true,
                        "type": "integer"
                    },
                    {
                        "name": "healthType",
                        "in": "query",
                        "required": false,
                        "type": "string"
                    },
                    {
                        "name": "includeHeadOffice",
                        "in": "query",
                        "required": false,
                        "type": "boolean"
                    },
                    {
                        "name": "includeInactive",
                        "in": "query",
                        "required": false,
                        "type": "boolean"
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "type": "integer"
                    },
                    {
                        "name": "offset",
                        "in": "query",
                        "required": false,
                        "type": "integer"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "schema": {
                            "properties": {
                                "data": {
                                    "type": "array",
                                    "items": {
                                        "properties": {
                                            "active": {
                                                "type": "boolean"
                                            },
                                            "addressLine1": {
                                                "type": "string",
                                                "description": "Address Line 1 (max length 35)"
                                            },
                                            "addressLine2": {
                                                "type": "string",
                                                "description": "Address Line 2 (max length 35)"
                                            },
                                            "bedCount": {
                                                "type": "integer",
                                                "description": "Number of beds"
                                            },
                                            "billingStyleCountry": {
                                                "default": "USA",
                                                "type": "string",
                                                "description": "Billing country Code",
                                                "enum": [
                                                    "USA",
                                                    "CAN"
                                                ]
                                            },
                                            "city": {
                                                "type": "string",
                                                "description": "City Name (max length 50)"
                                            },
                                            "clinicalConfiguration": {
                                                "properties": {
                                                    "unitOfMeasure": {
                                                        "properties": {
                                                            "bloodPressure": {
                                                                "type": "string"
                                                            },
                                                            "bloodSugar": {
                                                                "type": "string"
                                                            },
                                                            "heartRate": {
                                                                "type": "string"
                                                            },
                                                            "height": {
                                                                "type": "string"
                                                            },
                                                            "oxygenSaturation": {
                                                                "type": "string"
                                                            },
                                                            "respirations": {
                                                                "type": "string"
                                                            },
                                                            "temperature": {
                                                                "type": "string"
                                                            },
                                                            "weight": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    },
                                                    "weightScaleTypes": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "string"
                                                        }
                                                    }
                                                }
                                            },
                                            "country": {
                                                "default": "USA",
                                                "type": "string",
                                                "description": "Country Code",
                                                "enum": [
                                                    "USA",
                                                    "CAN"
                                                ]
                                            },
                                            "emailAddress": {
                                                "type": "string",
                                                "description": "Primary email (max length 75)"
                                            },
                                            "facId": {
                                                "default": 1,
                                                "type": "integer",
                                                "description": "Facility code"
                                            },
                                            "facilityCode": {
                                                "type": "string",
                                                "description": "Code of facility"
                                            },
                                            "facilityName": {
                                                "type": "string",
                                                "description": "Facility Name (max length 75)"
                                            },
                                            "fax": {
                                                "type": "string",
                                                "description": "Fax number (max length 35)"
                                            },
                                            "generalConfiguration": {
                                                "properties": {
                                                    "assessment": {
                                                        "properties": {
                                                            "electronicSignature": {
                                                                "properties": {
                                                                    "description": {
                                                                        "type": "string"
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            },
                                            "headOffice": {
                                                "type": "boolean"
                                            },
                                            "healthType": {
                                                "type": "string",
                                                "description": "Type of facility, possible values: SNF, ILF,ALF (max length 10)"
                                            },
                                            "inactiveDate": {
                                                "type": "string",
                                                "format": "date",
                                                "description": "Inactivation date"
                                            },
                                            "lineOfBusiness": {
                                                "properties": {
                                                    "longDesc": {
                                                        "type": "string"
                                                    },
                                                    "shortDesc": {
                                                        "type": "string"
                                                    }
                                                },
                                                "description": "Line of Business"
                                            },
                                            "orgId": {
                                                "default": 1401,
                                                "type": "integer",
                                                "description": "Organization code"
                                            },
                                            "phone": {
                                                "type": "string",
                                                "description": "Main phone (max length 35)"
                                            },
                                            "postalCode": {
                                                "type": "string",
                                                "description": "Postal/ZIP code (max length 15)"
                                            },
                                            "reportFilters": {
                                                "type": "array",
                                                "items": {
                                                    "properties": {
                                                        "id": {
                                                            "type": "integer"
                                                        },
                                                        "reportFilterItems": {
                                                            "type": "array",
                                                            "items": {
                                                                "properties": {
                                                                    "id": {
                                                                        "type": "integer"
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            },
                                            "state": {
                                                "type": "string",
                                                "description": "State code (max length 3)"
                                            },
                                            "timeZone": {
                                                "default": "America/New_York",
                                                "type": "string",
                                                "description": "Time Zone Code from IANA time zone database (https://www.iana.org/time-zones). Day Light Time support depends on Time Zone, please refer to IANA time zone database. Supported values: Europe/London, UTC, America/Halifax, America/Barbados, America/New_York, EST, America/Chicago, America/Regina, America/Denver, America/Phoenix, America/Los_Angeles, America/Metlakatla, America/Anchorage, Pacific/Gambier, US/Aleutian, Pacific/Honolulu, Asia/Hong_Kong."
                                            }
                                        }
                                    }
                                },
                                "paging": {
                                    "properties": {
                                        "hasMore": {
                                            "type": "boolean"
                                        },
                                        "limit": {
                                            "type": "integer"
                                        },
                                        "offset": {
                                            "type": "integer"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request"
                    },
                    "401": {
                        "description": "Unauthorized"
                    },
                    "404": {
                        "description": "Not Found"
                    },
                    "500": {
                        "description": "Internal Server Error"
                    }
                }
            }
        }
    },
    "securityDefinitions": {},
    "definitions": {}
}
jeffreyc commented 7 years ago

Thank you for your bug report, and for the example specifications! Looking at your specifications, the difference appears to be that the first specification uses a $ref in the response, while the second specification spells out the response via a properties hash. Both specification appear valid, so it looks like this is a bug with Swagger::Diff.

I don't think this will be too hard to fix, as this is already supported by request parameters. In the meantime, you should be able to work around this by using a $ref in your response instead of spelling out the full response via a properties hash.

jeffreyc commented 6 years ago

I just released Swagger::Diff 1.1.2, a bugfix release addressing this issue. If you encounter any other problems, please let us know.