openapi-diff
Advanced tools
Comparing version 0.5.0 to 0.6.0
@@ -0,1 +1,16 @@ | ||
<a name="0.6.0"></a> | ||
# [0.6.0](https://bitbucket.org/atlassian/openapi-diff/compare/0.5.0...0.6.0) (2018-01-23) | ||
### Features | ||
* **core:** Load specs from YAML sources ([6d0f5e4](https://bitbucket.org/atlassian/openapi-diff/commits/6d0f5e4)) | ||
### Reverts | ||
* unbump changelog dependencies for ci health ([18ae0d8](https://bitbucket.org/atlassian/openapi-diff/commits/18ae0d8)) | ||
<a name="0.5.0"></a> | ||
@@ -2,0 +17,0 @@ # [0.5.0](https://bitbucket.org/atlassian/openapi-diff/compare/0.4.0...0.5.0) (2017-08-17) |
#! /usr/bin/env node | ||
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -20,5 +28,5 @@ const commander = require("commander"); | ||
The <old> spec and <new> spec arguments should be paths to where the specs live in your filesystem.`) | ||
.action((oldSpecPath, newSpecPath) => { | ||
openapi_diff_1.default.run(oldSpecPath, newSpecPath) | ||
.then((results) => { | ||
.action((oldSpecPath, newSpecPath) => __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
const results = yield openapi_diff_1.openApiDiff.run(oldSpecPath, newSpecPath); | ||
console.log(`* OpenAPI Diff v${packageJson.version} *`); | ||
@@ -45,7 +53,8 @@ console.log(newLineChar); | ||
} | ||
}).catch((error) => { | ||
} | ||
catch (error) { | ||
console.error(error.message); | ||
process.exit(2); | ||
}); | ||
}) | ||
} | ||
})) | ||
.parse(process.argv); | ||
@@ -52,0 +61,0 @@ if (!commander.args.length) { |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const q = require("q"); | ||
const json_loader_1 = require("./openapi-diff/json-loader"); | ||
const file_system_1 = require("./openapi-diff/json-loader/file-system"); | ||
const http_client_1 = require("./openapi-diff/json-loader/http-client"); | ||
const file_system_1 = require("./openapi-diff/resource-loader/file-system"); | ||
const http_client_1 = require("./openapi-diff/resource-loader/http-client"); | ||
const result_reporter_1 = require("./openapi-diff/result-reporter"); | ||
const spec_differ_1 = require("./openapi-diff/spec-differ"); | ||
const spec_loader_1 = require("./openapi-diff/spec-loader"); | ||
const spec_parser_1 = require("./openapi-diff/spec-parser"); | ||
const openApiDiff = { | ||
run: (oldSpecPath, newSpecPath) => { | ||
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); | ||
const whenResults = whenDiff.then(result_reporter_1.default.build); | ||
return whenResults; | ||
} | ||
exports.openApiDiff = { | ||
run: (oldSpecPath, newSpecPath) => __awaiter(this, void 0, void 0, function* () { | ||
const whenOldSpec = spec_loader_1.default.load(oldSpecPath, file_system_1.default, http_client_1.default); | ||
const whenNewSpec = spec_loader_1.default.load(newSpecPath, file_system_1.default, http_client_1.default); | ||
const rawSpecs = yield Promise.all([whenOldSpec, whenNewSpec]); | ||
const oldSpec = rawSpecs[0]; | ||
const oldParsedSpec = spec_parser_1.default.parse(oldSpec); | ||
const newSpec = rawSpecs[1]; | ||
const newParsedSpec = spec_parser_1.default.parse(newSpec); | ||
const diff = spec_differ_1.default.diff(oldParsedSpec, newParsedSpec); | ||
const results = result_reporter_1.default.build(diff); | ||
return results; | ||
}) | ||
}; | ||
exports.default = openApiDiff; |
@@ -6,3 +6,3 @@ #! /usr/bin/env node | ||
import openApiDiff from './openapi-diff'; | ||
import {openApiDiff} from './openapi-diff'; | ||
@@ -25,5 +25,6 @@ // tslint:disable:no-var-requires | ||
The <old> spec and <new> spec arguments should be paths to where the specs live in your filesystem.`) | ||
.action((oldSpecPath, newSpecPath) => { | ||
openApiDiff.run(oldSpecPath, newSpecPath) | ||
.then((results) => { | ||
.action(async (oldSpecPath, newSpecPath) => { | ||
try { | ||
const results = await openApiDiff.run(oldSpecPath, newSpecPath); | ||
console.log(`* OpenAPI Diff v${packageJson.version} *`); | ||
@@ -54,6 +55,6 @@ console.log(newLineChar); | ||
} | ||
}).catch((error) => { | ||
} catch (error) { | ||
console.error(error.message); | ||
process.exit(2); | ||
}); | ||
} | ||
}) | ||
@@ -60,0 +61,0 @@ .parse(process.argv); |
@@ -1,28 +0,28 @@ | ||
import { OpenAPIDiff } from './openapi-diff/types'; | ||
import {OpenAPIDiff} from './openapi-diff/types'; | ||
import * as q from 'q'; | ||
import jsonLoader from './openapi-diff/json-loader'; | ||
import fileSystem from './openapi-diff/json-loader/file-system'; | ||
import httpClient from './openapi-diff/json-loader/http-client'; | ||
import fileSystem from './openapi-diff/resource-loader/file-system'; | ||
import httpClient from './openapi-diff/resource-loader/http-client'; | ||
import resultReporter from './openapi-diff/result-reporter'; | ||
import specDiffer from './openapi-diff/spec-differ'; | ||
import jsonLoader from './openapi-diff/spec-loader'; | ||
import specParser from './openapi-diff/spec-parser'; | ||
const openApiDiff: OpenAPIDiff = { | ||
run: (oldSpecPath, newSpecPath) => { | ||
export const openApiDiff: OpenAPIDiff = { | ||
run: async (oldSpecPath, newSpecPath) => { | ||
const whenOldSpec = jsonLoader.load(oldSpecPath, fileSystem, httpClient); | ||
const whenParsedOldSpec = whenOldSpec.then(specParser.parse); | ||
const whenNewSpec = jsonLoader.load(newSpecPath, fileSystem, httpClient); | ||
const whenParsedNewSpec = whenNewSpec.then(specParser.parse); | ||
const rawSpecs = await Promise.all([whenOldSpec, whenNewSpec]); | ||
const whenDiff = q.all([whenParsedOldSpec, whenParsedNewSpec]).spread(specDiffer.diff); | ||
const oldSpec = rawSpecs[0]; | ||
const oldParsedSpec = specParser.parse(oldSpec); | ||
const whenResults = whenDiff.then(resultReporter.build); | ||
const newSpec = rawSpecs[1]; | ||
const newParsedSpec = specParser.parse(newSpec); | ||
return whenResults; | ||
const diff = specDiffer.diff(oldParsedSpec, newParsedSpec); | ||
const results = resultReporter.build(diff); | ||
return results; | ||
} | ||
}; | ||
export default openApiDiff; |
// Diff types | ||
import * as q from 'q'; | ||
@@ -117,3 +116,3 @@ export interface DiffEntry { | ||
export interface FileSystem { | ||
readFile: JsonLoaderFunction; | ||
readFile: ResourceLoaderFunction; | ||
} | ||
@@ -127,9 +126,9 @@ | ||
export interface HttpClient { | ||
get: JsonLoaderFunction; | ||
get: ResourceLoaderFunction; | ||
} | ||
export type JsonLoaderFunction = (location: string) => q.Promise<string>; | ||
export type ResourceLoaderFunction = (location: string) => Promise<string>; | ||
export interface OpenAPIDiff { | ||
run: (oldSpecPath: string, newSpecPath: string) => q.Promise<ResultObject>; | ||
run: (oldSpecPath: string, newSpecPath: string) => Promise<ResultObject>; | ||
} |
{ | ||
"name": "openapi-diff", | ||
"version": "0.5.0", | ||
"version": "0.6.0", | ||
"description": "A CLI tool to identify differences between Swagger/OpenAPI specs.", | ||
@@ -36,31 +36,31 @@ "bin": { | ||
"devDependencies": { | ||
"@types/commander": "^2.9.1", | ||
"@types/express": "^4.0.36", | ||
"@types/jasmine": "^2.5.52", | ||
"@types/lodash": "^4.14.66", | ||
"@types/q": "^1.0.2", | ||
"@types/request": "0.0.45", | ||
"@types/swagger-schema-official": "^2.0.5", | ||
"@types/verror": "^1.10.0", | ||
"conventional-changelog-lint": "^1.1.9", | ||
"@types/commander": "^2.9.2", | ||
"@types/express": "^4.0.37", | ||
"@types/jasmine": "^2.8.4", | ||
"@types/js-yaml": "^3.10.1", | ||
"@types/lodash": "^4.14.74", | ||
"@types/request": "^2.0.3", | ||
"@types/swagger-schema-official": "^2.0.6", | ||
"@types/verror": "^1.10.1", | ||
"conventional-changelog-lint": "1.1.9", | ||
"del": "^3.0.0", | ||
"express": "^4.15.3", | ||
"express": "^4.15.4", | ||
"gulp": "^3.9.1", | ||
"gulp-clean": "^0.3.2", | ||
"gulp-conventional-changelog": "^1.1.3", | ||
"gulp-conventional-changelog": "^1.1.4", | ||
"gulp-git": "^2.4.1", | ||
"gulp-jasmine": "^2.4.2", | ||
"gulp-tslint": "^8.1.1", | ||
"gulp-typescript": "^3.1.7", | ||
"jasmine": "^2.7.0", | ||
"gulp-tslint": "^8.1.2", | ||
"gulp-typescript": "^3.2.2", | ||
"jasmine": "^2.8.0", | ||
"minimist": "^1.2.0", | ||
"run-sequence": "^1.2.2", | ||
"tslint": "5.4.3", | ||
"typescript": "2.3.4" | ||
"run-sequence": "^2.1.0", | ||
"tslint": "5.7.0", | ||
"typescript": "2.5.3" | ||
}, | ||
"dependencies": { | ||
"commander": "^2.10.0", | ||
"commander": "^2.11.0", | ||
"js-yaml": "^3.10.0", | ||
"lodash": "^4.17.4", | ||
"openapi3-ts": "^0.2.1", | ||
"q": "^1.5.0", | ||
"openapi3-ts": "^0.5.0", | ||
"request": "^2.81.0", | ||
@@ -67,0 +67,0 @@ "verror": "^1.10.0" |
@@ -16,3 +16,3 @@ # OpenAPI Diff | ||
## Usage | ||
Invoke the tool with two paths to Swagger/OpenAPI files in order to find differences between them, these paths can either be paths to the specs in the local filesystem or URLs to the specs (sorry, no YML support just yet). | ||
Invoke the tool with two paths to Swagger/OpenAPI files in order to find differences between them, these paths can either be paths to the specs in the local filesystem or URLs to the specs, both JSON and YAML are supported. | ||
The Open API specs should be in JSON format. | ||
@@ -23,4 +23,8 @@ ``` | ||
The tool's output will display the amount and type of changes (breaking, non-breaking, unclassified), and then list the changes with the relevant info. | ||
The tool's output will display the amount and type of changes, and then list the changes with the relevant info. Changes are classified as follows: | ||
* Breaking: changes that would make existing consumers incompatible with the API (deletion of paths, adding required properties...) | ||
* Non-breaking: changes that would **not** make existing consumers incompatible with the API (addition of paths, turning a required property into optional...) | ||
* Unclassified: changes that have been detected by the tool but can't be classified (modifications to X-Properties and other unforeseen changes) | ||
The command will exit with an exit code 1 if any breaking changes were found, so that you can fail builds in CI when this happens. | ||
@@ -27,0 +31,0 @@ |
import {exec} from 'child_process'; | ||
import {resolve} from 'path'; | ||
import ErrnoException = NodeJS.ErrnoException; | ||
import * as express from 'express'; | ||
import * as http from 'http'; | ||
import * as q from 'q'; | ||
import * as path from 'path'; | ||
import ErrnoException = NodeJS.ErrnoException; | ||
import * as VError from 'verror'; | ||
import expectToFail from '../support/expect-to-fail'; | ||
interface InvokeCommandOptions { | ||
@@ -16,18 +16,17 @@ newSpecLocation: string; | ||
const invokeCommand = (options: InvokeCommandOptions): Promise<string> => { | ||
const deferred = q.defer(); | ||
const command = `./bin/openapi-diff-local ${options.oldSpecLocation} ${options.newSpecLocation}`; | ||
exec(command, (error: ErrnoException, stdout, stderr) => { | ||
if (error) { | ||
deferred.reject(new VError(error, `Failed to run ${command}. ` | ||
+ `Stdout: ${stdout.toString()}. Exit code: ${error.code}`)); | ||
} else if (stderr) { | ||
deferred.reject(stderr); | ||
} else { | ||
deferred.resolve(stdout.toString()); | ||
} | ||
return new Promise((resolve, reject) => { | ||
exec(command, (error: ErrnoException, stdout, stderr) => { | ||
if (error) { | ||
reject(new VError(error, `Failed to run ${command}. ` | ||
+ `Stdout: ${stdout.toString()}. Exit code: ${error.code}`)); | ||
} else if (stderr) { | ||
reject(stderr); | ||
} else { | ||
resolve(stdout.toString()); | ||
} | ||
}); | ||
}); | ||
return deferred.promise as any; | ||
}; | ||
@@ -49,246 +48,247 @@ | ||
it('should work with absolute path files', (done) => { | ||
const currentDir = resolve(process.cwd()); | ||
invokeCommand({ | ||
it('should work with absolute path yaml files', async () => { | ||
const currentDir = path.resolve(process.cwd()); | ||
const result = await invokeCommand({ | ||
newSpecLocation: `${currentDir}/test/e2e/fixtures/basic-new.yaml`, | ||
oldSpecLocation: `${currentDir}/test/e2e/fixtures/basic-old.yaml` | ||
}); | ||
expect(result).toEqual(jasmine.stringMatching(`Old spec: ${currentDir}/test/e2e/fixtures/basic-old.yaml`)); | ||
expect(result).toEqual(jasmine.stringMatching(`New spec: ${currentDir}/test/e2e/fixtures/basic-new.yaml`)); | ||
expect(result).toEqual(jasmine.stringMatching('0 breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('1 non-breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('0 unclassified changes found.')); | ||
}); | ||
it('should work with absolute path json files', async () => { | ||
const currentDir = path.resolve(process.cwd()); | ||
const result = await invokeCommand({ | ||
newSpecLocation: `${currentDir}/test/e2e/fixtures/basic-new.json`, | ||
oldSpecLocation: `${currentDir}/test/e2e/fixtures/basic-old.json` | ||
}).then((result) => { | ||
expect(result).toEqual(jasmine.stringMatching(`Old spec: ${currentDir}/test/e2e/fixtures/basic-old.json`)); | ||
expect(result).toEqual(jasmine.stringMatching(`New spec: ${currentDir}/test/e2e/fixtures/basic-new.json`)); | ||
expect(result).toEqual(jasmine.stringMatching('0 breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('1 non-breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('0 unclassified changes found.')); | ||
}).then(done, done.fail); | ||
}); | ||
expect(result).toEqual(jasmine.stringMatching(`Old spec: ${currentDir}/test/e2e/fixtures/basic-old.json`)); | ||
expect(result).toEqual(jasmine.stringMatching(`New spec: ${currentDir}/test/e2e/fixtures/basic-new.json`)); | ||
expect(result).toEqual(jasmine.stringMatching('0 breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('1 non-breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('0 unclassified changes found.')); | ||
}); | ||
it('should error gently when unable to find files on the local filesystem', (done) => { | ||
invokeCommand({ | ||
it('should error gently when unable to find files on the local filesystem', async () => { | ||
const error = await expectToFail(invokeCommand({ | ||
newSpecLocation: 'test/e2e/fixtures/non-existing-new.json', | ||
oldSpecLocation: 'test/e2e/fixtures/non-existing-old.json' | ||
}).then(() => { | ||
fail('test expected to error out but it didn\'t'); | ||
}).catch((error) => { | ||
expect(error).toEqual(jasmine.stringMatching('ERROR: unable to read ' + | ||
'test/e2e/fixtures/non-existing-old.json')); | ||
})); | ||
expect(error).toEqual(jasmine.stringMatching('Exit code: 2')); | ||
}).then(done, done.fail); | ||
expect(error).toEqual(jasmine.stringMatching('ERROR: unable to read ' + | ||
'test/e2e/fixtures/non-existing-old.json')); | ||
expect(error).toEqual(jasmine.stringMatching('Exit code: 2')); | ||
}); | ||
it('should error gently when unable to parse files as json from the local filesystem', (done) => { | ||
invokeCommand({ | ||
newSpecLocation: 'test/e2e/fixtures/not-a-json.txt', | ||
oldSpecLocation: 'test/e2e/fixtures/not-a-json.txt' | ||
}).then(() => { | ||
fail('test expected to error out but it didn\'t'); | ||
}).catch((error) => { | ||
expect(error).toEqual(jasmine.stringMatching('ERROR: unable to parse ' + | ||
'test/e2e/fixtures/not-a-json.txt as a JSON file')); | ||
it('should error gently when unable to parse files as json from the local filesystem', async () => { | ||
const error = await expectToFail(invokeCommand({ | ||
newSpecLocation: 'test/e2e/fixtures/not-a-json-or-yaml.txt', | ||
oldSpecLocation: 'test/e2e/fixtures/not-a-json-or-yaml.txt' | ||
})); | ||
expect(error).toEqual(jasmine.stringMatching('Exit code: 2')); | ||
}).then(done, done.fail); | ||
expect(error).toEqual(jasmine.stringMatching('ERROR: unable to parse ' + | ||
'test/e2e/fixtures/not-a-json-or-yaml.txt as a JSON or YAML file')); | ||
expect(error).toEqual(jasmine.stringMatching('Exit code: 2')); | ||
}); | ||
it('should work with URL locations', (done) => { | ||
invokeCommand({ | ||
it('should work with URL locations', async () => { | ||
const result = await invokeCommand({ | ||
newSpecLocation: 'http://localhost:3000/basic-new.json', | ||
oldSpecLocation: 'http://localhost:3000/basic-old.json' | ||
}).then((result) => { | ||
expect(result).toEqual(jasmine.stringMatching('Old spec: http://localhost:3000/basic-old.json')); | ||
expect(result).toEqual(jasmine.stringMatching('New spec: http://localhost:3000/basic-new.json')); | ||
expect(result).toEqual(jasmine.stringMatching('0 breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('1 non-breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('0 unclassified changes found.')); | ||
}).then(done, done.fail); | ||
}); | ||
expect(result).toEqual(jasmine.stringMatching('Old spec: http://localhost:3000/basic-old.json')); | ||
expect(result).toEqual(jasmine.stringMatching('New spec: http://localhost:3000/basic-new.json')); | ||
expect(result).toEqual(jasmine.stringMatching('0 breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('1 non-breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('0 unclassified changes found.')); | ||
}); | ||
it('should error gently when unable to use the URLs provided', (done) => { | ||
invokeCommand({ | ||
it('should error gently when unable to use the URLs provided', async () => { | ||
const error = await expectToFail(invokeCommand({ | ||
newSpecLocation: 'htt://localhost:3000/basic-new.json', | ||
oldSpecLocation: 'htt://localhost:3000/basic-old.json' | ||
}).then(() => { | ||
fail('test expected to error out but it didn\'t'); | ||
}).catch((error) => { | ||
expect(error).toEqual(jasmine.stringMatching('ERROR: unable to open ' + | ||
'htt://localhost:3000/basic-old.json')); | ||
})); | ||
expect(error).toEqual(jasmine.stringMatching('Exit code: 2')); | ||
}).then(done, done.fail); | ||
expect(error).toEqual(jasmine.stringMatching('ERROR: unable to open ' + | ||
'htt://localhost:3000/basic-old.json')); | ||
expect(error).toEqual(jasmine.stringMatching('Exit code: 2')); | ||
}); | ||
it('should error gently when unable to fetch files over http', (done) => { | ||
invokeCommand({ | ||
it('should error gently when unable to fetch files over http', async () => { | ||
const error = await expectToFail(invokeCommand({ | ||
newSpecLocation: 'http://localhost:3000/non-existing-new.json', | ||
oldSpecLocation: 'http://localhost:3000/non-existing-old.json' | ||
}).then(() => { | ||
fail('test expected to error out but it didn\'t'); | ||
}).catch((error) => { | ||
expect(error).toEqual(jasmine.stringMatching( | ||
'ERROR: unable to fetch http://localhost:3000/non-existing-old.json. Response code: 404')); | ||
})); | ||
expect(error).toEqual(jasmine.stringMatching('Exit code: 2')); | ||
}).then(done, done.fail); | ||
expect(error).toEqual(jasmine.stringMatching( | ||
'ERROR: unable to fetch http://localhost:3000/non-existing-old.json. Response code: 404')); | ||
expect(error).toEqual(jasmine.stringMatching('Exit code: 2')); | ||
}); | ||
it('should error gently when unable to parse files as json over http', (done) => { | ||
invokeCommand({ | ||
newSpecLocation: 'http://localhost:3000/not-a-json.txt', | ||
oldSpecLocation: 'http://localhost:3000/not-a-json.txt' | ||
}).then(() => { | ||
fail('test expected to error out but it didn\'t'); | ||
}).catch((error) => { | ||
expect(error).toEqual(jasmine.stringMatching('ERROR: unable to parse ' + | ||
'http://localhost:3000/not-a-json.txt as a JSON file')); | ||
it('should error gently when unable to parse files as json over http', async () => { | ||
const error = await expectToFail(invokeCommand({ | ||
newSpecLocation: 'http://localhost:3000/not-a-json-or-yaml.txt', | ||
oldSpecLocation: 'http://localhost:3000/not-a-json-or-yaml.txt' | ||
})); | ||
expect(error).toEqual(jasmine.stringMatching('Exit code: 2')); | ||
}).then(done, done.fail); | ||
expect(error).toEqual(jasmine.stringMatching('ERROR: unable to parse ' + | ||
'http://localhost:3000/not-a-json-or-yaml.txt as a JSON or YAML file')); | ||
expect(error).toEqual(jasmine.stringMatching('Exit code: 2')); | ||
}); | ||
it('should succeed when the provided specs are equal', (done) => { | ||
invokeCommand({ | ||
it('should succeed when the provided specs are equal', async () => { | ||
const result = await invokeCommand({ | ||
newSpecLocation: 'test/e2e/fixtures/basic-old.json', | ||
oldSpecLocation: 'test/e2e/fixtures/basic-old.json' | ||
}).then((result) => { | ||
expect(result).toEqual(jasmine.stringMatching('0 breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('0 non-breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('0 unclassified changes found.')); | ||
}).then(done, done.fail); | ||
}); | ||
expect(result).toEqual(jasmine.stringMatching('0 breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('0 non-breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('0 unclassified changes found.')); | ||
}); | ||
it('should detect a single change', (done) => { | ||
invokeCommand({ | ||
it('should detect a single change', async () => { | ||
const result = await invokeCommand({ | ||
newSpecLocation: 'test/e2e/fixtures/basic-new.json', | ||
oldSpecLocation: 'test/e2e/fixtures/basic-old.json' | ||
}).then((result) => { | ||
expect(result).toEqual(jasmine.stringMatching('0 breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('1 non-breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('0 unclassified changes found.')); | ||
}); | ||
expect(result).toContain('Non-breaking: the path [info/title] was modified ' + | ||
'from \'Test API\' to \'New Test API\''); | ||
}).then(done, done.fail); | ||
expect(result).toEqual(jasmine.stringMatching('0 breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('1 non-breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('0 unclassified changes found.')); | ||
expect(result).toContain('Non-breaking: the path [info/title] was modified ' + | ||
'from \'Test API\' to \'New Test API\''); | ||
}); | ||
it('should detect multiple types of changes', (done) => { | ||
invokeCommand({ | ||
it('should detect multiple types of changes', async () => { | ||
const error = await expectToFail(invokeCommand({ | ||
newSpecLocation: 'test/e2e/fixtures/complex-new.json', | ||
oldSpecLocation: 'test/e2e/fixtures/complex-old.json' | ||
}).then(() => { | ||
fail('test expected to error out but it didn\'t'); | ||
}).catch((error) => { | ||
expect(error.message).toEqual(jasmine.stringMatching('2 breaking changes found.')); | ||
expect(error.message).toEqual(jasmine.stringMatching('4 non-breaking changes found.')); | ||
expect(error.message).toEqual(jasmine.stringMatching('2 unclassified changes found.')); | ||
})); | ||
expect(error.message).toContain('Breaking: the path [host] with value \'some host info\' was removed'); | ||
expect(error.message).toEqual(jasmine.stringMatching('2 breaking changes found.')); | ||
expect(error.message).toEqual(jasmine.stringMatching('4 non-breaking changes found.')); | ||
expect(error.message).toEqual(jasmine.stringMatching('2 unclassified changes found.')); | ||
expect(error.message).toContain('Breaking: the path [basePath] was modified ' + | ||
'from \'/\' to \'/v2\''); | ||
expect(error.message).toContain('Breaking: the path [host] with value \'some host info\' was removed'); | ||
expect(error.message).toContain('Non-breaking: the path [info/termsOfService] was modified ' + | ||
'from \'some terms\' to \'some new terms\''); | ||
expect(error.message).toContain('Breaking: the path [basePath] was modified ' + | ||
'from \'/\' to \'/v2\''); | ||
expect(error.message).toContain('Non-breaking: the path [info/contact/name] was modified ' + | ||
'from \'Test name\' to \'New test name\''); | ||
expect(error.message).toContain('Non-breaking: the path [info/termsOfService] was modified ' + | ||
'from \'some terms\' to \'some new terms\''); | ||
expect(error.message).toContain('Non-breaking: the path [info/license/url] was modified ' + | ||
'from \'http://license.example.com\' to \'http://new.license.example.com\''); | ||
expect(error.message).toContain('Non-breaking: the path [info/contact/name] was modified ' + | ||
'from \'Test name\' to \'New test name\''); | ||
expect(error.message).toContain('Non-breaking: the path [swagger] was modified ' + | ||
'from \'2.0\' to \'2.1\''); | ||
expect(error.message).toContain('Non-breaking: the path [info/license/url] was modified ' + | ||
'from \'http://license.example.com\' to \'http://new.license.example.com\''); | ||
expect(error.message).toContain('Unclassified: the path [info/x-info-property] was modified ' + | ||
'from \'some content\' to \'some new content\''); | ||
expect(error.message).toContain('Non-breaking: the path [swagger] was modified ' + | ||
'from \'2.0\' to \'2.1\''); | ||
expect(error.message).toContain('Unclassified: the path [x-generic-property] was modified ' + | ||
'from \'some content\' to \'some new content\''); | ||
expect(error.message).toContain('Unclassified: the path [info/x-info-property] was modified ' + | ||
'from \'some content\' to \'some new content\''); | ||
expect(error.message).not.toContain('the path [schemes'); | ||
expect(error.message).toContain('Unclassified: the path [x-generic-property] was modified ' + | ||
'from \'some content\' to \'some new content\''); | ||
expect(error.message).toEqual(jasmine.stringMatching('DANGER: Breaking changes found!')); | ||
expect(error.message).not.toContain('the path [schemes'); | ||
expect(error).toEqual(jasmine.stringMatching('Exit code: 1')); | ||
}).then(done, done.fail); | ||
expect(error.message).toEqual(jasmine.stringMatching('DANGER: Breaking changes found!')); | ||
expect(error).toEqual(jasmine.stringMatching('Exit code: 1')); | ||
}); | ||
it('should be able to process real Swagger 2.0 files', (done) => { | ||
invokeCommand({ | ||
it('should be able to process real Swagger 2.0 files', async () => { | ||
const error = await expectToFail(invokeCommand({ | ||
newSpecLocation: 'test/e2e/fixtures/petstore-swagger-2-new.json', | ||
oldSpecLocation: 'test/e2e/fixtures/petstore-swagger-2-old.json' | ||
}).then(() => { | ||
fail('test expected to error out but it didn\'t'); | ||
}).catch((error) => { | ||
expect(error.message).toEqual(jasmine.stringMatching('3 breaking changes found.')); | ||
expect(error.message).toEqual(jasmine.stringMatching('5 non-breaking changes found.')); | ||
expect(error.message).toEqual(jasmine.stringMatching('1 unclassified changes found.')); | ||
})); | ||
expect(error.message).toContain('Breaking: the path [host] was modified ' + | ||
'from \'petstore.swagger.io\' to \'petstore.swagger.org\''); | ||
expect(error.message).toEqual(jasmine.stringMatching('3 breaking changes found.')); | ||
expect(error.message).toEqual(jasmine.stringMatching('5 non-breaking changes found.')); | ||
expect(error.message).toEqual(jasmine.stringMatching('1 unclassified changes found.')); | ||
expect(error.message).toContain('Breaking: the path [basePath] was added with value \'/v2\''); | ||
expect(error.message).toContain('Breaking: the path [host] was modified ' + | ||
'from \'petstore.swagger.io\' to \'petstore.swagger.org\''); | ||
expect(error.message).toContain('Breaking: the value \'http\' was removed ' + | ||
'from the array in the path [schemes/0]'); | ||
expect(error.message).toContain('Breaking: the path [basePath] was added with value \'/v2\''); | ||
expect(error.message).toContain('Non-breaking: the path [swagger] was modified ' + | ||
'from \'2.0\' to \'2.1\''); | ||
expect(error.message).toContain('Breaking: the value \'http\' was removed ' + | ||
'from the array in the path [schemes/0]'); | ||
expect(error.message).toContain('Non-breaking: the path [info/version] was modified ' + | ||
'from \'1.0.0\' to \'1.0.1\''); | ||
expect(error.message).toContain('Non-breaking: the path [swagger] was modified ' + | ||
'from \'2.0\' to \'2.1\''); | ||
expect(error.message).toContain('Non-breaking: the path [info/license/url] was added ' + | ||
'with value \'http://www.apache.org/licenses/LICENSE-2.0.html\''); | ||
expect(error.message).toContain('Non-breaking: the path [info/version] was modified ' + | ||
'from \'1.0.0\' to \'1.0.1\''); | ||
expect(error.message).toContain('Non-breaking: the value \'https\' was added ' + | ||
'to the array in the path [schemes/0]'); | ||
expect(error.message).toContain('Non-breaking: the path [info/license/url] was added ' + | ||
'with value \'http://www.apache.org/licenses/LICENSE-2.0.html\''); | ||
expect(error.message).toContain('Non-breaking: the value \'ws\' was added ' + | ||
'to the array in the path [schemes/1]'); | ||
expect(error.message).toContain('Non-breaking: the value \'https\' was added ' + | ||
'to the array in the path [schemes/0]'); | ||
expect(error.message).toContain('Unclassified: the path [x-external-id] ' + | ||
'with value \'some x value\' was removed'); | ||
expect(error.message).toContain('Non-breaking: the value \'ws\' was added ' + | ||
'to the array in the path [schemes/1]'); | ||
expect(error.message).toEqual(jasmine.stringMatching('DANGER: Breaking changes found!')); | ||
expect(error.message).toContain('Unclassified: the path [x-external-id] ' + | ||
'with value \'some x value\' was removed'); | ||
expect(error).toEqual(jasmine.stringMatching('Exit code: 1')); | ||
}).then(done, done.fail); | ||
expect(error.message).toEqual(jasmine.stringMatching('DANGER: Breaking changes found!')); | ||
expect(error).toEqual(jasmine.stringMatching('Exit code: 1')); | ||
}); | ||
it('should be able to process real OpenApi 3.0.0 files', (done) => { | ||
invokeCommand({ | ||
it('should be able to process real OpenApi 3.0.0 files', async () => { | ||
const result = await 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('5 non-breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('4 unclassified changes found.')); | ||
}); | ||
expect(result).toContain('Non-breaking: the path [openapi] was modified ' + | ||
'from \'3.0.0\' to \'3.0.0-RC1\''); | ||
expect(result).toEqual(jasmine.stringMatching('0 breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('5 non-breaking changes found.')); | ||
expect(result).toEqual(jasmine.stringMatching('4 unclassified changes found.')); | ||
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 [openapi] was modified ' + | ||
'from \'3.0.0\' to \'3.0.0-RC1\''); | ||
expect(result).toContain('Non-breaking: the path [info/title] was modified ' + | ||
'from \'Test API\' to \'New test API\''); | ||
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/description] was added ' + | ||
'with value \'Brand new spec description\''); | ||
expect(result).toContain('Non-breaking: the path [info/title] was modified ' + | ||
'from \'Test API\' to \'New test API\''); | ||
expect(result).toContain('Non-breaking: the path [info/license/url] with value ' + | ||
'\'spec license url\' was removed'); | ||
expect(result).toContain('Non-breaking: the path [info/description] was added ' + | ||
'with value \'Brand new spec description\''); | ||
expect(result).toContain('Unclassified: the path [info/x-info-property] was modified ' + | ||
'from \'Some content\' to \'Some new content\''); | ||
expect(result).toContain('Non-breaking: the path [info/license/url] with value ' + | ||
'\'spec license url\' was removed'); | ||
expect(result).toContain('Unclassified: the path [x-generic-property] was modified ' + | ||
'from \'Some content\' to \'Some new content\''); | ||
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 [info/x-brand-new-property] was added ' + | ||
'with value \'Some brand new content\''); | ||
expect(result).toContain('Unclassified: the path [x-generic-property] was modified ' + | ||
'from \'Some content\' to \'Some new content\''); | ||
expect(result).toContain('Unclassified: the path [x-deleted-property] with value ' + | ||
'\'Some deleted content\' was removed'); | ||
}).then(done, done.fail); | ||
expect(result).toContain('Unclassified: the path [info/x-brand-new-property] was added ' + | ||
'with value \'Some brand new content\''); | ||
expect(result).toContain('Unclassified: the path [x-deleted-property] with value ' + | ||
'\'Some deleted content\' was removed'); | ||
}); | ||
}); |
import specDiffer from '../../../lib/openapi-diff/spec-differ'; | ||
import {parsedSpecBuilder} from '../support/parsed-spec-builder'; | ||
import {parsedSpecBuilder} from '../support/builders/parsed-spec-builder'; | ||
@@ -4,0 +4,0 @@ describe('specDiffer', () => { |
import specDiffer from '../../../lib/openapi-diff/spec-differ'; | ||
import {parsedSpecBuilder} from '../support/parsed-spec-builder'; | ||
import {parsedSpecBuilder} from '../support/builders/parsed-spec-builder'; | ||
@@ -4,0 +4,0 @@ describe('specDiffer', () => { |
import specDiffer from '../../../lib/openapi-diff/spec-differ'; | ||
import {parsedSpecBuilder, parsedSpecInfoBuilder} from '../support/parsed-spec-builder'; | ||
import {parsedSpecBuilder, parsedSpecInfoBuilder} from '../support/builders/parsed-spec-builder'; | ||
@@ -4,0 +4,0 @@ describe('specDiffer', () => { |
import specDiffer from '../../../lib/openapi-diff/spec-differ'; | ||
import {parsedSpecBuilder} from '../support/parsed-spec-builder'; | ||
import {parsedSpecBuilder} from '../support/builders/parsed-spec-builder'; | ||
@@ -4,0 +4,0 @@ describe('specDiffer', () => { |
import specDiffer from '../../../lib/openapi-diff/spec-differ'; | ||
import {parsedSpecBuilder} from '../support/parsed-spec-builder'; | ||
import {parsedSpecBuilder} from '../support/builders/parsed-spec-builder'; | ||
@@ -4,0 +4,0 @@ describe('specDiffer', () => { |
import specDiffer from '../../../lib/openapi-diff/spec-differ'; | ||
import { parsedSpecBuilder } from '../support/parsed-spec-builder'; | ||
import { parsedSpecBuilder } from '../support/builders/parsed-spec-builder'; | ||
@@ -4,0 +4,0 @@ describe('specDiffer', () => { |
import specParser from '../../../lib/openapi-diff/spec-parser'; | ||
import {openApi3SpecBuilder, openApi3SpecInfoBuilder} from '../support/openapi-3-spec-builder'; | ||
import {parsedSpecBuilder, parsedSpecInfoBuilder} from '../support/parsed-spec-builder'; | ||
import {swagger2SpecBuilder, swagger2SpecInfoBuilder} from '../support/swagger-2-spec-builder'; | ||
import {openApi3SpecBuilder, openApi3SpecInfoBuilder} from '../support/builders/openapi-3-spec-builder'; | ||
import {parsedSpecBuilder, parsedSpecInfoBuilder} from '../support/builders/parsed-spec-builder'; | ||
import {swagger2SpecBuilder, swagger2SpecInfoBuilder} from '../support/builders/swagger-2-spec-builder'; | ||
@@ -6,0 +6,0 @@ describe('specParser, with regards to the info object,', () => { |
import specParser from '../../../lib/openapi-diff/spec-parser'; | ||
import { openApi3SpecBuilder } from '../support/openapi-3-spec-builder'; | ||
import { parsedSpecBuilder } from '../support/parsed-spec-builder'; | ||
import { swagger2SpecBuilder } from '../support/swagger-2-spec-builder'; | ||
import { openApi3SpecBuilder } from '../support/builders/openapi-3-spec-builder'; | ||
import { parsedSpecBuilder } from '../support/builders/parsed-spec-builder'; | ||
import { swagger2SpecBuilder } from '../support/builders/swagger-2-spec-builder'; | ||
@@ -6,0 +6,0 @@ describe('specParser, with regards to the swagger/openapi object,', () => { |
import specParser from '../../../lib/openapi-diff/spec-parser'; | ||
import {openApi3SpecBuilder} from '../support/openapi-3-spec-builder'; | ||
import {parsedSpecBuilder} from '../support/parsed-spec-builder'; | ||
import {swagger2SpecBuilder} from '../support/swagger-2-spec-builder'; | ||
import {openApi3SpecBuilder} from '../support/builders/openapi-3-spec-builder'; | ||
import {parsedSpecBuilder} from '../support/builders/parsed-spec-builder'; | ||
import {swagger2SpecBuilder} from '../support/builders/swagger-2-spec-builder'; | ||
@@ -6,0 +6,0 @@ describe('specParser, with regards to arrays in the top level object,', () => { |
import specParser from '../../../lib/openapi-diff/spec-parser'; | ||
import { openApi3SpecBuilder } from '../support/openapi-3-spec-builder'; | ||
import { parsedSpecBuilder } from '../support/parsed-spec-builder'; | ||
import { swagger2SpecBuilder } from '../support/swagger-2-spec-builder'; | ||
import { openApi3SpecBuilder } from '../support/builders/openapi-3-spec-builder'; | ||
import { parsedSpecBuilder } from '../support/builders/parsed-spec-builder'; | ||
import { swagger2SpecBuilder } from '../support/builders/swagger-2-spec-builder'; | ||
@@ -6,0 +6,0 @@ describe('specParser, with regards to the top level object,', () => { |
{ | ||
"compileOnSave": false, | ||
"compilerOptions": { | ||
@@ -13,2 +14,4 @@ "forceConsistentCasingInFileNames": true, | ||
"noUnusedParameters": true, | ||
"sourceMap": true, | ||
"outDir": "build-output", | ||
"strictNullChecks": true, | ||
@@ -15,0 +18,0 @@ "target": "es6" |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
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
212661
67
5661
32
+ Addedjs-yaml@^3.10.0
+ Addedargparse@1.0.10(transitive)
+ Addedesprima@4.0.1(transitive)
+ Addedjs-yaml@3.14.1(transitive)
+ Addedopenapi3-ts@0.5.0(transitive)
+ Addedsprintf-js@1.0.3(transitive)
- Removedq@^1.5.0
- Removedopenapi3-ts@0.2.1(transitive)
- Removedq@1.5.1(transitive)
Updatedcommander@^2.11.0
Updatedopenapi3-ts@^0.5.0