openapi-diff
Advanced tools
Comparing version 0.2.0 to 0.3.0
@@ -0,1 +1,11 @@ | ||
<a name="0.3.0"></a> | ||
# [0.3.0](https://bitbucket.org/atlassian/openapi-diff/compare/0.2.0...v0.3.0) (2017-07-26) | ||
### Features | ||
* support for editions to the openapi / swagger property ([a8c2fc7](https://bitbucket.org/atlassian/openapi-diff/commits/a8c2fc7)) | ||
<a name="0.2.0"></a> | ||
@@ -2,0 +12,0 @@ # [0.2.0](https://bitbucket.org/atlassian/openapi-diff/compare/0.1.0...v0.2.0) (2017-07-19) |
@@ -12,6 +12,6 @@ "use strict"; | ||
run: (oldSpecPath, newSpecPath) => { | ||
const whenOldSpecPath = json_loader_1.default.load(oldSpecPath, file_system_1.default, http_client_1.default); | ||
const whenParsedOldSpec = whenOldSpecPath.then(spec_parser_1.default.parse); | ||
const whenNewSpecPath = json_loader_1.default.load(newSpecPath, file_system_1.default, http_client_1.default); | ||
const whenParsedNewSpec = whenNewSpecPath.then(spec_parser_1.default.parse); | ||
const whenOldSpec = json_loader_1.default.load(oldSpecPath, file_system_1.default, http_client_1.default); | ||
const whenParsedOldSpec = whenOldSpec.then(spec_parser_1.default.parse); | ||
const whenNewSpec = json_loader_1.default.load(newSpecPath, file_system_1.default, http_client_1.default); | ||
const whenParsedNewSpec = whenNewSpec.then(spec_parser_1.default.parse); | ||
const whenDiff = q.all([whenParsedOldSpec, whenParsedNewSpec]).spread(spec_differ_1.default.diff); | ||
@@ -18,0 +18,0 @@ const whenResults = whenDiff.then(result_reporter_1.default.build); |
@@ -13,3 +13,3 @@ "use strict"; | ||
for (const entry of result.nonBreakingChanges) { | ||
changeList.push(`Non-breaking: the path [${entry.path.join('/')}] ` | ||
changeList.push(`Non-breaking: the path [${entry.printablePath.join('/')}] ` | ||
+ `was modified from \'${entry.lhs}\' to \'${entry.rhs}\'`); | ||
@@ -19,3 +19,3 @@ } | ||
for (const entry of result.unclassifiedChanges) { | ||
changeList.push(`Unclassified: the path [${entry.path.join('/')}] ` | ||
changeList.push(`Unclassified: the path [${entry.printablePath.join('/')}] ` | ||
+ `was modified from \'${entry.lhs}\' to \'${entry.rhs}\'`); | ||
@@ -22,0 +22,0 @@ } |
@@ -6,6 +6,7 @@ "use strict"; | ||
const utils_1 = require("./utils"); | ||
const processDiff = (rawDiff) => { | ||
const processDiff = (parsedSpec, rawDiff) => { | ||
const processedDiff = []; | ||
if (hasChanges(rawDiff)) { | ||
if (rawDiff) { | ||
for (const entry of rawDiff) { | ||
const taxonomy = findChangeTaxonomy(entry); | ||
const processedEntry = { | ||
@@ -17,5 +18,6 @@ index: getChangeNullableProperties(entry.index), | ||
path: entry.path, | ||
printablePath: utils_1.default.findOriginalPath(parsedSpec, entry.path), | ||
rhs: entry.rhs, | ||
taxonomy: findChangeTaxonomy(entry), | ||
type: findChangeType(entry) | ||
taxonomy, | ||
type: findChangeType(taxonomy) | ||
}; | ||
@@ -33,13 +35,25 @@ processedDiff.push(processedEntry); | ||
}; | ||
const isOpenapiProperty = (entry) => { | ||
return entry.path[0] === 'openapi'; | ||
}; | ||
const isInfoChange = (entry) => { | ||
return isEdit(entry) && isInfoObject(entry) && !utils_1.default.isXProperty(entry.path[1]); | ||
}; | ||
const hasChanges = (rawDiff) => { | ||
return !_.isUndefined(rawDiff); | ||
const isOpenapiChange = (entry) => { | ||
return isEdit(entry) && isOpenapiProperty(entry); | ||
}; | ||
const findChangeTaxonomy = (change) => { | ||
return isInfoChange(change) ? 'info.object.edit' : 'zzz.unclassified.change'; | ||
if (isInfoChange(change)) { | ||
return 'info.object.edit'; | ||
} | ||
else if (isOpenapiChange(change)) { | ||
return 'openapi.property.edit'; | ||
} | ||
else { | ||
return 'unclassified.change'; | ||
} | ||
}; | ||
const findChangeType = (change) => { | ||
return isInfoChange(change) ? 'non-breaking' : 'unclassified'; | ||
const findChangeType = (taxonomy) => { | ||
const isNonBreakingChange = taxonomy === 'info.object.edit' || taxonomy === 'openapi.property.edit'; | ||
return isNonBreakingChange ? 'non-breaking' : 'unclassified'; | ||
}; | ||
@@ -58,5 +72,5 @@ const getChangeNullableProperties = (changeProperty) => { | ||
exports.default = { | ||
diff: (oldSpec, newSpec) => { | ||
const rawDiff = deepDiff.diff(oldSpec, newSpec); | ||
const processedDiff = processDiff(rawDiff); | ||
diff: (oldParsedSpec, newParsedSpec) => { | ||
const rawDiff = deepDiff.diff(oldParsedSpec, newParsedSpec); | ||
const processedDiff = processDiff(oldParsedSpec, rawDiff); | ||
const resultingDiff = sortProcessedDiff(processedDiff); | ||
@@ -63,0 +77,0 @@ return resultingDiff; |
@@ -8,2 +8,9 @@ "use strict"; | ||
}; | ||
const parseOpenApiProperty = (spec) => { | ||
const parsedOpenApiProperty = { | ||
originalPath: spec.swagger ? ['swagger'] : ['openapi'], | ||
parsedValue: spec.swagger ? spec.swagger : spec.openapi | ||
}; | ||
return parsedOpenApiProperty; | ||
}; | ||
const parseTopLevelXProperties = (spec) => { | ||
@@ -21,3 +28,4 @@ const xPropertiesArray = []; | ||
const parsedSpec = { | ||
info: parseInfoObject(spec) | ||
info: parseInfoObject(spec), | ||
openapi: parseOpenApiProperty(spec) | ||
}; | ||
@@ -24,0 +32,0 @@ for (const entry of parseTopLevelXProperties(spec)) { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const _ = require("lodash"); | ||
exports.default = { | ||
findOriginalPath: (parsedSpec, parsedPath) => { | ||
const parsedPathCopy = _.cloneDeep(parsedPath); | ||
if (_.last(parsedPathCopy) === 'parsedValue') { | ||
parsedPathCopy.pop(); | ||
} | ||
const parsedPathString = parsedPathCopy.join('.'); | ||
return _.has(parsedSpec, [parsedPathString, 'originalPath']) ? | ||
parsedSpec[parsedPathString].originalPath : | ||
parsedPath; | ||
}, | ||
isXProperty: (propertyPath) => { | ||
@@ -5,0 +16,0 @@ return propertyPath.startsWith('x-'); |
@@ -111,3 +111,3 @@ 'use strict'; | ||
gulp.task('lint-commits', (callback) => { | ||
return exec('./node_modules/.bin/conventional-changelog-lint --from \"b462f37\"', (err, stdout, stderr) => { | ||
return exec('./node_modules/.bin/conventional-changelog-lint --from \"5f39d3e\"', (err, stdout, stderr) => { | ||
console.log(stdout); | ||
@@ -114,0 +114,0 @@ console.log(stderr); |
@@ -1,4 +0,2 @@ | ||
import { | ||
OpenAPIDiff | ||
} from './openapi-diff/types'; | ||
import { OpenAPIDiff } from './openapi-diff/types'; | ||
@@ -16,7 +14,7 @@ import * as q from 'q'; | ||
run: (oldSpecPath, newSpecPath) => { | ||
const whenOldSpecPath = jsonLoader.load(oldSpecPath, fileSystem, httpClient); | ||
const whenParsedOldSpec = whenOldSpecPath.then(specParser.parse); | ||
const whenOldSpec = jsonLoader.load(oldSpecPath, fileSystem, httpClient); | ||
const whenParsedOldSpec = whenOldSpec.then(specParser.parse); | ||
const whenNewSpecPath = jsonLoader.load(newSpecPath, fileSystem, httpClient); | ||
const whenParsedNewSpec = whenNewSpecPath.then(specParser.parse); | ||
const whenNewSpec = jsonLoader.load(newSpecPath, fileSystem, httpClient); | ||
const whenParsedNewSpec = whenNewSpec.then(specParser.parse); | ||
@@ -23,0 +21,0 @@ const whenDiff = q.all([whenParsedOldSpec, whenParsedNewSpec]).spread(specDiffer.diff); |
@@ -9,3 +9,4 @@ import * as q from 'q'; | ||
JsonLoaderFunction, | ||
OpenAPISpec | ||
OpenAPI3Spec, | ||
Swagger2Spec | ||
} from './types'; | ||
@@ -18,7 +19,7 @@ | ||
const parseAsJson = (location: string, content: string): q.Promise<OpenAPISpec> => { | ||
const parseAsJson = (location: string, content: string): q.Promise<Swagger2Spec | OpenAPI3Spec> => { | ||
try { | ||
return q(JSON.parse(content)); | ||
} catch (error) { | ||
return q.reject<OpenAPISpec>(new VError(error, `ERROR: unable to parse ${location} as a JSON file`)); | ||
return q.reject<OpenAPI3Spec>(new VError(error, `ERROR: unable to parse ${location} as a JSON file`)); | ||
} | ||
@@ -25,0 +26,0 @@ }; |
@@ -15,3 +15,3 @@ import * as _ from 'lodash'; | ||
for (const entry of result.nonBreakingChanges) { | ||
changeList.push(`Non-breaking: the path [${entry.path.join('/')}] ` | ||
changeList.push(`Non-breaking: the path [${entry.printablePath.join('/')}] ` | ||
+ `was modified from \'${entry.lhs}\' to \'${entry.rhs}\'`); | ||
@@ -22,3 +22,3 @@ } | ||
for (const entry of result.unclassifiedChanges) { | ||
changeList.push(`Unclassified: the path [${entry.path.join('/')}] ` | ||
changeList.push(`Unclassified: the path [${entry.printablePath.join('/')}] ` | ||
+ `was modified from \'${entry.lhs}\' to \'${entry.rhs}\'`); | ||
@@ -25,0 +25,0 @@ } |
@@ -9,15 +9,18 @@ import * as deepDiff from 'deep-diff'; | ||
Diff, | ||
DiffChange, DiffChangeTaxonomy, | ||
DiffChange, | ||
DiffChangeTaxonomy, | ||
DiffChangeType, | ||
OpenAPISpec, | ||
ParsedSpec, | ||
ResultDiff | ||
} from './types'; | ||
const processDiff = (rawDiff: IDiff[]): DiffChange[] => { | ||
const processDiff = (parsedSpec: ParsedSpec, rawDiff: IDiff[] | undefined): DiffChange[] => { | ||
const processedDiff: DiffChange[] = []; | ||
if (hasChanges(rawDiff)) { | ||
if (rawDiff) { | ||
for (const entry of rawDiff) { | ||
const taxonomy = findChangeTaxonomy(entry); | ||
const processedEntry: DiffChange = { | ||
@@ -29,5 +32,6 @@ index: getChangeNullableProperties(entry.index), | ||
path: entry.path, | ||
printablePath: utils.findOriginalPath(parsedSpec, entry.path), | ||
rhs: entry.rhs, | ||
taxonomy: findChangeTaxonomy(entry), | ||
type: findChangeType(entry) | ||
taxonomy, | ||
type: findChangeType(taxonomy) | ||
}; | ||
@@ -50,2 +54,6 @@ | ||
const isOpenapiProperty = (entry: IDiff): boolean => { | ||
return entry.path[0] === 'openapi'; | ||
}; | ||
const isInfoChange = (entry: IDiff): boolean => { | ||
@@ -55,12 +63,19 @@ return isEdit(entry) && isInfoObject(entry) && !utils.isXProperty(entry.path[1]); | ||
const hasChanges = (rawDiff: IDiff[]): boolean => { | ||
return !_.isUndefined(rawDiff); | ||
const isOpenapiChange = (entry: IDiff): boolean => { | ||
return isEdit(entry) && isOpenapiProperty(entry); | ||
}; | ||
const findChangeTaxonomy = (change: IDiff): DiffChangeTaxonomy => { | ||
return isInfoChange(change) ? 'info.object.edit' : 'zzz.unclassified.change'; | ||
if (isInfoChange(change)) { | ||
return 'info.object.edit'; | ||
} else if (isOpenapiChange (change)) { | ||
return 'openapi.property.edit'; | ||
} else { | ||
return 'unclassified.change'; | ||
} | ||
}; | ||
const findChangeType = (change: IDiff): DiffChangeType => { | ||
return isInfoChange(change) ? 'non-breaking' : 'unclassified'; | ||
const findChangeType = (taxonomy: DiffChangeTaxonomy): DiffChangeType => { | ||
const isNonBreakingChange = taxonomy === 'info.object.edit' || taxonomy === 'openapi.property.edit'; | ||
return isNonBreakingChange ? 'non-breaking' : 'unclassified'; | ||
}; | ||
@@ -82,5 +97,6 @@ | ||
export default { | ||
diff: (oldSpec: OpenAPISpec, newSpec: OpenAPISpec): Diff => { | ||
const rawDiff: IDiff[] = deepDiff.diff(oldSpec, newSpec); | ||
const processedDiff: DiffChange[] = processDiff(rawDiff); | ||
diff: (oldParsedSpec: ParsedSpec, | ||
newParsedSpec: ParsedSpec): Diff => { | ||
const rawDiff: IDiff[] = deepDiff.diff(oldParsedSpec, newParsedSpec); | ||
const processedDiff: DiffChange[] = processDiff(oldParsedSpec, rawDiff); | ||
const resultingDiff = sortProcessedDiff(processedDiff); | ||
@@ -87,0 +103,0 @@ return resultingDiff; |
@@ -6,13 +6,23 @@ import * as _ from 'lodash'; | ||
import { | ||
OpenAPISpec, | ||
OpenAPI3Spec, | ||
ParsedInfoObject, | ||
ParsedOpenApiProperty, | ||
ParsedSpec, | ||
Swagger2Spec, | ||
XProperty | ||
} from './types'; | ||
const parseInfoObject = (spec: OpenAPISpec): ParsedInfoObject => { | ||
const parseInfoObject = (spec: Swagger2Spec | OpenAPI3Spec): ParsedInfoObject => { | ||
return spec.info; | ||
}; | ||
const parseTopLevelXProperties = (spec: OpenAPISpec): XProperty[] => { | ||
const parseOpenApiProperty = (spec: Swagger2Spec | OpenAPI3Spec): ParsedOpenApiProperty => { | ||
const parsedOpenApiProperty: ParsedOpenApiProperty = { | ||
originalPath: spec.swagger ? ['swagger'] : ['openapi'], | ||
parsedValue: spec.swagger ? spec.swagger : spec.openapi | ||
}; | ||
return parsedOpenApiProperty; | ||
}; | ||
const parseTopLevelXProperties = (spec: Swagger2Spec | OpenAPI3Spec): XProperty[] => { | ||
const xPropertiesArray: XProperty[] = []; | ||
@@ -28,11 +38,14 @@ _.forIn(spec, (value, key) => { | ||
export default { | ||
parse: (spec: OpenAPISpec): ParsedSpec => { | ||
parse: (spec: Swagger2Spec | OpenAPI3Spec): ParsedSpec => { | ||
const parsedSpec: ParsedSpec = { | ||
info: parseInfoObject(spec) | ||
info: parseInfoObject(spec), | ||
openapi: parseOpenApiProperty(spec) | ||
}; | ||
for (const entry of parseTopLevelXProperties(spec)) { | ||
_.set(parsedSpec, entry.key, entry.value); | ||
} | ||
return parsedSpec; | ||
} | ||
}; |
@@ -13,2 +13,3 @@ // Diff types | ||
export interface DiffChange extends IDiff { | ||
printablePath: string[]; | ||
taxonomy: DiffChangeTaxonomy; | ||
@@ -20,3 +21,4 @@ type: DiffChangeType; | ||
'info.object.edit' | | ||
'zzz.unclassified.change'; | ||
'openapi.property.edit' | | ||
'unclassified.change'; | ||
@@ -40,7 +42,14 @@ export type DiffChangeType = | ||
export interface OpenAPISpec { | ||
export interface Swagger2Spec { | ||
info: OpenAPISpecInfo; | ||
[xProperty: string]: any; | ||
swagger: string; | ||
} | ||
export interface OpenAPI3Spec { | ||
info: OpenAPISpecInfo; | ||
[xProperty: string]: any; | ||
openapi: string; | ||
} | ||
// Parsed Spec types | ||
@@ -69,4 +78,10 @@ | ||
export interface ParsedOpenApiProperty { | ||
originalPath: string[]; | ||
parsedValue: string; | ||
} | ||
export interface ParsedSpec { | ||
info: ParsedInfoObject; | ||
openapi: ParsedOpenApiProperty; | ||
[xProperty: string]: any; | ||
@@ -73,0 +88,0 @@ } |
@@ -0,2 +1,19 @@ | ||
import * as _ from 'lodash'; | ||
import {ParsedSpec} from './types'; | ||
export default { | ||
findOriginalPath: (parsedSpec: ParsedSpec, parsedPath: string[]): string[] => { | ||
const parsedPathCopy = _.cloneDeep(parsedPath); | ||
if (_.last(parsedPathCopy) === 'parsedValue') { | ||
parsedPathCopy.pop(); | ||
} | ||
const parsedPathString: string = parsedPathCopy.join('.'); | ||
return _.has(parsedSpec, [parsedPathString, 'originalPath']) ? | ||
parsedSpec[parsedPathString].originalPath : | ||
parsedPath; | ||
}, | ||
isXProperty: (propertyPath: string): boolean => { | ||
@@ -3,0 +20,0 @@ return propertyPath.startsWith('x-'); |
{ | ||
"name": "openapi-diff", | ||
"version": "0.2.0", | ||
"version": "0.3.0", | ||
"description": "A CLI tool to identify differences between Swagger/OpenAPI specs.", | ||
@@ -5,0 +5,0 @@ "bin": { |
@@ -28,6 +28,7 @@ # OpenAPI Diff | ||
- Specs in the local filesystem or as URLs | ||
- Editions to the Info object and ^x- properties at the top level of the spec. | ||
- Detects editions to the `swagger` / `openapi` object. | ||
- Detects editions to the `info` object and `^x- properties` at the top level of the spec. | ||
### Beta support | ||
- Additions and deletions to the Info object and ^x- properties at the top level of the spec. | ||
- Additions and deletions to the `info` object and `^x- properties` at the top level of the spec. | ||
@@ -34,0 +35,0 @@ ### Not supported |
@@ -16,3 +16,4 @@ { | ||
"version": "1.0.0" | ||
} | ||
}, | ||
"swagger": "2.0" | ||
} |
@@ -16,3 +16,4 @@ { | ||
"version": "1.0.0" | ||
} | ||
}, | ||
"swagger": "2.0" | ||
} |
@@ -18,3 +18,4 @@ { | ||
}, | ||
"x-generic-property": "some new content" | ||
"x-generic-property": "some new content", | ||
"swagger": "2.1" | ||
} |
@@ -18,3 +18,4 @@ { | ||
}, | ||
"x-generic-property": "some content" | ||
"x-generic-property": "some content", | ||
"swagger": "2.0" | ||
} |
@@ -1,1 +0,1035 @@ | ||
{"swagger":"2.0","info":{"description":"This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.","version":"1.0.1","title":"Swagger Petstore","termsOfService":"http://swagger.io/terms/","contact":{"email":"apiteam@swagger.io"},"license":{"name":"Apache 2.1","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}},"host":"petstore.swagger.io","basePath":"/v2","tags":[{"name":"pet","description":"Everything about your Pets","externalDocs":{"description":"Find out more","url":"http://swagger.io"}},{"name":"store","description":"Access to Petstore orders"},{"name":"user","description":"Operations about user","externalDocs":{"description":"Find out more about our store","url":"http://swagger.io"}}],"schemes":["http"],"paths":{"/pet":{"post":{"tags":["pet"],"summary":"Add a new pet to the store","description":"","operationId":"addPet","consumes":["application/json","application/xml"],"produces":["application/xml","application/json"],"parameters":[{"in":"body","name":"body","description":"Pet object that needs to be added to the store","required":true,"schema":{"$ref":"#/definitions/Pet"}}],"responses":{"405":{"description":"Invalid input"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]},"put":{"tags":["pet"],"summary":"Update an existing pet","description":"","operationId":"updatePet","consumes":["application/json","application/xml"],"produces":["application/xml","application/json"],"parameters":[{"in":"body","name":"body","description":"Pet object that needs to be added to the store","required":true,"schema":{"$ref":"#/definitions/Pet"}}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"},"405":{"description":"Validation exception"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/findByStatus":{"get":{"tags":["pet"],"summary":"Finds Pets by status","description":"Multiple status values can be provided with comma separated strings","operationId":"findPetsByStatus","produces":["application/xml","application/json"],"parameters":[{"name":"status","in":"query","description":"Status values that need to be considered for filter","required":true,"type":"array","items":{"type":"string","enum":["available","pending","sold"],"default":"available"},"collectionFormat":"multi"}],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/Pet"}}},"400":{"description":"Invalid status value"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/findByTags":{"get":{"tags":["pet"],"summary":"Finds Pets by tags","description":"Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.","operationId":"findPetsByTags","produces":["application/xml","application/json"],"parameters":[{"name":"tags","in":"query","description":"Tags to filter by","required":true,"type":"array","items":{"type":"string"},"collectionFormat":"multi"}],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/Pet"}}},"400":{"description":"Invalid tag value"}},"security":[{"petstore_auth":["write:pets","read:pets"]}],"deprecated":true}},"/pet/{petId}":{"get":{"tags":["pet"],"summary":"Find pet by ID","description":"Returns a single pet","operationId":"getPetById","produces":["application/xml","application/json"],"parameters":[{"name":"petId","in":"path","description":"ID of pet to return","required":true,"type":"integer","format":"int64"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Pet"}},"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"}},"security":[{"api_key":[]}]},"post":{"tags":["pet"],"summary":"Updates a pet in the store with form data","description":"","operationId":"updatePetWithForm","consumes":["application/x-www-form-urlencoded"],"produces":["application/xml","application/json"],"parameters":[{"name":"petId","in":"path","description":"ID of pet that needs to be updated","required":true,"type":"integer","format":"int64"},{"name":"name","in":"formData","description":"Updated name of the pet","required":false,"type":"string"},{"name":"status","in":"formData","description":"Updated status of the pet","required":false,"type":"string"}],"responses":{"405":{"description":"Invalid input"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]},"delete":{"tags":["pet"],"summary":"Deletes a pet","description":"","operationId":"deletePet","produces":["application/xml","application/json"],"parameters":[{"name":"api_key","in":"header","required":false,"type":"string"},{"name":"petId","in":"path","description":"Pet id to delete","required":true,"type":"integer","format":"int64"}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/{petId}/uploadImage":{"post":{"tags":["pet"],"summary":"uploads an image","description":"","operationId":"uploadFile","consumes":["multipart/form-data"],"produces":["application/json"],"parameters":[{"name":"petId","in":"path","description":"ID of pet to update","required":true,"type":"integer","format":"int64"},{"name":"additionalMetadata","in":"formData","description":"Additional data to pass to server","required":false,"type":"string"},{"name":"file","in":"formData","description":"file to upload","required":false,"type":"file"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/ApiResponse"}}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/store/inventory":{"get":{"tags":["store"],"summary":"Returns pet inventories by status","description":"Returns a map of status codes to quantities","operationId":"getInventory","produces":["application/json"],"parameters":[],"responses":{"200":{"description":"successful operation","schema":{"type":"object","additionalProperties":{"type":"integer","format":"int32"}}}},"security":[{"api_key":[]}]}},"/store/order":{"post":{"tags":["store"],"summary":"Place an order for a pet","description":"","operationId":"placeOrder","produces":["application/xml","application/json"],"parameters":[{"in":"body","name":"body","description":"order placed for purchasing the pet","required":true,"schema":{"$ref":"#/definitions/Order"}}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Order"}},"400":{"description":"Invalid Order"}}}},"/store/order/{orderId}":{"get":{"tags":["store"],"summary":"Find purchase order by ID","description":"For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions","operationId":"getOrderById","produces":["application/xml","application/json"],"parameters":[{"name":"orderId","in":"path","description":"ID of pet that needs to be fetched","required":true,"type":"integer","maximum":10.0,"minimum":1.0,"format":"int64"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Order"}},"400":{"description":"Invalid ID supplied"},"404":{"description":"Order not found"}}},"delete":{"tags":["store"],"summary":"Delete purchase order by ID","description":"For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors","operationId":"deleteOrder","produces":["application/xml","application/json"],"parameters":[{"name":"orderId","in":"path","description":"ID of the order that needs to be deleted","required":true,"type":"integer","minimum":1.0,"format":"int64"}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Order not found"}}}},"/user":{"post":{"tags":["user"],"summary":"Create user","description":"This can only be done by the logged in user.","operationId":"createUser","produces":["application/xml","application/json"],"parameters":[{"in":"body","name":"body","description":"Created user object","required":true,"schema":{"$ref":"#/definitions/User"}}],"responses":{"default":{"description":"successful operation"}}}},"/user/createWithArray":{"post":{"tags":["user"],"summary":"Creates list of users with given input array","description":"","operationId":"createUsersWithArrayInput","produces":["application/xml","application/json"],"parameters":[{"in":"body","name":"body","description":"List of user object","required":true,"schema":{"type":"array","items":{"$ref":"#/definitions/User"}}}],"responses":{"default":{"description":"successful operation"}}}},"/user/createWithList":{"post":{"tags":["user"],"summary":"Creates list of users with given input array","description":"","operationId":"createUsersWithListInput","produces":["application/xml","application/json"],"parameters":[{"in":"body","name":"body","description":"List of user object","required":true,"schema":{"type":"array","items":{"$ref":"#/definitions/User"}}}],"responses":{"default":{"description":"successful operation"}}}},"/user/login":{"get":{"tags":["user"],"summary":"Logs user into the system","description":"","operationId":"loginUser","produces":["application/xml","application/json"],"parameters":[{"name":"username","in":"query","description":"The user name for login","required":true,"type":"string"},{"name":"password","in":"query","description":"The password for login in clear text","required":true,"type":"string"}],"responses":{"200":{"description":"successful operation","schema":{"type":"string"},"headers":{"X-Rate-Limit":{"type":"integer","format":"int32","description":"calls per hour allowed by the user"},"X-Expires-After":{"type":"string","format":"date-time","description":"date in UTC when token expires"}}},"400":{"description":"Invalid username/password supplied"}}}},"/user/logout":{"get":{"tags":["user"],"summary":"Logs out current logged in user session","description":"","operationId":"logoutUser","produces":["application/xml","application/json"],"parameters":[],"responses":{"default":{"description":"successful operation"}}}},"/user/{username}":{"get":{"tags":["user"],"summary":"Get user by user name","description":"","operationId":"getUserByName","produces":["application/xml","application/json"],"parameters":[{"name":"username","in":"path","description":"The name that needs to be fetched. Use user1 for testing. ","required":true,"type":"string"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/User"}},"400":{"description":"Invalid username supplied"},"404":{"description":"User not found"}}},"put":{"tags":["user"],"summary":"Updated user","description":"This can only be done by the logged in user.","operationId":"updateUser","produces":["application/xml","application/json"],"parameters":[{"name":"username","in":"path","description":"name that need to be updated","required":true,"type":"string"},{"in":"body","name":"body","description":"Updated user object","required":true,"schema":{"$ref":"#/definitions/User"}}],"responses":{"400":{"description":"Invalid user supplied"},"404":{"description":"User not found"}}},"delete":{"tags":["user"],"summary":"Delete user","description":"This can only be done by the logged in user.","operationId":"deleteUser","produces":["application/xml","application/json"],"parameters":[{"name":"username","in":"path","description":"The name that needs to be deleted","required":true,"type":"string"}],"responses":{"400":{"description":"Invalid username supplied"},"404":{"description":"User not found"}}}}},"securityDefinitions":{"petstore_auth":{"type":"oauth2","authorizationUrl":"http://petstore.swagger.io/oauth/dialog","flow":"implicit","scopes":{"write:pets":"modify pets in your account","read:pets":"read your pets"}},"api_key":{"type":"apiKey","name":"api_key","in":"header"}},"definitions":{"Order":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"petId":{"type":"integer","format":"int64"},"quantity":{"type":"integer","format":"int32"},"shipDate":{"type":"string","format":"date-time"},"status":{"type":"string","description":"Order Status","enum":["placed","approved","delivered"]},"complete":{"type":"boolean","default":false}},"xml":{"name":"Order"}},"Category":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}},"xml":{"name":"Category"}},"User":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"username":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"},"password":{"type":"string"},"phone":{"type":"string"},"userStatus":{"type":"integer","format":"int32","description":"User Status"}},"xml":{"name":"User"}},"Tag":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}},"xml":{"name":"Tag"}},"Pet":{"type":"object","required":["name","photoUrls"],"properties":{"id":{"type":"integer","format":"int64"},"category":{"$ref":"#/definitions/Category"},"name":{"type":"string","example":"doggie"},"photoUrls":{"type":"array","xml":{"name":"photoUrl","wrapped":true},"items":{"type":"string"}},"tags":{"type":"array","xml":{"name":"tag","wrapped":true},"items":{"$ref":"#/definitions/Tag"}},"status":{"type":"string","description":"pet status in the store","enum":["available","pending","sold"]}},"xml":{"name":"Pet"}},"ApiResponse":{"type":"object","properties":{"code":{"type":"integer","format":"int32"},"type":{"type":"string"},"message":{"type":"string"}}}},"externalDocs":{"description":"Find out more about Swagger","url":"http://swagger.io"}} | ||
{ | ||
"swagger": "2.1", | ||
"info": { | ||
"description": "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.", | ||
"version": "1.0.1", | ||
"title": "Swagger Petstore", | ||
"termsOfService": "http://swagger.io/terms/", | ||
"contact": { | ||
"email": "apiteam@swagger.io" | ||
}, | ||
"license": { | ||
"name": "Apache 2.1", | ||
"url": "http://www.apache.org/licenses/LICENSE-2.0.html" | ||
} | ||
}, | ||
"host": "petstore.swagger.io", | ||
"basePath": "/v2", | ||
"tags": [ | ||
{ | ||
"name": "pet", | ||
"description": "Everything about your Pets", | ||
"externalDocs": { | ||
"description": "Find out more", | ||
"url": "http://swagger.io" | ||
} | ||
}, | ||
{ | ||
"name": "store", | ||
"description": "Access to Petstore orders" | ||
}, | ||
{ | ||
"name": "user", | ||
"description": "Operations about user", | ||
"externalDocs": { | ||
"description": "Find out more about our store", | ||
"url": "http://swagger.io" | ||
} | ||
} | ||
], | ||
"schemes": [ | ||
"http" | ||
], | ||
"paths": { | ||
"/pet": { | ||
"post": { | ||
"tags": [ | ||
"pet" | ||
], | ||
"summary": "Add a new pet to the store", | ||
"description": "", | ||
"operationId": "addPet", | ||
"consumes": [ | ||
"application/json", | ||
"application/xml" | ||
], | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"in": "body", | ||
"name": "body", | ||
"description": "Pet object that needs to be added to the store", | ||
"required": true, | ||
"schema": { | ||
"$ref": "#/definitions/Pet" | ||
} | ||
} | ||
], | ||
"responses": { | ||
"405": { | ||
"description": "Invalid input" | ||
} | ||
}, | ||
"security": [ | ||
{ | ||
"petstore_auth": [ | ||
"write:pets", | ||
"read:pets" | ||
] | ||
} | ||
] | ||
}, | ||
"put": { | ||
"tags": [ | ||
"pet" | ||
], | ||
"summary": "Update an existing pet", | ||
"description": "", | ||
"operationId": "updatePet", | ||
"consumes": [ | ||
"application/json", | ||
"application/xml" | ||
], | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"in": "body", | ||
"name": "body", | ||
"description": "Pet object that needs to be added to the store", | ||
"required": true, | ||
"schema": { | ||
"$ref": "#/definitions/Pet" | ||
} | ||
} | ||
], | ||
"responses": { | ||
"400": { | ||
"description": "Invalid ID supplied" | ||
}, | ||
"404": { | ||
"description": "Pet not found" | ||
}, | ||
"405": { | ||
"description": "Validation exception" | ||
} | ||
}, | ||
"security": [ | ||
{ | ||
"petstore_auth": [ | ||
"write:pets", | ||
"read:pets" | ||
] | ||
} | ||
] | ||
} | ||
}, | ||
"/pet/findByStatus": { | ||
"get": { | ||
"tags": [ | ||
"pet" | ||
], | ||
"summary": "Finds Pets by status", | ||
"description": "Multiple status values can be provided with comma separated strings", | ||
"operationId": "findPetsByStatus", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "status", | ||
"in": "query", | ||
"description": "Status values that need to be considered for filter", | ||
"required": true, | ||
"type": "array", | ||
"items": { | ||
"type": "string", | ||
"enum": [ | ||
"available", | ||
"pending", | ||
"sold" | ||
], | ||
"default": "available" | ||
}, | ||
"collectionFormat": "multi" | ||
} | ||
], | ||
"responses": { | ||
"200": { | ||
"description": "successful operation", | ||
"schema": { | ||
"type": "array", | ||
"items": { | ||
"$ref": "#/definitions/Pet" | ||
} | ||
} | ||
}, | ||
"400": { | ||
"description": "Invalid status value" | ||
} | ||
}, | ||
"security": [ | ||
{ | ||
"petstore_auth": [ | ||
"write:pets", | ||
"read:pets" | ||
] | ||
} | ||
] | ||
} | ||
}, | ||
"/pet/findByTags": { | ||
"get": { | ||
"tags": [ | ||
"pet" | ||
], | ||
"summary": "Finds Pets by tags", | ||
"description": "Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", | ||
"operationId": "findPetsByTags", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "tags", | ||
"in": "query", | ||
"description": "Tags to filter by", | ||
"required": true, | ||
"type": "array", | ||
"items": { | ||
"type": "string" | ||
}, | ||
"collectionFormat": "multi" | ||
} | ||
], | ||
"responses": { | ||
"200": { | ||
"description": "successful operation", | ||
"schema": { | ||
"type": "array", | ||
"items": { | ||
"$ref": "#/definitions/Pet" | ||
} | ||
} | ||
}, | ||
"400": { | ||
"description": "Invalid tag value" | ||
} | ||
}, | ||
"security": [ | ||
{ | ||
"petstore_auth": [ | ||
"write:pets", | ||
"read:pets" | ||
] | ||
} | ||
], | ||
"deprecated": true | ||
} | ||
}, | ||
"/pet/{petId}": { | ||
"get": { | ||
"tags": [ | ||
"pet" | ||
], | ||
"summary": "Find pet by ID", | ||
"description": "Returns a single pet", | ||
"operationId": "getPetById", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "petId", | ||
"in": "path", | ||
"description": "ID of pet to return", | ||
"required": true, | ||
"type": "integer", | ||
"format": "int64" | ||
} | ||
], | ||
"responses": { | ||
"200": { | ||
"description": "successful operation", | ||
"schema": { | ||
"$ref": "#/definitions/Pet" | ||
} | ||
}, | ||
"400": { | ||
"description": "Invalid ID supplied" | ||
}, | ||
"404": { | ||
"description": "Pet not found" | ||
} | ||
}, | ||
"security": [ | ||
{ | ||
"api_key": [] | ||
} | ||
] | ||
}, | ||
"post": { | ||
"tags": [ | ||
"pet" | ||
], | ||
"summary": "Updates a pet in the store with form data", | ||
"description": "", | ||
"operationId": "updatePetWithForm", | ||
"consumes": [ | ||
"application/x-www-form-urlencoded" | ||
], | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "petId", | ||
"in": "path", | ||
"description": "ID of pet that needs to be updated", | ||
"required": true, | ||
"type": "integer", | ||
"format": "int64" | ||
}, | ||
{ | ||
"name": "name", | ||
"in": "formData", | ||
"description": "Updated name of the pet", | ||
"required": false, | ||
"type": "string" | ||
}, | ||
{ | ||
"name": "status", | ||
"in": "formData", | ||
"description": "Updated status of the pet", | ||
"required": false, | ||
"type": "string" | ||
} | ||
], | ||
"responses": { | ||
"405": { | ||
"description": "Invalid input" | ||
} | ||
}, | ||
"security": [ | ||
{ | ||
"petstore_auth": [ | ||
"write:pets", | ||
"read:pets" | ||
] | ||
} | ||
] | ||
}, | ||
"delete": { | ||
"tags": [ | ||
"pet" | ||
], | ||
"summary": "Deletes a pet", | ||
"description": "", | ||
"operationId": "deletePet", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "api_key", | ||
"in": "header", | ||
"required": false, | ||
"type": "string" | ||
}, | ||
{ | ||
"name": "petId", | ||
"in": "path", | ||
"description": "Pet id to delete", | ||
"required": true, | ||
"type": "integer", | ||
"format": "int64" | ||
} | ||
], | ||
"responses": { | ||
"400": { | ||
"description": "Invalid ID supplied" | ||
}, | ||
"404": { | ||
"description": "Pet not found" | ||
} | ||
}, | ||
"security": [ | ||
{ | ||
"petstore_auth": [ | ||
"write:pets", | ||
"read:pets" | ||
] | ||
} | ||
] | ||
} | ||
}, | ||
"/pet/{petId}/uploadImage": { | ||
"post": { | ||
"tags": [ | ||
"pet" | ||
], | ||
"summary": "uploads an image", | ||
"description": "", | ||
"operationId": "uploadFile", | ||
"consumes": [ | ||
"multipart/form-data" | ||
], | ||
"produces": [ | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "petId", | ||
"in": "path", | ||
"description": "ID of pet to update", | ||
"required": true, | ||
"type": "integer", | ||
"format": "int64" | ||
}, | ||
{ | ||
"name": "additionalMetadata", | ||
"in": "formData", | ||
"description": "Additional data to pass to server", | ||
"required": false, | ||
"type": "string" | ||
}, | ||
{ | ||
"name": "file", | ||
"in": "formData", | ||
"description": "file to upload", | ||
"required": false, | ||
"type": "file" | ||
} | ||
], | ||
"responses": { | ||
"200": { | ||
"description": "successful operation", | ||
"schema": { | ||
"$ref": "#/definitions/ApiResponse" | ||
} | ||
} | ||
}, | ||
"security": [ | ||
{ | ||
"petstore_auth": [ | ||
"write:pets", | ||
"read:pets" | ||
] | ||
} | ||
] | ||
} | ||
}, | ||
"/store/inventory": { | ||
"get": { | ||
"tags": [ | ||
"store" | ||
], | ||
"summary": "Returns pet inventories by status", | ||
"description": "Returns a map of status codes to quantities", | ||
"operationId": "getInventory", | ||
"produces": [ | ||
"application/json" | ||
], | ||
"parameters": [], | ||
"responses": { | ||
"200": { | ||
"description": "successful operation", | ||
"schema": { | ||
"type": "object", | ||
"additionalProperties": { | ||
"type": "integer", | ||
"format": "int32" | ||
} | ||
} | ||
} | ||
}, | ||
"security": [ | ||
{ | ||
"api_key": [] | ||
} | ||
] | ||
} | ||
}, | ||
"/store/order": { | ||
"post": { | ||
"tags": [ | ||
"store" | ||
], | ||
"summary": "Place an order for a pet", | ||
"description": "", | ||
"operationId": "placeOrder", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"in": "body", | ||
"name": "body", | ||
"description": "order placed for purchasing the pet", | ||
"required": true, | ||
"schema": { | ||
"$ref": "#/definitions/Order" | ||
} | ||
} | ||
], | ||
"responses": { | ||
"200": { | ||
"description": "successful operation", | ||
"schema": { | ||
"$ref": "#/definitions/Order" | ||
} | ||
}, | ||
"400": { | ||
"description": "Invalid Order" | ||
} | ||
} | ||
} | ||
}, | ||
"/store/order/{orderId}": { | ||
"get": { | ||
"tags": [ | ||
"store" | ||
], | ||
"summary": "Find purchase order by ID", | ||
"description": "For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions", | ||
"operationId": "getOrderById", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "orderId", | ||
"in": "path", | ||
"description": "ID of pet that needs to be fetched", | ||
"required": true, | ||
"type": "integer", | ||
"maximum": 10.0, | ||
"minimum": 1.0, | ||
"format": "int64" | ||
} | ||
], | ||
"responses": { | ||
"200": { | ||
"description": "successful operation", | ||
"schema": { | ||
"$ref": "#/definitions/Order" | ||
} | ||
}, | ||
"400": { | ||
"description": "Invalid ID supplied" | ||
}, | ||
"404": { | ||
"description": "Order not found" | ||
} | ||
} | ||
}, | ||
"delete": { | ||
"tags": [ | ||
"store" | ||
], | ||
"summary": "Delete purchase order by ID", | ||
"description": "For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors", | ||
"operationId": "deleteOrder", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "orderId", | ||
"in": "path", | ||
"description": "ID of the order that needs to be deleted", | ||
"required": true, | ||
"type": "integer", | ||
"minimum": 1.0, | ||
"format": "int64" | ||
} | ||
], | ||
"responses": { | ||
"400": { | ||
"description": "Invalid ID supplied" | ||
}, | ||
"404": { | ||
"description": "Order not found" | ||
} | ||
} | ||
} | ||
}, | ||
"/user": { | ||
"post": { | ||
"tags": [ | ||
"user" | ||
], | ||
"summary": "Create user", | ||
"description": "This can only be done by the logged in user.", | ||
"operationId": "createUser", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"in": "body", | ||
"name": "body", | ||
"description": "Created user object", | ||
"required": true, | ||
"schema": { | ||
"$ref": "#/definitions/User" | ||
} | ||
} | ||
], | ||
"responses": { | ||
"default": { | ||
"description": "successful operation" | ||
} | ||
} | ||
} | ||
}, | ||
"/user/createWithArray": { | ||
"post": { | ||
"tags": [ | ||
"user" | ||
], | ||
"summary": "Creates list of users with given input array", | ||
"description": "", | ||
"operationId": "createUsersWithArrayInput", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"in": "body", | ||
"name": "body", | ||
"description": "List of user object", | ||
"required": true, | ||
"schema": { | ||
"type": "array", | ||
"items": { | ||
"$ref": "#/definitions/User" | ||
} | ||
} | ||
} | ||
], | ||
"responses": { | ||
"default": { | ||
"description": "successful operation" | ||
} | ||
} | ||
} | ||
}, | ||
"/user/createWithList": { | ||
"post": { | ||
"tags": [ | ||
"user" | ||
], | ||
"summary": "Creates list of users with given input array", | ||
"description": "", | ||
"operationId": "createUsersWithListInput", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"in": "body", | ||
"name": "body", | ||
"description": "List of user object", | ||
"required": true, | ||
"schema": { | ||
"type": "array", | ||
"items": { | ||
"$ref": "#/definitions/User" | ||
} | ||
} | ||
} | ||
], | ||
"responses": { | ||
"default": { | ||
"description": "successful operation" | ||
} | ||
} | ||
} | ||
}, | ||
"/user/login": { | ||
"get": { | ||
"tags": [ | ||
"user" | ||
], | ||
"summary": "Logs user into the system", | ||
"description": "", | ||
"operationId": "loginUser", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "username", | ||
"in": "query", | ||
"description": "The user name for login", | ||
"required": true, | ||
"type": "string" | ||
}, | ||
{ | ||
"name": "password", | ||
"in": "query", | ||
"description": "The password for login in clear text", | ||
"required": true, | ||
"type": "string" | ||
} | ||
], | ||
"responses": { | ||
"200": { | ||
"description": "successful operation", | ||
"schema": { | ||
"type": "string" | ||
}, | ||
"headers": { | ||
"X-Rate-Limit": { | ||
"type": "integer", | ||
"format": "int32", | ||
"description": "calls per hour allowed by the user" | ||
}, | ||
"X-Expires-After": { | ||
"type": "string", | ||
"format": "date-time", | ||
"description": "date in UTC when token expires" | ||
} | ||
} | ||
}, | ||
"400": { | ||
"description": "Invalid username/password supplied" | ||
} | ||
} | ||
} | ||
}, | ||
"/user/logout": { | ||
"get": { | ||
"tags": [ | ||
"user" | ||
], | ||
"summary": "Logs out current logged in user session", | ||
"description": "", | ||
"operationId": "logoutUser", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [], | ||
"responses": { | ||
"default": { | ||
"description": "successful operation" | ||
} | ||
} | ||
} | ||
}, | ||
"/user/{username}": { | ||
"get": { | ||
"tags": [ | ||
"user" | ||
], | ||
"summary": "Get user by user name", | ||
"description": "", | ||
"operationId": "getUserByName", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "username", | ||
"in": "path", | ||
"description": "The name that needs to be fetched. Use user1 for testing. ", | ||
"required": true, | ||
"type": "string" | ||
} | ||
], | ||
"responses": { | ||
"200": { | ||
"description": "successful operation", | ||
"schema": { | ||
"$ref": "#/definitions/User" | ||
} | ||
}, | ||
"400": { | ||
"description": "Invalid username supplied" | ||
}, | ||
"404": { | ||
"description": "User not found" | ||
} | ||
} | ||
}, | ||
"put": { | ||
"tags": [ | ||
"user" | ||
], | ||
"summary": "Updated user", | ||
"description": "This can only be done by the logged in user.", | ||
"operationId": "updateUser", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "username", | ||
"in": "path", | ||
"description": "name that need to be updated", | ||
"required": true, | ||
"type": "string" | ||
}, | ||
{ | ||
"in": "body", | ||
"name": "body", | ||
"description": "Updated user object", | ||
"required": true, | ||
"schema": { | ||
"$ref": "#/definitions/User" | ||
} | ||
} | ||
], | ||
"responses": { | ||
"400": { | ||
"description": "Invalid user supplied" | ||
}, | ||
"404": { | ||
"description": "User not found" | ||
} | ||
} | ||
}, | ||
"delete": { | ||
"tags": [ | ||
"user" | ||
], | ||
"summary": "Delete user", | ||
"description": "This can only be done by the logged in user.", | ||
"operationId": "deleteUser", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "username", | ||
"in": "path", | ||
"description": "The name that needs to be deleted", | ||
"required": true, | ||
"type": "string" | ||
} | ||
], | ||
"responses": { | ||
"400": { | ||
"description": "Invalid username supplied" | ||
}, | ||
"404": { | ||
"description": "User not found" | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
"securityDefinitions": { | ||
"petstore_auth": { | ||
"type": "oauth2", | ||
"authorizationUrl": "http://petstore.swagger.io/oauth/dialog", | ||
"flow": "implicit", | ||
"scopes": { | ||
"write:pets": "modify pets in your account", | ||
"read:pets": "read your pets" | ||
} | ||
}, | ||
"api_key": { | ||
"type": "apiKey", | ||
"name": "api_key", | ||
"in": "header" | ||
} | ||
}, | ||
"definitions": { | ||
"Order": { | ||
"type": "object", | ||
"properties": { | ||
"id": { | ||
"type": "integer", | ||
"format": "int64" | ||
}, | ||
"petId": { | ||
"type": "integer", | ||
"format": "int64" | ||
}, | ||
"quantity": { | ||
"type": "integer", | ||
"format": "int32" | ||
}, | ||
"shipDate": { | ||
"type": "string", | ||
"format": "date-time" | ||
}, | ||
"status": { | ||
"type": "string", | ||
"description": "Order Status", | ||
"enum": [ | ||
"placed", | ||
"approved", | ||
"delivered" | ||
] | ||
}, | ||
"complete": { | ||
"type": "boolean", | ||
"default": false | ||
} | ||
}, | ||
"xml": { | ||
"name": "Order" | ||
} | ||
}, | ||
"Category": { | ||
"type": "object", | ||
"properties": { | ||
"id": { | ||
"type": "integer", | ||
"format": "int64" | ||
}, | ||
"name": { | ||
"type": "string" | ||
} | ||
}, | ||
"xml": { | ||
"name": "Category" | ||
} | ||
}, | ||
"User": { | ||
"type": "object", | ||
"properties": { | ||
"id": { | ||
"type": "integer", | ||
"format": "int64" | ||
}, | ||
"username": { | ||
"type": "string" | ||
}, | ||
"firstName": { | ||
"type": "string" | ||
}, | ||
"lastName": { | ||
"type": "string" | ||
}, | ||
"email": { | ||
"type": "string" | ||
}, | ||
"password": { | ||
"type": "string" | ||
}, | ||
"phone": { | ||
"type": "string" | ||
}, | ||
"userStatus": { | ||
"type": "integer", | ||
"format": "int32", | ||
"description": "User Status" | ||
} | ||
}, | ||
"xml": { | ||
"name": "User" | ||
} | ||
}, | ||
"Tag": { | ||
"type": "object", | ||
"properties": { | ||
"id": { | ||
"type": "integer", | ||
"format": "int64" | ||
}, | ||
"name": { | ||
"type": "string" | ||
} | ||
}, | ||
"xml": { | ||
"name": "Tag" | ||
} | ||
}, | ||
"Pet": { | ||
"type": "object", | ||
"required": [ | ||
"name", | ||
"photoUrls" | ||
], | ||
"properties": { | ||
"id": { | ||
"type": "integer", | ||
"format": "int64" | ||
}, | ||
"category": { | ||
"$ref": "#/definitions/Category" | ||
}, | ||
"name": { | ||
"type": "string", | ||
"example": "doggie" | ||
}, | ||
"photoUrls": { | ||
"type": "array", | ||
"xml": { | ||
"name": "photoUrl", | ||
"wrapped": true | ||
}, | ||
"items": { | ||
"type": "string" | ||
} | ||
}, | ||
"tags": { | ||
"type": "array", | ||
"xml": { | ||
"name": "tag", | ||
"wrapped": true | ||
}, | ||
"items": { | ||
"$ref": "#/definitions/Tag" | ||
} | ||
}, | ||
"status": { | ||
"type": "string", | ||
"description": "pet status in the store", | ||
"enum": [ | ||
"available", | ||
"pending", | ||
"sold" | ||
] | ||
} | ||
}, | ||
"xml": { | ||
"name": "Pet" | ||
} | ||
}, | ||
"ApiResponse": { | ||
"type": "object", | ||
"properties": { | ||
"code": { | ||
"type": "integer", | ||
"format": "int32" | ||
}, | ||
"type": { | ||
"type": "string" | ||
}, | ||
"message": { | ||
"type": "string" | ||
} | ||
} | ||
} | ||
}, | ||
"externalDocs": { | ||
"description": "Find out more about Swagger", | ||
"url": "http://swagger.io" | ||
} | ||
} |
@@ -1,1 +0,1035 @@ | ||
{"swagger":"2.0","info":{"description":"This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.","version":"1.0.0","title":"Swagger Petstore","termsOfService":"http://swagger.io/terms/","contact":{"email":"apiteam@swagger.io"},"license":{"name":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}},"host":"petstore.swagger.io","basePath":"/v2","tags":[{"name":"pet","description":"Everything about your Pets","externalDocs":{"description":"Find out more","url":"http://swagger.io"}},{"name":"store","description":"Access to Petstore orders"},{"name":"user","description":"Operations about user","externalDocs":{"description":"Find out more about our store","url":"http://swagger.io"}}],"schemes":["http"],"paths":{"/pet":{"post":{"tags":["pet"],"summary":"Add a new pet to the store","description":"","operationId":"addPet","consumes":["application/json","application/xml"],"produces":["application/xml","application/json"],"parameters":[{"in":"body","name":"body","description":"Pet object that needs to be added to the store","required":true,"schema":{"$ref":"#/definitions/Pet"}}],"responses":{"405":{"description":"Invalid input"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]},"put":{"tags":["pet"],"summary":"Update an existing pet","description":"","operationId":"updatePet","consumes":["application/json","application/xml"],"produces":["application/xml","application/json"],"parameters":[{"in":"body","name":"body","description":"Pet object that needs to be added to the store","required":true,"schema":{"$ref":"#/definitions/Pet"}}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"},"405":{"description":"Validation exception"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/findByStatus":{"get":{"tags":["pet"],"summary":"Finds Pets by status","description":"Multiple status values can be provided with comma separated strings","operationId":"findPetsByStatus","produces":["application/xml","application/json"],"parameters":[{"name":"status","in":"query","description":"Status values that need to be considered for filter","required":true,"type":"array","items":{"type":"string","enum":["available","pending","sold"],"default":"available"},"collectionFormat":"multi"}],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/Pet"}}},"400":{"description":"Invalid status value"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/findByTags":{"get":{"tags":["pet"],"summary":"Finds Pets by tags","description":"Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.","operationId":"findPetsByTags","produces":["application/xml","application/json"],"parameters":[{"name":"tags","in":"query","description":"Tags to filter by","required":true,"type":"array","items":{"type":"string"},"collectionFormat":"multi"}],"responses":{"200":{"description":"successful operation","schema":{"type":"array","items":{"$ref":"#/definitions/Pet"}}},"400":{"description":"Invalid tag value"}},"security":[{"petstore_auth":["write:pets","read:pets"]}],"deprecated":true}},"/pet/{petId}":{"get":{"tags":["pet"],"summary":"Find pet by ID","description":"Returns a single pet","operationId":"getPetById","produces":["application/xml","application/json"],"parameters":[{"name":"petId","in":"path","description":"ID of pet to return","required":true,"type":"integer","format":"int64"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Pet"}},"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"}},"security":[{"api_key":[]}]},"post":{"tags":["pet"],"summary":"Updates a pet in the store with form data","description":"","operationId":"updatePetWithForm","consumes":["application/x-www-form-urlencoded"],"produces":["application/xml","application/json"],"parameters":[{"name":"petId","in":"path","description":"ID of pet that needs to be updated","required":true,"type":"integer","format":"int64"},{"name":"name","in":"formData","description":"Updated name of the pet","required":false,"type":"string"},{"name":"status","in":"formData","description":"Updated status of the pet","required":false,"type":"string"}],"responses":{"405":{"description":"Invalid input"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]},"delete":{"tags":["pet"],"summary":"Deletes a pet","description":"","operationId":"deletePet","produces":["application/xml","application/json"],"parameters":[{"name":"api_key","in":"header","required":false,"type":"string"},{"name":"petId","in":"path","description":"Pet id to delete","required":true,"type":"integer","format":"int64"}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Pet not found"}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/pet/{petId}/uploadImage":{"post":{"tags":["pet"],"summary":"uploads an image","description":"","operationId":"uploadFile","consumes":["multipart/form-data"],"produces":["application/json"],"parameters":[{"name":"petId","in":"path","description":"ID of pet to update","required":true,"type":"integer","format":"int64"},{"name":"additionalMetadata","in":"formData","description":"Additional data to pass to server","required":false,"type":"string"},{"name":"file","in":"formData","description":"file to upload","required":false,"type":"file"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/ApiResponse"}}},"security":[{"petstore_auth":["write:pets","read:pets"]}]}},"/store/inventory":{"get":{"tags":["store"],"summary":"Returns pet inventories by status","description":"Returns a map of status codes to quantities","operationId":"getInventory","produces":["application/json"],"parameters":[],"responses":{"200":{"description":"successful operation","schema":{"type":"object","additionalProperties":{"type":"integer","format":"int32"}}}},"security":[{"api_key":[]}]}},"/store/order":{"post":{"tags":["store"],"summary":"Place an order for a pet","description":"","operationId":"placeOrder","produces":["application/xml","application/json"],"parameters":[{"in":"body","name":"body","description":"order placed for purchasing the pet","required":true,"schema":{"$ref":"#/definitions/Order"}}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Order"}},"400":{"description":"Invalid Order"}}}},"/store/order/{orderId}":{"get":{"tags":["store"],"summary":"Find purchase order by ID","description":"For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions","operationId":"getOrderById","produces":["application/xml","application/json"],"parameters":[{"name":"orderId","in":"path","description":"ID of pet that needs to be fetched","required":true,"type":"integer","maximum":10.0,"minimum":1.0,"format":"int64"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/Order"}},"400":{"description":"Invalid ID supplied"},"404":{"description":"Order not found"}}},"delete":{"tags":["store"],"summary":"Delete purchase order by ID","description":"For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors","operationId":"deleteOrder","produces":["application/xml","application/json"],"parameters":[{"name":"orderId","in":"path","description":"ID of the order that needs to be deleted","required":true,"type":"integer","minimum":1.0,"format":"int64"}],"responses":{"400":{"description":"Invalid ID supplied"},"404":{"description":"Order not found"}}}},"/user":{"post":{"tags":["user"],"summary":"Create user","description":"This can only be done by the logged in user.","operationId":"createUser","produces":["application/xml","application/json"],"parameters":[{"in":"body","name":"body","description":"Created user object","required":true,"schema":{"$ref":"#/definitions/User"}}],"responses":{"default":{"description":"successful operation"}}}},"/user/createWithArray":{"post":{"tags":["user"],"summary":"Creates list of users with given input array","description":"","operationId":"createUsersWithArrayInput","produces":["application/xml","application/json"],"parameters":[{"in":"body","name":"body","description":"List of user object","required":true,"schema":{"type":"array","items":{"$ref":"#/definitions/User"}}}],"responses":{"default":{"description":"successful operation"}}}},"/user/createWithList":{"post":{"tags":["user"],"summary":"Creates list of users with given input array","description":"","operationId":"createUsersWithListInput","produces":["application/xml","application/json"],"parameters":[{"in":"body","name":"body","description":"List of user object","required":true,"schema":{"type":"array","items":{"$ref":"#/definitions/User"}}}],"responses":{"default":{"description":"successful operation"}}}},"/user/login":{"get":{"tags":["user"],"summary":"Logs user into the system","description":"","operationId":"loginUser","produces":["application/xml","application/json"],"parameters":[{"name":"username","in":"query","description":"The user name for login","required":true,"type":"string"},{"name":"password","in":"query","description":"The password for login in clear text","required":true,"type":"string"}],"responses":{"200":{"description":"successful operation","schema":{"type":"string"},"headers":{"X-Rate-Limit":{"type":"integer","format":"int32","description":"calls per hour allowed by the user"},"X-Expires-After":{"type":"string","format":"date-time","description":"date in UTC when token expires"}}},"400":{"description":"Invalid username/password supplied"}}}},"/user/logout":{"get":{"tags":["user"],"summary":"Logs out current logged in user session","description":"","operationId":"logoutUser","produces":["application/xml","application/json"],"parameters":[],"responses":{"default":{"description":"successful operation"}}}},"/user/{username}":{"get":{"tags":["user"],"summary":"Get user by user name","description":"","operationId":"getUserByName","produces":["application/xml","application/json"],"parameters":[{"name":"username","in":"path","description":"The name that needs to be fetched. Use user1 for testing. ","required":true,"type":"string"}],"responses":{"200":{"description":"successful operation","schema":{"$ref":"#/definitions/User"}},"400":{"description":"Invalid username supplied"},"404":{"description":"User not found"}}},"put":{"tags":["user"],"summary":"Updated user","description":"This can only be done by the logged in user.","operationId":"updateUser","produces":["application/xml","application/json"],"parameters":[{"name":"username","in":"path","description":"name that need to be updated","required":true,"type":"string"},{"in":"body","name":"body","description":"Updated user object","required":true,"schema":{"$ref":"#/definitions/User"}}],"responses":{"400":{"description":"Invalid user supplied"},"404":{"description":"User not found"}}},"delete":{"tags":["user"],"summary":"Delete user","description":"This can only be done by the logged in user.","operationId":"deleteUser","produces":["application/xml","application/json"],"parameters":[{"name":"username","in":"path","description":"The name that needs to be deleted","required":true,"type":"string"}],"responses":{"400":{"description":"Invalid username supplied"},"404":{"description":"User not found"}}}}},"securityDefinitions":{"petstore_auth":{"type":"oauth2","authorizationUrl":"http://petstore.swagger.io/oauth/dialog","flow":"implicit","scopes":{"write:pets":"modify pets in your account","read:pets":"read your pets"}},"api_key":{"type":"apiKey","name":"api_key","in":"header"}},"definitions":{"Order":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"petId":{"type":"integer","format":"int64"},"quantity":{"type":"integer","format":"int32"},"shipDate":{"type":"string","format":"date-time"},"status":{"type":"string","description":"Order Status","enum":["placed","approved","delivered"]},"complete":{"type":"boolean","default":false}},"xml":{"name":"Order"}},"Category":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}},"xml":{"name":"Category"}},"User":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"username":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"},"password":{"type":"string"},"phone":{"type":"string"},"userStatus":{"type":"integer","format":"int32","description":"User Status"}},"xml":{"name":"User"}},"Tag":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}},"xml":{"name":"Tag"}},"Pet":{"type":"object","required":["name","photoUrls"],"properties":{"id":{"type":"integer","format":"int64"},"category":{"$ref":"#/definitions/Category"},"name":{"type":"string","example":"doggie"},"photoUrls":{"type":"array","xml":{"name":"photoUrl","wrapped":true},"items":{"type":"string"}},"tags":{"type":"array","xml":{"name":"tag","wrapped":true},"items":{"$ref":"#/definitions/Tag"}},"status":{"type":"string","description":"pet status in the store","enum":["available","pending","sold"]}},"xml":{"name":"Pet"}},"ApiResponse":{"type":"object","properties":{"code":{"type":"integer","format":"int32"},"type":{"type":"string"},"message":{"type":"string"}}}},"externalDocs":{"description":"Find out more about Swagger","url":"http://swagger.io"}} | ||
{ | ||
"swagger": "2.0", | ||
"info": { | ||
"description": "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.", | ||
"version": "1.0.0", | ||
"title": "Swagger Petstore", | ||
"termsOfService": "http://swagger.io/terms/", | ||
"contact": { | ||
"email": "apiteam@swagger.io" | ||
}, | ||
"license": { | ||
"name": "Apache 2.0", | ||
"url": "http://www.apache.org/licenses/LICENSE-2.0.html" | ||
} | ||
}, | ||
"host": "petstore.swagger.io", | ||
"basePath": "/v2", | ||
"tags": [ | ||
{ | ||
"name": "pet", | ||
"description": "Everything about your Pets", | ||
"externalDocs": { | ||
"description": "Find out more", | ||
"url": "http://swagger.io" | ||
} | ||
}, | ||
{ | ||
"name": "store", | ||
"description": "Access to Petstore orders" | ||
}, | ||
{ | ||
"name": "user", | ||
"description": "Operations about user", | ||
"externalDocs": { | ||
"description": "Find out more about our store", | ||
"url": "http://swagger.io" | ||
} | ||
} | ||
], | ||
"schemes": [ | ||
"http" | ||
], | ||
"paths": { | ||
"/pet": { | ||
"post": { | ||
"tags": [ | ||
"pet" | ||
], | ||
"summary": "Add a new pet to the store", | ||
"description": "", | ||
"operationId": "addPet", | ||
"consumes": [ | ||
"application/json", | ||
"application/xml" | ||
], | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"in": "body", | ||
"name": "body", | ||
"description": "Pet object that needs to be added to the store", | ||
"required": true, | ||
"schema": { | ||
"$ref": "#/definitions/Pet" | ||
} | ||
} | ||
], | ||
"responses": { | ||
"405": { | ||
"description": "Invalid input" | ||
} | ||
}, | ||
"security": [ | ||
{ | ||
"petstore_auth": [ | ||
"write:pets", | ||
"read:pets" | ||
] | ||
} | ||
] | ||
}, | ||
"put": { | ||
"tags": [ | ||
"pet" | ||
], | ||
"summary": "Update an existing pet", | ||
"description": "", | ||
"operationId": "updatePet", | ||
"consumes": [ | ||
"application/json", | ||
"application/xml" | ||
], | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"in": "body", | ||
"name": "body", | ||
"description": "Pet object that needs to be added to the store", | ||
"required": true, | ||
"schema": { | ||
"$ref": "#/definitions/Pet" | ||
} | ||
} | ||
], | ||
"responses": { | ||
"400": { | ||
"description": "Invalid ID supplied" | ||
}, | ||
"404": { | ||
"description": "Pet not found" | ||
}, | ||
"405": { | ||
"description": "Validation exception" | ||
} | ||
}, | ||
"security": [ | ||
{ | ||
"petstore_auth": [ | ||
"write:pets", | ||
"read:pets" | ||
] | ||
} | ||
] | ||
} | ||
}, | ||
"/pet/findByStatus": { | ||
"get": { | ||
"tags": [ | ||
"pet" | ||
], | ||
"summary": "Finds Pets by status", | ||
"description": "Multiple status values can be provided with comma separated strings", | ||
"operationId": "findPetsByStatus", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "status", | ||
"in": "query", | ||
"description": "Status values that need to be considered for filter", | ||
"required": true, | ||
"type": "array", | ||
"items": { | ||
"type": "string", | ||
"enum": [ | ||
"available", | ||
"pending", | ||
"sold" | ||
], | ||
"default": "available" | ||
}, | ||
"collectionFormat": "multi" | ||
} | ||
], | ||
"responses": { | ||
"200": { | ||
"description": "successful operation", | ||
"schema": { | ||
"type": "array", | ||
"items": { | ||
"$ref": "#/definitions/Pet" | ||
} | ||
} | ||
}, | ||
"400": { | ||
"description": "Invalid status value" | ||
} | ||
}, | ||
"security": [ | ||
{ | ||
"petstore_auth": [ | ||
"write:pets", | ||
"read:pets" | ||
] | ||
} | ||
] | ||
} | ||
}, | ||
"/pet/findByTags": { | ||
"get": { | ||
"tags": [ | ||
"pet" | ||
], | ||
"summary": "Finds Pets by tags", | ||
"description": "Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", | ||
"operationId": "findPetsByTags", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "tags", | ||
"in": "query", | ||
"description": "Tags to filter by", | ||
"required": true, | ||
"type": "array", | ||
"items": { | ||
"type": "string" | ||
}, | ||
"collectionFormat": "multi" | ||
} | ||
], | ||
"responses": { | ||
"200": { | ||
"description": "successful operation", | ||
"schema": { | ||
"type": "array", | ||
"items": { | ||
"$ref": "#/definitions/Pet" | ||
} | ||
} | ||
}, | ||
"400": { | ||
"description": "Invalid tag value" | ||
} | ||
}, | ||
"security": [ | ||
{ | ||
"petstore_auth": [ | ||
"write:pets", | ||
"read:pets" | ||
] | ||
} | ||
], | ||
"deprecated": true | ||
} | ||
}, | ||
"/pet/{petId}": { | ||
"get": { | ||
"tags": [ | ||
"pet" | ||
], | ||
"summary": "Find pet by ID", | ||
"description": "Returns a single pet", | ||
"operationId": "getPetById", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "petId", | ||
"in": "path", | ||
"description": "ID of pet to return", | ||
"required": true, | ||
"type": "integer", | ||
"format": "int64" | ||
} | ||
], | ||
"responses": { | ||
"200": { | ||
"description": "successful operation", | ||
"schema": { | ||
"$ref": "#/definitions/Pet" | ||
} | ||
}, | ||
"400": { | ||
"description": "Invalid ID supplied" | ||
}, | ||
"404": { | ||
"description": "Pet not found" | ||
} | ||
}, | ||
"security": [ | ||
{ | ||
"api_key": [] | ||
} | ||
] | ||
}, | ||
"post": { | ||
"tags": [ | ||
"pet" | ||
], | ||
"summary": "Updates a pet in the store with form data", | ||
"description": "", | ||
"operationId": "updatePetWithForm", | ||
"consumes": [ | ||
"application/x-www-form-urlencoded" | ||
], | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "petId", | ||
"in": "path", | ||
"description": "ID of pet that needs to be updated", | ||
"required": true, | ||
"type": "integer", | ||
"format": "int64" | ||
}, | ||
{ | ||
"name": "name", | ||
"in": "formData", | ||
"description": "Updated name of the pet", | ||
"required": false, | ||
"type": "string" | ||
}, | ||
{ | ||
"name": "status", | ||
"in": "formData", | ||
"description": "Updated status of the pet", | ||
"required": false, | ||
"type": "string" | ||
} | ||
], | ||
"responses": { | ||
"405": { | ||
"description": "Invalid input" | ||
} | ||
}, | ||
"security": [ | ||
{ | ||
"petstore_auth": [ | ||
"write:pets", | ||
"read:pets" | ||
] | ||
} | ||
] | ||
}, | ||
"delete": { | ||
"tags": [ | ||
"pet" | ||
], | ||
"summary": "Deletes a pet", | ||
"description": "", | ||
"operationId": "deletePet", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "api_key", | ||
"in": "header", | ||
"required": false, | ||
"type": "string" | ||
}, | ||
{ | ||
"name": "petId", | ||
"in": "path", | ||
"description": "Pet id to delete", | ||
"required": true, | ||
"type": "integer", | ||
"format": "int64" | ||
} | ||
], | ||
"responses": { | ||
"400": { | ||
"description": "Invalid ID supplied" | ||
}, | ||
"404": { | ||
"description": "Pet not found" | ||
} | ||
}, | ||
"security": [ | ||
{ | ||
"petstore_auth": [ | ||
"write:pets", | ||
"read:pets" | ||
] | ||
} | ||
] | ||
} | ||
}, | ||
"/pet/{petId}/uploadImage": { | ||
"post": { | ||
"tags": [ | ||
"pet" | ||
], | ||
"summary": "uploads an image", | ||
"description": "", | ||
"operationId": "uploadFile", | ||
"consumes": [ | ||
"multipart/form-data" | ||
], | ||
"produces": [ | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "petId", | ||
"in": "path", | ||
"description": "ID of pet to update", | ||
"required": true, | ||
"type": "integer", | ||
"format": "int64" | ||
}, | ||
{ | ||
"name": "additionalMetadata", | ||
"in": "formData", | ||
"description": "Additional data to pass to server", | ||
"required": false, | ||
"type": "string" | ||
}, | ||
{ | ||
"name": "file", | ||
"in": "formData", | ||
"description": "file to upload", | ||
"required": false, | ||
"type": "file" | ||
} | ||
], | ||
"responses": { | ||
"200": { | ||
"description": "successful operation", | ||
"schema": { | ||
"$ref": "#/definitions/ApiResponse" | ||
} | ||
} | ||
}, | ||
"security": [ | ||
{ | ||
"petstore_auth": [ | ||
"write:pets", | ||
"read:pets" | ||
] | ||
} | ||
] | ||
} | ||
}, | ||
"/store/inventory": { | ||
"get": { | ||
"tags": [ | ||
"store" | ||
], | ||
"summary": "Returns pet inventories by status", | ||
"description": "Returns a map of status codes to quantities", | ||
"operationId": "getInventory", | ||
"produces": [ | ||
"application/json" | ||
], | ||
"parameters": [], | ||
"responses": { | ||
"200": { | ||
"description": "successful operation", | ||
"schema": { | ||
"type": "object", | ||
"additionalProperties": { | ||
"type": "integer", | ||
"format": "int32" | ||
} | ||
} | ||
} | ||
}, | ||
"security": [ | ||
{ | ||
"api_key": [] | ||
} | ||
] | ||
} | ||
}, | ||
"/store/order": { | ||
"post": { | ||
"tags": [ | ||
"store" | ||
], | ||
"summary": "Place an order for a pet", | ||
"description": "", | ||
"operationId": "placeOrder", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"in": "body", | ||
"name": "body", | ||
"description": "order placed for purchasing the pet", | ||
"required": true, | ||
"schema": { | ||
"$ref": "#/definitions/Order" | ||
} | ||
} | ||
], | ||
"responses": { | ||
"200": { | ||
"description": "successful operation", | ||
"schema": { | ||
"$ref": "#/definitions/Order" | ||
} | ||
}, | ||
"400": { | ||
"description": "Invalid Order" | ||
} | ||
} | ||
} | ||
}, | ||
"/store/order/{orderId}": { | ||
"get": { | ||
"tags": [ | ||
"store" | ||
], | ||
"summary": "Find purchase order by ID", | ||
"description": "For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions", | ||
"operationId": "getOrderById", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "orderId", | ||
"in": "path", | ||
"description": "ID of pet that needs to be fetched", | ||
"required": true, | ||
"type": "integer", | ||
"maximum": 10.0, | ||
"minimum": 1.0, | ||
"format": "int64" | ||
} | ||
], | ||
"responses": { | ||
"200": { | ||
"description": "successful operation", | ||
"schema": { | ||
"$ref": "#/definitions/Order" | ||
} | ||
}, | ||
"400": { | ||
"description": "Invalid ID supplied" | ||
}, | ||
"404": { | ||
"description": "Order not found" | ||
} | ||
} | ||
}, | ||
"delete": { | ||
"tags": [ | ||
"store" | ||
], | ||
"summary": "Delete purchase order by ID", | ||
"description": "For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors", | ||
"operationId": "deleteOrder", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "orderId", | ||
"in": "path", | ||
"description": "ID of the order that needs to be deleted", | ||
"required": true, | ||
"type": "integer", | ||
"minimum": 1.0, | ||
"format": "int64" | ||
} | ||
], | ||
"responses": { | ||
"400": { | ||
"description": "Invalid ID supplied" | ||
}, | ||
"404": { | ||
"description": "Order not found" | ||
} | ||
} | ||
} | ||
}, | ||
"/user": { | ||
"post": { | ||
"tags": [ | ||
"user" | ||
], | ||
"summary": "Create user", | ||
"description": "This can only be done by the logged in user.", | ||
"operationId": "createUser", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"in": "body", | ||
"name": "body", | ||
"description": "Created user object", | ||
"required": true, | ||
"schema": { | ||
"$ref": "#/definitions/User" | ||
} | ||
} | ||
], | ||
"responses": { | ||
"default": { | ||
"description": "successful operation" | ||
} | ||
} | ||
} | ||
}, | ||
"/user/createWithArray": { | ||
"post": { | ||
"tags": [ | ||
"user" | ||
], | ||
"summary": "Creates list of users with given input array", | ||
"description": "", | ||
"operationId": "createUsersWithArrayInput", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"in": "body", | ||
"name": "body", | ||
"description": "List of user object", | ||
"required": true, | ||
"schema": { | ||
"type": "array", | ||
"items": { | ||
"$ref": "#/definitions/User" | ||
} | ||
} | ||
} | ||
], | ||
"responses": { | ||
"default": { | ||
"description": "successful operation" | ||
} | ||
} | ||
} | ||
}, | ||
"/user/createWithList": { | ||
"post": { | ||
"tags": [ | ||
"user" | ||
], | ||
"summary": "Creates list of users with given input array", | ||
"description": "", | ||
"operationId": "createUsersWithListInput", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"in": "body", | ||
"name": "body", | ||
"description": "List of user object", | ||
"required": true, | ||
"schema": { | ||
"type": "array", | ||
"items": { | ||
"$ref": "#/definitions/User" | ||
} | ||
} | ||
} | ||
], | ||
"responses": { | ||
"default": { | ||
"description": "successful operation" | ||
} | ||
} | ||
} | ||
}, | ||
"/user/login": { | ||
"get": { | ||
"tags": [ | ||
"user" | ||
], | ||
"summary": "Logs user into the system", | ||
"description": "", | ||
"operationId": "loginUser", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "username", | ||
"in": "query", | ||
"description": "The user name for login", | ||
"required": true, | ||
"type": "string" | ||
}, | ||
{ | ||
"name": "password", | ||
"in": "query", | ||
"description": "The password for login in clear text", | ||
"required": true, | ||
"type": "string" | ||
} | ||
], | ||
"responses": { | ||
"200": { | ||
"description": "successful operation", | ||
"schema": { | ||
"type": "string" | ||
}, | ||
"headers": { | ||
"X-Rate-Limit": { | ||
"type": "integer", | ||
"format": "int32", | ||
"description": "calls per hour allowed by the user" | ||
}, | ||
"X-Expires-After": { | ||
"type": "string", | ||
"format": "date-time", | ||
"description": "date in UTC when token expires" | ||
} | ||
} | ||
}, | ||
"400": { | ||
"description": "Invalid username/password supplied" | ||
} | ||
} | ||
} | ||
}, | ||
"/user/logout": { | ||
"get": { | ||
"tags": [ | ||
"user" | ||
], | ||
"summary": "Logs out current logged in user session", | ||
"description": "", | ||
"operationId": "logoutUser", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [], | ||
"responses": { | ||
"default": { | ||
"description": "successful operation" | ||
} | ||
} | ||
} | ||
}, | ||
"/user/{username}": { | ||
"get": { | ||
"tags": [ | ||
"user" | ||
], | ||
"summary": "Get user by user name", | ||
"description": "", | ||
"operationId": "getUserByName", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "username", | ||
"in": "path", | ||
"description": "The name that needs to be fetched. Use user1 for testing. ", | ||
"required": true, | ||
"type": "string" | ||
} | ||
], | ||
"responses": { | ||
"200": { | ||
"description": "successful operation", | ||
"schema": { | ||
"$ref": "#/definitions/User" | ||
} | ||
}, | ||
"400": { | ||
"description": "Invalid username supplied" | ||
}, | ||
"404": { | ||
"description": "User not found" | ||
} | ||
} | ||
}, | ||
"put": { | ||
"tags": [ | ||
"user" | ||
], | ||
"summary": "Updated user", | ||
"description": "This can only be done by the logged in user.", | ||
"operationId": "updateUser", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "username", | ||
"in": "path", | ||
"description": "name that need to be updated", | ||
"required": true, | ||
"type": "string" | ||
}, | ||
{ | ||
"in": "body", | ||
"name": "body", | ||
"description": "Updated user object", | ||
"required": true, | ||
"schema": { | ||
"$ref": "#/definitions/User" | ||
} | ||
} | ||
], | ||
"responses": { | ||
"400": { | ||
"description": "Invalid user supplied" | ||
}, | ||
"404": { | ||
"description": "User not found" | ||
} | ||
} | ||
}, | ||
"delete": { | ||
"tags": [ | ||
"user" | ||
], | ||
"summary": "Delete user", | ||
"description": "This can only be done by the logged in user.", | ||
"operationId": "deleteUser", | ||
"produces": [ | ||
"application/xml", | ||
"application/json" | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "username", | ||
"in": "path", | ||
"description": "The name that needs to be deleted", | ||
"required": true, | ||
"type": "string" | ||
} | ||
], | ||
"responses": { | ||
"400": { | ||
"description": "Invalid username supplied" | ||
}, | ||
"404": { | ||
"description": "User not found" | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
"securityDefinitions": { | ||
"petstore_auth": { | ||
"type": "oauth2", | ||
"authorizationUrl": "http://petstore.swagger.io/oauth/dialog", | ||
"flow": "implicit", | ||
"scopes": { | ||
"write:pets": "modify pets in your account", | ||
"read:pets": "read your pets" | ||
} | ||
}, | ||
"api_key": { | ||
"type": "apiKey", | ||
"name": "api_key", | ||
"in": "header" | ||
} | ||
}, | ||
"definitions": { | ||
"Order": { | ||
"type": "object", | ||
"properties": { | ||
"id": { | ||
"type": "integer", | ||
"format": "int64" | ||
}, | ||
"petId": { | ||
"type": "integer", | ||
"format": "int64" | ||
}, | ||
"quantity": { | ||
"type": "integer", | ||
"format": "int32" | ||
}, | ||
"shipDate": { | ||
"type": "string", | ||
"format": "date-time" | ||
}, | ||
"status": { | ||
"type": "string", | ||
"description": "Order Status", | ||
"enum": [ | ||
"placed", | ||
"approved", | ||
"delivered" | ||
] | ||
}, | ||
"complete": { | ||
"type": "boolean", | ||
"default": false | ||
} | ||
}, | ||
"xml": { | ||
"name": "Order" | ||
} | ||
}, | ||
"Category": { | ||
"type": "object", | ||
"properties": { | ||
"id": { | ||
"type": "integer", | ||
"format": "int64" | ||
}, | ||
"name": { | ||
"type": "string" | ||
} | ||
}, | ||
"xml": { | ||
"name": "Category" | ||
} | ||
}, | ||
"User": { | ||
"type": "object", | ||
"properties": { | ||
"id": { | ||
"type": "integer", | ||
"format": "int64" | ||
}, | ||
"username": { | ||
"type": "string" | ||
}, | ||
"firstName": { | ||
"type": "string" | ||
}, | ||
"lastName": { | ||
"type": "string" | ||
}, | ||
"email": { | ||
"type": "string" | ||
}, | ||
"password": { | ||
"type": "string" | ||
}, | ||
"phone": { | ||
"type": "string" | ||
}, | ||
"userStatus": { | ||
"type": "integer", | ||
"format": "int32", | ||
"description": "User Status" | ||
} | ||
}, | ||
"xml": { | ||
"name": "User" | ||
} | ||
}, | ||
"Tag": { | ||
"type": "object", | ||
"properties": { | ||
"id": { | ||
"type": "integer", | ||
"format": "int64" | ||
}, | ||
"name": { | ||
"type": "string" | ||
} | ||
}, | ||
"xml": { | ||
"name": "Tag" | ||
} | ||
}, | ||
"Pet": { | ||
"type": "object", | ||
"required": [ | ||
"name", | ||
"photoUrls" | ||
], | ||
"properties": { | ||
"id": { | ||
"type": "integer", | ||
"format": "int64" | ||
}, | ||
"category": { | ||
"$ref": "#/definitions/Category" | ||
}, | ||
"name": { | ||
"type": "string", | ||
"example": "doggie" | ||
}, | ||
"photoUrls": { | ||
"type": "array", | ||
"xml": { | ||
"name": "photoUrl", | ||
"wrapped": true | ||
}, | ||
"items": { | ||
"type": "string" | ||
} | ||
}, | ||
"tags": { | ||
"type": "array", | ||
"xml": { | ||
"name": "tag", | ||
"wrapped": true | ||
}, | ||
"items": { | ||
"$ref": "#/definitions/Tag" | ||
} | ||
}, | ||
"status": { | ||
"type": "string", | ||
"description": "pet status in the store", | ||
"enum": [ | ||
"available", | ||
"pending", | ||
"sold" | ||
] | ||
} | ||
}, | ||
"xml": { | ||
"name": "Pet" | ||
} | ||
}, | ||
"ApiResponse": { | ||
"type": "object", | ||
"properties": { | ||
"code": { | ||
"type": "integer", | ||
"format": "int32" | ||
}, | ||
"type": { | ||
"type": "string" | ||
}, | ||
"message": { | ||
"type": "string" | ||
} | ||
} | ||
} | ||
}, | ||
"externalDocs": { | ||
"description": "Find out more about Swagger", | ||
"url": "http://swagger.io" | ||
} | ||
} |
@@ -164,3 +164,3 @@ import {exec} from 'child_process'; | ||
expect(result).toEqual(jasmine.stringMatching('0 breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('3 non-breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('4 non-breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('2 unclassified changes found.')); | ||
@@ -177,2 +177,5 @@ | ||
expect(result).toContain('Non-breaking: the path [swagger] was modified ' + | ||
'from \'2.0\' to \'2.1\''); | ||
expect(result).toContain('Unclassified: the path [info/x-info-property] was modified ' + | ||
@@ -193,5 +196,8 @@ 'from \'some content\' to \'some new content\''); | ||
expect(result).toEqual(jasmine.stringMatching('0 breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('2 non-breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('3 non-breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('0 unclassified changes found.')); | ||
expect(result).toContain('Non-breaking: the path [swagger] was modified ' + | ||
'from \'2.0\' to \'2.1\''); | ||
expect(result).toContain('Non-breaking: the path [info/version] was modified ' + | ||
@@ -204,2 +210,28 @@ 'from \'1.0.0\' to \'1.0.1\''); | ||
}); | ||
it('should be able to process real OpenApi 3.0.0 files', (done) => { | ||
invokeCommand({ | ||
newSpecLocation: 'test/e2e/fixtures/openapi-3-new.json', | ||
oldSpecLocation: 'test/e2e/fixtures/openapi-3-old.json' | ||
}).then((result) => { | ||
expect(result).toEqual(jasmine.stringMatching('0 breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('3 non-breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('2 unclassified changes found.')); | ||
expect(result).toContain('Non-breaking: the path [openapi] was modified ' + | ||
'from \'3.0.0\' to \'3.0.0-RC1\''); | ||
expect(result).toContain('Non-breaking: the path [info/version] was modified ' + | ||
'from \'Test version\' to \'New test version\''); | ||
expect(result).toContain('Non-breaking: the path [info/title] was modified ' + | ||
'from \'Test API\' to \'New test API\''); | ||
expect(result).toContain('Unclassified: the path [info/x-info-property] was modified ' + | ||
'from \'Some content\' to \'Some new content\''); | ||
expect(result).toContain('Unclassified: the path [x-generic-property] was modified ' + | ||
'from \'Some content\' to \'Some new content\''); | ||
}).then(done, done.fail); | ||
}); | ||
}); |
import specDiffer from '../../../lib/openapi-diff/spec-differ'; | ||
import { | ||
@@ -7,87 +8,44 @@ Diff, | ||
let result: Diff; | ||
describe('specDiffer', () => { | ||
const buildParsedSpecWithFullInfoObject = (): ParsedSpec => { | ||
const spec = { | ||
info: { | ||
contact: { | ||
email: 'contact email', | ||
name: 'contact name', | ||
url: 'contact url' | ||
}, | ||
description: 'spec description', | ||
licence: { | ||
name: 'licence name', | ||
url: 'licence url' | ||
}, | ||
termsOfService: 'terms of service', | ||
title: 'spec title', | ||
version: 'version' | ||
}, | ||
openapi: { | ||
originalPath: ['openapi'], | ||
parsedValue: '3.0.0' | ||
} | ||
}; | ||
return spec; | ||
}; | ||
describe('when there is a single change in the info object', () => { | ||
beforeEach(() => { | ||
const oldParsedSpec = buildParsedSpecWithFullInfoObject(); | ||
const newParsedSpec = buildParsedSpecWithFullInfoObject(); | ||
newParsedSpec.info.title = 'NEW spec title'; | ||
result = specDiffer.diff(oldParsedSpec, newParsedSpec); | ||
}); | ||
it('should classify a single change in the info object as non-breaking', () => { | ||
const oldSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'old contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'old spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
const newSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'old contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'new spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
const result: Diff = specDiffer.diff(oldSpec, newSpec); | ||
expect(result.breakingChanges.length).toEqual(0); | ||
expect(result.unclassifiedChanges.length).toEqual(0); | ||
expect(result.nonBreakingChanges.length).toBe(1); | ||
}); | ||
it('should populate the type of a single change in the info object as non-breaking', () => { | ||
const oldSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'old contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'old spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
const newSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'old contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'new spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
const result: Diff = specDiffer.diff(oldSpec, newSpec); | ||
expect(result.nonBreakingChanges[0].type).toEqual('non-breaking'); | ||
@@ -97,124 +55,15 @@ }); | ||
it('should populate the taxonomy of a single change in the info object as an edition in it', () => { | ||
const oldSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'old contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'old spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
const newSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'old contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'new spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
const result: Diff = specDiffer.diff(oldSpec, newSpec); | ||
expect(result.nonBreakingChanges[0].taxonomy).toEqual('info.object.edit'); | ||
}); | ||
it('should populate the path of a single change in the info object correctly', () => { | ||
const oldSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'old contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'old spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
const newSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'old contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'new spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
const result: Diff = specDiffer.diff(oldSpec, newSpec); | ||
it('should populate the paths of a single change in the info object correctly', () => { | ||
expect(result.nonBreakingChanges[0].path[0]).toEqual('info'); | ||
expect(result.nonBreakingChanges[0].path[1]).toEqual('title'); | ||
expect(result.nonBreakingChanges[0].printablePath[0]).toEqual('info'); | ||
expect(result.nonBreakingChanges[0].printablePath[1]).toEqual('title'); | ||
}); | ||
it('should copy the rest of the individual diff attributes across', () => { | ||
const oldSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'old contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'old spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
const newSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'old contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'new spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
const result: Diff = specDiffer.diff(oldSpec, newSpec); | ||
expect(result.nonBreakingChanges[0].lhs).toEqual('old spec title'); | ||
expect(result.nonBreakingChanges[0].rhs).toEqual('new spec title'); | ||
expect(result.nonBreakingChanges[0].lhs).toEqual('spec title'); | ||
expect(result.nonBreakingChanges[0].rhs).toEqual('NEW spec title'); | ||
expect(result.nonBreakingChanges[0].index).toBeNull(); | ||
@@ -227,83 +76,19 @@ expect(result.nonBreakingChanges[0].item).toBeNull(); | ||
it('should classify multiple changes in the info object as non-breaking', () => { | ||
const oldSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'old contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'old spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
beforeEach(() => { | ||
const oldParsedSpec = buildParsedSpecWithFullInfoObject(); | ||
const newParsedSpec = buildParsedSpecWithFullInfoObject(); | ||
newParsedSpec.info.title = 'NEW spec title'; | ||
const newSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'new contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'new spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
if (newParsedSpec.info.contact) { | ||
newParsedSpec.info.contact.name = 'NEW contact name'; | ||
} else { | ||
fail('Unexpected mock spec attributes missing'); | ||
} | ||
result = specDiffer.diff(oldParsedSpec, newParsedSpec); | ||
}); | ||
const result: Diff = specDiffer.diff(oldSpec, newSpec); | ||
it('should classify multiple changes in the info object as non-breaking', () => { | ||
expect(result.breakingChanges.length).toEqual(0); | ||
expect(result.unclassifiedChanges.length).toEqual(0); | ||
expect(result.nonBreakingChanges.length).toEqual(2); | ||
}); | ||
it('should populate the types of multiple changes in the info object as non-breaking', () => { | ||
const oldSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'old contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'old spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
const newSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'new contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'new spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
const result: Diff = specDiffer.diff(oldSpec, newSpec); | ||
expect(result.nonBreakingChanges[0].type).toEqual('non-breaking'); | ||
@@ -314,39 +99,2 @@ expect(result.nonBreakingChanges[1].type).toEqual('non-breaking'); | ||
it('should populate the taxonomy of multiple changes in the info object as an edition to it', () => { | ||
const oldSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'old contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'old spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
const newSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'new contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'new spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
const result: Diff = specDiffer.diff(oldSpec, newSpec); | ||
expect(result.nonBreakingChanges[0].taxonomy).toEqual('info.object.edit'); | ||
@@ -356,89 +104,16 @@ expect(result.nonBreakingChanges[1].taxonomy).toEqual('info.object.edit'); | ||
it('should populate the path of the multiple changes in the info object correctly', () => { | ||
const oldSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'old contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'old spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
it('should populate the paths of the multiple changes in the info object correctly', () => { | ||
expect(result.nonBreakingChanges[0].path[0]).toEqual('info'); | ||
expect(result.nonBreakingChanges[0].path[1]).toEqual('contact'); | ||
expect(result.nonBreakingChanges[0].path[2]).toEqual('name'); | ||
expect(result.nonBreakingChanges[0].printablePath[0]).toEqual('info'); | ||
expect(result.nonBreakingChanges[0].printablePath[1]).toEqual('contact'); | ||
expect(result.nonBreakingChanges[0].printablePath[2]).toEqual('name'); | ||
const newSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'old contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'new spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
const result: Diff = specDiffer.diff(oldSpec, newSpec); | ||
expect(result.nonBreakingChanges[0].path[0]).toEqual('info'); | ||
expect(result.nonBreakingChanges[0].path[1]).toEqual('title'); | ||
expect(result.nonBreakingChanges[1].path[0]).toEqual('info'); | ||
expect(result.nonBreakingChanges[1].path[1]).toEqual('title'); | ||
expect(result.nonBreakingChanges[1].printablePath[0]).toEqual('info'); | ||
expect(result.nonBreakingChanges[1].printablePath[1]).toEqual('title'); | ||
}); | ||
}); | ||
it('should populate the path of the multiple changes in the info object correctly when nested', () => { | ||
const oldSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'old contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'old spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
const newSpec: ParsedSpec = { | ||
info: { | ||
contact: { | ||
email: 'old contact email', | ||
name: 'new contact name', | ||
url: 'old contact url' | ||
}, | ||
description: 'old spec description', | ||
licence: { | ||
name: 'old licence name', | ||
url: 'old licence url' | ||
}, | ||
termsOfService: 'old terms of service', | ||
title: 'old spec title', | ||
version: 'old version' | ||
} | ||
}; | ||
const result: Diff = specDiffer.diff(oldSpec, newSpec); | ||
expect(result.nonBreakingChanges[0].path[0]).toEqual('info'); | ||
expect(result.nonBreakingChanges[0].path[1]).toEqual('contact'); | ||
expect(result.nonBreakingChanges[0].path[2]).toEqual('name'); | ||
}); | ||
}); |
import specParser from '../../../lib/openapi-diff/spec-parser'; | ||
import {OpenAPISpec, ParsedSpec} from '../../../lib/openapi-diff/types'; | ||
import {OpenAPI3Spec, ParsedSpec} from '../../../lib/openapi-diff/types'; | ||
let resultingSpec: ParsedSpec; | ||
describe('specParser, with regards to the info object,', () => { | ||
const buildSimpleOpenApi3Spec = (): OpenAPI3Spec => { | ||
const spec = { | ||
info: { | ||
title: 'spec title', | ||
version: 'spec version' | ||
}, | ||
openapi: '3.0.0' | ||
}; | ||
return spec; | ||
}; | ||
const buildOpenApi3SpecWithCompleteInfoObject = (): OpenAPI3Spec => { | ||
const spec = { | ||
info: { | ||
contact: { | ||
email: 'contact email', | ||
name: 'contact name', | ||
url: 'contact url' | ||
}, | ||
description: 'spec description', | ||
licence: { | ||
name: 'licence name', | ||
url: 'licence url' | ||
}, | ||
termsOfService: 'terms of service', | ||
title: 'spec title', | ||
version: 'version' | ||
}, | ||
openapi: '3.0.0' | ||
}; | ||
return spec; | ||
}; | ||
describe('when the original spec has all the default fields populated', () => { | ||
beforeEach(() => { | ||
const originalSpec = buildOpenApi3SpecWithCompleteInfoObject(); | ||
resultingSpec = specParser.parse(originalSpec); | ||
}); | ||
it('should generate a parsed spec with an info object', () => { | ||
const originalSpec: OpenAPISpec = { | ||
info: { | ||
contact: { | ||
email: 'contact email', | ||
name: 'contact name', | ||
url: 'contact url' | ||
}, | ||
description: 'spec description', | ||
licence: { | ||
name: 'licence name', | ||
url: 'licence url' | ||
}, | ||
termsOfService: 'terms of service', | ||
title: 'spec title', | ||
version: 'version' | ||
} | ||
}; | ||
const resultingSpec: OpenAPISpec = specParser.parse(originalSpec); | ||
expect(resultingSpec.info).toBeDefined(); | ||
@@ -33,21 +53,2 @@ }); | ||
it('should generate a parsed spec copying across all the default fields to the info object', () => { | ||
const originalSpec: OpenAPISpec = { | ||
info: { | ||
contact: { | ||
email: 'contact email', | ||
name: 'contact name', | ||
url: 'contact url' | ||
}, | ||
description: 'spec description', | ||
licence: { | ||
name: 'licence name', | ||
url: 'licence url' | ||
}, | ||
termsOfService: 'terms of service', | ||
title: 'spec title', | ||
version: 'version' | ||
} | ||
}; | ||
const resultingSpec: OpenAPISpec = specParser.parse(originalSpec); | ||
expect(resultingSpec.info.title).toBe('spec title'); | ||
@@ -77,12 +78,8 @@ expect(resultingSpec.info.description).toBe('spec description'); | ||
beforeEach(() => { | ||
const originalSpec = buildSimpleOpenApi3Spec(); | ||
resultingSpec = specParser.parse(originalSpec); | ||
}); | ||
it('should generate a parsed spec with an info object', () => { | ||
const originalSpec: OpenAPISpec = { | ||
info: { | ||
title: 'spec title', | ||
version: 'version' | ||
} | ||
}; | ||
const resultingSpec: ParsedSpec = specParser.parse(originalSpec); | ||
expect(resultingSpec.info).toBeDefined(); | ||
@@ -92,12 +89,4 @@ }); | ||
it('should generate a parsed spec copying across only the required fields to the info object', () => { | ||
const originalSpec: OpenAPISpec = { | ||
info: { | ||
title: 'spec title', | ||
version: 'version' | ||
} | ||
}; | ||
const resultingSpec: ParsedSpec = specParser.parse(originalSpec); | ||
expect(resultingSpec.info.title).toBe('spec title'); | ||
expect(resultingSpec.info.version).toBe('version'); | ||
expect(resultingSpec.info.version).toBe('spec version'); | ||
}); | ||
@@ -108,13 +97,9 @@ }); | ||
beforeEach(() => { | ||
const originalSpec = buildSimpleOpenApi3Spec(); | ||
originalSpec.info['x-external-id'] = 'some id'; | ||
resultingSpec = specParser.parse(originalSpec); | ||
}); | ||
it('should generate a parsed spec with an info object', () => { | ||
const originalSpec: OpenAPISpec = { | ||
info: { | ||
title: 'spec title', | ||
version: 'version', | ||
'x-external-id': 'some id' | ||
} | ||
}; | ||
const resultingSpec: ParsedSpec = specParser.parse(originalSpec); | ||
expect(resultingSpec.info).toBeDefined(); | ||
@@ -124,31 +109,5 @@ }); | ||
it('should generate a parsed spec copying across the x-property and its value', () => { | ||
const originalSpec: OpenAPISpec = { | ||
info: { | ||
title: 'spec title', | ||
version: 'version', | ||
'x-external-id': 'some id' | ||
} | ||
}; | ||
const resultingSpec: ParsedSpec = specParser.parse(originalSpec); | ||
expect(resultingSpec.info['x-external-id']).toBe('some id'); | ||
}); | ||
}); | ||
describe('when the original spec has an x-property at the top level', () => { | ||
it('should generate a parsed spec copying across the x-property and its value', () => { | ||
const originalSpec: OpenAPISpec = { | ||
info: { | ||
title: 'spec title', | ||
version: 'version' | ||
}, | ||
'x-external-id': 'some id' | ||
}; | ||
const resultingSpec: ParsedSpec = specParser.parse(originalSpec); | ||
expect(resultingSpec['x-external-id']).toBe('some id'); | ||
}); | ||
}); | ||
}); |
import specParser from '../../../lib/openapi-diff/spec-parser'; | ||
import {OpenAPISpec, ParsedSpec} from '../../../lib/openapi-diff/types'; | ||
import {OpenAPI3Spec, ParsedSpec} from '../../../lib/openapi-diff/types'; | ||
@@ -10,3 +10,3 @@ describe('specParser, with regards to the top level object,', () => { | ||
const originalSpec: OpenAPISpec = { | ||
const originalSpec: OpenAPI3Spec = { | ||
info: { | ||
@@ -16,2 +16,3 @@ title: 'spec title', | ||
}, | ||
openapi: '3.0.0', | ||
'x-external-id': 'some id', | ||
@@ -18,0 +19,0 @@ 'x-internal-id': 'some other id' |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
126463
53
3800
36
2