-
-
Notifications
You must be signed in to change notification settings - Fork 698
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
Allow writing JSLint/JSHint friendly tests #41
Allow writing JSLint/JSHint friendly tests #41
Comments
JSHint is a set of guidelines, not laws, so it has never really been a concern. IMHO, everyone has their own coding style, which may or may not comply with the default JSLint specs. For example, I prefer to have comma separated lists have the comma start on a new line. JSLint hates this: var chai = require('chai')
, expect = chai.expect; But, it is my personal preference and I am consistent with it. My point is, I don't see it as a problem. The goal of chai, specifically the That is not to say that JSHint/Lint doesn't have it's place, or that it isn't a useful tool. It is that in chai's case, our need for ease of use outweighs being a guideline-abiding citizen. |
Many thanks for your comments. I agree that linters are not laws. I will look at fixing this in another place :) |
In case anyone else looks at this, the problem can be resolved for jshint by configuring it with the "expr" option. Another issue that comes up is the use of "null" and "instanceof" as property names, which can be resolved by suppressing that particular warning. You can get both by including the following in your code:
|
Suppressing the jslint/jshint warning does not solve the problem. An expression statement without an assignment has normally no effect because an expression statement is intended to return a value and not actually doing stuff. I really hope this will be changed in chai 2.0. |
There's nothing wrong with expression statements with side effects. They may not have been common in ES3, the 1999 version of the language, but in ES5, the 2009 version, they're quite normal, due to the existence of getters. |
The problem is you wouldn’t expect that such an expression statement would do anything if you just read the code, you have to know that there is a getter defined. |
What I'm trying to say is that you would expect such things if you've been programming JavaScript after 2009. |
No, I wouldn’t expect side effects on a simple getter. |
For anyone looking to suppress these warnings globally, I was able to do so by including these options in my {
"es5": true,
"expr": true
} |
The expr option is not available in jslint. Furthermore it is probably not a good idea to suppress the warning globally. The warning exists for a reason. |
I agree completely with @lo1tuma. This warning is broadly useful and shouldn't be disabled, at least not to support an unusual idiom which is only used in tests. A useful resolution would be to allow these to be functions, e.g.: expect(value).to.exist(); such would remove the jshint warnings while preserving the expect style. |
I am actually horrified to see people acting like it's no problem, because it is, for the reasons elaborated in the article @lo1tuma linked to in the last post. This is not a style thing. Please reconsider your decision of not fixing this. |
@domenic Your getters could have side-effects, but for the sake of a few exceptions that only appear in your Chai tests, I don’t think it’s sensible to disable the Will look into Must.js now, but it’s a shame the simple solution suggested by @gyllstromk cannot be re-considered given the argument we are making here. |
What was your other place? |
+1 For also allowing getters to be called as functions. |
@OliverJAsh This was reported 2 years ago... since then I just slowly re-invented the wheel and wrote my own (sane) assertions. I am not a big fan of assert(object).is().fubar() and I prefer assertIsFUBAR(object) |
specs need a separate jshintrc, since chai needs '"expr": true' option because of chaijs/chai#41
I agree that this is a ridiculous situation and it is disappointing to see the complaints brushed off. |
👍 I am willing to contribute a patch to support both Before starting my work, I'd like to check with the project maintainers that such patch would be accepted. @logicalparadox @vesln what's your opinion? My plan is to use the mechanism in |
+1 Silently failing assertions are a potential source of errors. Therefor chai should at least have the option to avoid them by allowing getters to be called as functions. |
Can you provide a list of which assertions you would be changing in this patch? |
My original intention was to modify As I looked at the places where that method is called, I realised that would change assertions that should not support function call - e.g. Here is the list of assertions I'd like to change:
|
Crazy that I just found this issue as I searched for a way to squelch these jsHint errors in my IDE, they distract from actual issues in my test code and I don't believe disabling the errors is a proper workaround. Just because we now have getters in JS does not mean that getters with side-effects is recommended or even idiomatic JS. Getters with side-effects, especially throwing or asserting is a major anti-pattern in most other languages that have supported getters since their inception. I'm definitely on the side of @bajtos and others that have voiced their concerns with this issue. I'm happy to pitch in and help as well. Just my $0.010b |
A quick workaround for this: If each of those properties just return an no-op function, while still operating as a getter, it'll appease both camps. They can still be used as getters (as the assertion is done in a getter) but can be called like functions (as they return an no-op function, the getter does the logic but the function can be called). It would also allow a mixed style like:
|
@keithamus that's exactly what I was proposing. However, the implementation is not trivial, thus I don't want to invest my time until the project maintainers confirm that they are willing to accept such patch. |
I guess the main complexity would be that the function returned would have to have all of the same properties as the assertion chain. It could be cheated by setting |
Well, I changed the test not to trigger this bug and the PR for the noop function chain is passing all the tests now. |
Definitely looking forward to having this. It'll protect us from fat-fingered |
@mockdeep couldn't agree more. It's unfortunate that authors of popular plugins may be another hurdle: chaijs/sinon-chai#48 |
@joshperry Bummer. Well hopefully he'll come around. It's a small change and allows people who like either syntax to do as they please. I'm personally in favor of a syntax that fails loudly instead of silently. |
Hey guys, I don't have any back-compat issues, so I figured I would roll this whole change into a new plugin. It supports everything this patch did, with a couple caveats: requires terminating the chain with the function form, and the With these caveats, it also supports custom error messages for these asserts. I also added an
Enjoy |
Just pushed a new version of dirty-chai that hooks any chai plugins that are 'used' after dirty-chai and also makes their property assertions into chainable method assertions.
|
Can't fix "Expected an assignment or function call and instead saw an expression." because chai uses properties to call an assertion. Problem was discussed in: chaijs/chai#41
Can't fix "Expected an assignment or function call and instead saw an expression." because chai uses properties to call an assertion. Problem was discussed in: chaijs/chai#41
For me, this little plugin allowed me to write the assertions in a lint-friendly way: https://github.com/LFDM/chai-lint |
Another approach might be to have a Linters (JSHint/JSLint/ESLint/..):
The thing is that I strongly agree it is highly recommended to use Still JavaScript is a language that can be used in different contexts, and in some of them code readability are much more important than performance, and in which some application code rules can be less relevant. As an example, it can be legitimate to use synchronous APIs in simple generators or tasks. On the same idea, the role of Note that unit and behavior test code should be as simple as possible, and should, to me, really benefit from some very different coding rules than application, generator, or task code ex:
I would find it perfectly legitimate to have some "unit test", "behavior test", or even "chai" option Some Linters already provide some environment/context specific options such as:
see JSLint By the way JSHint already provides some additionnal TDD/BDD related options such as:
See JSHint Environment options And ESLint also add supports for
See ESLint Environment options So the best thing to me is to send a pull request to at least JSHint to propose a "chai" option (potentially relaxing the "expr" rules for accessor properties) |
Solves chaijs/chai#41
For those of using WebStorm or other IntelliJ based editors, what I do is to click on the warning's "inspection profile settings" (for JavaScript validity issues -> Expression statement which is not assignment or call") and uncheck it as a warning for the scope "Tests", but keep it as "Warning" for "Everywhere else". |
After using chai with dirty-chai plugin for some time, I eventually decided to switch to should.js and have never looked back ever since. 👋 |
For vscoders you can supress the warnings hacking the settings.json by adding an entry for jshint.options:
|
Is there a good reason for chai using this pattern? (side-effects on property getters) |
When using expect() for writing asserting, some of the assertion are using properties as the mean for calling assert.
For example
expect(foo).to.exist
JSLint/JSHint will complain about such code, since it expects an assignment or function call.
Hiding a function call, behind getting a property can be sweet but in tests, it leads to such warnings.
I know that one can use assert calls, or not use JSHint/JSLint or configure JSHint/JSLint to ignore such warnings, but I just want to know what is your feeling about this problem.
The text was updated successfully, but these errors were encountered: