Skip to content

Commit

Permalink
#50 and Fixed #53 - Update prefer-property-order (#54)
Browse files Browse the repository at this point in the history
* #50 and Fixed #53 - Update prefer-property-order

Add defaults if an empty array is passed. Prevent the rule from failing
if package.json file is missing a node that exists in the preferred
property list.

* Revert from array includes to indexOf for Node 4 and 5 support
  • Loading branch information
tclindner committed Aug 22, 2017
1 parent 89d8422 commit f37e271
Show file tree
Hide file tree
Showing 6 changed files with 251 additions and 42 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).

### Removed

## [2.8.1] - 2017-08-21
### Changed/Fixed
- Updated rule: [prefer-property-order](https://github.com/tclindner/npm-package-json-lint/wiki/prefer-property-order) based on discussion with @moshest in [issue #50](https://github.com/tclindner/npm-package-json-lint/issues/50) and @evilebottnawi in [issue #53](https://github.com/tclindner/npm-package-json-lint/issues/53).

## [2.8.0] - 2017-08-16
### Added
- New rule: [prefer-property-order](https://github.com/tclindner/npm-package-json-lint/wiki/prefer-property-order)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "npm-package-json-lint",
"version": "2.8.0",
"version": "2.8.1",
"description": "CLI app for linting package.json files.",
"keywords": [
"lint",
Expand Down
10 changes: 1 addition & 9 deletions src/rules/prefer-property-order.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,7 @@ const lint = function(packageJsonData, lintType, preferredOrder) {
const result = isInPreferredOrder(packageJsonData, preferredOrder);

if (!result.status) {
let helpTip = '';

if (result.data.actualNode === null) {
helpTip = `Please add ${result.data.desiredNode} at the end of the file.`;
} else {
helpTip = `Please move ${result.data.actualNode} after ${result.data.desiredNode}.`;
}

return new LintIssue(lintId, lintType, nodeName, `${message} ${helpTip}`);
return new LintIssue(lintId, lintType, nodeName, `${message} ${result.msg}`);
}

return true;
Expand Down
93 changes: 73 additions & 20 deletions src/validators/property-order.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,95 @@
'use strict';

/* eslint max-statements: 'off' */

const notFound = -1;
const empty = 0;
const increment = 1;
const defaultPreferredNodeOrder = [
'name',
'version',
'description',
'keywords',
'homepage',
'bugs',
'license',
'author',
'contributors',
'files',
'main',
'module',
'jsnext:main',
'types',
'typings',
'style',
'example',
'examplestyle',
'assets',
'bin',
'man',
'directories',
'repository',
'scripts',
'config',
'pre-commit',
'browser',
'browserify',
'babel',
'eslintConfig',
'stylelint',
'npmPackageJsonLintConfig',
'dependencies',
'devDependencies',
'peerDependencies',
'bundledDependencies',
'bundleDependencies',
'optionalDependencies',
'engines',
'engineStrict',
'os',
'cpu',
'preferGlobal',
'private',
'publishConfig'
];

/**
* Determines whether an array is in the specified order
* @param {Object} packageJsonData Valid JSON
* @param {Array} preferredNodeOrder Preferred order of nodes
* @return {Object} Object containing the status and the node that is out of order, if applicable
* @param {Object} packageJsonData Valid JSON
* @param {Array} userPreferredNodeOrder Preferred order of nodes
* @return {Object} Object containing the status and the node that is out of order, if applicable
*/
const isInPreferredOrder = function(packageJsonData, preferredNodeOrder) {
const isInPreferredOrder = function(packageJsonData, userPreferredNodeOrder) {
let isValid = true;
let data = {
actualNode: null,
desiredNode: null
};
let msg = null;
const actualNodeList = Object.keys(packageJsonData);
const preferredNodeOrder = userPreferredNodeOrder.length === empty ? Array.from(defaultPreferredNodeOrder) : Array.from(userPreferredNodeOrder);
const preferredNodeOrderCopy = Array.from(preferredNodeOrder);

for (let keyIndex = 0;keyIndex < preferredNodeOrder.length;keyIndex += increment) {
if (typeof actualNodeList[keyIndex] === 'undefined') {
for (let keyIndex = 0;keyIndex < actualNodeList.length;keyIndex += increment) {
let preferredNodeOrderItem = null;

if (preferredNodeOrder.indexOf(actualNodeList[keyIndex]) === notFound) {
isValid = false;
data = {
actualNode: null,
desiredNode: preferredNodeOrder[keyIndex]
};
msg = `${actualNodeList[keyIndex]} is not in the preferred property list.`;
break;
} else if (actualNodeList[keyIndex] !== preferredNodeOrder[keyIndex]) {
}

if (preferredNodeOrderCopy.indexOf(actualNodeList[keyIndex]) === notFound) {
isValid = false;
data = {
actualNode: actualNodeList[keyIndex],
desiredNode: preferredNodeOrder[keyIndex]
};
msg = `Please move ${actualNodeList[keyIndex]} before ${actualNodeList[keyIndex - increment]}.`;
break;
}

do {
preferredNodeOrderItem = preferredNodeOrderCopy.shift();

} while (actualNodeList[keyIndex] !== preferredNodeOrderItem);
}

return {
status: isValid,
data
msg
};
};

Expand Down
7 changes: 2 additions & 5 deletions tests/unit/rules/prefer-property-order.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,7 @@ describe('prefer-property-order Unit Tests', function() {
];
const response = lint(packageJsonData, 'error', preferredOrder);

response.lintId.should.equal('prefer-property-order');
response.lintType.should.equal('error');
response.node.should.equal('');
response.lintMessage.should.equal('Your package.json properties are not in the desired order. Please add description at the end of the file.');
response.should.be.true;
});
});

Expand All @@ -61,7 +58,7 @@ describe('prefer-property-order Unit Tests', function() {
response.lintId.should.equal('prefer-property-order');
response.lintType.should.equal('error');
response.node.should.equal('');
response.lintMessage.should.equal('Your package.json properties are not in the desired order. Please move description after version.');
response.lintMessage.should.equal('Your package.json properties are not in the desired order. Please move version before description.');
});
});
});
177 changes: 170 additions & 7 deletions tests/unit/validators/property-order.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,22 @@ describe('property-order Unit Tests', function() {
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);

response.status.should.be.true;
(response.data.actualNode === null).should.be.true;
(response.data.desiredNode === null).should.be.true;
(response.msg === null).should.be.true;
});
});

context('when the properties in the package.json file are in the desired order, but the defaults are used', function() {
it('true should be returned', function() {
const packageJson = {
name: 'awesome-module',
version: '1.0.0',
description: 'description'
};
const preferredOrder = [];
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);

response.status.should.be.true;
(response.msg === null).should.be.true;
});
});

Expand All @@ -40,9 +54,8 @@ describe('property-order Unit Tests', function() {
];
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);

response.status.should.be.false;
(response.data.actualNode === null).should.be.true;
response.data.desiredNode.should.equal('description');
response.status.should.be.true;
(response.msg === null).should.be.true;
});
});

Expand All @@ -61,8 +74,158 @@ describe('property-order Unit Tests', function() {
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);

response.status.should.be.false;
response.data.actualNode.should.equal('description');
response.data.desiredNode.should.equal('version');
response.msg.should.equal('Please move version before description.');
});
});

context('when the actual node list is in a different order than desired', function() {
it('false should be returned', function() {
const packageJson = {
version: '1.0.0',
name: 'awesome-module',
description: 'description'
};
const preferredOrder = [
'name',
'version',
'description'
];
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);

response.status.should.be.false;
response.msg.should.equal('Please move name before version.');
});
});

context('when the actual node list is in a different order than desired', function() {
it('false should be returned', function() {
const packageJson = {
name: 'awesome-module',
version: '1.0.0',
description: 'description'
};
const preferredOrder = [
'name',
'version',
'homepage',
'description'
];
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);

response.status.should.be.true;
(response.msg === null).should.be.true;
});
});

context('when the actual node list is in a different order than desired', function() {
it('false should be returned', function() {
const packageJson = {
name: 'awesome-module',
version: '1.0.0',
description: 'description',
homepage: 'https://github.com/tclindner/npm-package-json-lint'
};
const preferredOrder = [
'name',
'version',
'description',
'keywords',
'homepage'
];
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);

response.status.should.be.true;
(response.msg === null).should.be.true;
});
});

context('when the actual node list is in correct order, but has extra values in preferred order', function() {
it('true should be returned', function() {
const packageJson = {
name: 'awesome-module',
version: '1.0.0',
description: 'description',
homepage: 'https://github.com/tclindner/npm-package-json-lint'
};
const preferredOrder = [
'name',
'version',
'description',
'scripts',
'bin',
'keywords',
'homepage'
];
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);

response.status.should.be.true;
(response.msg === null).should.be.true;
});
});

context('when the actual node list is not in correct order and also has extra values in preferred order', function() {
it('true should be returned', function() {
const packageJson = {
name: 'awesome-module',
version: '1.0.0',
description: 'description',
homepage: 'https://github.com/tclindner/npm-package-json-lint',
keywords: ['word']
};
const preferredOrder = [
'name',
'version',
'description',
'scripts',
'bin',
'keywords',
'homepage'
];
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);

response.status.should.be.false;
response.msg.should.equal('Please move keywords before homepage.');
});
});

context('when node is not in the preferred node list', function() {
it('false should be returned', function() {
const packageJson = {
name: 'awesome-module',
version: '1.0.0',
description: 'description',
homepage: 'https://github.com/tclindner/npm-package-json-lint'
};
const preferredOrder = [
'name',
'version',
'keywords',
'homepage'
];
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);

response.status.should.be.false;
response.msg.should.equal('description is not in the preferred property list.');
});
});

context('when node is not in the preferred node list', function() {
it('false should be returned', function() {
const packageJson = {
name: 'awesome-module',
version: '1.0.0',
description: 'description',
homepage: 'https://github.com/tclindner/npm-package-json-lint'
};
const preferredOrder = [
'version',
'keywords',
'homepage'
];
const response = propertyOrder.isInPreferredOrder(packageJson, preferredOrder);

response.status.should.be.false;
response.msg.should.equal('name is not in the preferred property list.');
});
});
});
Expand Down

0 comments on commit f37e271

Please sign in to comment.