I was writing a feature in which I had webrat push a button. However, there are many buttons on this page with the same text. I wanted to specify which one would be push in as close a way I could to the way a person would describe which one he was pushing. Here is what I ended up with: #custom_webrate_steps.rb require ''rexml/document'' include REXML When /^I push "(.*)" near "(.*)"$/ do |button, text| #The dom element that contains the text must have an id rexml_doc = Document.new(response.body) regexp = /#{Regexp.escape(text)}/ nodes = find_nodes_with_regexp(rexml_doc, regexp) dom_id = nodes.first.attributes[''id''] within ''#'' + dom_id do |scope| scope.clicks_button(button) end end def find_nodes_with_regexp(node, regexp) result = [] result << node if node.methods.include?(''text'') && node.text =~ regexp node.each {|n| result += find_nodes_with_regexp(n, regexp)} if node.methods.include?(''each'') result end Any ideas for making this *nicer*? -- Posted via http://www.ruby-forum.com/.
aslak hellesoy
2008-Nov-20 05:06 UTC
[rspec-users] specifying which button webrat should press
On Thu, Nov 20, 2008 at 4:32 AM, Pau Cor <lists at ruby-forum.com> wrote:> I was writing a feature in which I had webrat push a button. However, > there are many buttons on this page with the same text. I wanted to > specify which one would be push in as close a way I could to the way a > person would describe which one he was pushing. Here is what I ended up > with: > > #custom_webrate_steps.rb > require ''rexml/document'' > include REXML > > When /^I push "(.*)" near "(.*)"$/ do |button, text| > #The dom element that contains the text must have an id > > rexml_doc = Document.new(response.body) > regexp = /#{Regexp.escape(text)}/ > nodes = find_nodes_with_regexp(rexml_doc, regexp) > dom_id = nodes.first.attributes[''id''] > > within ''#'' + dom_id do |scope| > scope.clicks_button(button) > end > end > > > def find_nodes_with_regexp(node, regexp) > result = [] > result << node if node.methods.include?(''text'') && node.text =~ regexp > node.each {|n| result += find_nodes_with_regexp(n, regexp)} if > node.methods.include?(''each'') > result > end > > > Any ideas for making this *nicer*?give buttons unique dom ids and pass the id to #clicks_button ?> -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
aslak hellesoy wrote:> give buttons unique dom ids and pass the id to #clicks_button ?Of course that''s the easy way to do it :) I was hoping to keep my stories a bit closer to English. Plus then I''d need some extra instance variable so that step can calculate the dom_id. Here is an example of what I''m going for: Scenario: Accepting a friend request Given there is a user named "Fred" And I am logged in as a normal user named "Joe" And there is an unaccepted invite from "Fred" to me And there is a user named "Sally" And there is an unaccepted invite from "Sally" to me When I go to "the invites from friends page" And I push "accept" near "Fred" # I want to avoid: And I push #accept_button_user_1 Then I should see "Now you are friends with Fred" When I push "ignore" near "Sally" Then I should see "Sally won''t ever bother you again" Or maybe you are suggesting: Scenario: Accepting a friend request Given there is a user named "Fred" And I am logged in as a normal user named "Joe" And there is an unaccepted invite from "Fred" to me And there is a user named "Sally" And there is an unaccepted invite from "Sally" to me When I go to "the invites from friends page" And I push "accept" for user "Fred" Then I should see "Now you are friends with Fred" When I push "ignore" for user "Sally" Then I should see "Sally won''t ever bother you again" with this matcher: When /^I push "(.*)" for user "(.*)"$/ do |button, user_name| user = User.find_by_name(user_name) scope.clicks_button("accept_#{dom_id(user)}") end Am I putting too much thought into this? Paul P.S. I am sorry if this has been a dumb question. I''m still just trying to learn the best way to approach this stuff. -- Posted via http://www.ruby-forum.com/.
David Chelimsky
2008-Nov-20 07:06 UTC
[rspec-users] specifying which button webrat should press
On Thu, Nov 20, 2008 at 12:07 AM, Pau Cor <lists at ruby-forum.com> wrote:> aslak hellesoy wrote: >> give buttons unique dom ids and pass the id to #clicks_button ? > > Of course that''s the easy way to do it :) > > I was hoping to keep my stories a bit closer to English. Plus then I''d > need some extra instance variable so that step can calculate the dom_id. > Here is an example of what I''m going for: > > Scenario: Accepting a friend request > Given there is a user named "Fred" > And I am logged in as a normal user named "Joe" > And there is an unaccepted invite from "Fred" to me > And there is a user named "Sally" > And there is an unaccepted invite from "Sally" to me > When I go to "the invites from friends page" > And I push "accept" near "Fred" > # I want to avoid: And I push #accept_button_user_1You''re on the right track, and I don''t think Aslak was recommending putting accept_button_user_1 in the step. What you can do is put it in the step definition, and use some sort of map. For example, I usually have a map of page names to paths so I can say: When I visit the new pet form which is implemented like this: When /I visit the (.*)/ do |page| visit case page when "new pet form" new_pet_path end end So you can do a similar mapping with Fred. Maybe it works like this (just guessing - don''t know what your app looks like) When /I push "(.)" near "(.*)" do |what, who| user = User.find_by_first_name(who) clicks_button "#{what}_button_user_#{user.id}" end As long as you keep this sort of thing simple, I find it very manageable and it actually begins to encourage good APIs and conventions in the app.> Then I should see "Now you are friends with Fred" > When I push "ignore" near "Sally" > Then I should see "Sally won''t ever bother you again" > > > Or maybe you are suggesting: > > Scenario: Accepting a friend request > Given there is a user named "Fred" > And I am logged in as a normal user named "Joe" > And there is an unaccepted invite from "Fred" to me > And there is a user named "Sally" > And there is an unaccepted invite from "Sally" to meI might do something to eliminate the need for the previous statement: Given /there is an unaccepted invite from "(.*)" to me/ do |username| user = User.find_or_create_by_first_name(username) # whatever you need to create the invite end Now these first lines can be reduced to: Given I am logged in as a normal user named "Joe" And there is an unaccepted invite from "Fred" to me And there is an unaccepted invite from "Sally" to me That''s a lot less noise, and there is a clear implication that Fred and Sally exist. WDYT? David> When I go to "the invites from friends page" > And I push "accept" for user "Fred" > Then I should see "Now you are friends with Fred" > When I push "ignore" for user "Sally" > Then I should see "Sally won''t ever bother you again" > > with this matcher: > When /^I push "(.*)" for user "(.*)"$/ do |button, user_name| > user = User.find_by_name(user_name) > scope.clicks_button("accept_#{dom_id(user)}") > end > > Am I putting too much thought into this? > > Paul > > P.S. I am sorry if this has been a dumb question. I''m still just trying > to learn the best way to approach this stuff. > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Andrew Premdas
2008-Nov-20 13:44 UTC
[rspec-users] specifying which button webrat should press
I did something similar with Scenario: Cart shows item price and total price Given there is a product with name foo and price ?24.50 And I am on the products page When I add product with name foo to cart And a step matcher When /^I add product with name (.*) to cart$/ do |name| p = Product.find_by_name(name) p.should_not be_nil clicks_link_within("#product_#{product.id}", "Add to Basket") end A couple of things that influenced this where 1) I didn''t think it was appropriate to have the technical mechanism for adding the product (push button, click add link etc.) in the feature 2) Any page with multiple button|links with the same text must have some surrounding element that allows you to differentiate. This technical detail belongs in the steps As far as your features go I think that And I accept Fred''s invite scans better than And I push "accept" near "Fred" HTH 2008/11/20 Pau Cor <lists at ruby-forum.com>:> aslak hellesoy wrote: >> give buttons unique dom ids and pass the id to #clicks_button ? > > Of course that''s the easy way to do it :) > > I was hoping to keep my stories a bit closer to English. Plus then I''d > need some extra instance variable so that step can calculate the dom_id. > Here is an example of what I''m going for: > > Scenario: Accepting a friend request > Given there is a user named "Fred" > And I am logged in as a normal user named "Joe" > And there is an unaccepted invite from "Fred" to me > And there is a user named "Sally" > And there is an unaccepted invite from "Sally" to me > When I go to "the invites from friends page" > And I push "accept" near "Fred" > # I want to avoid: And I push #accept_button_user_1 > Then I should see "Now you are friends with Fred" > When I push "ignore" near "Sally" > Then I should see "Sally won''t ever bother you again" > > > Or maybe you are suggesting: > > Scenario: Accepting a friend request > Given there is a user named "Fred" > And I am logged in as a normal user named "Joe" > And there is an unaccepted invite from "Fred" to me > And there is a user named "Sally" > And there is an unaccepted invite from "Sally" to me > When I go to "the invites from friends page" > And I push "accept" for user "Fred" > Then I should see "Now you are friends with Fred" > When I push "ignore" for user "Sally" > Then I should see "Sally won''t ever bother you again" > > with this matcher: > When /^I push "(.*)" for user "(.*)"$/ do |button, user_name| > user = User.find_by_name(user_name) > scope.clicks_button("accept_#{dom_id(user)}") > end > > Am I putting too much thought into this? > > Paul > > P.S. I am sorry if this has been a dumb question. I''m still just trying > to learn the best way to approach this stuff. > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Andrew Premdas wrote:> And I accept Fred''s invite > scans better than > And I push "accept" near "Fred"That definitely is better. I guess I was trying to be too broad. My original goal was to write a match that would work on any page with multiple links/buttons (of the same name). It seems like everyone is suggesting that I write a step that is more specific to this particular page. That will make my step matcher MUCH simpler, and it will make my story more readable. Thanks for all the advice! Paul -- Posted via http://www.ruby-forum.com/.
James Byrne
2009-Feb-20 20:13 UTC
[rspec-users] specifying which button webrat should press
Given this: <form> <p> <input id="submit_commit_client" name="commit" type="submit" value="Create" /> </p> </form> If I want webrat to select on the ccs id (#submit_commit_client) rather than the value (Create) how do I pass this to click_button? I have tried this: click_button("#submit_commit_client") Which gives this error: Could not find button "#submit_commit_client" (Webrat::NotFoundError) /usr/lib64/ruby/gems/1.8/gems/webrat-0.4.1/lib/webrat/core/locators/locator.rb:14:in `locate!'' -- Posted via http://www.ruby-forum.com/.
Zach Dennis
2009-Feb-20 20:24 UTC
[rspec-users] specifying which button webrat should press
On Fri, Feb 20, 2009 at 3:13 PM, James Byrne <lists at ruby-forum.com> wrote:> Given this: > > <form> > > <p> > <input id="submit_commit_client" name="commit" type="submit" > value="Create" /> > </p> > > </form> > > If I want webrat to select on the ccs id (#submit_commit_client) rather > than the value (Create) how do I pass this to click_button? > > I have tried this: > > click_button("#submit_commit_client") >Can you use the following or do you need to use an id for other reason? click_button "Create"> Which gives this error: > > Could not find button "#submit_commit_client" (Webrat::NotFoundError) > > /usr/lib64/ruby/gems/1.8/gems/webrat-0.4.1/lib/webrat/core/locators/locator.rb:14:in > `locate!'' > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-- Zach Dennis http://www.continuousthinking.com http://www.mutuallyhuman.com
James Byrne
2009-Feb-20 20:50 UTC
[rspec-users] specifying which button webrat should press
Zach Dennis wrote:> > Can you use the following or do you need to use an id for other reason? > > click_button "Create" >That is how I am doing the check now. I am simply investigating whether another means is available to me. At the back of my mind is the idea that it is the presence of the function and not the form of the label that is important. By adding an id to the input tag and selecting on that then whatever the button itself is labeled as becomes unimportant. -- Posted via http://www.ruby-forum.com/.
Zach Dennis
2009-Feb-20 21:03 UTC
[rspec-users] specifying which button webrat should press
On Fri, Feb 20, 2009 at 3:50 PM, James Byrne <lists at ruby-forum.com> wrote:> Zach Dennis wrote: > >> >> Can you use the following or do you need to use an id for other reason? >> >> click_button "Create" >> > > That is how I am doing the check now. I am simply investigating whether > another means is available to me.You should be able to click the button by id, by not using a CSS selector. ie: click_button "submit_commit_client"> At the back of my mind is the idea > that it is the presence of the function and not the form of the label > that is important. By adding an id to the input tag and selecting on > that then whatever the button itself is labeled as becomes unimportant.-- Zach Dennis http://www.continuousthinking.com http://www.mutuallyhuman.com
James Byrne
2009-Feb-20 21:28 UTC
[rspec-users] specifying which button webrat should press
Zach Dennis wrote:> > You should be able to click the button by id, by not using a CSS > selector. ie: > > click_button "submit_commit_client" >You are right. That works. Thank you. Regards, -- Posted via http://www.ruby-forum.com/.