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 cop for Capybara expectations set on current_path #470

Merged
merged 1 commit into from Sep 27, 2017

Conversation

timrogers
Copy link
Contributor

@timrogers timrogers commented Sep 26, 2017

Setting expectations on current_path in our Capybara feature specs leads to flaky tests. Switching to using Capybara's have_current_path matcher helps since it uses Capybara's waiting functionality that ensures that preceding actions (like click_link) have completed.

This cop tells you not to use expect(current_path).to match(/lol/), encouraging you to use the have_current_path matcher instead.

@timrogers timrogers changed the title [WIP] Add cop for Capybara expectations set on current_path Add cop for Capybara expectations set on current_path Sep 26, 2017
@Darhazer
Copy link
Member

You have to:

  • add entry to the config/default.yml (run bin/build_config)
  • add entry to the changelog
  • add bad and good examples as comments (see the other cops)
  • add test that shows you can have current_path outside of the expectation block (like just assigning to a variable)
  • I see often expect(page.current_path).to. Please cover this scenario

@timrogers
Copy link
Contributor Author

Will do! Thanks @Darhazer - really helpful list.

@timrogers
Copy link
Contributor Author

@Darhazer I've managed to do everything except no. 1 - I get the following:

$ bin/build_config
/Users/timrogers/Projects/rubocop-rspec/lib/rubocop/rspec/config_formatter.rb:23:in `fetch': key not found: "Capybara/CurrentPathExpectation" (KeyError)
	from /Users/timrogers/Projects/rubocop-rspec/lib/rubocop/rspec/config_formatter.rb:23:in `block in unified_config'
	from /Users/timrogers/Projects/rubocop-rspec/lib/rubocop/rspec/config_formatter.rb:22:in `each'
	from /Users/timrogers/Projects/rubocop-rspec/lib/rubocop/rspec/config_formatter.rb:22:in `each_with_object'
	from /Users/timrogers/Projects/rubocop-rspec/lib/rubocop/rspec/config_formatter.rb:22:in `unified_config'
	from /Users/timrogers/Projects/rubocop-rspec/lib/rubocop/rspec/config_formatter.rb:16:in `dump'
	from bin/build_config:20:in `<main>'

Any ideas? I'm sure I'm missing something obvious!

Copy link
Member

@Darhazer Darhazer left a comment

Choose a reason for hiding this comment

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

just make sure bin/rake passes

'`have_current_path` matcher on `page`'.freeze

def_node_matcher :expectation_set_on_current_path, <<-PATTERN
(send nil :expect {(send nil :current_path) (send (send nil :page) :current_path)})
Copy link
Member

Choose a reason for hiding this comment

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

I believe this could be written as (send nil :expect (send {(send nil :page) nil} :current_path)})

@Darhazer
Copy link
Member

@timrogers you need to add the key in config/default.yml. build_config will take care to sync description between the cop and the config

@timrogers
Copy link
Contributor Author

@Darhazer Aha - thanks! All done and I've pushed a finished, squashed version.

@Darhazer
Copy link
Member

Great job, @timrogers

Would you be willing to add another one, to check for not_to have_ calls, that should be avoided for the very same reason (see #378)?

@timrogers
Copy link
Contributor Author

Yes, sure!

@bquorning bquorning mentioned this pull request Sep 26, 2017
@Darhazer
Copy link
Member

Note: generally only eq / match kind of matchers can be replaced with have_current_path. I didn't see other usages though; and even if someone uses current_path with some fancy matcher, refactoring to have_current_path is the right thing to do. So I'm going to merge this as is, unless there are any objections; the note should be respected however if someone adds an autocorrect to this.

@bquorning any thoughts?

@timrogers
Copy link
Contributor Author

timrogers commented Sep 26, 2017 via email

@@ -334,3 +334,8 @@ FactoryGirl/DynamicAttributeDefinedStatically:
Description: Prefer declaring dynamic attribute values in a block.
Enabled: true
StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryGirl/DynamicAttributeDefinedStatically

Capybara/CurrentPathExpectation:
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is a semi-alphabetical list (RSpec/ is before Capybara/) – could we move this entry to line 328?

PATTERN

def on_send(node)
expectation_set_on_current_path(node) do |_match|
Copy link
Collaborator

@bquorning bquorning Sep 26, 2017

Choose a reason for hiding this comment

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

There are no captures in the node matcher, so no block arguments are passed: You can remove |_match|.

https://github.com/bbatsov/rubocop/blob/e7cfdc47c0a7522c4de64af82f0ea0e04b22f1c8/lib/rubocop/node_pattern.rb#L18-L19

RUBY
end

it 'doesn\'t flag a violation for other references to `current_path`' do
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nitpick: If you use double quotes around the string, you don’t need to escape the ' in the middle. (also in line 18).

Setting expectations on `current_path` in our Capybara feature
specs leads to flaky tests.  Switching to using
[Capybara's `have_current_path` matcher](http://www.rubydoc.info/github/teamcapybara/capybara/master/Capybara/RSpecMatchers#have_current_path-instance_method)
helps since it uses Capybara's
[waiting functionality](https://github.com/teamcapybara/capybara/blob/master/README.md#asynchronous-javascript-ajax-and-friends)
that ensures that preceding actions (like `click_link`) have
completed.

This cop tells you not to use `expect(current_path).to
match(/lol/)` or `expect(page.current_path).to match(/lol)`,
encouraging you to use the `have_current_path` matcher instead.
@timrogers
Copy link
Contributor Author

@bquorning Done!

@Darhazer Darhazer merged commit e298e26 into rubocop:master Sep 27, 2017
markburns pushed a commit to markburns/rubocop-rails-ddd that referenced this pull request Nov 7, 2017
Add cop for Capybara expectations set on `current_path`
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.

None yet

3 participants