John Lolis wrote:
> A second, slightly related question. Regardless of how you do it, i'm
> wondering whats going on behind the scenes.
> If you do
>
>> headline = $ie.div(:text, 'Pragmatic Version Control')
>> link = $ie.link(:class => 'addtocart', :after? => headline)
>>
>
> Is headline now 'frozen'? For example, lets say there is a 'addtocart' after
> headline. What happens if after you create your headline variable the page
> changes (headline is now at the bottom of the page)? Will the after method re
> evaluate headlines position in the page? Or is headline now static so after
> would would be true even if it isn't?
>
> I'm not sure if that even made sense.
>
Actually this is a good question.
Let's call each of these "Watir expressions". They can refer to
different objects on different pages, or sometimes they refer to nothing.
> $ie.div(:text, 'Pragmatic Version Control')
> $ie.link(:class => 'addtocart', :after? => headline)
>
When they are used, they end up referring to specific control on a
specific page at a specific point in time. Let's call this an "element
reference" (internally it is called @o and getOLEobject and ole_object,
variously depending on version). This reference is actually a COM object
that will become stale as soon as a new page is loaded. However it will
remain valid if javascript-based changes are made to the DOM.
So your question becomes: What is the relationship between Watir
expressions and element references? And the answer depends on whether
you are using Watir 1.4 or 1.5.
Both versions of Watir use "locate" methods to tie the Watir objects
returned by Watir expressions to the element references, and we might
call this process "binding". In Watir 1.4, this binding was made at call
time. When the expression was executed, the Watir object would be bound.
However, if there was a failure to bind (ObjectNotFound), an error would
not be raised until you actually made a call to the object -- for
example, calling its "click" method. The reason for this was to allow us
to have an "exists?" method. This method would only return false if we
had failed to bind -- not raise an error.
In Watir 1.5, i moved the timing of the locate method (in most cases) so
that binding itself would not happen until this time -- when we
previously were just checking to see if the binding had been made or
not. In other words, we had "late binding" in 1.4 and "really-late
binding" in 1.5.
In theory, really-late binding would allow you to create objects that
would rebind themselves after a page load. However, i've never
encouraged this, nor have i seen any evidence that people have actually
been doing this. A big issue is that this automatic rebinding would
happen in simple cases but not in complex cases and understanding the
difference was really too much to expect from our users. I'm reluctant
to even try and explain it, and frankly there are edge cases that i'm
unsure of myself, and i also suspect there are bugs.
So we have consistently urged people to wrap their watir expressions in
methods rather than assign them to global variables. This makes it easy
to reuse them, and ensure that a correct rebinding occurs on each reuse.
Also, as i have been using Watir more on large projects, i am finding
that there are other reasons why this is a sound way to structure Watir
libraries.
This made the automatic-rebinding we have in place simply a performance
hog with no real benefit. I posted a patch the other day that removes it
and will probably commit this to trunk soon. It has the potential to
break tests, so first i want to post a release that rolls up the new
features and bug fixes that will assuredly be popular.
So the short answer to your question, is "it depends".
Is headline now 'frozen'? For example, lets say there is a 'addtocart'
after headline. What happens if after you create your headline variable the
page changes (headline is now at the bottom of the page)? Will the after method
re evaluate headlines position in the page? Or is headline now static so after
would would be true even if it isn't?
So when you say the page changes, we need to know whether a new page is
loaded (or even reloading the same page) or whether the change is made
dynamically. Right now, it will rebind if we get a page load (but, like
i said, i'm considering removing this behavior). If it is an
AJAX/Javascript change, then we would need more details. In particular,
a lot of times when we see AJAX/Javascript page elements moving, they
are actually being made visible or invisible, which is a whole other
thing, since Watir can "see" invisible elements.
The important message is that you really should re-execute the headline
Watir expression after a page change. That will ensure that your tests
work correctly, not matter how your page works or what version of Watir
you are using.
Bret
_______________________________________________
Wtr-general mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/wtr-general