Updates to tests, adding system tests, lint warning fixes

This commit is contained in:
abhijitkane
2019-06-05 12:54:47 +05:30
parent b4c14ba22a
commit c8553fb0f8
11 changed files with 462 additions and 23 deletions

14
.editorconfig Normal file
View File

@@ -0,0 +1,14 @@
# editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
max_length = 120
trim_trailing_whitespace = true
insert_final_newline = true
[*.{json, yml, html, hbs}]
indent_size = 2

51
.gitignore vendored
View File

@@ -1,8 +1,45 @@
# PLATFORM
# ========
# All exclusions that are specific to the NPM, GIT, IDE and Operating Systems.
node_modules/*
.idea/*
.vscode/*
.coverage/*
npm-debug.log
npm-debug.log.*
tempOutput.json
# - Do not allow installed node modules to be committed. Doing `npm install -d` will bring them in root or other places.
node_modules
# - Do not commit any log file from anywhere
*.log
*.log.*
# - Prevent addition of OS specific file explorer files
Thumbs.db
.DS_Store
# Prevent IDE stuff
.idea
.vscode
# All temporary stuff from one folder
.temp
test/data/.temp
# PROJECT
# =======
# Configuration pertaining to project specific repository structure.
# - Prevent Sublime text IDE files from being commited to repository
*.sublime-*
# - Allow sublime text project file to be commited in the development directory.
!/develop/*.sublime-project
# - Prevent CI output files from being Added
/out/
# - Prevent diff backups from SourceTree from showing as commit.
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
*.orig
# Prevent unit test coverage reports from being added
.coverage

View File

@@ -1,8 +1,45 @@
.idea/*
.vscode/*
.coverage/*
npm-debug.log
npm-debug.log.*
tempOutput.json
.travis.yml
valid_openapi_temp/*
# PLATFORM
# ========
# All exclusions that are specific to the NPM, GIT, IDE and Operating Systems.
# - Do not allow installed node modules to be committed. Doing `npm install -d` will bring them in root or other places.
node_modules
# - Do not commit any log file from anywhere
*.log
*.log.*
# - Prevent addition of OS specific file explorer files
Thumbs.db
.DS_Store
# Prevent IDE stuff
.idea
.vscode
# All temporary stuff from one folder
.temp
test/data/.temp
# PROJECT
# =======
# Configuration pertaining to project specific repository structure.
# - Prevent Sublime text IDE files from being commited to repository
*.sublime-*
# - Allow sublime text project file to be commited in the development directory.
!/develop/*.sublime-project
# - Prevent CI output files from being Added
/out/
# - Prevent diff backups from SourceTree from showing as commit.
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
*.orig
# Prevent unit test coverage reports from being added
.coverage

View File

@@ -115,7 +115,7 @@ module.exports = {
* something that can be added to the collection
* TODO: Figure out better description
* @param {object} serverVariables - Object containing the server variables at the root/path-item level
* @param {string} keyName
* @param {string} keyName - an additional key to add the serverUrl to the variable list
* @param {string} serverUrl - URL from the server object
* @returns {object} modified collection after the addition of the server variables
*/
@@ -518,8 +518,8 @@ module.exports = {
/**
* Gets helper object based on the root spec and the operation.security object
* @param {*} openapi
* @param {Array<object>} securitySet
* @param {*} openapi - the json object representing the OAS spec
* @param {Array<object>} securitySet - the security object at an operation level
* @returns {object} The authHelper to use while constructing the Postman Request. This is
* not directly supported in the SDK - the caller needs to determine the header/body based on the return
* value
@@ -587,6 +587,7 @@ module.exports = {
hasComputedType = true;
return false;
}
return true;
});
// if no JSON or XML, take whatever we have
@@ -777,7 +778,8 @@ module.exports = {
* Handles array/object/string param types
* @param {*} param - the param object, as defined in
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#parameterObject
* @param {any} paramValue
* @param {any} paramValue - the value to use (from schema or example) for the given param.
* This will be exploded/parsed according to the param type
* @returns {array} parameters. One param with type=array might lead to multiple params
* in the return value
* The styles are documented at

View File

@@ -2,6 +2,15 @@
"name": "openapi-to-postmanv2",
"version": "0.0.14",
"description": "Convert a given OpenAPI specification to Postman Collection v2.0",
"homepage": "https://github.com/postmanlabs/openapi-to-postman",
"bugs": "https://github.com/postmanlabs/openapi-to-postman/issues",
"repository": {
"type": "git",
"url": "git://github.com/postmanlabs/openapi-to-postman.git"
},
"keywords": [
"openapi", "postman", "api", "schema", "swagger", "oas"
],
"com_postman_plugin": {
"plugin_type": "importer",
"name": "OPENAPI 3.0",
@@ -94,6 +103,9 @@
}
}
},
"engines": {
"node": ">=4"
},
"main": "index.js",
"bin": {
"openapi2postmanv2": "./bin/openapi2postmanv2.js"
@@ -104,22 +116,25 @@
"lodash": "4.17.11",
"postman-collection": "3.4.7"
},
"author": "Postman",
"license": "Apache",
"author": "Postman Labs <help@getpostman.com>",
"license": "Apache-2.0",
"devDependencies": {
"chai": "4.1.2",
"eslint": "^5.16.0",
"editorconfig": "0.15.3",
"eslint": "5.16.0",
"eslint-plugin-jsdoc": "3.8.0",
"eslint-plugin-mocha": "5.2.0",
"eslint-plugin-security": "1.4.0",
"expect.js": "0.3.1",
"istanbul": "0.4.5",
"mocha": "5.2.0"
"mocha": "5.2.0",
"parse-gitignore": "0.4.0"
},
"scripts": {
"test": "./scripts/test.sh",
"test-unit": "./scripts/test-unit.sh",
"test-lint": "./scripts/test-lint.sh",
"test-system": "./scripts/test-system.sh",
"coverage": "nyc report --reporter=html --reporter=text mocha"
}
}

44
scripts/test-system.sh Executable file
View File

@@ -0,0 +1,44 @@
#!/bin/bash
# ----------------------------------------------------------------------------------------------------------------------
# This script is intended to contain all actions pertaining to repository structure.
#
# ----------------------------------------------------------------------------------------------------------------------
# stop on first error
set -e;
# function to be called on exit
# and ensure cleanup is called before the script exits
function cleanup {
unset XUNIT_FILE;
if [ "$?" != "0" ]; then
exit 1;
fi
}
trap cleanup EXIT;
# set file for xunit report
export XUNIT_FILE=".tmp/report-system.xml";
# run mocha tests
echo -e "\033[93mRunning mocha system tests...\033[0m";
echo -en "\033[0m\033[2mmocha `mocha --version`\033[0m";
# set mocha reporter
if [ "$CI" = "true" ]; then
MOCHA_REPORTER="xunit";
ISTANBUL_REPORT="--report cobertura";
else
MOCHA_REPORTER="spec";
ISTANBUL_REPORT="";
fi
# delete old repor directory
[ -d .coverage ] && rm -rf .coverage && mkdir .coverage;
# run test
node --max-old-space-size=2048 node_modules/.bin/istanbul cover ${ISTANBUL_REPORT} \
--dir ./.coverage -x **/assets/** --print both _mocha -- \
--reporter ${MOCHA_REPORTER} --reporter-options output=${XUNIT_FILE} \
test/system/*.test.js --recursive --prof --grep "$1";

View File

@@ -28,5 +28,10 @@ which git &>/dev/null && \
# run lint
npm run test-lint;
# run system tests
npm run test-system;
# run unit tests
npm run test-unit;

View File

@@ -0,0 +1,41 @@
/**
* @fileOverview Ensures that editorconfig settings are appropriate
*/
var expect = require('expect.js'),
editorconfig = require('editorconfig'),
/**
* The width (in spaces) of tabs used for indentation throughout the project
* @type {Number}
*/
TAB_WIDTH = 2;
/* global describe, it */
describe('.editorconfig', function () {
var config = editorconfig.parseSync('.editorconfig'); // eslint-disable-line no-sync
it('should have a tab_width of 2', function () {
expect(config.tab_width).to.be(TAB_WIDTH);
});
it('should have a charset of utf-8', function () {
expect(config.charset).to.be('utf-8');
});
it('should have an indent_size of 2', function () {
expect(config.indent_size).to.be(TAB_WIDTH);
});
it('should have an indent_style of 2', function () {
expect(config.indent_style).to.be('space');
});
it('should have a truthy insert_final_newline value', function () {
expect(config.insert_final_newline).to.be(true);
});
it('should have a truthy trim_trailing_whitespace', function () {
expect(config.trim_trailing_whitespace).to.be(true);
});
});

View File

@@ -0,0 +1,179 @@
/**
* @fileOverview This test specs runs tests on the package.json file of repository. It has a set of strict tests on the
* content of the file as well. Any change to package.json must be accompanied by valid test case in this spec-sheet.
*/
var _ = require('lodash'),
expect = require('expect.js'),
parseIgnore = require('parse-gitignore');
/* global describe, it */
describe('project repository', function () {
var fs = require('fs');
describe('package.json', function () {
var content,
json;
try {
content = fs.readFileSync('./package.json').toString();
json = JSON.parse(content);
}
catch (e) {
console.error(e);
content = '';
json = {};
}
it('must have readable JSON content', function () {
expect(content).to.be.ok();
expect(json).to.not.eql({});
});
describe('package.json JSON data', function () {
it('must have valid name, description and author', function () {
expect(json).to.have.property('name', 'openapi-to-postmanv2');
expect(json).to.have.property('description',
'Convert a given OpenAPI specification to Postman Collection v2.0');
expect(json).to.have.property('author', 'Postman Labs <help@getpostman.com>');
expect(json).to.have.property('license', 'Apache-2.0');
expect(json).to.have.property('homepage', 'https://github.com/postmanlabs/openapi-to-postman');
expect(json).to.have.property('bugs', 'https://github.com/postmanlabs/openapi-to-postman/issues');
expect(json).to.have.property('repository');
expect(json.repository).to.eql({
type: 'git',
url: 'git://github.com/postmanlabs/openapi-to-postman.git'
});
expect(json).to.have.property('keywords');
expect(json.keywords).to.eql(['openapi', 'postman', 'api', 'schema', 'swagger', 'oas']);
expect(json).to.have.property('engines');
expect(json.engines).to.eql({ node: '>=4' });
});
it('must have a valid version string in form of <major>.<minor>.<revision>', function () {
// eslint-disable-next-line max-len
expect(json.version).to.match(/^((\d+)\.(\d+)\.(\d+))(?:-([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?(?:\+([\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*))?$/);
});
});
describe('binary definitions', function () {
it('must exist', function () {
expect(json.bin).be.ok();
expect(json.bin).to.eql({ 'openapi2postmanv2': './bin/openapi2postmanv2.js' });
});
it('must have valid node shebang', function () {
json.bin && Object.keys(json.bin).forEach(function (scriptName) {
var fileContent = fs.readFileSync(json.bin[scriptName]).toString();
expect((/^#!\/(bin\/bash|usr\/bin\/env\snode)[\r\n][\W\w]*$/g).test(fileContent)).to.be.ok();
});
});
});
describe('dependencies', function () {
it('must exist', function () {
expect(json.dependencies).to.be.a('object');
});
it('must point to a valid and precise (no * or ^) semver', function () {
json.dependencies && Object.keys(json.dependencies).forEach(function (item) {
expect(json.dependencies[item]).to.match(new RegExp('^((\\d+)\\.(\\d+)\\.(\\d+))(?:-' +
'([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?(?:\\+([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?$'));
});
});
});
describe('devDependencies', function () {
it('must exist', function () {
expect(json.devDependencies).to.be.a('object');
});
it('must point to a valid and precise (no * or ^) semver', function () {
json.devDependencies && Object.keys(json.devDependencies).forEach(function (item) {
expect(json.devDependencies[item]).to.match(new RegExp('^((\\d+)\\.(\\d+)\\.(\\d+))(?:-' +
'([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?(?:\\+([\\dA-Za-z\\-]+(?:\\.[\\dA-Za-z\\-]+)*))?$'));
});
});
it('should not overlap devDependencies', function () {
var clean = [];
json.devDependencies && Object.keys(json.devDependencies).forEach(function (item) {
!json.dependencies[item] && clean.push(item);
});
expect(Object.keys(json.devDependencies)).to.eql(clean);
});
});
describe('main entry script', function () {
it('must point to a valid file', function (done) {
expect(json.main).to.equal('index.js');
fs.stat(json.main, done);
});
});
});
describe('README.md', function () {
it('must exist', function (done) {
fs.stat('./README.md', done);
});
it('must have readable content', function () {
expect(fs.readFileSync('./README.md').toString()).to.be.ok();
});
});
describe('LICENSE.md', function () {
it('must exist', function (done) {
fs.stat('./LICENSE.md', done);
});
it('must have readable content', function () {
expect(fs.readFileSync('./LICENSE.md').toString()).to.be.ok();
});
});
describe('.ignore files', function () {
var gitignorePath = '.gitignore',
npmignorePath = '.npmignore',
npmignore = parseIgnore(npmignorePath),
gitignore = parseIgnore(gitignorePath);
describe(gitignorePath, function () {
it('must exist', function (done) {
fs.stat(gitignorePath, done);
});
it('must have valid content', function () {
expect(_.isEmpty(gitignore)).to.not.be.ok();
});
});
describe(npmignorePath, function () {
it('must exist', function (done) {
fs.stat(npmignorePath, done);
});
it('must have valid content', function () {
expect(_.isEmpty(npmignore)).to.not.be.ok();
});
});
it('.gitignore coverage must be a subset of .npmignore coverage', function () {
expect(_.intersection(gitignore, npmignore)).to.eql(gitignore);
});
});
describe('.eslintrc', function () {
it('must exist', function (done) {
fs.stat('./.eslintrc', done);
});
it('must have readable content', function () {
expect(fs.readFileSync('./.eslintrc').toString()).to.be.ok();
});
});
});

View File

@@ -0,0 +1,31 @@
/* global describe, it */
var expect = require('expect.js');
describe('travis.yml', function () {
var fs = require('fs'),
yaml = require('js-yaml'),
travisYAML,
travisYAMLError;
try {
travisYAML = yaml.safeLoad(fs.readFileSync('.travis.yml').toString());
}
catch (e) {
travisYAMLError = e;
}
it('must exist', function (done) {
fs.stat('.travis.yml', done);
});
it('must be a valid yml', function () {
expect(travisYAMLError && travisYAMLError.message || travisYAMLError).to.not.be.ok();
});
describe('strucure', function () {
it('language must be set to node', function () {
expect(travisYAML.language).to.be('node_js');
expect(travisYAML.node_js).to.eql(['6', '7', '8', '9', 'node', 'lts/*']);
});
});
});

34
test/unit/convert.temp.js Normal file
View File

@@ -0,0 +1,34 @@
/**
* This file is meant for debugging purposes only. It is excluded from `npm test`
* Add any openapi file to ../data/.temp before running this
*/
var expect = require('chai').expect,
Converter = require('../../index.js'),
fs = require('fs'),
path = require('path'),
VALID_OPENAPI_PATH = '../data/.temp';
describe('The converter must generate a collection conforming to the schema', function () {
var pathPrefix = VALID_OPENAPI_PATH,
sampleSpecs = fs.readdirSync(path.join(__dirname, pathPrefix));
sampleSpecs.map((sample) => {
var specPath = path.join(__dirname, pathPrefix, sample);
it('Should generate collection conforming to schema for and fail if not valid ' + specPath, function(done) {
// var openapi = fs.readFileSync(specPath, 'utf8');
var result = Converter.validate({ type: 'file', data: specPath });
expect(result.result).to.equal(true);
Converter.convert({ type: 'file', data: specPath },
{}, (err, conversionResult) => {
expect(err).to.be.null;
let collection = conversionResult.output[0].data;
// eslint-disable-next-line no-console
// console.log(JSON.stringify(collection, null, 2));
fs.writeFileSync('./temp/temp-collection.json', JSON.stringify(collection, null, 2));
done();
});
});
});
});