Skip to content

Commit

Permalink
chore: release 5.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastian Tello committed Aug 23, 2018
1 parent 19deb93 commit 7313110
Show file tree
Hide file tree
Showing 61 changed files with 1,099 additions and 597 deletions.
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,32 @@
<a name="5.0.0"></a>
# [5.0.0](https://bitbucket.org/atlassian/swagger-mock-validator/compare/4.0.1...5.0.0) (2018-08-23)


### Bug Fixes

* do not crash if path-item contains an ^x- property ([d57f887](https://bitbucket.org/atlassian/swagger-mock-validator/commits/d57f887))
* fixed issue with format not being validated for bodies containing primitive values ([dca4654](https://bitbucket.org/atlassian/swagger-mock-validator/commits/dca4654))
* use case-sensitive matching for query string parameters ([f269cd9](https://bitbucket.org/atlassian/swagger-mock-validator/commits/f269cd9))


### Chores

* removed support for node version 4.x and added build test for node version 10.x ([52c4963](https://bitbucket.org/atlassian/swagger-mock-validator/commits/52c4963))


### Features

* add support for OpenApi 3 specs ([19deb93](https://bitbucket.org/atlassian/swagger-mock-validator/commits/19deb93))
* removed swagger warnings from validation results ([9a3b757](https://bitbucket.org/atlassian/swagger-mock-validator/commits/9a3b757))


### BREAKING CHANGES

* Removed support for node 4.x. Migrate to node 6.x or higher.
* Prior to this change swagger-mock-validator would return any pact/swagger warnings or errors as part of the validation result. Now when a validation error is encountered with a swagger or pact file the tool will fail with an error. Warnings are no longer reported at all. The list of validation result codes returned by the programatic API have been updated to reflect this change.



<a name="4.0.1"></a>
## [4.0.1](https://bitbucket.org/atlassian/swagger-mock-validator/compare/4.0.0...4.0.1) (2018-07-05)

Expand Down
5 changes: 3 additions & 2 deletions dist/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
const commander = require("commander");
const _ = require("lodash");
const util = require("util");
const swagger_mock_validator_1 = require("./swagger-mock-validator");
const swagger_mock_validator_factory_1 = require("./swagger-mock-validator-factory");
// tslint:disable:no-var-requires
const packageJson = require('../package.json');
const swaggerMockValidator = swagger_mock_validator_factory_1.SwaggerMockValidatorFactory.create();
const displaySummaryForValidationResults = (name, resultsOrNone) => {
const results = resultsOrNone || [];
const summary = results.reduce((partialSummary, result) => {
Expand Down Expand Up @@ -62,7 +63,7 @@ the specified provider name. The <swagger> argument should be the path or url to
json file.`)
.action((swagger, mock, options) => __awaiter(this, void 0, void 0, function* () {
try {
const result = yield swagger_mock_validator_1.swaggerMockValidator.validate({
const result = yield swaggerMockValidator.validate({
analyticsUrl: options.analyticsUrl,
mockPathOrUrl: mock,
providerName: options.provider,
Expand Down
23 changes: 23 additions & 0 deletions dist/swagger-mock-validator-factory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const swagger_mock_validator_1 = require("./swagger-mock-validator");
const analytics_1 = require("./swagger-mock-validator/analytics");
const metadata_1 = require("./swagger-mock-validator/analytics/metadata");
const file_system_1 = require("./swagger-mock-validator/clients/file-system");
const http_client_1 = require("./swagger-mock-validator/clients/http-client");
const file_store_1 = require("./swagger-mock-validator/file-store");
const resource_loader_1 = require("./swagger-mock-validator/resource-loader");
const uuid_generator_1 = require("./swagger-mock-validator/uuid-generator");
class SwaggerMockValidatorFactory {
static create() {
const fileSystem = new file_system_1.FileSystem();
const httpClient = new http_client_1.HttpClient();
const uuidGenerator = new uuid_generator_1.UuidGenerator();
const metadata = new metadata_1.Metadata();
const fileStore = new file_store_1.FileStore(fileSystem, httpClient);
const resourceLoader = new resource_loader_1.ResourceLoader(fileStore);
const analytics = new analytics_1.Analytics(httpClient, uuidGenerator, metadata);
return new swagger_mock_validator_1.SwaggerMockValidator(fileStore, resourceLoader, analytics);
}
}
exports.SwaggerMockValidatorFactory = SwaggerMockValidatorFactory;
176 changes: 80 additions & 96 deletions dist/swagger-mock-validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
};
Object.defineProperty(exports, "__esModule", { value: true });
const _ = require("lodash");
const analytics_1 = require("./swagger-mock-validator/analytics");
const metadata_1 = require("./swagger-mock-validator/analytics/metadata");
const file_store_1 = require("./swagger-mock-validator/file-store");
const file_system_1 = require("./swagger-mock-validator/json-loader/file-system");
const http_client_1 = require("./swagger-mock-validator/json-loader/http-client");
const mock_parser_1 = require("./swagger-mock-validator/mock-parser");
const resolve_swagger_1 = require("./swagger-mock-validator/resolve-swagger");
const resource_loader_1 = require("./swagger-mock-validator/resource-loader");
const spec_parser_1 = require("./swagger-mock-validator/spec-parser");
const transform_string_to_object_1 = require("./swagger-mock-validator/transform-string-to-object");
const uuid_generator_1 = require("./swagger-mock-validator/uuid-generator");
const validate_pact_1 = require("./swagger-mock-validator/validate-pact");
const swagger_mock_validator_error_impl_1 = require("./swagger-mock-validator/swagger-mock-validator-error-impl");
const validate_spec_and_mock_1 = require("./swagger-mock-validator/validate-spec-and-mock");
const validate_swagger_1 = require("./swagger-mock-validator/validate-swagger");
const getMockSource = (mockPathOrUrl, providerName) => {
if (providerName) {
return 'pactBroker';
Expand All @@ -36,15 +27,11 @@ const getSpecSource = (specPathOrUrl) => file_store_1.FileStore.isUrl(specPathOr
// tslint:disable:cyclomatic-complexity
const parseUserOptions = (userOptions) => ({
analyticsUrl: userOptions.analyticsUrl,
fileSystem: userOptions.fileSystem || file_system_1.defaultFileSystem,
httpClient: userOptions.httpClient || http_client_1.defaultHttpClient,
metadata: userOptions.metadata || metadata_1.defaultMetadata,
mockPathOrUrl: userOptions.mockPathOrUrl,
mockSource: getMockSource(userOptions.mockPathOrUrl, userOptions.providerName),
providerName: userOptions.providerName,
specPathOrUrl: userOptions.specPathOrUrl,
specSource: getSpecSource(userOptions.specPathOrUrl),
uuidGenerator: userOptions.uuidGenerator || uuid_generator_1.defaultUuidGenerator
specSource: getSpecSource(userOptions.specPathOrUrl)
});
const combineValidationResults = (validationResults) => {
const flattenedValidationResults = _.flatten(validationResults);
Expand All @@ -61,98 +48,95 @@ const combineValidationOutcomes = (validationOutcomes) => {
warnings: combineValidationResults(validationOutcomes.map((validationOutcome) => validationOutcome.warnings))
};
};
const createPostAnalyticEventFunction = (options) => {
const analyticsUrl = options.analyticsUrl;
if (!analyticsUrl) {
return () => Promise.resolve(undefined);
}
const parentId = options.uuidGenerator.generate();
return (parsedMock, validationOutcome) => analytics_1.analytics.postEvent({
analyticsUrl,
consumer: parsedMock.consumer,
httpClient: options.httpClient,
metadata: options.metadata,
mockPathOrUrl: parsedMock.pathOrUrl,
mockSource: options.mockSource,
parentId,
provider: parsedMock.provider,
specPathOrUrl: options.specPathOrUrl,
specSource: options.specSource,
uuidGenerator: options.uuidGenerator,
validationOutcome
}).catch(() => {
return;
});
};
const getPactFilesFromBroker = (mockPathOrUrl, providerName, resourceLoader) => __awaiter(this, void 0, void 0, function* () {
const pactBrokerResponse = yield resourceLoader.load(mockPathOrUrl);
const providerPactsUrlTemplate = _.get(pactBrokerResponse, '_links.pb:latest-provider-pacts.href');
if (!providerPactsUrlTemplate) {
throw new Error(`No latest pact file url found at "${mockPathOrUrl}"`);
}
const providerPactsUrl = providerPactsUrlTemplate.replace('{provider}', providerName);
const providerPactsResponse = yield resourceLoader.load(providerPactsUrl);
const providerPacts = _.get(providerPactsResponse, '_links.pacts', []);
return _.map(providerPacts, (providerPact) => providerPact.href);
});
exports.validateSpecAndMockContent = (options) => __awaiter(this, void 0, void 0, function* () {
const spec = options.spec;
const mock = options.mock;
const specJson = transform_string_to_object_1.transformStringToObject(spec.content, spec.pathOrUrl);
const specOutcome = yield validate_swagger_1.validateSwagger(specJson, spec.pathOrUrl);
if (!specOutcome.success) {
return { validationOutcome: specOutcome };
}
const mockJson = transform_string_to_object_1.transformStringToObject(mock.content, mock.pathOrUrl);
const mockOutcome = validate_pact_1.validatePact(mockJson, mock.pathOrUrl);
if (!mockOutcome.success) {
return { validationOutcome: mockOutcome };
}
const resolvedSpec = yield resolve_swagger_1.resolveSwagger(specJson);
const parsedSpec = spec_parser_1.specParser.parseSwagger(resolvedSpec, spec.pathOrUrl);
const parsedMock = mock_parser_1.mockParser.parsePact(mockJson, mock.pathOrUrl);
const specAndMockOutcome = yield validate_spec_and_mock_1.validateSpecAndMock(parsedMock, parsedSpec);
const validationOutcome = combineValidationOutcomes([specOutcome, mockOutcome, specAndMockOutcome]);
const parsedSpec = yield spec_parser_1.SpecParser.parse(spec);
const parsedMock = mock_parser_1.MockParser.parse(mock);
const validationOutcome = yield validate_spec_and_mock_1.validateSpecAndMock(parsedMock, parsedSpec);
return {
parsedMock,
validationOutcome
};
});
exports.swaggerMockValidator = {
validate: (userOptions) => __awaiter(this, void 0, void 0, function* () {
const options = parseUserOptions(userOptions);
const fileStore = new file_store_1.FileStore(options.fileSystem, options.httpClient);
const resourceLoader = new resource_loader_1.ResourceLoader(fileStore);
const postAnalyticEvent = createPostAnalyticEventFunction(options);
const whenSpecContent = fileStore.loadFile(options.specPathOrUrl);
const whenMockPathsOrUrls = options.providerName
? getPactFilesFromBroker(options.mockPathOrUrl, options.providerName, resourceLoader)
: Promise.resolve([options.mockPathOrUrl]);
const whenMocks = whenMockPathsOrUrls.then((mockPathsOrUrls) => {
return Promise.all(mockPathsOrUrls.map((mockPathOrUrl) => {
return fileStore.loadFile(mockPathOrUrl).then((content) => {
return {
content,
format: 'pact',
pathOrUrl: mockPathOrUrl
};
class SwaggerMockValidator {
constructor(fileStore, resourceLoader, analytics) {
this.fileStore = fileStore;
this.resourceLoader = resourceLoader;
this.analytics = analytics;
}
validate(userOptions) {
return __awaiter(this, void 0, void 0, function* () {
const options = parseUserOptions(userOptions);
const { spec, mocks } = yield this.loadSpecAndMocks(options);
const validationOutcomes = yield Promise.all(mocks.map((mock) => this.validateSpecAndMock(spec, mock, options)));
return combineValidationOutcomes(validationOutcomes);
});
}
loadSpecAndMocks(options) {
return __awaiter(this, void 0, void 0, function* () {
const whenSpecContent = this.fileStore.loadFile(options.specPathOrUrl);
const mockPathsOrUrls = options.providerName
? yield this.getPactFilesFromBroker(options.mockPathOrUrl, options.providerName)
: [options.mockPathOrUrl];
const whenMocks = Promise.all(mockPathsOrUrls.map((mockPathOrUrl) => __awaiter(this, void 0, void 0, function* () {
return ({
content: yield this.fileStore.loadFile(mockPathOrUrl),
format: 'auto-detect',
pathOrUrl: mockPathOrUrl
});
}));
})));
const [specContent, mocks] = yield Promise.all([whenSpecContent, whenMocks]);
const spec = {
content: specContent,
format: 'auto-detect',
pathOrUrl: options.specPathOrUrl
};
return { spec, mocks };
});
const specContentAndMocks = yield Promise.all([whenSpecContent, whenMocks]);
const spec = {
content: specContentAndMocks[0],
format: 'swagger2',
pathOrUrl: options.specPathOrUrl
};
const mocks = specContentAndMocks[1];
const validationOutcomes = yield Promise.all(mocks.map((mock) => __awaiter(this, void 0, void 0, function* () {
}
validateSpecAndMock(spec, mock, options) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield exports.validateSpecAndMockContent({ mock, spec });
if (result.parsedMock) {
yield postAnalyticEvent(result.parsedMock, result.validationOutcome);
yield this.postAnalyticEvent(options, result.parsedMock, result.validationOutcome);
}
return result.validationOutcome;
})));
return combineValidationOutcomes(validationOutcomes);
})
};
});
}
postAnalyticEvent(options, parsedMock, validationOutcome) {
return __awaiter(this, void 0, void 0, function* () {
if (options.analyticsUrl) {
try {
yield this.analytics.postEvent({
analyticsUrl: options.analyticsUrl,
consumer: parsedMock.consumer,
mockPathOrUrl: parsedMock.pathOrUrl,
mockSource: options.mockSource,
provider: parsedMock.provider,
specPathOrUrl: options.specPathOrUrl,
specSource: options.specSource,
validationOutcome
});
}
catch (error) {
// do not fail tool on analytics errors
}
}
});
}
getPactFilesFromBroker(mockPathOrUrl, providerName) {
return __awaiter(this, void 0, void 0, function* () {
const pactBrokerResponse = yield this.resourceLoader.load(mockPathOrUrl);
const providerPactsUrlTemplate = _.get(pactBrokerResponse, '_links.pb:latest-provider-pacts.href');
if (!providerPactsUrlTemplate) {
throw new swagger_mock_validator_error_impl_1.SwaggerMockValidatorErrorImpl('SWAGGER_MOCK_VALIDATOR_READ_ERROR', `Unable to read "${mockPathOrUrl}": No latest pact file url found`);
}
const providerPactsUrl = providerPactsUrlTemplate.replace('{provider}', providerName);
const providerPactsResponse = yield this.resourceLoader.load(providerPactsUrl);
const providerPacts = _.get(providerPactsResponse, '_links.pacts', []);
return _.map(providerPacts, (providerPact) => providerPact.href);
});
}
}
exports.SwaggerMockValidator = SwaggerMockValidator;
65 changes: 37 additions & 28 deletions dist/swagger-mock-validator/analytics.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,40 @@ const generateResultSummary = (results) => {
summary.count = results.length;
return summary;
};
exports.analytics = {
postEvent: (options) => options.httpClient.post(options.analyticsUrl, {
execution: {
consumer: options.consumer,
mockFormat: 'pact',
mockPathOrUrl: options.mockPathOrUrl,
mockSource: options.mockSource,
provider: options.provider,
specFormat: 'swagger',
specPathOrUrl: options.specPathOrUrl,
specSource: options.specSource
},
id: options.uuidGenerator.generate(),
metadata: {
hostname: options.metadata.getHostname(),
osVersion: options.metadata.getOsVersion(),
toolVersion: options.metadata.getToolVersion()
},
parentId: options.parentId,
result: {
duration: options.metadata.getUptime(),
errors: generateResultSummary(options.validationOutcome.errors),
success: options.validationOutcome.success,
warnings: generateResultSummary(options.validationOutcome.warnings)
},
source: 'swagger-mock-validator'
})
};
class Analytics {
constructor(httpClient, uuidGenerator, metadata) {
this.httpClient = httpClient;
this.uuidGenerator = uuidGenerator;
this.metadata = metadata;
this.parentId = this.uuidGenerator.generate();
}
postEvent(options) {
return this.httpClient.post(options.analyticsUrl, {
execution: {
consumer: options.consumer,
mockFormat: 'pact',
mockPathOrUrl: options.mockPathOrUrl,
mockSource: options.mockSource,
provider: options.provider,
specFormat: 'swagger',
specPathOrUrl: options.specPathOrUrl,
specSource: options.specSource
},
id: this.uuidGenerator.generate(),
metadata: {
hostname: this.metadata.getHostname(),
osVersion: this.metadata.getOsVersion(),
toolVersion: this.metadata.getToolVersion()
},
parentId: this.parentId,
result: {
duration: this.metadata.getUptime(),
errors: generateResultSummary(options.validationOutcome.errors),
success: options.validationOutcome.success,
warnings: generateResultSummary(options.validationOutcome.warnings)
},
source: 'swagger-mock-validator'
});
}
}
exports.Analytics = Analytics;
21 changes: 15 additions & 6 deletions dist/swagger-mock-validator/analytics/metadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
const os = require("os");
// tslint:disable:no-var-requires
const packageJson = require('../../../package.json');
exports.defaultMetadata = {
getHostname: () => os.hostname(),
getOsVersion: () => `${os.platform()} ${os.arch()} ${os.release()}`,
getToolVersion: () => packageJson.version,
getUptime: () => process.uptime()
};
class Metadata {
getHostname() {
return os.hostname();
}
getOsVersion() {
return `${os.platform()} ${os.arch()} ${os.release()}`;
}
getToolVersion() {
return packageJson.version;
}
getUptime() {
return process.uptime();
}
}
exports.Metadata = Metadata;
Loading

0 comments on commit 7313110

Please sign in to comment.