Skip to content

Instantly share code, notes, and snippets.

@amarzavery
Created January 18, 2017 05:37
Show Gist options
  • Save amarzavery/b5080f711743e59834f2e509390ae611 to your computer and use it in GitHub Desktop.
Save amarzavery/b5080f711743e59834f2e509390ae611 to your computer and use it in GitHub Desktop.
test script
// Please install sway and request before executing the script
'use strict';
var Sway = require('sway'),
request = require('request'),
path = require('path'),
fs = require('fs'),
util = require('util');
class SpecValidator {
constructor(specPath, specInJson) {
if (specPath === null || specPath === undefined || typeof specPath.valueOf() !== 'string' || !specPath.trim().length) {
throw new Error ('specPath is a required parameter of type string and it cannot be an empty string.')
}
//If the spec path is a url starting with https://github then let us auto convert it to an https://raw.githubusercontent url.
if (specPath.startsWith('https://github')) {
specPath = specPath.replace(/^https:\/\/(github.com)(.*)blob\/(.*)/ig, 'https://raw.githubusercontent.com$2$3');
}
this.specPath = specPath;
this.specDir = path.dirname(this.specPath);
this.specInJson = specInJson;
this.specValidationResult = { validityStatus: true, operations: { } };
this.swaggerApi = null;
}
initialize() {
let self = this;
return self.parseJson(self.specPath).then(function (result) {
self.specInJson = result;
let options = {};
options.definition = self.specInJson;
//These are the options to jsonRefs that will be passed to Sway.create
options.jsonRefs = {};
options.jsonRefs.includeInvalid = true;
options.jsonRefs.relativeBase = self.specDir;
return Sway.create(options);
}).then(function (api) {
self.swaggerApi = api;
return Promise.resolve(api);
}).catch(function (err) {
console.error(err);
return Promise.reject(e);
});
}
validateSpec() {
let self = this;
if (!self.swaggerApi) {
throw new Error(`Please call "specValidator.initialize()" before calling this method, so that swaggerApi is populated.`);
}
try {
let validationResult = self.swaggerApi.validate();
if (validationResult) {
if (validationResult.errors && validationResult.errors.length) {
console.error('Errors');
console.error('------');
console.error(validationResult.errors);
}
if (validationResult.warnings && validationResult.warnings.length > 0) {
console.log('Warnings');
console.log('--------');
console.log(util.inspect(validationResult.warnings));
}
}
} catch (err) {
console.error(err);
}
}
parseJson(specPath) {
let self = this;
let result = null;
if (!specPath || (specPath && typeof specPath.valueOf() !== 'string')) {
let err = new Error('A (github) url or a local file path to the swagger spec is required and must be of type string.');
return Promise.rject(err);
}
//url
if (specPath.match(/^http.*/ig) !== null) {
//If the spec path is a url starting with https://github then let us auto convert it to an https://raw.githubusercontent url.
if (specPath.startsWith('https://github')) {
specPath = specPath.replace(/^https:\/\/(github.com)(.*)blob\/(.*)/ig, 'https://raw.githubusercontent.com$2$3');
}
return self.makeRequest({ url: specPath, errorOnNon200Response: true});
} else {
//local filepath
try {
result = JSON.parse(self.stripBOM(fs.readFileSync(specPath, 'utf8')));
return Promise.resolve(result);
} catch (err) {
return Promise.reject(err);
}
}
}
stripBOM(content) {
if (Buffer.isBuffer(content)) {
content = content.toString();
}
if (content.charCodeAt(0) === 0xFEFF || content.charCodeAt(0) === 0xFFFE) {
content = content.slice(1);
}
return content;
}
makeRequest(options) {
var self = this;
var promise = new Promise(function (resolve, reject) {
request(options, function (err, response, responseBody) {
if (err) {
return reject(err);
}
if (options.errorOnNon200Response && response.statusCode !== 200) {
var msg = `StatusCode: "${response.statusCode}", ResponseBody: "${responseBody}."`;
return reject(new Error(msg));
}
let res;
try {
res = typeof responseBody.valueOf() === 'string'? JSON.parse(self.stripBOM(responseBody)) : responseBody;
} catch (error) {
let msg = `An error occurred while executing JSON.parse() on the responseBody. ${util.inspect(error, {depth: null})}.`
let e = new Error(msg);
return reject(e);
}
return resolve(res);
});
});
return promise;
}
}
var testSpec = 'https://github.com/tjlvtao/azure-rest-api-specs/blob/master/arm-customer-insights/2016-01-01/swagger/customer-insights.json';
let validator = new SpecValidator(testSpec);
validator.initialize().then(function() {
console.log(`Semantically validating ${testSpec}:\n`);
return validator.validateSpec();
}).catch(function(err) {
console.error(err);
return;
});
@amarzavery
Copy link
Author

The output:

Semantically validating  https://github.com/tjlvtao/azure-rest-api-specs/blob/master/arm-customer-insights/2016-01-01/swagger/customer-insights.json:

Errors
------
[ { code: 'UNRESOLVABLE_REFERENCE',
    message: 'Reference could not be resolved: ../examples/RelationshipsDelete.json',
    path:
     [ 'paths',
       '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CustomerInsights/hubs/{hubName}/relationships/{relationshipName}',
       'delete',
       'x-ms-examples',
       'Relationships_Delete',
       '$ref' ],
    error: 'ptr must be a JSON Pointer' },
  { code: 'UNRESOLVABLE_REFERENCE',
    message: 'Reference could not be resolved: ../examples/RelationshipLinksDelete.json',
    path:
     [ 'paths',
       '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CustomerInsights/hubs/{hubName}/relationshipLinks/{relationshipLinkName}',
       'delete',
       'x-ms-examples',
       'RelationshipLinks_Delete',
       '$ref' ],
    error: 'ptr must be a JSON Pointer' } ]
Warnings
--------
[ { code: 'EXTRA_REFERENCE_PROPERTIES',
    message: 'Extra JSON Reference properties will be ignored: description',
    path: [ 'definitions', 'KpiDefinition', 'properties', 'thresholds' ] },
  { code: 'EXTRA_REFERENCE_PROPERTIES',
    message: 'Extra JSON Reference properties will be ignored: description',
    path:
     [ 'definitions',
       'RoleAssignment',
       'properties',
       'roleAssignments' ] },
  { code: 'EXTRA_REFERENCE_PROPERTIES',
    message: 'Extra JSON Reference properties will be ignored: description',
    path: [ 'definitions', 'RoleAssignment', 'properties', 'widgetTypes' ] },
  { code: 'EXTRA_REFERENCE_PROPERTIES',
    message: 'Extra JSON Reference properties will be ignored: description',
    path: [ 'definitions', 'RoleAssignment', 'properties', 'relationships' ] },
  { code: 'EXTRA_REFERENCE_PROPERTIES',
    message: 'Extra JSON Reference properties will be ignored: description',
    path:
     [ 'definitions',
       'RoleAssignment',
       'properties',
       'relationshipLinks' ] },
  { code: 'EXTRA_REFERENCE_PROPERTIES',
    message: 'Extra JSON Reference properties will be ignored: description',
    path: [ 'definitions', 'RoleAssignment', 'properties', 'views' ] },
  { code: 'EXTRA_REFERENCE_PROPERTIES',
    message: 'Extra JSON Reference properties will be ignored: description',
    path: [ 'definitions', 'RoleAssignment', 'properties', 'connectors' ] },
  { code: 'EXTRA_REFERENCE_PROPERTIES',
    message: 'Extra JSON Reference properties will be ignored: description',
    path: [ 'definitions', 'RoleAssignment', 'properties', 'sasPolicies' ] },
  { code: 'EXTRA_REFERENCE_PROPERTIES',
    message: 'Extra JSON Reference properties will be ignored: description',
    path: [ 'definitions', 'RoleAssignment', 'properties', 'kpis' ] },
  { code: 'EXTRA_REFERENCE_PROPERTIES',
    message: 'Extra JSON Reference properties will be ignored: description',
    path: [ 'definitions', 'RoleAssignment', 'properties', 'links' ] },
  { code: 'EXTRA_REFERENCE_PROPERTIES',
    message: 'Extra JSON Reference properties will be ignored: description',
    path: [ 'definitions', 'RoleAssignment', 'properties', 'interactions' ] },
  { code: 'EXTRA_REFERENCE_PROPERTIES',
    message: 'Extra JSON Reference properties will be ignored: description',
    path: [ 'definitions', 'RoleAssignment', 'properties', 'profiles' ] } ]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment