Skip to content
This repository has been archived by the owner on Mar 25, 2021. It is now read-only.

Add support for error templates in tests #2481

Merged
merged 8 commits into from
Apr 12, 2017
Merged

Add support for error templates in tests #2481

merged 8 commits into from
Apr 12, 2017

Conversation

ajafff
Copy link
Contributor

@ajafff ajafff commented Apr 2, 2017

PR checklist

  • Addresses an existing issue: #0000
  • New feature, bugfix, or enhancement
    • Includes tests
  • Documentation update

Overview of change:

It's pretty unwieldy to write and maintain test for rules that contain a name in the error message (e.g. prefer-const, no-unused-variable, no-shadowed-variable, ...). I added basic template support to error message substitutions which uses node's util.format() to replace placeholders.
Syntax is inspired by python: name % (substitution1[, substitution2, ...]). I doubt this will accidentally break anyone's tests.

The added test shows best what can be done with this.
As an example I also rewrote the tests of prefer-const to use templates.

Is there anything you'd like reviewers to focus on?

Do you have a better idea for the syntax?

I'll add documentation once there is consensus regarding the syntax.

CHANGELOG.md entry:

[develop] added support for error templates in rule tests

@ajafff ajafff changed the title Add support for message templates in tests Add support for error templates in tests Apr 2, 2017
@adidahiya adidahiya requested review from nchen63 and adidahiya April 3, 2017 03:44
@nchen63
Copy link
Contributor

nchen63 commented Apr 3, 2017

Is it common to manually generate the .lint file errors? My workflow is usually to write out the file without the errors, run the test, then copy the generated actual output. This feature seems unnecessarily complex.

@ajafff
Copy link
Contributor Author

ajafff commented Apr 3, 2017

Is it common to manually generate the .lint file errors?

At least I do. And given that @andy-hanson uses message substitutions a lot in his PRs, I think he also does.

Call it test driven development if you like. I want to test what I expect the implementation to do instead of using the output of the initial implementation for future testing.
Your workflow works for setting up the initial test. When the rule changes, e.g. finds more failures or changes its error message, you will also have to edit the test by hand.

@@ -114,6 +118,25 @@ export function parseErrorsFromMarkup(text: string): LintError[] {
return lintErrors;
}

function substituteMessage(substitutions: Map<string, string>, message: string): string {
Copy link
Contributor

Choose a reason for hiding this comment

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

can you rename substitutions to templateMap? It's confusing because the values that are put into the template are also substitutions. Maybe also rename message to something like templateCall

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Re substitutions: It's not really a templateMap, it's a map of substitutions that may happen to contain a template

Re message: It's not necessarily a templateCall. It may be an identifier of a substitution, a "template call" or just plain text

I'd prefer leaving the names that way.

}

function formatMessage(substitutions: Map<string, string>, message: string): string {
const formatMatch = /^([\w_]+) % \(\s*([^,]+(?:\s*,\s*[^,]+)*)\s*\)$/.exec(message);
Copy link
Contributor

Choose a reason for hiding this comment

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

add a comment somewhere about the expected format of message and the substitutions since the regex is hard to parse

if (formatMatch !== null) {
const base = substitutions.get(formatMatch[1]);
if (base !== undefined) {
message = format(base, ...(formatMatch[2].trim().split(/\s*,\s*/g)));
Copy link
Contributor

@nchen63 nchen63 Apr 3, 2017

Choose a reason for hiding this comment

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

what if the argument has a comma or space? Spaces could be trimmed away and commas could cause unwanted splits. Consider using quotes around each arg

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Format arguments now need quotes. The implementation uses typescript's scanner to parse them. Escaping also works.

@nchen63
Copy link
Contributor

nchen63 commented Apr 3, 2017

@ajafff
Copy link
Contributor Author

ajafff commented Apr 3, 2017

@nchen63 I updated the implementation and added docs

* Where `name` is the name of a message substitution that is used as format string.
* If `name` is not found in `substitutions`, `message` is returned unchanged.
*/
function formatMessage(substitutions: Map<string, string>, message: string): string {
Copy link
Contributor

Choose a reason for hiding this comment

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

The reason I suggested the name change, is that if one were to look at just this function signature, you'd assume that substitutions: Map<string, string> is a map between placeholders and replacement values, and that message is the template string.

Also, I think it's fine calling these templates since template strings don't necessarily have placeholders

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That makes sense. I renamed it to templates hoping it's less confusing now

@ajafff
Copy link
Contributor Author

ajafff commented Apr 12, 2017

@nchen63 @adidahiya you both approved this PR. Can this be merged? I recently missed this feature while I refactored some rules and needed to edit their tests.

@adidahiya
Copy link
Contributor

@ajafff thanks for the reminder, sorry for the delay.

@adidahiya adidahiya merged commit e55ba6f into palantir:master Apr 12, 2017
@adidahiya adidahiya added this to the TSLint v5.2 milestone Apr 12, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants