All files / src/plugins/validation/2and3/semantic-validators refs.js

100% Statements 29/29
100% Branches 16/16
100% Functions 5/5
100% Lines 29/29

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87      29x 29x 29x 29x 29x   29x 96x   96x   26x       70x 70x 70x 70x 333x 333x     70x   70x 207x       70x     35x                   35x 280x 44x                 35x 32x                 70x                 76x 241x 34x                
// Assertation 1:
// Referenceable definitions should be used by being referenced in the appropriate way
 
const uniq = require('lodash/uniq');
const filter = require('lodash/filter');
const startsWith = require('lodash/startsWith');
const each = require('lodash/each');
const MessageCarrier = require('../../../utils/messageCarrier');
 
module.exports.validate = function({ jsSpec, specStr, isOAS3 }) {
  const messages = new MessageCarrier();
 
  if (isOAS3 && !jsSpec.components) {
    // prevent trying to access components.schemas if components is undefined
    return messages;
  }
 
  // Collects all refs in the API definition
  const refRegex = /\$ref.*["'](.*)["']/g;
  let match = refRegex.exec(specStr);
  const refs = [];
  while (match !== null) {
    refs.push(match[1]);
    match = refRegex.exec(specStr);
  }
 
  const definitionSectionName = isOAS3 ? 'components' : 'definitions';
  // de-dupe the array, and filter out non-definition refs
  const definitionsRefs = filter(uniq(refs), v =>
    startsWith(v, `#/${definitionSectionName}`)
  );
 
  // checks if the definitions are used, and if not, record a warning
  if (isOAS3) {
    // securitySchemes definition type excluded because
    // security-definitions-ibm.js checks for unused security schemes
    const definitionTypeList = [
      'schemas',
      'parameters',
      'responses',
      'examples',
      'requestBodies',
      'headers',
      'links',
      'callbacks'
    ];
    definitionTypeList.forEach(function(definitionType) {
      if (jsSpec.components && jsSpec.components[definitionType]) {
        recordDefinitionsNotUsed(
          jsSpec.components[definitionType],
          definitionsRefs,
          ['components', definitionType],
          messages
        );
      }
    });
  } else {
    if (jsSpec.definitions) {
      recordDefinitionsNotUsed(
        jsSpec.definitions,
        definitionsRefs,
        ['definitions'],
        messages
      );
    }
  }
 
  return messages;
};
 
function recordDefinitionsNotUsed(
  definitions,
  definitionsRefs,
  basePath,
  messages
) {
  each(definitions, (_, defName) => {
    if (!definitionsRefs.includes(`#/${basePath.join('/')}/${defName}`)) {
      messages.addMessage(
        `${basePath.join('.')}.${defName}`,
        'Definition was declared but never used in document',
        'warning'
      );
    }
  });
}