diff --git a/lib/index.js b/lib/index.js index dcbc161..e6fb181 100644 --- a/lib/index.js +++ b/lib/index.js @@ -4,8 +4,8 @@ const Filter = require('broccoli-persistent-filter'); const CLIEngine = require('eslint').CLIEngine; const md5Hex = require('md5-hex'); const stringify = require('json-stable-stringify'); -const sep = require('path').sep; -const BUILD_DIR_REGEX = new RegExp('(' + sep + ')?build(' + sep + ')?$'); +const path = require('path'); +const BUILD_DIR_REGEX = new RegExp('(' + path.sep + ')?build(' + path.sep + ')?$'); /** @@ -108,19 +108,24 @@ EslintValidationFilter.prototype.baseDir = function baseDir() { }; EslintValidationFilter.prototype.cacheKeyProcessString = function cacheKeyProcessString(content, relativePath) { - return md5Hex([content, relativePath, stringify(this.options, { - replacer(key, value) { - if (typeof value === 'function') { - return value.toString(); - } - return value; + function functionStringifier(key, value) { + if (typeof value === 'function') { + return value.toString(); } - })]); + return value; + } + + return md5Hex([ + content, + relativePath, + stringify(this.options, {replacer: functionStringifier}), + stringify(this.cli.getConfigForFile(path.join(this.eslintrc, relativePath))) + ]); }; EslintValidationFilter.prototype.processString = function processString(content, relativePath) { // verify file content - const output = this.cli.executeOnText(content, this.eslintrc + '/' + relativePath); + const output = this.cli.executeOnText(content, path.join(this.eslintrc, relativePath)); const filteredOutput = filterAllIgnoredFileMessages(output); const toCache = { lint: filteredOutput, diff --git a/test/test.js b/test/test.js index b1a57b9..744fca8 100644 --- a/test/test.js +++ b/test/test.js @@ -1,4 +1,5 @@ const fs = require('fs'); +const path = require('path'); const expect = require('chai').expect; const eslint = require('../index'); const runEslint = require('./helpers/run-eslint'); @@ -10,6 +11,19 @@ const DOUBLEQUOTE = 'Strings must use doublequote.'; const FILEPATH = 'fixture/1.js'; describe('EslintValidationFilter', function describeEslintValidationFilter() { + before(function beforeEslintValidationFilter() { + this.setupSpies = function setupSpies() { + // spy on filter process methods + const processStringSpy = this.sinon.spy(eslint.prototype, 'processString'); + const postProcessSpy = this.sinon.spy(eslint.prototype, 'postProcess'); + + return { + processStringSpy, + postProcessSpy + }; + }; + }); + function shouldReportErrors() { // lint test fixtures const promise = runEslint(FIXTURES); @@ -67,9 +81,10 @@ describe('EslintValidationFilter', function describeEslintValidationFilter() { }); it('should cache results, but still log errors', function shouldHaveCachedResults() { - // spy on filter process methods - const processStringSpy = this.sinon.spy(eslint.prototype, 'processString'); - const postProcessSpy = this.sinon.spy(eslint.prototype, 'postProcess'); + const { + processStringSpy, + postProcessSpy + } = this.setupSpies(); // run first test again, should use cache but still log errors return shouldReportErrors() @@ -81,9 +96,10 @@ describe('EslintValidationFilter', function describeEslintValidationFilter() { }); it('should allow disabling the cache', function shouldAllowDisablingCache() { - // spy on filter process methods - const processStringSpy = this.sinon.spy(eslint.prototype, 'processString'); - const postProcessSpy = this.sinon.spy(eslint.prototype, 'postProcess'); + const { + processStringSpy, + postProcessSpy + } = this.setupSpies(); function runNonpersistent() { return runEslint(FIXTURES, { @@ -100,4 +116,50 @@ describe('EslintValidationFilter', function describeEslintValidationFilter() { expect(postProcessSpy, 'Logged errors (twice)').to.have.callCount(6); }); }); + + it('should use the configuration to cache results', function shouldCacheByConfig() { + const { + processStringSpy, + postProcessSpy + } = this.setupSpies(); + let processStringInitialCount; + let postProcessInitialCount; + const eslintrcPath = path.join(FIXTURES, '.eslintrc'); + let eslintrcContent; + + function runCustomRule() { + return runEslint(FIXTURES, { + options: { + rulePaths: ['conf/rules'] + } + }); + } + + return runCustomRule().then(function retrieveCallCount() { + processStringInitialCount = processStringSpy.callCount; + postProcessInitialCount = postProcessSpy.callCount; + }) + .then(function backupConfig() { + eslintrcContent = fs.readFileSync(eslintrcPath); + }) + .then(function writeNewConfig() { + fs.writeFileSync(eslintrcPath, JSON.stringify({ + extends: 'nightmare-mode/node', + rules: { + 'custom-no-alert': 2 + } + })); + }) + .then(runCustomRule) + .then(function assertCaching() { + // check that it did not use the cache + expect(processStringSpy, 'Didn\'t use cache').to.have.callCount(processStringInitialCount + 3); + expect(postProcessSpy, 'Logged errors').to.have.callCount(postProcessInitialCount + 3); + }) + .finally(function restoreConfig() { + if (typeof eslintrcContent !== 'undefined') { + fs.writeFileSync(eslintrcPath, eslintrcContent); + } + }); + }); });