Repository: tclindner/npm-package-json-lint
Pull request #24 (2017-02-19 01:06:39)

2.0.2


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9c822e5..ed0e980 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 
 ### Removed
 
+## [2.0.2] - 2017-02-18
+### Fixed
+- Issue .npmpackagejsonlintrc.json files that only have a extends value with no rules object
+
 ## [2.0.1] - 2017-02-18
 ### Fixed
 - Issue with relative path local config extension modules. Now relative path modules are load relative to the current working directory of the active process.
diff --git a/package.json b/package.json
index 08ef6bc..04df202 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "npm-package-json-lint",
-  "version": "2.0.1",
+  "version": "2.0.2",
   "description": "CLI app for linting package.json files.",
   "keywords": [
     "lint",
diff --git a/src/Config.js b/src/Config.js
index ff68ed7..5c52a76 100755
--- a/src/Config.js
+++ b/src/Config.js
@@ -37,6 +37,10 @@ class Config {
         extendsConfig = this._getExtendsConfig(passedConfig.extends);
       }
 
+      if (!passedConfig.hasOwnProperty('rules')) {
+        return Object.assign({}, extendsConfig);
+      }
+
       return Object.assign({}, extendsConfig, passedConfig.rules);
     } else {
       throw new Error('No configuration passed');
@@ -84,7 +88,15 @@ class Config {
    * @return {Object}             Configuration object
    */
   _getExtendsConfig(moduleName) {
-    const configObj = this._getExtendsConfigModule(moduleName);
+    let adjustedModuleName;
+
+    if (moduleName.startsWith('./')) {
+      adjustedModuleName = path.join(process.cwd(), moduleName);
+    } else {
+      adjustedModuleName = moduleName;
+    }
+
+    const configObj = this._getExtendsConfigModule(adjustedModuleName);
 
     this._validateConfig(configObj);
 
@@ -98,7 +110,7 @@ class Config {
    */
   _getExtendsConfigModule(moduleName) {
     /* istanbul ignore next */
-    return require(path.join(process.cwd(), moduleName));
+    return require(moduleName);
   }
 
   /**
@@ -109,8 +121,6 @@ class Config {
   _validateConfig(rcFileObj) {
     if (rcFileObj.hasOwnProperty('rules')) {
       this._validateRulesConfig(rcFileObj.rules);
-    } else {
-      throw new Error('`rules` object missing in config');
     }
 
     return true;


Test patch:
diff --git a/tests/unit/ConfigTest.js b/tests/unit/ConfigTest.js
index 41d35cf..a4f1c0d 100755
--- a/tests/unit/ConfigTest.js
+++ b/tests/unit/ConfigTest.js
@@ -130,6 +130,58 @@ describe('Config Unit Tests', function() {
 
         config._getExtendsConfigModule.restore();
       });
+
+      it('and the module name is relative path', function() {
+        const moduleName = './index.js';
+        const passedConfig = {
+          extends: './index.js',
+          rules: {
+            'version-type': 'warning'
+          }
+        };
+        const config = new Config(passedConfig);
+        const extendsObj = {
+          rules: {
+            'version-type': 'warning'
+          }
+        };
+        const stubbedGetExtendCfgModule = sinon.stub(config, '_getExtendsConfigModule').returns(extendsObj);
+        const result = config.get(moduleName);
+        const expectedObj = {
+          'version-type': 'warning'
+        };
+
+        spy.calledOnce.should.be.true();
+        spy.firstCall.calledWithExactly(process.cwd(), moduleName);
+        stubbedGetExtendCfgModule.calledWithExactly(path.join(process.cwd(), moduleName));
+        result.should.eql(expectedObj);
+
+        config._getExtendsConfigModule.restore();
+      });
+
+      it('and the module name is a node module', function() {
+        const moduleName = 'npm-package-json-lint-config-tc';
+        const passedConfig = {
+          extends: 'npm-package-json-lint-config-tc'
+        };
+        const config = new Config(passedConfig);
+        const extendsObj = {
+          rules: {
+            'version-type': 'warning'
+          }
+        };
+        const stubbedGetExtendCfgModule = sinon.stub(config, '_getExtendsConfigModule').returns(extendsObj);
+        const result = config.get();
+        const expectedObj = {
+          'version-type': 'warning'
+        };
+
+        spy.called.should.be.false();
+        stubbedGetExtendCfgModule.calledWithExactly(moduleName);
+        result.should.eql(expectedObj);
+
+        config._getExtendsConfigModule.restore();
+      });
     });
   });
 
@@ -157,24 +209,6 @@ describe('Config Unit Tests', function() {
     });
   });
 
-  context('_validateConfig tests', function() {
-    context('when a invalid config object is passed', function() {
-      it('an error should be thrown', function() {
-        const rcFileObj = {
-          'require-author': 'error',
-          'require-version': 'warning',
-          'valid-values-author': ['error', ['Thomas', 'Lindner', 'Thomas Lindner']],
-          'valid-values-private': ['warning', [true, false]]
-        };
-        const config = new Config(rcFileObj);
-
-        (function() {
-          config._validateConfig(rcFileObj);
-        }).should.throw('`rules` object missing in config');
-      });
-    });
-  });
-
   context('_validateRulesConfig tests', function() {
     context('when a valid npmpackagejsonlintrc file object is passed', function() {
       it('true should be returned', function() {
diff --git a/tests/unit/NpmPackageJsonLintTest.js b/tests/unit/NpmPackageJsonLintTest.js
index c49874f..d36e7e5 100755
--- a/tests/unit/NpmPackageJsonLintTest.js
+++ b/tests/unit/NpmPackageJsonLintTest.js
@@ -125,6 +125,30 @@ describe('NpmPackageJsonLint Unit Tests', function() {
         response.hasOwnProperty('warnings').should.be.false();
       });
     });
+
+    context('validate that errors and warnings are set', function() {
+      it('one error and one warning expected', function() {
+        const packageJsonData = {
+          author: 'Caitlin Snow'
+        };
+        const config = {
+          'valid-values-author': ['off', [
+            'Barry Allen',
+            'Iris West'
+          ]]
+        };
+        const options = {
+          ignoreWarnings: true
+        };
+        const npmPackageJsonLint = new NpmPackageJsonLint(packageJsonData, config, options);
+        const configStub = sinon.stub(npmPackageJsonLint, '_getConfig').returns(config);
+        const response = npmPackageJsonLint.lint();
+        const expectedErrorCount = 0;
+
+        response.errors.length.should.equal(expectedErrorCount);
+        response.hasOwnProperty('warnings').should.be.false();
+      });
+    });
   });
 
   describe('_getConfig method', function() {