154

The page url is something like /people?search=name while I used current_path method of capybara it returned /people only.

current_path.should == people_path(:search => 'name')

But it fails saying

expected: "/people?search=name"
got: "/people"

How we can make it pass? Is there is any way to do this?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
kriysna
  • 6,118
  • 7
  • 30
  • 30

6 Answers6

236

I've updated this answer to reflect modern conventions in capybara. I think this is ideal since this is the accepted answer, and what many people are being referred to when looking for a solution. With that said, the correct way to check the current path is to use the has_current_path? matcher provided by Capybara, as documented here: Click Here

Example usage:

expect(page).to have_current_path(people_path(search: 'name'))

As you can see in the documentation, other options are available. If the current page is /people?search=name but you only care that it's on the /people page regardless of the param, you can send the only_path option:

expect(page).to have_current_path(people_path, only_path: true)

Additionally, if you want to compare the entire URL:

expect(page).to have_current_path(people_url, url: true)

Credit to Tom Walpole for pointing out this method.

nzifnab
  • 15,876
  • 3
  • 50
  • 65
  • 4
    I'll probably need this syntax very soon, I'm writing tests for a legacy application. Using `current_path.should ==` is working for now (though I need to add a trailing forward-slash as a string). I'm thanking you in advance for code I'll likely need. – Tass Aug 19 '11 at 21:16
  • 3
    `URI.parse(current_url).request_uri` is more succinct. See @Lasse Bunk's answer. – Richard Jones Nov 27 '13 at 01:16
  • As of Capybara 2.5, this is no longer the best answer. See @tom-walpole's answer below. – dkniffin Aug 25 '16 at 15:43
  • Since the asker is unlikely to change the accepted answer, I've updated the answer to reflect modern times. This should be more helpful to new users looking for a solution and seeing the first answer. Thanks @OddityOverseer for pointing it out – nzifnab Sep 08 '16 at 17:16
  • 5
    For new Capybara versions use `ignore_query: true` instead of `only_path: true` – Alexander Mar 19 '20 at 14:55
94

I replaced the _path method with _url to achieve comparing the full urls with parameters.

current_url.should == people_url(:search => 'name')
Robert Starsi
  • 941
  • 6
  • 2
56

Just updating this question for modern times. The current best practice for checking current_paths when using Capybara 2.5+ is to use the current_path matcher, which will use Capybaras waiting behavior to check the path. If wanting to check against the request_uri (path and query string)

expect(page).to have_current_path(people_path(:search => 'name'))  

If only wanting the path part (ignoring the query string)

expect(page).to have_current_path(people_path, only_path: true) # Capybara < 2.16
expect(page).to have_current_path(people_path, ignore_query: true) # Capybara >= 2.16

If wanting to match the full url

expect(page).to have_current_path(people_url, url: true) # Capybara < 2.16
expect(page).to have_current_path(people_url) # Capybara >= 2.16

the matcher will take a string which is compared with == or a regex to match against

expect(page).to have_current_path(/search=name/)
Thomas Walpole
  • 48,548
  • 5
  • 64
  • 78
  • 4
    in these modern times this should be marked as *the* answer. This will safe a lot of vague timing issues, thanks! – Axe Mar 06 '16 at 12:12
  • 1
    @Vanuan rspec has been deprecating the `should` syntax. You should strive to use `expect().to` in your specs going forward. – nzifnab Sep 08 '16 at 17:17
  • 1
    `only_path: true` is now `ignore_query: true` – srghma Mar 13 '18 at 19:25
20

I know an answer has been selected, but I just wanted to give an alternative solution. So:

To get the path and querystring, like request.fullpath in Rails, you can do:

URI.parse(current_url).request_uri.should == people_path(:search => 'name')

You can also do a helper method in your test class (like ActionDispatch::IntegrationTest) like this (which is what I did):

def current_fullpath
  URI.parse(current_url).request_uri
end

Hope this helps.

Lasse Bunk
  • 1,848
  • 20
  • 21
2

EDIT: as Tinynumberes mentioned, this fails for URLs with port number. Keeping it here in case anyone else has the same brilliant idea.

current_url[current_host.size..-1]

golfs exactly as well (35 chars) as URI.parse(current_url).request_uri, but is potentially faster because there is no explicit URI parsing involved.

I have made a pull request to add this to Capybara at: https://github.com/jnicklas/capybara/pull/1405

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
  • This doesn't work if the `current_url` might contain a port number. E.g. given a `current_url` of `http://foo.com:8888/some/path`, `current_url[current_host.size..-1]` will equal `:8888/some/path`. Also, behind the scenes `current_host` does the same sort of `URI.parse` logic that @nzifnab recommended in the accepted answer. – Tinynumbers Jan 29 '15 at 14:36
0

Beware that author mentioned in this comment. That usage of current_url can lead to flaky tests.

woto
  • 2,893
  • 1
  • 29
  • 24