How to find out the checkbox name attribute based on the before_text or after_text

3 views
Skip to first unread message

xul...@yahoo.com

unread,
Aug 7, 2010, 7:45:34 PM8/7/10
to Vapir
Dear Folks,

I have a long list of checkbox in our web page which has dynamic name
based on different permission, From the IE, we can use before_text to
locate the checkbox name and then click the checkbox.
neither in firewatir, nor in vapir, there is no before_text attribute
for the checkbox.
Does anybody know other way to figure it out?
I need find the checkbox name attribute when I only know the
description for the checkbox in UI.

Many thanks,

xulivan

Ethan

unread,
Aug 7, 2010, 8:36:42 PM8/7/10
to va...@googlegroups.com
using :before_text and :after_text are not supported in vapir - I believe the are also going to be deprecated from watir, because they tend to be very unreliable, and the implementation isn't great. 

the recommended way of getting a checkbox like this is that the application should use a <label> pointing at the checkbox. then you would do something like 
checkbox = browser.label(:text => 'Text of the label').for_element
which will return a Checkbox element. 

but, of course, we don't always control the application to be able to enforce things like that, and in that case, it is possible in vapir. try something like:
checkbox = browser.checkboxes.detect{|cb| cb.before_text == 'some text' }

note that #before_text returns the text that comes after the checkbox; #after_text returns what comes before. I have no idea why. that code is inherited from watir, it makes no sense at all to me. 

xul...@yahoo.com

unread,
Aug 7, 2010, 9:16:11 PM8/7/10
to Vapir
Thanks,
there is no method for before_text. it returns the following errors.

irb(main):026:0> ie_offer.checkboxes.detect{|cb| cb.before_text ==
'some text' }
NoMethodError: undefined method `before_text' for
#<Vapir::Firefox::CheckBox:0x32d9a08>
from (irb):26
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-common-1.7.0/lib/
vapir-common/element.rb:651:in `call'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-common-1.7.0/lib/
vapir-common/element.rb:651:in `locate'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-common-1.7.0/lib/
vapir-common/element.rb:552:in `candidate_match_at_in
dex'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-common-1.7.0/lib/
vapir-common/specifier.rb:221:in `match_candidates'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-firefox-1.7.0/lib/
vapir-firefox/jssh_socket.rb:1031:in `each'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-firefox-1.7.0/lib/
vapir-firefox/jssh_socket.rb:1025:in `each'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-common-1.7.0/lib/
vapir-common/specifier.rb:220:in `match_candidates'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-common-1.7.0/lib/
vapir-common/specifier.rb:48:in `matched_candidates'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-common-1.7.0/lib/
vapir-common/element.rb:551:in `call'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-common-1.7.0/lib/
vapir-common/element.rb:551:in `candidate_match_at_in
dex'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-common-1.7.0/lib/
vapir-common/element.rb:650:in `locate'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-common-1.7.0/lib/
vapir-common/element.rb:675:in `exists?'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-common-1.7.0/lib/
vapir-common/element_collection.rb:57:in `detect'
from (irb):26
from :0

On Aug 7, 5:36 pm, Ethan <notet...@gmail.com> wrote:
> using :before_text and :after_text are not supported in vapir - I believe
> the are also going to be deprecated from watir, because they tend to be very
> unreliable, and the implementation isn't great.
>
> the recommended way of getting a checkbox like this is that the application
> should use a <label> pointing at the checkbox. then you would do something
> like
> checkbox = browser.label(:text => 'Text of the label').for_element
> which will return a Checkbox element.
>
> but, of course, we don't always control the application to be able to
> enforce things like that, and in that case, it is possible in vapir. try
> something like:
> checkbox = browser.checkboxes.detect{|cb| cb.before_text == 'some text' }
>
> note that #before_text returns the text that comes after the checkbox;
> #after_text returns what comes before. I have no idea why. that code is
> inherited from watir, it makes no sense at all to me.
>

Ethan

unread,
Aug 7, 2010, 10:01:37 PM8/7/10
to va...@googlegroups.com
oh, yes. that is only defined for IE, not firefox. 

well, I threw together a quick implementation for ff, but it behaves rather differently than the one IE defines. you can try it out and see if it works for you. maybe I will include it in the next version if so. 

I think I also need to deprecate the extraordinarily confusing method names, they seem wholly counterintuitive to me - what do you think? 

code follows.

-Ethan

class Vapir::Firefox::Element
  # return the text the element comes before (the returned text is after the element) 
  def before_text
    matched = false
    text = ''
    element_object.parentNode.childNodes.to_array.each do |node|
      text << node.textContent if matched
      if node==element_object
        matched = true
      end
    end
    text
  end
  # return the text the element comes after (the returned text is before the element) 
  def after_text
    matched = false
    text = ''
    element_object.parentNode.childNodes.to_array.each do |node|
      text << node.textContent if !matched
      if node==element_object
        matched = true
      end
    end
    text
  end
end

xul...@yahoo.com

unread,
Aug 8, 2010, 12:26:49 AM8/8/10
to Vapir
I got the following error, which method works ok in watir IE.

within IE implementation. I used the following code to find out the
name of checkbox. but don't work in vapir.

if @ie.checkbox(:before_text,/some text/).exists?
Checkbox_Name = @ie.checkbox(:before_text,/some
text/).attribute_value("name")
end


irb(main):043:0* ie_offer.checkbox(:name,"permission_197").before_text
JsshError: Expected a prompt! received unexpected data "37\n{\"errored
\":false,\"value\":\"undefined\"}\n> ". maybe left
on the socket by last evaluated expression? last expression was:

try
{ nativeJSON_encode_length({errored: false, value: (function(object)
{ return (object===null) ? 'null' : (typeof object);
})(JsshTemp["trs5ke"])});
} catch(e)
{ if(e.name=='ReferenceError')
{ nativeJSON_encode_length({errored: false, value: 'undefined'});
}
else
{ nativeJSON_encode_length({errored: true, value: Object.extend({},
e)});
}
}
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-firefox-1.7.0/lib/
vapir-firefox/jssh_socket.rb:177:in `read_value'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-firefox-1.7.0/lib/
vapir-firefox/jssh_socket.rb:279:in `send_and_read'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-firefox-1.7.0/lib/
vapir-firefox/jssh_socket.rb:478:in `typeof'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-firefox-1.7.0/lib/
vapir-firefox/jssh_socket.rb:582:in `type'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-firefox-1.7.0/lib/
vapir-firefox/jssh_socket.rb:723:in `store_rand_name
d'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-firefox-1.7.0/lib/
vapir-firefox/jssh_socket.rb:736:in `store_rand_obje
ct_key'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-firefox-1.7.0/lib/
vapir-firefox/jssh_socket.rb:622:in `val_or_object'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-firefox-1.7.0/lib/
vapir-firefox/jssh_socket.rb:702:in `call'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-firefox-1.7.0/lib/
vapir-firefox/jssh_socket.rb:941:in `to_js_array'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-firefox-1.7.0/lib/
vapir-firefox/firefox.rb:210:in `exists?'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-common-1.7.0/lib/
vapir-common/browser.rb:172:in `locate'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-common-1.7.0/lib/
vapir-common/browser.rb:175:in `locate!'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-common-1.7.0/lib/
vapir-common/element.rb:620:in `locate'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-common-1.7.0/lib/
vapir-common/element.rb:522:in `default_initialize'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-firefox-1.7.0/lib/
vapir-firefox/element.rb:20:in `initialize'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-common-1.7.0/lib/
vapir-common/container.rb:39:in `new'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-common-1.7.0/lib/
vapir-common/container.rb:39:in `element_by_howwhat'
from C:/Ruby/lib/ruby/gems/1.8/gems/vapir-common-1.7.0/lib/
vapir-common/element.rb:317:in `checkbox'
from (irb):43
from :0irb(main):044:0>

Ethan

unread,
Aug 8, 2010, 12:47:55 AM8/8/10
to va...@googlegroups.com
using :before_text as a 'how' specifier like that isn't supported by vapir, and support isn't planned. however, the code using browser.checkboxes.detect{ ... } might work, combined with the methods that I included in the previous e-mail defining #before_text and #after_text for firefox. if you paste that code in, and then try the browser.checkboxes.detect{ ... } code, that may work for you. 

something along the lines of:

require 'vapir'

browser = Vapir::Firefox.attach(:title, 'whatever')

cb = browser.checkboxes.detect{|cb| cb.before_text == 'some text' }

Or maybe use String#include? since the text may be different than IE returns:

cb = browser.checkboxes.detect{|cb| cb.before_text.include? 'some text' }


-Ethan

xul...@yahoo.com

unread,
Aug 8, 2010, 1:16:46 AM8/8/10
to Vapir
Can I just added those lines into element.rb file under firefox
folder?

Ethan

unread,
Aug 8, 2010, 1:19:30 AM8/8/10
to va...@googlegroups.com
yeah, that'll work, though I would make sure that the function actually does work for your purposes first. like I said, I just threw that together, I'm not sure how good it is. 

xul...@yahoo.com

unread,
Aug 8, 2010, 1:54:47 AM8/8/10
to Vapir
irb(main):033:0> ie_offer.checkbox(:name,'permission_197').before_text

it returns all text in the page include other checkbox text too.
so, the following one return the first checkbox all the time.

cb = ie_offer.checkboxes.detect{|cb| cb.before_text.include?
'MessageOf' }

cb is the first one checkbox.

On Aug 7, 10:19 pm, Ethan <notet...@gmail.com> wrote:
> yeah, that'll work, though I would make sure that the function actually does
> work for your purposes first. like I said, I just threw that together, I'm
> not sure how good it is.
>
> ...
>
> read more »

Ethan

unread,
Aug 8, 2010, 11:52:22 AM8/8/10
to va...@googlegroups.com
maybe you can check that the text it's before begins with the text you're looking for? 

like

checkboxes.detect{|cb| cb.before_text =~ /\A\s*MessageOf/ }

\A matches the beginning of the string, there, in case you're not familiar. 

xul...@yahoo.com

unread,
Aug 8, 2010, 2:32:16 PM8/8/10
to Vapir
yes, it kindly work, however, since our web page has more than 100
checkboxes with similar start string.

it return the results very slow. it took more than 5-10 minutes
depends on the check box location.
ie. if checkbox is at the bottom of page, it took long time.

irb(main):129:0* ie_offer.checkboxes.detect{|cb| cb.before_text =~ /
\A.*search.Glance/}

If the before_text just return the exactly the string for the checkbox
instead of all in the web page, I think the performance will be much
better.

Again,thanks,

On Aug 8, 8:52 am, Ethan <notet...@gmail.com> wrote:
> maybe you can check that the text it's before begins with the text you're
> looking for?
>
> like
>
> checkboxes.detect{|cb| cb.before_text =~ /\A\s*MessageOf/ }
>
> \A matches the beginning of the string, there, in case you're not familiar.
>
> ...
>
> read more »

xul...@yahoo.com

unread,
Aug 8, 2010, 3:19:43 PM8/8/10
to Vapir
I added another code to your class after
text << node.textContent if matched
break if matched.

this gives us more efficient way. and return the right "before_text" .

thanks,
> ...
>
> read more »

Ethan

unread,
Aug 8, 2010, 4:13:10 PM8/8/10
to va...@googlegroups.com
that makes sense. I was worried that just looking at the immediate sibling would be too limiting, but if that is working for you, then great. 

xul...@yahoo.com

unread,
Aug 8, 2010, 4:26:48 PM8/8/10
to Vapir
the performance is still poor even it is faster than before.
since the code need to detect (which is the first loop) and then
figure out the before_text (which is the 2nd loop). when the 2nd loop
has more than 100 checkboxes, it is waiting for long time.

IE.checkbox(:before_text, "some string") works much faster though.

Thanks,

On Aug 8, 1:13 pm, Ethan <notet...@gmail.com> wrote:
> that makes sense. I was worried that just looking at the immediate sibling
> would be too limiting, but if that is working for you, then great.
>
> ...
>
> read more »

Ethan

unread,
Aug 8, 2010, 7:46:48 PM8/8/10
to va...@googlegroups.com
since you only want the one sibling, the functions can be rewritten more simply and efficiently:

class Vapir::Firefox::Element
  # return the text the element comes before (the returned text is after the element) 
  def before_text
    (sibling = element_object.nextSibling) ? sibling.textContent : ''
  end
  # return the text the element comes after (the returned text is before the element) 
  def after_text
    (sibling = element_object.previousSibling) ? sibling.textContent : ''
  end
end


-Ethan
Reply all
Reply to author
Forward
0 new messages