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

feat(rule): add valid-describe rule #57

Merged
merged 2 commits into from
Feb 9, 2018

Conversation

macklinu
Copy link
Collaborator

@macklinu macklinu commented Feb 3, 2018

Resolves #18

This rule validates that the second parameter of a describe() function is a callback function. This callback function:

  • should not be async
  • should not contain any parameters
  • should not contain any return statements

File naming is kebab-case, per the discussion in #60.

index.js Outdated
@@ -1,5 +1,4 @@
'use strict';
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm not sure why lint-staged is removing this as part of the eslint --fix step in my local environment.

Copy link
Member

Choose a reason for hiding this comment

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

you probably have an eslintrc file in $HOME or something. Try adding root: true in the eslintrc.js in this repo

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for the tip! I had an unexpected .eslintrc file one level up from this repo on my machine. Removed that and was able to see my local linting match up with what Travis CI is reporting. 👍

@SimenB
Copy link
Member

SimenB commented Feb 3, 2018

Fitting, my first eslint rule ever was handling a callback in describe for jasmine! 🙂 See tlvince/eslint-plugin-jasmine#17, can probably copy that implementation.

I'm not sure how we could figure out nr 2, though. You can take a look at #42, there is some promise detection in it.

@macklinu
Copy link
Collaborator Author

macklinu commented Feb 3, 2018

I'll work towards including the two other use cases in this PR - thanks for the suggestions on other implementations to look at. We can figure out a proper name for this rule before merging, but I won't worry much about that right now.

@macklinu
Copy link
Collaborator Author

macklinu commented Feb 4, 2018

I'm still working on use case number 2, but is there ever a reason to return within a describe() callback?

// invalid
describe('foo', () => {
  return Promise.resolve().then(() => {
    it('breaks', () => {
      throw new Error('Fail')
    })
  })
})

Looking at this code, return Promise.resolve() is something we want this rule to detect and report. 886ce50 is simply checking if the describe() callback body contains any return statements, not necessarily that it's returning a Promise.

I can update to check that the returned value is a Promise (by looking at #42, as suggested), but I am wondering if there's a code example where returning anything within the body of a describe() callback is a good practice.

@macklinu
Copy link
Collaborator Author

macklinu commented Feb 8, 2018

I'm still unsure about the previous comment. Also, is there ever a reason to call await within a describe() block?

// we will warn on the `async` describe callback function
describe('foo', async () => {
  // should we also warn that we are calling `await` here
  // or is the `async` warning above enough?
  await something()
  it('does something', () => {
    // ...
  })
})

@SimenB
Copy link
Member

SimenB commented Feb 8, 2018

You have to call it synchronously, so no, there's never a reason to make describe async

@macklinu macklinu force-pushed the describe-callback branch 2 times, most recently from 7ea9894 to 5cea64a Compare February 8, 2018 18:57
@macklinu macklinu changed the title feat(wip): add no-async-describe rule feat(rule): add valid-describe rule Feb 8, 2018
Copy link
Collaborator Author

@macklinu macklinu left a comment

Choose a reason for hiding this comment

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

This is now ready for review. 👍

@@ -0,0 +1,53 @@
# Enforce valid `describe()` callback (valid-describe)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I settled on calling this valid-describe since this addresses a few different cases. This follows the convention of the valid-expect rule. Open to other naming suggestions too!

@@ -0,0 +1,66 @@
'use strict';

const describeAliases = Object.assign(Object.create(null), {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This was taken from no-identical-title:

const describeAliases = Object.assign(Object.create(null), {
describe: true,
'describe.only': true,
'describe.skip': true,
fdescribe: true,
xdescribe: true,
});

I can extract an isDescribe(node) function, move it to util.js and import it into no-identical-title and this rule, if that refactor would be helpful.

Copy link
Member

Choose a reason for hiding this comment

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

yeah, that sounds good

create(context) {
return {
CallExpression(node) {
if (node && isDescribe(node)) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Can node ever be falsy here? I'm not sure I need to include this node &&.

Copy link
Member

Choose a reason for hiding this comment

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

not sure. Seems weird if it can be?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Does seem weird, will remove that check

if (hasParams(callbackFunction)) {
context.report({
message: 'Unexpected argument in describe callback',
node: callbackFunction.params[0],
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This only warns for the first param - perhaps this should warn for all passed in params?

Copy link
Member

Choose a reason for hiding this comment

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

yeah, that makes sense.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Will update with a test case for multiple params in a describe() callback

@SimenB
Copy link
Member

SimenB commented Feb 9, 2018

needs a rebase

@macklinu
Copy link
Collaborator Author

macklinu commented Feb 9, 2018

Rebased and force pushed up.

],
invalid: [
{
code: 'describe("foo", async () => {})',
Copy link
Member

Choose a reason for hiding this comment

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

as a follow up, mind adding a rule that describe(() => {}) is invalid as well?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

For sure, I'll open an issue to track that suggestion. 👍

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.

2 participants