Skip to content
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

Add no-inline-assertions rule #262

Merged
merged 19 commits into from Jul 5, 2019

Conversation

JLHwung
Copy link
Contributor

@JLHwung JLHwung commented Jun 13, 2019

Update (2019-06-13): I have pushed no-inline-assertions rule implementation, see the docs and test cases. This rule will fail

Any MemberExpression as the arrow function body

test('foo', t => t.true(fn()));
test('foo', t => t.skip());
test('foo', t => 
    t.true(fn())
);
// ...

And any BlockStatement within the same line

test('foo', t => { t.true(fn()) });
test('foo', t => { t.skip() });

(2019-06-12)
This is an early-stage design discussion, as I have the following question regards to this rule. I would also put up my thoughts and any community input is welcome.

Background: Recap of #152

The no-inline-assertions was originally proposed at #152, where Sindre listed two example

Pass

test('foo', t => t.true(fn()));

Failure

test('foo', t => {
    t.true(fn());
});

Question on extra examples

While the example above is unambiguous, there is more question to be addressed after I ponder for a while.

  1. Should inline arrow function with block statement be failed?
test('foo', t => { t.true(fn()) });
  1. Should inline arrow function with a return statement be failed?
test('foo', t => { return t.true(fn()) });
  1. Should inline arrow function with assertion call as last expression be failed?
test('foo', t => { t.log('Meow');t.true(fn()) });

Here are my thoughts on these cases,
On the first, I think it should be failed as an inline arrow function with block statement is still inline.
On the second one, I think there should be a separate rule, e.g. no-return-assertions to take care of this. Otherwise we will have also to fail the following case

test('foo', t => {
  return t.true(fn());
});

which is, of course, not an inline arrow function. So rule no-inline-assertions should not be triggered by case 2.

On the third one, I think it should be failed as it is still an inline arrow function with assertion calls inside. But I am not an ava user so I can't triage the impact of the third case. Is it common? Or we can neglect this case?

The docs here reflects my thoughts and is suggested to any changes.

Fixes #152

@JLHwung JLHwung changed the title WIP: Add no-inline-assertion rule (Fixes #152) WIP: Add no-inline-assertions rule (Fixes #152) Jun 13, 2019
@GMartigny
Copy link
Contributor

I think the 2nd example fall under the arrow-body-style rule of eslint.

IMO, this no-inline-assertion should fail no matter what, when test second param is in the same line.

@JLHwung
Copy link
Contributor Author

JLHwung commented Jun 14, 2019

IMO, this no-inline-assertion should fail no matter what, when test second param is in the same line.

Agree. I was worrying about test("somethigs", (t) => { t.skip() }); before but since there is an ava/use-t-well rule, it should be straightforward to fail when the block statement is a one-liner.

I suggest there be an exception:

When there is an empty test body

test("something", (t) => {});

we should not fail as it may be an IDE auto-completed scaffold. And developer may leave it as is when writing test to drive development.

@JLHwung JLHwung changed the title WIP: Add no-inline-assertions rule (Fixes #152) Add no-inline-assertions rule (Fixes #152) Jun 14, 2019
@GMartigny
Copy link
Contributor

When there is an empty test body, we should not fail

I agree, no body is not an inline body.

You forgot to add the rule to recommended config in index.js.

readme.md Outdated Show resolved Hide resolved
@sindresorhus
Copy link
Member

Should inline arrow function with block statement be failed?

That's not an inline arrow function. And no.

Should inline arrow function with a return statement be failed?

That's not an inline arrow function. And no, I think this would be a better fit for the use-t-well rule. It could validate that no assertion is returned, unless it's an assertion that returns a promise, in which, it's allowed.

Should inline arrow function with assertion call as last expression be failed?

That's not an inline arrow function. And no.

@sindresorhus
Copy link
Member

IMO, this no-inline-assertion should fail no matter what, when test second param is in the same line.

I disagree. That's better handled by normal ESLint style rules. The point here is to handle an inline arrow function, meaning x => x (not x => { return x }).

@sindresorhus sindresorhus changed the title Add no-inline-assertions rule (Fixes #152) Add no-inline-assertions rule Jul 1, 2019
function report({node, context}) {
context.report({
node,
message: 'Assertions should not be called from an inline function.'
Copy link
Member

Choose a reason for hiding this comment

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

This would be more correct:

Suggested change
message: 'Assertions should not be called from an inline function.'
message: 'The test implementation should not be just an assertion in an inline arrow function.'

But would be nice to find a way to shorten the above slightly.

@JLHwung
Copy link
Contributor Author

JLHwung commented Jul 1, 2019

The point here is to handle an inline arrow function, meaning x => x (not x => { return x }).

Per https://tc39.es/ecma262/#prod-ConciseBody, we should alias our definition of "inline arrow function" to "arrow function with concise body", and then we can clearly state that x => { return x } is not an inline arrow function.

And the error message could be

The test implementation should not be an inline arrow function.

If we agree that BlockStatement should not be considered inline, we should leave it as-is and only take care of CallExpression.

@sindresorhus
Copy link
Member

The test implementation should not be an inline arrow function.

👍

If we agree that BlockStatement should not be considered inline, we should leave it as-is and only take care of CallExpression.

👍

@JLHwung
Copy link
Contributor Author

JLHwung commented Jul 1, 2019

@sindresorhus Just pushed a new version and revised test cases.

docs/rules/no-inline-assertions.md Outdated Show resolved Hide resolved
@@ -0,0 +1,19 @@
# Ensure no assertions are called from inline functions

Prevent assertions being called from an inline function, to make it clear that it does not return.
Copy link
Member

Choose a reason for hiding this comment

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

This is repeating the title too much. It should also use the wording "test implementation".

test/no-inline-assertions.js Outdated Show resolved Hide resolved
@sindresorhus
Copy link
Member

Can you make the rule auto-fixable?

JLHwung and others added 2 commits July 3, 2019 13:23
Co-Authored-By: Sindre Sorhus <sindresorhus@gmail.com>
@JLHwung
Copy link
Contributor Author

JLHwung commented Jul 3, 2019

Can you make the rule auto-fixable?

Good idea, it could be autofixable and I would look into it later. Anyway I have fixed the writing issues.

@JLHwung
Copy link
Contributor Author

JLHwung commented Jul 3, 2019

@sindresorhus I have pushed a simple fixer. The fixer wraps callExpression inside brackets. i.e. () => x() will be fixed to () => {x()}.

I tend to keep the fixer as minimal as possible, which means the other ESLint style rules, i.e. prettier should take care of the formatting of the new BlockStatement, such as the extra space before or after brackets or potential line breaks around the brackets.

@sindresorhus
Copy link
Member

You need to mark it as being fixable in the readme and the rule docs.

@sindresorhus
Copy link
Member

I have pushed a simple fixer. The fixer wraps callExpression inside brackets. i.e. () => x() will be fixed to () => {x()}.

👍 Yup. That's the correct way to do it.

readme.md Outdated Show resolved Hide resolved
@sindresorhus
Copy link
Member

You need to mark it as being fixable in the readme and the rule docs.

Not resolved yet.

@sindresorhus sindresorhus merged commit b829dbc into avajs:master Jul 5, 2019
@sindresorhus
Copy link
Member

This looks good now. Thanks for working on this rule :)

@JLHwung JLHwung deleted the no-inline-assertions branch July 5, 2019 11:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

no-inline-assertions rule
4 participants