How to isolate specific ESLint errors? [duplicate] - javascript

I know you can define rules in an .eslintrc file, but what if I just want to run eslint and check for one specific rule?
E.g. $ eslint helpme.js --rule some-important-rule

I don't know if this is the best way, but I was able to get this working:
$ eslint helpme.js --no-eslintrc --env "es6" --env "node" --parser-options "{ecmaVersion: 2018}" --rule "{some-important-rule: error}"
Note: With this method (ignoring .eslintrc completeley) you still have to add some stuff from .eslintrc like your environment and parser options.

If you want to use your .eslintrc file to keep your configuration (parser, plugin settings, etc), you can use eslint-nibble with the --rule=some-important-rule flag. This will respect your normal configuration, but only show you errors from that rule. There are some other flags as well like --no-interactive if you want to run this in something like a CI environment.
Disclaimer: I'm the creator of eslint-nibble.

Expanding on #matrik answer, this doesn't require me to define all eslint config again and also shows the file name.
eslint helpme.js | egrep "react/jsx-no-literals" -B 1

Try ESLint custom formatter.
It can be used to filter part of rules, files you want to pay attention to.
And you don't need to :
Edit your ESLint config file.
Use complicate command.
DEMO for filter files contain error which rules id is prop-types:
// ./eslint-file-path-formatter.js
const fs = require('fs');
function containRules(result, targetRuleId) {
if (!result || !targetRuleId) {
return false;
}
return result.messages.some((cur) => {
// console.log(`cur?.ruleId = ${cur?.ruleId}`);
if (cur?.ruleId?.includes(targetRuleId)) {
return true;
}
});
}
module.exports = function (results, context) {
const summary = [];
results.forEach((cur) => {
if (containRules(cur, 'prop-types')) {
summary.push(`'${cur.filePath}',`);
}
});
// fs.writeFileSync('eslint-error-files.txt', summary.join('\n'));
// return 'Done Write';
return summary.join('\n');
};
Usage:
eslint . -f ./eslint-file-path-formatter.js
Then this formatter will print all files name to console.
You can also write result to local files, do whatever you want.

Simple way to see single rule output while still using .eslintrc is to use grep:
$ eslint helpme.js | egrep "(^/|some\-important\-rule$)"

Related

how to fix error for "Expected an assignment or function call and instead saw an expression" [duplicate]

In my Chai tests I often find myself wanting to use their assertions that are something like .to.be.empty, .to.be.true e.t.c., because I find them to be cleaner to read than .to.be.length(1) or .to.be.equal(true). However, this breaks my linter (I'm using default Airbnb linting).
I could use the // disable-eslint-line syntax, but then I'd have to add it to every single line that reads like that and that seems tedious.
I've also read about the DirtyChai library, but that would require me to go back through my entire testing library adding brackets to them all which seems like something I shouldn't have to do simply to get my linter to pass something it should probably be OK with in the first place.
Does anyone know a nicer way to handle this than the ways I've outlined above?
You can disable the rule for the entire file using eslint-disable at the top of the file in question:
/* eslint-disable no-unused-expressions */
expect(someTrueValue).to.be.true;
However, adding this at the top of every test file can be tedious. To disable this rule for all relevant files, you can:
Put a new .eslintc configuration file in the same directory as your test files, configured to disable that rule. This allows you to use the default configuration for all other rules while ignoring that rule specifically only on files in that folder. ESLint calls this Configuration Cascading.
{
"rules": {
"no-unused-expressions": "off"
}
}
Use the overrides key in your main .eslintrc file to disable rules for groups of files with glob pattern matching:
{
"overrides": [
{
"files": ["*.test.js", "*.spec.js"],
"rules": {
"no-unused-expressions": "off"
}
}
]
}
This also allows you to disable other rules which become troublesome in testing, such as no-underscore-dangle when using rewire.
Just found another option using Relative Glob Patterns:
In your .eslintrc file:
"overrides": [
{
"files": "*.test.js",
"rules": {
"no-unused-expressions": "off"
}
}
]
I've made a small plugin called eslint-plugin-chai-friendly that overrides the default no-unused-expressions rule and makes it friendly towards chai. The modified rule ignores the expect and should statements while keeping default behavior for everything else.
Combining jonalvarezz's answer with Ihor Diachenko's answer gave me exactly what I wanted:
npm install --save-dev eslint-plugin-chai-friendly
// .eslintrc.js
module.exports = {
// ...
plugins: ['chai-friendly'],
overrides: [{
files: '*.test.js',
rules: {
'no-unused-expressions': 'off',
'chai-friendly/no-unused-expressions': 'error',
},
}],
// ...
}
This way, the no-unused-expression rule will only be overridden in *.test.js files
AND
a no-unused-expression rule will still be in place to catch any unused expressions in the test files that are unrelated to chai.
In case anyone is stumbling upon this today, I had the same issue and found this solution on eslint documentation. In your eslint configuration file, you can specify one or several environments, which will predefine global variables for this environment. For us, it'd be mocha, and you'd configure like this in your .eslintrc.json:
{
"env": {
"mocha": true
},
...
...
...
}
As a result, it will remove all false positive about mocha describe, it, beforeEach, etc. without needing to completely disable eslint or completely disable any specific rule.
Tested with ESLint v.4.11 and mocha 5.0
I had this issue with tslint and solved it by simply moving the rule for unused expressions down one level. My ./tslint.json has all the other rules I care about, then I made ./src/tslint.json that just looks like
{
"rules": {
"no-unused-expression": true
},
"extends": "../tslint.json"
}
tslint automatically checks for a config file in every level as it descends the tree (with --project or using the VSCode extension) so this means that my tests (under ./test/) have all the other rules applied, but no-unused-expression only applies to files under ./src/.

How to use the same rules for js and ts in TSLint

I want to use the same style in .js files and .ts files. I know there is jsRules property in tslint.json, but I see 2 problems with it:
Copying ant pasting exactly the same rules
When extending some configurations, e.g. tslint-react, you don't get the rules in jsRules, meaning that you have to go to the source code of the ruleset and copy it manually.
Any other way to have the same code style without having to maintain both eslint and tslint?
Not everyone knows that, but TSLint configuration doesn't have to come in a .json file. You can use the .js extension, and keep whatever logic you like inside.
In this case, we can split TSLint rules into two categories — universal rules and React-specific ones. Both rulesets will be used for TypeScript files, but only the first ones will be applied to JavaScript.
tslint.js
const UNIVERSAL_RULES = {
"max-line-length": [true, 120]
}
const REACT_RULES = {
"jsx-space-before-trailing-slash": true
}
module.exports = {
extends: [
"tslint:recommended"
],
jsRules: UNIVERSAL_RULES,
rules: {
...UNIVERSAL_RULES,
...REACT_RULES
}
}
When running TSLint CLI, it may be required to point to your configuration file explicitly. You can do that by adding --config tslint.js to your tslint command.

Gulp eslint doesn't find my .eslintrc file

It looks like my .eslintrc file is not found my gulp-eslint
I defined a lint task:
gulp.task('lint', function () {
gulp.src(['src/**/*.js', 'src/**/*.jsx'])
.pipe(eslint())
.pipe(eslint.format());
})
It runs but doesn't show any error.
My .eslintrc file is defined in src folder. I tried to move it to the root folder of my project but it didn't change anything.
It's a pretty simple file:
{
"parser": "babel-eslint",
"ecmaFeatures": {
"classes": true,
"jsx": true
},
"plugins": [
"react"
],
"extends": "eslint-config-airbnb"
}
When I run eslint src in the terminal, I get a bunch of eslint errors, which is fine.
Any idea what is not properly working?
According to the docs you need to fail on error in the pipe.
gulp.task('lint', function () {
// ESLint ignores files with "node_modules" paths.
// So, it's best to have gulp ignore the directory as well.
// Also, Be sure to return the stream from the task;
// Otherwise, the task may end before the stream has finished.
return gulp.src(['**/*.js','!node_modules/**'])
// eslint() attaches the lint output to the "eslint" property
// of the file object so it can be used by other modules.
.pipe(eslint())
// eslint.format() outputs the lint results to the console.
// Alternatively use eslint.formatEach() (see Docs).
.pipe(eslint.format())
// To have the process exit with an error code (1) on
// lint error, return the stream and pipe to failAfterError last.
.pipe(eslint.failAfterError());
});
Just a heads-up, the documentation is extremely useful and succinct on using configuration files, their precedence of usage and how they are located. You can also add the path to specify the location of your configuration file for a particular pipe:
gulp.task('lint', function () {
gulp.src(['src/**/*.js', 'src/**/*.jsx'])
.pipe(eslint({ configFile: '.eslintrc'}))
.pipe(eslint.format())
.pipe(eslint.failAfterError())
})
In the gulp-eslint documentation it should be noted that usage of the failOnError() and failAfterError() methods are advisable in that the task/stream is stopped and hence there is no invalid code written to the output.
If you use neither then the error is still caught but displayed only in the console output. So dependent on your task flow and design the destination file may still be written but you can conveniently correct the error immediately and carry on without having to start up your pipe processing/watch task again. An alternative is to look into gulp-plumber or some other means whereby you're not breaking out of a gulp watch task and yet also not writing a file containing code that doesn't pass linting validation.

browserify - exclude code blocks?

I'm building an app with shared React components in the browser and server-side Node.
Right now, I'm using Marty.js to do this:
function getUser() {
if (Marty.isBrowser) {
/* Get user using some client method */
} else {
/* otherwise, use some secret server code */
}
}
I'm bundling those functions up via Browserify, so they can run on the client as well as the server.
What I'd like to do is remove the else block from the bundle entirely, so I'm not leaking sensitive server-side code.
Is there a way to exclude blocks of code from the bundle?
I would create separate modules, one for the browser and one for the server. Then in your package.json, you tell browserify to use the browser module:
"browser": {
"./path/to/node-module.js": "./path/to/browser-module.js"
}
Now, whereever you call require('path/to/node-module'), browserify will load the other module instead.
More information from the docs:
browser field
There is a special "browser" field you can set in your package.json on a per-module basis to override file resolution for browser-specific versions of files.
For example, if you want to have a browser-specific module entry point for your "main" field you can just set the "browser" field to a string:
"browser": "./browser.js"
or you can have overrides on a per-file basis:
"browser": {
"fs": "level-fs",
"./lib/ops.js": "./browser/opts.js"
}
Note that the browser field only applies to files in the local module, and like transforms, it doesn't apply into node_modules directories.
While I'm not sure if it possible with Browserify, you can do it with Webpack using its DefinePlugin
From the docs (little modified):
Example:
new webpack.DefinePlugin({
DEBUG: false,
PRODUCTION: true,
...
})
...
Example:
if(DEBUG)
console.log('Debug info')
if(PRODUCTION)
console.log('Production log')
After passing through webpack with no minification results in:
if(false)
console.log('Debug info')
if(true)
console.log('Production log')
and then after a minification pass results in:
console.log('Production log')
You can use an environment variable, envify and uglify to do this.
if ('browser' === process.env.ENVIRONMENT) {
...
}
else {
...
}
Set process.env.ENVIRONMENT = 'browser' when doing your browser build, use the envify transform to substitute references to process.env with their current values and uglify will then perform dead code elimination to remove the branches which will never be hit.
Be more explicit about your intent, and put your code in their own files:
function getUser(options, callback) {
var fn;
if (Marty.isBrowser) {
fn = require("./lib/users/get.browser");
} else {
fn = require("./lib/users/get.server");
}
fn(options, callback);
}
and then as a browserify option you can say "replace require("./lib/users/get.server") with this variable instead, when you see it: ..." so that you don't build in that server file when you build for the browser.
However, if getUser can do different things based on where it's running, it feels far more likely that you're doing something wrong here: maybe that getUser should be a REST call to your server from the browser instead, but without more information, that's always hard to determine.
What about putting the code in a module for example UserServer and then exclude that module when you are compiling for the client? Your code becomes:
function getUser() {
if (Marty.isBrowser) {
/* Get user using some client method */
} else {
require('UserServer').getUser();
}
}
Browserify provides the following option to exclude files from the bundle:
--exclude, -u Omit a file from the output bundle. Files can be globs.

Karma: Running a single test file from command line

So, I've been looking all over for this, found "similar" answers here, but not exactly what I want.
Right now if I want to test a single file with karma, I need to do fit(), fdescribe() on the file in question...
However, what I do want is to be able to just call karma, with the config file, and direct it to a specific file, so I don't need to modify the file at all, ie:
karma run --conf karma.conf.js --file /path/to/specific/test_file.js
is it possible to do this? Or with any helper? (using grunt or gulp?)
First you need to start karma server with
karma start
Then, you can use grep to filter a specific test or describe block:
karma run -- --grep=testDescriptionFilter
Even though --files is no longer supported, you can use an env variable to provide a list of files:
// karma.conf.js
function getSpecs(specList) {
if (specList) {
return specList.split(',')
} else {
return ['**/*_spec.js'] // whatever your default glob is
}
}
module.exports = function(config) {
config.set({
//...
files: ['app.js'].concat(getSpecs(process.env.KARMA_SPECS))
});
});
Then in CLI:
$ env KARMA_SPECS="spec1.js,spec2.js" karma start karma.conf.js --single-run
This option is no longer supported in recent versions of karma:
see https://github.com/karma-runner/karma/issues/1731#issuecomment-174227054
The files array can be redefined using the CLI as such:
karma start --files=Array("test/Spec/services/myServiceSpec.js")
or escaped:
karma start --files=Array\(\"test/Spec/services/myServiceSpec.js\"\)
References
karma-runner source: cli.js
karma-runner source: config.js
I tried #Yuriy Kharchenko's solution but ran into a Expected string or object with "pattern" property error.
Therefore I made the following modifications to his answer and now I'm able to run single files using Karma:
function getSpecs(specList) {
if (specList) {
return specList.toString();
} else {
return ['**/*_spec.js'] // whatever your default glob is
}
}
module.exports = function(config) {
config.set({
//...
files: [
{ pattern: getSpecs(process.env.KARMA_SPECS), type: "module"}
]
});
});
Note: This solution only works with a single file mentioned in the KARMA_SPECS env variable. Ex: export KARMA_SPECS="src/plugins/muc-views/tests/spec1.js"

Categories

Resources