Skip to content

Conversation

@ST-DDT
Copy link
Contributor

@ST-DDT ST-DDT commented Jul 10, 2025

Summary

Add options that control which assertions are required for each RuleTester test case.

Related Issues

The idea was initially sparked by this comment: vuejs/eslint-plugin-vue#2773 (comment)

It might be helpful to include more detailed error information, such as line, column, endLine, and endColumn...
[...]
Let’s make the new cases more detailed first. 😊

The first steps have been taken in: eslint/eslint#19904

This lead to the issue that this RFC is based on: eslint/eslint#19921

@michaelfaith
Copy link

michaelfaith commented Jul 10, 2025

I think it's a great idea to drive this kind of consistency, but I do wonder if this is the best place to set that kind of expectation. It seems like something that might be more appropriate as an eslint rule in eslint-plugin-eslint-plugin, which has rules governing conventions of authoring eslint plugins: https://github.com/eslint-community/eslint-plugin-eslint-plugin Something like require-test-assertions that's configurable with the specific assertions the project wants to enforce.

@nzakas nzakas added the Initial Commenting This RFC is in the initial feedback stage label Jul 11, 2025
Copy link
Member

@nzakas nzakas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for putting this together. I left some comments inline.

@ST-DDT
Copy link
Contributor Author

ST-DDT commented Jul 17, 2025

I think I covered all comments.

@ST-DDT
Copy link
Contributor Author

ST-DDT commented Jul 21, 2025

All addressed

@ST-DDT
Copy link
Contributor Author

ST-DDT commented Aug 7, 2025

All addressed

@ST-DDT
Copy link
Contributor Author

ST-DDT commented Sep 14, 2025

All pending comments addressed.

@ST-DDT
Copy link
Contributor Author

ST-DDT commented Sep 19, 2025

All pending comments addressed.

mdjermanovic
mdjermanovic previously approved these changes Sep 20, 2025
Copy link
Member

@mdjermanovic mdjermanovic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

fasttime
fasttime previously approved these changes Sep 22, 2025
Copy link
Member

@fasttime fasttime left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a suggestion, but otherwise LGTM.

@ST-DDT ST-DDT dismissed stale reviews from fasttime and mdjermanovic via 50b7323 September 22, 2025 07:24
*
* @default false
*/
requireMessage?: boolean | 'message' | 'messageId';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there should be an extra assertion to disallow using a number for errors (maybe named disallowErrorShorthand).
As a result the boolean variant would be useless as the rule tester checks this by default for error objects.
Further this allows an easier migration, as the plugin maintainers can gradually enable the rules by either:

  • First disallowing the error shorthand and then requiring the properties
  • First adding the required location or message properties and then handling the error shorthands

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for clarification, so instead of

errors: 5

You have to use

A) errors: ['foo',...]
or B) errors: [{...}]

Copy link
Contributor

@DMartens DMartens Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is dependent on the other assertions.

  • none: allows both
  • requireMessage: "message" would allow both as the message provided
  • requireMessage: "messageId" would only allow B) as the message is provided
  • requireLocation: true would only allow B) as a location is required

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this is entirely/mostly covered by adding requireMessage.
What do the others think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DMartens Are you suggesting that requireMessage and requireLocation alone should not disallow numeric values for errors, and instead there should be a separate option to do so?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if disallowShorthand is false/undefined, you can just use the error count even if requireMessage is enabled?

I dont like that. Because then it behaves like requireMessage/location isnt set in the first place.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can handle the option as true by default (when not specified) for the other options but I think the possibility to differentiate should be there.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The requirement for errors to include either a message or messageId was discussed in #84. While this makes sense in many scenarios, it can be bypassed by specifying errors as a number (accepting all the implied limitations of doing so). That discussion also affirmed that using a numeric value for errors remains a valid option.

Given that ESLint has supported this behavior by default, I tend to agree with @DMartens that it makes sense to maintain the possibility of specifying a number for errors, even if requireMessage will enforce one of message or messageId when errors is an array. I'm open to revisiting the scope of this RFC if the team can reach an agreement.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I agree that we should make a change here. To me, if someone wants to use errors: number, then they wouldn't opt-in to these assertions in the first place.

I think requireMessage: true explicitly affirms that someone does not want to allow errors: number.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is solved with the mentioned additional assertion disallowErrorShorthand, which defaults to true.
This keeps the current proposed behavior but allows users to opt-out.
This behaviour could also be implemented with requireMessage: false but I think disallowErrorShorthand should be preferred as requireLoc (and maybe requireData) is also affected.

* @default false
*/
requireLocation?: boolean;
},
Copy link
Contributor

@DMartens DMartens Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another helpful check would be requireData which requires the data error property when a messageId is used and the referenced message has placeholders ({{ placeholder }}).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this imply requireMessage: 'messageId'?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also considered requiring the data block (if needed) into requireMessage: 'messageId'.
What do you+the others think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would not imply requireMessage: 'messageId' as the message already has the placeholders filled in. So there is no need for data.

Copy link
Contributor Author

@ST-DDT ST-DDT Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure whether I understand the last comment.

IMO requireData results in ({data: *})[]

AFAICT The current code only checks for data in the messageId block. Which makes sense to me, as data is used to fill in the placeholders in its message.

Most messageId checks are very broad as most rules only have one or two messages. So also checking for data is kind of relevant. Which is why I would implicitly attach it to the requireMessageId option.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This option (requireData) should only be active when the error has a messageId as data is useless when message is specified (you already provide the message with every placeholder filled in).
The validator only has to check whether data is specified as there is already an error when data is specified and placeholders are missing.
Coupling this with the requireMessage: "messageId" would be unintuitive as that reads as only the "messageId" is required.

Copy link
Member

@fasttime fasttime Sep 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree a requireData assertion could be helpful. As this would be a separate option, it could be also discussed in a follow-up RFC.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, the scope of this RFC is already well-defined and I don't think we should be expanding at this point in time. @DMartens feel free to open an issue to start the discussion around a requireData assertion option.

Copy link
Member

@nzakas nzakas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy with the current state of this RFC.

@mdjermanovic
Copy link
Member

@fasttime can you check if your review comments have been addressed?

Copy link
Member

@fasttime fasttime left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have any concerns with the proposed solution. @DMartens, I understand you see room for improvement and would prefer some changes. Do you think the RFC is acceptable in its current form nonetheless?

@DMartens
Copy link
Contributor

Yes, I see both of the suggestions to be non-blocking:

  • disallowErrorShorthand: This suggestion was preventative of what I thought users may want and users can then raise the issue
  • requireData: I will raise an issue for this after this has landed

@mdjermanovic
Copy link
Member

Moving to final commenting.

@mdjermanovic mdjermanovic added Final Commenting This RFC is in the final week of commenting and removed Initial Commenting This RFC is in the initial feedback stage labels Oct 12, 2025
@fasttime
Copy link
Member

No further comments here, so merging.

@fasttime fasttime merged commit 40a0775 into eslint:main Oct 24, 2025
5 checks passed
@ST-DDT ST-DDT deleted the 2025-rule-tester-assertion-options branch October 24, 2025 07:23
@ST-DDT
Copy link
Contributor Author

ST-DDT commented Oct 24, 2025

Should I create a PR for the implementation now?

@fasttime
Copy link
Member

Should I create a PR for the implementation now?

@ST-DDT yes, please! Issue eslint/eslint#19921 is already assigned to you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Final Commenting This RFC is in the final week of commenting

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants