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
messageId messages with placeholders fail during tests. #9890
Comments
Thanks for the bug report! This definitely needs another look, for sure. |
I didn’t think of that use case when making this API. See #9892 for how I intended the tests to be written. However, now that I see this, I think it would be a good idea to allow people to only specify some (or none) of the data keys in a test. |
Looking through the rule-tester code, it looks like the anticipated use case is to store the data for formatting the error in the test file itself. This doesn't really help isolate the string information, which would be ideal for maintainability. Previously, I've been using the following pattern to keep a single source of truth -- but also doesn't work out of the box for formatted errors. // rules/my-rule.js
module.exports = { \* actual rule code \*};
module.exports.errorStrings = { \* store error strings on the exported object *\ }
// test/rule.js
const rule = require('../rules/my-rule');
const errorStrings = rule.errorStrings;
const RuleTester = require('eslint').RuleTester;
const ruleTester = new RuleTester();
ruleTester.run('my-rule', rule, {
valid: [/* valid case... */]
invalid: [{
code: 'test case',
errors: [{
message: errorStrings.myError,
type: 'Literal'
}]
}]
}); Ideally, if we're using IDs for messages, we would just be able to refer and validate against them. It would hopefully be a win for both maintainability as well as localization etc. |
@j-f1 Makes total sense. Like ruleTester.run('my-rule', rule, {
errors: [{
rawMessageId: 'myErrorMessageId',
type: 'Literal'
}]
}) Hopefully we could come up with something better than |
Here's what I think we should consider (@j-f1 I assume most of this is already happening, but let me know if I'm missing something):
How does that sound? Have I missed anything? How far off are we right now? |
I think this is where we might run afoul of the current implementation; right now, when We could change this behavior or we could introduce a different property (like the |
Reworded a bit to reflect the data we have on hand at runtime and to make it easy to turn into tests. Tell me what you think of the following:
|
LGTM 👍 |
Does Assuming |
It does not currently have access to the data provided by rules.
To be clear, I’m almost never for expanding public interfaces, but I think the relatively smooth path to messageId/data, the fact that messageId paired with data is a complete source of truth, and the large potential upsides for both maintenance as well as localization makes it worth it. |
I'd be interested to see if we could explore separating out the message hydration logic, so that it would be possible to call the rule and get @not-an-aardvark Would my proposal above address your concerns about expanding the API surface? (Of course, the added complexity might not be worth it anyway, but I wanted to get your thoughts about expanding the surface only for RuleTester.) |
Relabeling as enhancement rather than bug, since it seems like this is going slightly beyond a bugfix. The TSC will probably need to review/approve whatever changes we decide to propose here. @betaorbust No worries about making a PR, but just note that we might go back and forth on a few proposals here until we get something that the team agrees is the best way forward. I apologize for any confusion that resulted from the initial labeling as a bug. |
Totally happy for this to be addressed at a larger and more orchestrated level.
The large number of rule tests (in the main eslint codebase and in 3rd-part plugins) that are partial regex matches against the message string tells me that I’m not the only one wanting to do this. |
While the data portion of this is being worked out, I’d like to propose fixing the unexpected behavior of checking messageId today. |
This change makes rule-tester check messageId directly by value provided instead of the current behavior, which is to check the messageId's message value against the message returned from the rule at runtime.
#9908 For proposed changes to |
That would address the concerns, although ideally it would be nice if the functionality of Personally, I think the following behavior would make the most sense, and wouldn't require
All of these three assertions would be independent, and more than one could be checked for a given test case. Additionally, all of the following cases would be invalid:
I think this is similar to the existing behavior, except that (a) we would match against the |
This seems like it complicates the expected use of the RuleTester API as the rest of the attributes are independent and direct-comparison (and getting stricter via #9417 in 5.0) but it does free up the solo I'm very familiar with this code at this point, so just give me the green light when you guys finalize the proposal and I can drop a PR. |
That's a fair point. I think eslint/lib/rules/prefer-const.js Lines 300 to 305 in 084351b
With code like that, it probably wouldn't make sense to match against every property of |
Yeah, looks like there are a lot of places that do that. It kind of seems like an antipattern to not be explicit about what’s being used, but the rework effort would be substantial. |
@platinumazure Do you have any thoughts on the proposal in #9890 (comment)?
|
@not-an-aardvark I'm okay with that proposal. This means it is impossible for now to use |
So, everybody good if I put a PR in that satisfies #9890 (comment)? |
@betaorbust Yes, I think that's a good approach. Does #9908 satisfy the requirements described in the comment? If not, please close (or, if you just need to make a few modifications in the branch, please edit the PR title to say "WIP" so we don't merge it accidentally). Thanks! |
This change makes rule-tester check messageId directly by value provided instead of the current behavior, which is to check the messageId's message value against the message returned from the rule at runtime.
This change makes rule-tester check messageId directly by value provided instead of the current behavior, which is to check the messageId's message value against the message returned from the rule at runtime.
This change makes rule-tester check messageId directly by value provided instead of the current behavior, which is to check the messageId's message value against the message returned from the rule at runtime.
@platinumazure This issue is marked as |
@not-an-aardvark I think this could be considered a bugfix since we're not really trying to add new functionality, but rather stabilize this API for tests in a way that meshes with the original vision. I'm okay with relabeling as bug. |
Awesome. As a bug fix, is it ready to go in or do you need anything else from me? |
@betaorbust I think it just needs review at this point. Just to be absolutely sure, is #9908 the PR that goes with this issue, that we should review? Thanks! |
Yup. I closed the breaking change/enhancement PR and updated #9908 as described in #9890 (comment), so it should be good to go. |
@betaorbust After merging #9908, is there anything else that we still want to try to address with this issue? Or can we close the issue? Thanks! |
@platinumazure Yup. My preference would have been to make it an even more restrictive API, but #9890 (comment) makes sense, so I think we can close this out 👍 |
Tell us about your environment
What parser (default, Babel-ESLint, etc.) are you using?
default
Please show your full configuration:
N/A
What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.
Write a test where the message is a placeholder and the message is referred to via the new
meta.messageId
. Run the test runner against it with a messageId to match against.lib/rules/no-foo.js
test/rules/no-foo.js
npm run test
What did you expect to happen?
Tests pass.
What actually happened? Please include the actual, raw output from ESLint.
So it looks like ruleTester is comparing the value of
messageId
's pre-formatted template to the post-formatted runtime error.It seems like the ideal behavior is:
message
in the ruleTester.mesageId
in the ruleTester.My guess is that most use cases fall under the second category, but that the first category is worth supporting as well to give access to the direct output during testing if needed.
The text was updated successfully, but these errors were encountered: