Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accept non-string input trees #25

Merged
merged 1 commit into from
Apr 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 34 additions & 7 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const Filter = require('broccoli-filter');
const CLIEngine = require('eslint').CLIEngine;
const path = require('path');

/**
* Calculates the severity of a eslint.linter.verify result
Expand Down Expand Up @@ -57,27 +58,52 @@ function filterAllIgnoredFileMessages(result) {
return resultOutput;
}

function resolveInputDirectory(inputNode) {
if (typeof inputNode === 'string') {
return inputNode;
}

// eslint-disable-next-line no-underscore-dangle
const nodeInfo = inputNode.__broccoliGetInfo__();

if (nodeInfo.nodeType === 'source') {
return nodeInfo.sourceDirectory;
}

if (nodeInfo.inputNodes.length > 1) {
// eslint-disable-next-line max-len
throw new Error('EslintValidationFilter can only handle one:* broccoli nodes, but part of the given input pipeline is a many:* node. (broccoli-merge-trees is an example of a many:* node) Please perform many:* operations after linting.');
}

return resolveInputDirectory(nodeInfo.inputNodes[0]);
}

/**
* Uses the content of each file in a given tree and runs eslint validation on it.
* @param {Object} inputTree Tree from broccoli.makeTree
* @param {Object} inputNode Tree from broccoli.makeTree
* @param {{config: String, rulesdir: String, format: String}} options Filter options
* @returns {EslintValidationFilter} Filter obconfig @constructor
*/
function EslintValidationFilter(inputTree, options) {
function EslintValidationFilter(inputNode, options) {
if (!(this instanceof EslintValidationFilter)) {
return new EslintValidationFilter(inputTree, options);
return new EslintValidationFilter(inputNode, options);
}
this.options = options || {};
this.eslintOptions = options.options || {};
// call base class constructor
Filter.call(this, inputTree);
Filter.call(this, inputNode);

// set formatter
this.formatter = require(this.options.format || 'eslint/lib/formatters/stylish'); // eslint-disable-line global-require
if (typeof this.options.format === 'function') {
this.formatter = this.options.format;
} else {
// eslint-disable-next-line global-require
this.formatter = require(this.options.format || 'eslint/lib/formatters/stylish');
}

this.cli = new CLIEngine(this.eslintOptions);

this.eslintrc = inputTree;
this.eslintrc = resolveInputDirectory(inputNode);

this.testGenerator = options.testGenerator;
if (this.testGenerator) {
Expand All @@ -95,7 +121,8 @@ EslintValidationFilter.prototype.processString = function processString(content,
'use strict'; // eslint-disable-line strict

// verify file content
const output = this.cli.executeOnText(content, this.eslintrc + '/' + relativePath);
const configPath = path.join(this.eslintrc, relativePath);
const output = this.cli.executeOnText(content, configPath);
const filteredOutput = filterAllIgnoredFileMessages(output);

// if verification has result
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
"broccoli": "^0.16.9",
"broccoli-cli": "^1.0.0",
"broccoli-merge-trees": "^1.1.1",
"broccoli-source": "^1.1.0",
"broccoli-stew": "^1.2.0",
"chai": "^3.5.0",
"eslint-config-nightmare-mode": "^2.3.0",
"mocha": "^2.2.4",
Expand Down
19 changes: 7 additions & 12 deletions test/helpers/run-eslint.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,15 @@ const eslint = require('../../index');
module.exports = function runEslint(path, _options) {
const options = _options || {};
const buildLog = [];
const consoleLog = console.log;

// stub console.log so we can get the formatter's output
console.log = function appendToBuildLog(...args) {
const text = args.join(' ');

buildLog.push(text);
};

// default options
options.format = options.format || 'eslint/lib/formatters/compact';
// eslint-disable-next-line global-require, newline-after-var
const formatter = require(options.format || 'eslint/lib/formatters/compact');
options.format = function spyFormatter(results) {
buildLog.push(formatter(results));
// prevent console spew
return '';
};
options.options = options.options || {};
options.options.ignore = options.options.ignore || false;

Expand All @@ -26,9 +24,6 @@ module.exports = function runEslint(path, _options) {

promise.finally(function builderCleanup() {
builder.cleanup();

// restore the original console.log
console.log = consoleLog;
});

return promise;
Expand Down
40 changes: 29 additions & 11 deletions test/test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
/* eslint-disable no-unused-expressions */
const fs = require('fs');
const expect = require('chai').expect;
const stew = require('broccoli-stew');
const mv = stew.mv;
const UnwatchedDir = require('broccoli-source').UnwatchedDir;
const MergeTrees = require('broccoli-merge-trees');
const runEslint = require('./helpers/run-eslint');
const FIXTURES = 'test/fixture';
const CAMELCASE = '(camelcase)';
Expand All @@ -9,18 +14,22 @@ const DOUBLEQUOTE = 'Strings must use doublequote.';
const FILEPATH = 'fixture/1.js';

describe('EslintValidationFilter', function describeEslintValidationFilter() {
it('should report errors', function shouldReportErrors() {
// lint test fixtures
const promise = runEslint(FIXTURES);
function shouldReportErrors(inputTree) {
return function _shouldReportErrors() {
// lint test fixtures
const promise = runEslint(inputTree);

return promise.then(function assertLinting({buildLog}) {
expect(buildLog, 'Used eslint validation').to.have.string(CAMELCASE);
expect(buildLog, 'Shows filepath').to.have.string(FILEPATH);
expect(buildLog, 'Used relative config - console not allowed').to.have.string(CONSOLE);
expect(buildLog, 'Used relative config - single quotes').to.not.have.string(DOUBLEQUOTE);
expect(buildLog, 'No custom rules defined').to.not.have.string(CUSTOM_RULES);
});
});
return promise.then(function assertLinting({buildLog}) {
expect(buildLog, 'Used eslint validation').to.have.string(CAMELCASE);
expect(buildLog, 'Shows filepath').to.have.string(FILEPATH);
expect(buildLog, 'Used relative config - console not allowed').to.have.string(CONSOLE);
expect(buildLog, 'Used relative config - single quotes').to.not.have.string(DOUBLEQUOTE);
expect(buildLog, 'No custom rules defined').to.not.have.string(CUSTOM_RULES);
});
};
}

it('should report errors', shouldReportErrors(FIXTURES));

it('should accept rule paths', function shouldAcceptRulePaths() {
// lint test fixtures using a custom rule
Expand Down Expand Up @@ -65,4 +74,13 @@ describe('EslintValidationFilter', function describeEslintValidationFilter() {
expect(content, 'Used the testGenerator').to.equal('test-content');
});
});

// specify test fixtures via a broccoli node
it('should accept a node as the input', shouldReportErrors(mv(new UnwatchedDir(FIXTURES), 'foobar/fixture')));

it('should not accept a many:* node as the input', function shouldNotAcceptManyStarNode() {
expect(() => {
runEslint(new MergeTrees([FIXTURES, 'lib']));
}, 'Should throw descriptive error').to.throw('many:*');
});
});