2

I'm usisng cucmber to test a php app and it's working quite well actually.

I have a cucmber feature that uses the following step to check for the presence of a link in a page:

Then /^I should see a link that contains "(.+)"$/ do |link|
    assert !!(response_body =~ 
      /<a ([\w\.]*="[\w\.]*" )*href="(http:\/\/)?([\w\.\/]*)?(#{link})/m), response_body
end

Now, this works but it's butt ugly and complicated.

Originally I tried using the xpath thing:

response_body.should have_xpath("//a[@href=\"#{link}\"]")

But then if I check for a link to 'blah.com' then it won't match 'http://blah.com" - which kind of defeats the whole purpose of the test. Hence the reason I switched to regex.

So is there a simpler way to write the test which doesn't rely on complicated regular expressions?

Cheers.

EDIT: After lots of hair-pulling... I did find a less messy way to find images on my page:

response_body.should include(image)

Where the image string is set to something like 'myimage.png' - of course, this will break if the actual text 'myimage.png' is on the page and not the image. There must be a better way. I was considering Hpricot to see if I can parse the html and pull out the attribute I want to test, then test that with a regex but that all seems so... bloated.

ac_
  • 1,147
  • 4
  • 13
  • 34
  • Ok, just discovered this little gem... http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454 – ac_ Sep 28 '11 at 11:20
  • I hear that 'parsing html with regex is evil/improssible/opens a portal to hell, etc' - I'm starting to discover my img regex doesn't seem to work on large html files but it does on smaller samples. I don't really understand why but I guess that's because I don't understand the inner-workings of the regex engine (so sue me). – ac_ Sep 28 '11 at 11:27

2 Answers2

1

Something like this should work:

response_body.should have_css("a[href*='#{link}']")

See this for details: http://www.w3.org/TR/css3-selectors/#attribute-substrings

EDIT: Looks like the equivalent method for webrat is have_selector, so:

response_body.should have_selector("a[href*='#{link}']")
AlistairH
  • 3,139
  • 2
  • 21
  • 19
  • I get 'undefined method `has_css?' - That's not webrat is it? I don't think won't work anyway because it's not a CSS attribute I'm looking for, it's an HTML attribute. – ac_ Sep 28 '11 at 16:49
  • Capybara has a method called has_css?. RSpec maps that to have_css. Capybara acts is an abstraction layer between Cucumber and a variety of drivers including Mechanize and Selenium. CSS Selectors are an alternative to XPath and they generally have a simpler syntax: http://ejohn.org/blog/xpath-css-selectors/ – Andy Waite Sep 28 '11 at 18:46
  • 1
    try replacing 'have_css' with 'have_selector' – AlistairH Sep 28 '11 at 19:15
0
Then /^I should see the image "(.+)"$/ do |image|    
  response_body.should have_selector("img[src*='#{image}']")
end

Then /^I should see a link that contains "(.+)"$/ do |link|    
  response_body.should have_selector("a[href*='#{link}']")
end

Thanks AlistairH - your advice worked! :)

I still don't undestand why it's searching html with a css selector syntax but maybe that was just a design choice they guy who wrote it took because it looked easier than regex...? I don't know.

ac_
  • 1,147
  • 4
  • 13
  • 34
  • When writing CSS, you are attempting to select elements on a page to apply a particular style to. It's not so different to selecting elements on a page to test. It's well worth learning some css syntax - as you can see it's pretty flexible and often more concise than the equivalent xpath or a regex. – AlistairH Sep 29 '11 at 12:34