Socket
Socket
Sign inDemoInstall

swagger-tools

Package Overview
Dependencies
Maintainers
1
Versions
78
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

swagger-tools - npm Package Compare versions

Comparing version 0.1.6 to 0.2.0

test/v1_2-invalid-api-resource-listing.json

360

index.js
/*
* Copyright 2014 Apigee Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.

@@ -11,3 +11,3 @@ * You may obtain a copy of the License at

* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

@@ -35,2 +35,18 @@ * See the License for the specific language governing permissions and

var mergeResults = function mergeResults (errors, warnings, results) {
if (_.isObject(results)) {
if (results.errors && _.isArray(results.errors) && _.isArray(errors)) {
results.errors.forEach(function (error) {
errors.push(error);
});
}
if (results.warnings && _.isArray(results.warnings) && _.isArray(warnings)) {
results.warnings.forEach(function (warning) {
warnings.push(warning);
});
}
}
};
var throwUnsupportedVersion = function (version) {

@@ -70,2 +86,3 @@ throw new Error(version + ' is an unsupported Swagger specification version');

'double',
'number',
'string',

@@ -179,2 +196,102 @@ 'byte',

var validateDefaultValue = function validateDefaultValue (data, path) {
var defaultValue = data.defaultValue;
var errors = [];
var type = data.type;
var parsedValue;
var parsedMaximumValue;
var parsedMinimumValue;
// Should we return an error/warning when defaultValue is used without a type?
if (!_.isUndefined(defaultValue) && !_.isUndefined(type)) {
if (data.enum && _.isArray(data.enum) && data.enum.indexOf(defaultValue) === -1) {
errors.push({
code: 'ENUM_MISMATCH',
message: 'Default value is not within enum values (' + data.enum.join(', ') + '): ' + defaultValue,
data: defaultValue,
path: path + '.defaultValue'
});
}
// Should we return an error/warning when minimum and/or maximum is used with for a non-integer/non-number?
switch (type) {
case 'integer':
case 'number':
if (['integer', 'number'].indexOf(type) > -1) {
parsedValue = parseFloat(defaultValue);
if (isNaN(parsedValue)) {
errors.push({
code: 'INVALID_TYPE',
message: 'Invalid type (expected parseable number): ' + defaultValue,
data: defaultValue,
path: path + '.defaultValue'
});
}
if (!_.isUndefined(data.maximum)) {
parsedMaximumValue = parseFloat(data.maximum);
if (isNaN(parsedMaximumValue)) {
errors.push({
code: 'INVALID_TYPE',
message: 'Invalid type (expected parseable number): ' + data.maximum,
data: data.maximum,
path: path + '.maximum'
});
} else if (_.isNumber(parsedValue) && _.isNumber(parsedMaximumValue) && parsedValue > parsedMaximumValue) {
errors.push({
code: 'MAXIMUM',
message: 'Default value is greater than maximum (' + data.maximum + '): ' + defaultValue,
data: defaultValue,
path: path + '.defaultValue'
});
}
}
if (!_.isUndefined(data.minimum)) {
parsedMinimumValue = parseFloat(data.minimum);
if (isNaN(parsedMinimumValue)) {
errors.push({
code: 'INVALID_TYPE',
message: 'Invalid type (expected parseable number): ' + data.minimum,
data: data.minimum,
path: path + '.minimum'
});
} else if (_.isNumber(parsedValue) && _.isNumber(parsedMinimumValue) && parsedValue < parsedMinimumValue) {
errors.push({
code: 'MINIMUM',
message: 'Default value is less than minimum (' + data.minimum + '): ' + defaultValue,
data: defaultValue,
path: path + '.defaultValue'
});
}
}
}
break;
case 'boolean':
if (['false', 'true'].indexOf(defaultValue) === -1) {
errors.push({
code: 'INVALID_TYPE',
message: 'Invalid type (expected parseable boolean): ' + defaultValue,
data: defaultValue,
path: path + '.defaultValue'
});
}
break;
}
}
return {
errors: errors,
warnings: []
};
};
var validateModels = function validateModels (spec, resource) {

@@ -375,2 +492,4 @@ var addModelRef = function (modelId, modelRef) {

addModelRef(property.items.$ref, propPath + '.items.$ref');
} else {
mergeResults(errors, warnings, validateDefaultValue(property, propPath));
}

@@ -472,2 +591,9 @@ });

if (operation.parameters && _.isArray(operation.parameters)) {
_.each(operation.parameters, function (parameter, index) {
mergeResults(errors, warnings,
validateDefaultValue(parameter, operationPath + '.parameters[' + index + ']'));
});
}
// Identify duplicate operation methods

@@ -545,3 +671,3 @@ if (operation.method) {

*
* @returns undefined if validation passes or an array of error objects
* @returns undefined if validation passes or an object containing errors and/or warnings
*/

@@ -574,3 +700,4 @@ Specification.prototype.validate = function (data, schemaName) {

if (!schema) {
throw new Error('schemaName is not valid. Valid schema names: ' + Object.keys(this.schemas).join(', '));
throw new Error('schemaName is not valid (' + schemaName + '). Valid schema names: ' +
Object.keys(this.schemas).join(', '));
}

@@ -586,14 +713,7 @@

// Do semantic validation
switch (schemaName) {
case 'apiDeclaration.json':
[validateModels, validateOperations].forEach(function (func) {
result = func(this, data);
if (result.errors && _.isArray(result.errors)) {
errors = errors.concat(result.errors);
}
if (result.warnings && _.isArray(result.warnings)) {
warnings = warnings.concat(result.warnings);
}
mergeResults(errors, warnings, func(this, data));
}.bind(this));

@@ -607,2 +727,216 @@

/**
* Returns the result of the validation of the Swagger API as a whole.
*
* @param {object} resourceListing - The resource listing object
* @param {object[]} resources - The array of resources
*
* @returns undefined if validation passes or an object containing errors and/or warnings
*/
Specification.prototype.validateApi = function (resourceList, resources) {
if (_.isUndefined(resourceList)) {
throw new Error('resourceList is required');
} else if (!_.isObject(resourceList)) {
throw new TypeError('resourceList must be an object');
}
if (_.isUndefined(resources)) {
throw new Error('resources is required');
} else if (!_.isArray(resources)) {
throw new TypeError('resources must be an array');
}
var authNames = [];
var authScopes = {};
var resourcePaths = [];
var resourceRefs = {};
var result = {
errors: [],
warnings: [],
resources: []
};
var seenAuthScopes = {};
var seenResourcePaths = [];
var swaggerVersion = resourceList.swaggerVersion;
// Generate list of declared API paths
if (_.isArray(resourceList.apis)) {
resourceList.apis.forEach(function (api, index) {
if (api.path) {
if (resourcePaths.indexOf(api.path) > -1) {
result.errors.push({
code: 'DUPLICATE_RESOURCE_PATH',
message: 'Resource path already defined: ' + api.path,
data: api.path,
path: '$.apis[' + index + '].path'
});
} else {
resourcePaths.push(api.path);
resourceRefs[api.path] = [];
}
}
});
}
// Generate list of declared auth scopes
_.each(resourceList.authorizations, function (authorization, name) {
var scopes = [];
authNames.push(name);
if (authorization.type === 'oauth2' && _.isArray(authorization.scopes)) {
scopes = _.map(authorization.scopes, function (scope) {
return scope.scope;
});
}
authScopes[name] = scopes;
});
// Validate the resource listing (structural)
mergeResults(result.errors, result.warnings, this.validate(resourceList, 'resourceListing.json'));
// Validate the resources
resources.forEach(function (resource, index) {
var vResult = this.validate(resource) || {errors: [], warnings: []};
var recordAuth = function (authorization, name, path) {
var scopes = authScopes[name];
if (!_.isArray(seenAuthScopes[name])) {
seenAuthScopes[name] = [];
}
// Identify missing models (referenced but not declared)
if (_.isUndefined(scopes)) {
vResult.errors.push({
code: 'UNRESOLVABLE_AUTHORIZATION_REFERENCE',
message: 'Authorization reference could not be resolved: ' + name,
data: authorization,
path: path
});
} else if (_.isArray(authorization) && authorization.length > 0) {
if (scopes.length > 0) {
_.each(authorization, function (scope, index) {
if (scopes.indexOf(scope.scope) === -1) {
vResult.errors.push({
code: 'UNRESOLVABLE_AUTHORIZATION_SCOPE_REFERENCE',
message: 'Authorization scope reference could not be resolved: ' + scope.scope,
data: scope.scope,
path: path + '.scopes[' + index + ']'
});
} else {
if (seenAuthScopes[name].indexOf(scope.scope) === -1) {
seenAuthScopes[name].push(scope.scope);
}
}
});
}
}
};
if (swaggerVersion && resource.swaggerVersion && swaggerVersion !== resource.swaggerVersion) {
vResult.warnings.push({
code: 'SWAGGER_VERSION_MISMATCH',
message: 'Swagger version differs from resource listing (' + swaggerVersion + '): ' + resource.swaggerVersion,
data: resource.swaggerVersion,
path: '$.swaggerVersion'
});
}
// References in resource
if (_.isObject(resource.authorizations)) {
_.each(resource.authorizations, function (authorization, name) {
recordAuth(authorization, name, '$.authorizations[\'' + name + ']');
});
}
// References in resource operations
if (_.isArray(resource.apis)) {
_.each(resource.apis, function (api, index) {
var aPath = '$.apis[' + index + ']';
if (_.isArray(api.operations)) {
_.each(api.operations, function (operation, index) {
var oPath = aPath + '.operations[' + index + ']';
if (_.isObject(operation.authorizations)) {
_.each(operation.authorizations, function (authorization, name) {
recordAuth(authorization, name, oPath + '.authorizations[\'' + name + '\']');
});
}
});
}
});
}
if (resource.resourcePath) {
if (resourcePaths.indexOf(resource.resourcePath) === -1) {
vResult.errors.push({
code: 'UNRESOLVABLE_RESOURCEPATH_REFERENCE',
message: 'Resource defined but not declared in resource listing: ' + resource.resourcePath,
data: resource.resourcePath,
path: '$.resourcePath'
});
} else if (seenResourcePaths.indexOf(resource.resourcePath) > -1) {
vResult.errors.push({
code: 'DUPLICATE_RESOURCE_PATH',
message: 'Resource path already defined: ' + resource.resourcePath,
data: resource.resourcePath,
path: '$.resourcePath'
});
} else {
if (seenResourcePaths.indexOf(resource.resourcePath) === -1) {
seenResourcePaths.push(resource.resourcePath);
}
}
}
result.resources[index] = vResult;
}.bind(this));
// Identify unused resources (declared but not referenced)
_.difference(resourcePaths, seenResourcePaths).forEach(function (unused) {
var index = _.map(resourceList.apis, function (api) { return api.path; }).indexOf(unused);
result.errors.push({
code: 'UNUSED_RESOURCE',
message: 'Resource is defined but is not used: ' + unused,
data: resourceList.apis[index],
path: '$.apis[' + index + ']'
});
});
// Identify unused authorizations (declared but not referenced)
_.difference(Object.keys(authScopes), Object.keys(seenAuthScopes)).forEach(function (unused) {
result.errors.push({
code: 'UNUSED_AUTHORIZATION',
message: 'Authorization is defined but is not used: ' + unused,
data: resourceList.authorizations[unused],
path: '$.authorizations[\'' + unused + '\']'
});
});
_.each(authScopes, function (scopes, name) {
var path = '$.authorizations[\'' + name + '\']';
// Identify unused authorization scope (declared but not referenced)
_.difference(scopes, seenAuthScopes[name] || []).forEach(function (unused) {
var index = scopes.indexOf(unused);
result.errors.push({
code: 'UNUSED_AUTHORIZATION_SCOPE',
message: 'Authorization scope is defined but is not used: ' + unused,
data: resourceList.authorizations[name].scopes[index],
path: path + '.scopes[' + index + ']'
});
});
});
return result.errors.length + result.warnings.length + _.reduce(result.resources, function(count, resource) {
return count +
(_.isArray(resource.errors) ? resource.errors.length : 0) +
(_.isArray(resource.warnings) ? resource.warnings.length : 0);
}, 0) > 0 ? result : undefined;
};
var v1_2 = module.exports.v1_2 = new Specification('1.2'); // jshint ignore:line

2

package.json
{
"name": "swagger-tools",
"version": "0.1.6",
"version": "0.2.0",
"description": "Various tools for using and integrating with Swagger.",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -25,3 +25,3 @@ The project provides various tools for integrating and interacting with Swagger. This project is in its infancy but

* `schemasUrl`: This is a link to the Swagger JSON Schema files for the corresponding specification version
* `verison`: This is the Swagger specification version
* `version`: This is the Swagger specification version
* `schemas`: This is an object where the keys are the Swagger JSON Schema file names and the object is the loaded schema

@@ -28,0 +28,0 @@ contents

@@ -42,2 +42,6 @@ /* global describe, it */

var allSampleFiles = {};
var invalidApiResourceListingJson = require('./v1_2-invalid-api-resource-listing.json');
var invalidApiResource1Json = require('./v1_2-invalid-api-resource1.json');
var invalidApiResource2Json = require('./v1_2-invalid-api-resource2.json');
var invalidApiResource3Json = require('./v1_2-invalid-api-resource3.json');
var invalidModelMiscJson = require('./v1_2-invalid-model-misc.json');

@@ -47,3 +51,21 @@ var invalidModelRefsJson = require('./v1_2-invalid-model-refs.json');

var invalidOperationMiscJson = require('./v1_2-invalid-operation-misc.json');
var findAllErrorsOrWarnings = function (type, code, results) {
var arr = [];
var finder = function (result) {
if (result.code === code) {
arr.push(result);
}
};
if (_.isArray(results)) {
results.forEach(function (resource) {
resource[type].forEach(finder);
});
} else {
results[type].forEach(finder);
}
return arr;
};
// Load the sample files from disk

@@ -58,3 +80,3 @@ fs.readdirSync(path.join(__dirname, '..', 'samples', '1.2'))

describe('swagger-tools v1.2 Specification', function () {
describe('Specification v1.2', function () {
describe('metadata', function () {

@@ -76,2 +98,3 @@ it('should have proper docsUrl, primitives, options, schemasUrl and verison properties', function () {

'double',
'number',
'string',

@@ -228,10 +251,5 @@ 'byte',

it('should return errors for duplicate model ids in apiDeclaration files', function () {
var errors = [];
var result = spec.validate(invalidModelInheritanceJson);
var errors = findAllErrorsOrWarnings('errors', 'DUPLICATE_MODEL_DEFINITION', result);
spec.validate(invalidModelInheritanceJson).errors.forEach(function (error) {
if (error.code === 'DUPLICATE_MODEL_DEFINITION') {
errors.push(error);
}
});
assert.deepEqual(errors, [

@@ -248,10 +266,5 @@ {

it('should return errors for cyclical model subTypes in apiDeclaration files', function () {
var errors = [];
var result = spec.validate(invalidModelInheritanceJson);
var errors = findAllErrorsOrWarnings('errors', 'CYCLICAL_MODEL_INHERITANCE', result);
spec.validate(invalidModelInheritanceJson).errors.forEach(function (error) {
if (error.code === 'CYCLICAL_MODEL_INHERITANCE') {
errors.push(error);
}
});
assert.deepEqual(errors, [

@@ -274,10 +287,5 @@ {

it('should return errors for model multiple inheritance in apiDeclaration files', function () {
var errors = [];
var result = spec.validate(invalidModelInheritanceJson);
var errors = findAllErrorsOrWarnings('errors', 'MULTIPLE_MODEL_INHERITANCE', result);
spec.validate(invalidModelInheritanceJson).errors.forEach(function (error) {
if (error.code === 'MULTIPLE_MODEL_INHERITANCE') {
errors.push(error);
}
});
assert.deepEqual(errors, [

@@ -294,10 +302,5 @@ {

it('should return errors for model subTypes redeclaring ancestor properties in apiDeclaration files', function () {
var errors = [];
var result = spec.validate(invalidModelInheritanceJson);
var errors = findAllErrorsOrWarnings('errors', 'CHILD_MODEL_REDECLARES_PROPERTY', result);
spec.validate(invalidModelInheritanceJson).errors.forEach(function (error) {
if (error.code === 'CHILD_MODEL_REDECLARES_PROPERTY') {
errors.push(error);
}
});
assert.deepEqual(errors, [

@@ -314,10 +317,5 @@ {

it('should return warning for model subTypes with duplicate entries in apiDeclaration files', function () {
var warnings = [];
var result = spec.validate(invalidModelInheritanceJson);
var warnings = findAllErrorsOrWarnings('warnings', 'DUPLICATE_MODEL_SUBTYPE_DEFINITION', result);
spec.validate(invalidModelInheritanceJson).warnings.forEach(function (warning) {
if (warning.code === 'DUPLICATE_MODEL_SUBTYPE_DEFINITION') {
warnings.push(warning);
}
});
assert.deepEqual(warnings, [

@@ -334,10 +332,5 @@ {

it('should return errors for model with invalid discriminator in apiDeclaration files', function () {
var errors = [];
var result = spec.validate(invalidModelMiscJson);
var errors = findAllErrorsOrWarnings('errors', 'INVALID_MODEL_DISCRIMINATOR', result);
spec.validate(invalidModelMiscJson).errors.forEach(function (error) {
if (error.code === 'INVALID_MODEL_DISCRIMINATOR') {
errors.push(error);
}
});
assert.deepEqual(errors, [

@@ -354,10 +347,5 @@ {

it('should return errors for model with missing required property in apiDeclaration files', function () {
var errors = [];
var result = spec.validate(invalidModelMiscJson);
var errors = findAllErrorsOrWarnings('errors', 'MISSING_REQUIRED_MODEL_PROPERTY', result);
spec.validate(invalidModelMiscJson).errors.forEach(function (error) {
if (error.code === 'MISSING_REQUIRED_MODEL_PROPERTY') {
errors.push(error);
}
});
assert.deepEqual(errors, [

@@ -374,10 +362,5 @@ {

it('should return warning for operations with duplicate method apiDeclaration files', function () {
var errors = [];
var result = spec.validate(invalidOperationMiscJson);
var errors = findAllErrorsOrWarnings('errors', 'DUPLICATE_OPERATION_METHOD', result);
spec.validate(invalidOperationMiscJson).errors.forEach(function (error) {
if (error.code === 'DUPLICATE_OPERATION_METHOD') {
errors.push(error);
}
});
assert.deepEqual(errors, [

@@ -394,10 +377,5 @@ {

it('should return warning for operations with duplicate nickname apiDeclaration files', function () {
var errors = [];
var result = spec.validate(invalidOperationMiscJson);
var errors = findAllErrorsOrWarnings('errors', 'DUPLICATE_OPERATION_NICKNAME', result);
spec.validate(invalidOperationMiscJson).errors.forEach(function (error) {
if (error.code === 'DUPLICATE_OPERATION_NICKNAME') {
errors.push(error);
}
});
assert.deepEqual(errors, [

@@ -414,10 +392,5 @@ {

it('should return warning for operations with responseMessage codes nickname apiDeclaration files', function () {
var errors = [];
var result = spec.validate(invalidOperationMiscJson);
var errors = findAllErrorsOrWarnings('errors', 'DUPLICATE_OPERATION_RESPONSEMESSAGE_CODE', result);
spec.validate(invalidOperationMiscJson).errors.forEach(function (error) {
if (error.code === 'DUPLICATE_OPERATION_RESPONSEMESSAGE_CODE') {
errors.push(error);
}
});
assert.deepEqual(errors, [

@@ -437,10 +410,8 @@ {

var warnings = [];
var result;
json.apis[0].operations[1].summary = summary;
spec.validate(json).warnings.forEach(function (warning) {
if (warning.code === 'OPERATION_SUMMARY_LONG') {
warnings.push(warning);
}
});
result = spec.validate(json);
warnings = findAllErrorsOrWarnings('warnings', 'OPERATION_SUMMARY_LONG', result);

@@ -456,3 +427,239 @@ assert.deepEqual(warnings, [

});
it('should return errors for defaultValue related properties in apiDeclaration files', function () {
var result = spec.validate(require('./v1_2-invalid-defaultValues.json'));
var expectedErrors = [
{
code: 'ENUM_MISMATCH',
message: 'Default value is not within enum values (A, B): C',
data: 'C',
path: '$.apis[0].operations[0].parameters[0].defaultValue'
},
{
code: 'INVALID_TYPE',
message: 'Invalid type (expected parseable number): NaN',
data: 'NaN',
path: '$.apis[0].operations[0].parameters[1].defaultValue'
},
{
code: 'INVALID_TYPE',
message: 'Invalid type (expected parseable number): NaN',
data: 'NaN',
path: '$.apis[0].operations[0].parameters[2].maximum'
},
{
code: 'MAXIMUM',
message: 'Default value is greater than maximum (1): 2',
data: '2',
path: '$.apis[0].operations[0].parameters[3].defaultValue'
},
{
code: 'INVALID_TYPE',
message: 'Invalid type (expected parseable number): NaN',
data: 'NaN',
path: '$.apis[0].operations[0].parameters[4].minimum'
},
{
code: 'MINIMUM',
message: 'Default value is less than minimum (2): 1',
data: '1',
path: '$.apis[0].operations[0].parameters[5].defaultValue'
},
{
code: 'INVALID_TYPE',
message: 'Invalid type (expected parseable boolean): NaN',
data: 'NaN',
path: '$.apis[0].operations[0].parameters[6].defaultValue'
}
];
assert.equal(result.errors.length, Object.keys(expectedErrors).length);
assert.equal(result.warnings.length, 0);
assert.deepEqual(result.errors, expectedErrors);
});
});
describe('#validateApi', function () {
it('should return errors for duplicate resource paths in resource listing JSON files', function () {
var result = spec.validateApi(invalidApiResourceListingJson, [
invalidApiResource1Json,
invalidApiResource2Json,
invalidApiResource3Json
]);
var errors = findAllErrorsOrWarnings('errors', 'DUPLICATE_RESOURCE_PATH', result);
assert.deepEqual(errors, [
{
code: 'DUPLICATE_RESOURCE_PATH',
message: 'Resource path already defined: /resource1',
data: '/resource1',
path: '$.apis[2].path'
}
]);
});
it('should return errors for defined but unused resource paths in resource listing JSON files', function () {
var result = spec.validateApi(invalidApiResourceListingJson, [
invalidApiResource1Json,
invalidApiResource2Json,
invalidApiResource3Json
]);
var errors = findAllErrorsOrWarnings('errors', 'UNUSED_RESOURCE', result);
assert.deepEqual(errors, [
{
code: 'UNUSED_RESOURCE',
message: 'Resource is defined but is not used: /resource2',
data: {
description: 'Operations about resource2',
path: '/resource2'
},
path: '$.apis[1]'
},
{
code: 'UNUSED_RESOURCE',
message: 'Resource is defined but is not used: /resource4',
data: {
description: 'Operations about resource4',
path: '/resource4'
},
path: '$.apis[3]'
}
]);
});
it('should return errors for defined but unused authorizations in resource listing JSON files', function () {
var result = spec.validateApi(invalidApiResourceListingJson, [
invalidApiResource1Json,
invalidApiResource2Json,
invalidApiResource3Json
]);
var errors = findAllErrorsOrWarnings('errors', 'UNUSED_AUTHORIZATION', result);
assert.deepEqual(errors, [
{
code: 'UNUSED_AUTHORIZATION',
message: 'Authorization is defined but is not used: unusedBasicAuth',
data: {
type: 'basicAuth'
},
path: '$.authorizations[\'unusedBasicAuth\']'
}
]);
});
it('should return errors for defined but unused authorization scopes in resource listing JSON files', function () {
var result = spec.validateApi(invalidApiResourceListingJson, [
invalidApiResource1Json,
invalidApiResource2Json,
invalidApiResource3Json
]);
var errors = findAllErrorsOrWarnings('errors', 'UNUSED_AUTHORIZATION_SCOPE', result);
assert.deepEqual(errors, [
{
code: 'UNUSED_AUTHORIZATION_SCOPE',
message: 'Authorization scope is defined but is not used: scope2',
data: {
description: 'Scope 2',
scope: 'scope2'
},
path: '$.authorizations[\'oauth2\'].scopes[1]'
}
]);
});
it('should return errors for missing authorization references in apiDeclaration JSON files', function () {
var result = spec.validateApi(invalidApiResourceListingJson, [
invalidApiResource1Json,
invalidApiResource2Json,
invalidApiResource3Json
]);
var errors = findAllErrorsOrWarnings('errors', 'UNRESOLVABLE_AUTHORIZATION_REFERENCE', result.resources);
assert.deepEqual(errors, [
{
code: 'UNRESOLVABLE_AUTHORIZATION_REFERENCE',
message: 'Authorization reference could not be resolved: missingAuth',
data: [],
path: '$.apis[0].operations[0].authorizations[\'missingAuth\']'
}
]);
});
it('should return errors for missing authorization scope reference in apiDeclaration JSON files', function () {
var result = spec.validateApi(invalidApiResourceListingJson, [
invalidApiResource1Json,
invalidApiResource2Json,
invalidApiResource3Json
]);
var errors = findAllErrorsOrWarnings('errors', 'UNRESOLVABLE_AUTHORIZATION_SCOPE_REFERENCE', result.resources);
assert.deepEqual(errors, [
{
code: 'UNRESOLVABLE_AUTHORIZATION_SCOPE_REFERENCE',
message: 'Authorization scope reference could not be resolved: missingScope',
data: 'missingScope',
path: '$.apis[1].operations[0].authorizations[\'oauth2\'].scopes[1]'
}
]);
});
it('should return errors for duplicate resource path in apiDeclaration JSON files', function () {
var result = spec.validateApi(invalidApiResourceListingJson, [
invalidApiResource1Json,
invalidApiResource2Json,
invalidApiResource3Json
]);
var errors = findAllErrorsOrWarnings('errors', 'DUPLICATE_RESOURCE_PATH', result.resources);
assert.deepEqual(errors, [
{
code: 'DUPLICATE_RESOURCE_PATH',
message: 'Resource path already defined: /resource1',
data: '/resource1',
path: '$.resourcePath'
}
]);
});
it('should return errors for missing resource listing for resource path in apiDeclaration JSON files', function () {
var result = spec.validateApi(invalidApiResourceListingJson, [
invalidApiResource1Json,
invalidApiResource2Json,
invalidApiResource3Json
]);
var errors = findAllErrorsOrWarnings('errors', 'UNRESOLVABLE_RESOURCEPATH_REFERENCE', result.resources);
assert.deepEqual(errors, [
{
code: 'UNRESOLVABLE_RESOURCEPATH_REFERENCE',
message: 'Resource defined but not declared in resource listing: /resource3',
data: '/resource3',
path: '$.resourcePath'
}
]);
});
it('should return warning for Swagger version mismatch in apiDeclaration JSON files', function () {
var result = spec.validateApi(invalidApiResourceListingJson, [
invalidApiResource1Json,
invalidApiResource2Json,
invalidApiResource3Json
]);
var warnings = findAllErrorsOrWarnings('warnings', 'SWAGGER_VERSION_MISMATCH', result.resources);
assert.deepEqual(warnings, [
{
code: 'SWAGGER_VERSION_MISMATCH',
message: 'Swagger version differs from resource listing (1.2): 1.1',
data: '1.1',
path: '$.swaggerVersion'
}
]);
});
});
});
// TODO: Add test for calling 'validate' with invalid schema name

@@ -59,2 +59,2 @@ {

"swaggerVersion": "1.2"
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc