[WebDriver] Proposed changes to frame handling behavior

169 views
Skip to first unread message

Jason Leyba

unread,
Jul 3, 2010, 12:18:59 AM7/3/10
to selenium-...@googlegroups.com
Hi All,

While working on improvements to the Android and Chrome drivers, we've realized there is a lot of ambiguity in WebDriver's frame handling behavior.  Since this adds a lot of complexity to the code, I'd like to simplify things a bit.  To start things off, here's how things work now:

After navigating to a new page, the driver automatically sets its focus on the root document...unless the root document contains a frameset.  If the root document contains a frameset, the driver automatically focuses on the first frame in the set.  This is only done for the root document - if the first frame is itself another frameset, the driver does not switch again.  When you switch back to the default content, this auto-frameset check is performed again.  As a side effect, there is no way to ever focus on the frameset itself (if, for whatever reason you wanted to verify something on that page).

The next area of ambiguous behavior is when switching to a frame using a string, where paths to child frames can be specified using "." as a delimiter.  Consider the following:

<iframe id="foo"></iframe>
<iframe name="foo">
<iframe>
    <iframe name="baz"></iframe>
</iframe>
    <iframe name="0" id="bar">
        <iframe name="baz"></iframe>
    </iframe>
</iframe>
<iframe name="foo.bar">
    <iframe name="baz"></iframe>
</iframe>
<iframe name="foo.0.baz"></iframe>
<iframe name="foo.bar.baz"></iframe>

driver.switchTo().frame("foo");
driver.switchTo().frame("foo.bar");
driver.switchTo().frame("baz");
driver.switchTo().frame("foo.0.baz");
driver.switchTo().frame("foo.bar.baz");

In this situation, what should the driver do?
------------------------------------

This vague behavior is especially jarring considering the rest of the API is all very clear.  Accordingly, I'd like to make the following changes:

- The default content is *always* the root document.  If you open a frameset, you must explicitly switch to one of the frames on the page.

- When switching frames, the driver always searches in the currently selected frame and it only accepts exact matches.  Switching to a nested frame would require multiple switchTo().frame() commands.

- As a bonus change, we add the ability to switch to a frame using a WebElement.  Example:

WebElement frameContainer = driver.findElement(By.id("my-frame-container"));
WebElement frame = frameContainer.findElement(By.xpath(".//iframe[1]"));
driver.switchTo().frame(frame);

Except for the last item, which is an API addition, none of this requires modifying the API or wire protocol.  There is still a significant change in behavior and could cause a lot of tests to start failing.  Still, I think it's a worthy change to make and will avoid a lot of potential confusion + bugs in the long run.

Simon Stewart

unread,
Jul 5, 2010, 11:19:00 AM7/5/10
to selenium-...@googlegroups.com
+1. Clarity is a Good Thing, and we should take opportunities to
improve the usability of the API where we can. I suspect that there
are others on this list who like this change too.

Simon

> --
> You received this message because you are subscribed to the Google Groups
> "Selenium Developers" group.
> To post to this group, send email to selenium-...@googlegroups.com.
> To unsubscribe from this group, send email to
> selenium-develo...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/selenium-developers?hl=en.
>

Adam Goucher

unread,
Jul 5, 2010, 11:20:11 AM7/5/10
to selenium-...@googlegroups.com


- When switching frames, the driver always searches in the currently selected frame and it only accepts exact matches.  Switching to a nested frame would require multiple switchTo().frame() commands.

Could you give an example of this? I'm working with one client right now that has lots of frames and the ability to specify a deeply nested frame using driver.switchTo().frame("foo.bar.baz"); is nice.

Would it be

driver.switchTo().frame("foo").frame("bar").frame("baz");

or

driver.switchTo().switchTo().frame("foo").switchTo().frame("bar").switchTo().frame("baz");

Or something else. Neither is all that elegant I think.

-adam

Jari Bakken

unread,
Jul 5, 2010, 11:21:47 AM7/5/10
to selenium-...@googlegroups.com
Sounds great. Especially the ability to switch to a frame using a
WebElement, which should make the mapping to Watir's Frame API easier
for watir-webdriver.

Daniel Wagner-Hall

unread,
Jul 5, 2010, 11:42:37 AM7/5/10
to selenium-...@googlegroups.com

+1

Also, can we clear up the confusion of IDs, names and indices? If
we're getting rid of .s, an int argument can be an index and string
arguments can *never* be treated as indices, but switching by string
accepting either name or ID is another area of ambiguity...

Jason Leyba

unread,
Jul 5, 2010, 3:01:26 PM7/5/10
to selenium-...@googlegroups.com

On Mon, Jul 5, 2010 at 8:20 AM, Adam Goucher <ad...@goucher.ca> wrote:


- When switching frames, the driver always searches in the currently selected frame and it only accepts exact matches.  Switching to a nested frame would require multiple switchTo().frame() commands.

Could you give an example of this? I'm working with one client right now that has lots of frames and the ability to specify a deeply nested frame using driver.switchTo().frame("foo.bar.baz"); is nice.

<html>                   // DefaultContent
  <iframe id="foo">        // A
    <iframe id="bar"/>     // B
  </iframe>
  <iframe id="bar"/>       // C
  <iframe id="baz"/>       // D

// Starting at DefaultContent
driver.switchTo().frame("foo")      // At A
      .switchTo().frame("bar")      // At B
      .switchTo().frame("baz");     // NoSuchFrameException

driver.switchTo().defaultContent()  // At DefaultContent
      .switchTo().frame("bar");     // At C

driver.switchTo().defaultContent()  // At DefaultContent
      .switchTo().frame("baz");     // At D


Would it be

driver.switchTo().frame("foo").frame("bar").frame("baz");

or

driver.switchTo().switchTo().frame("foo").switchTo().frame("bar").switchTo().frame("baz");

Or something else. Neither is all that elegant I think.

I'd vote for the second, as it doesn't require an API change.  There may be a more elegant solution, but it's still very readable (if you chain the calls on multiple lines), and you could extract it to a helper function too.

driver.switchTo().frame("foo")
      .switchTo().frame("bar")
      .switchTo().frame("baz");
 

-adam

Jason Leyba

unread,
Jul 5, 2010, 3:09:39 PM7/5/10
to selenium-...@googlegroups.com
+1 to strings being name/ID (and number for indices).  It's still a bit ambiguous, but I think its manageable (as long as we standardize on name over id or vice-versa).  I'd wager most users will adopt switching-by-WebElement if we add that.

Daniel Wagner-Hall

unread,
Jul 5, 2010, 3:20:59 PM7/5/10
to selenium-developers

Michael Tamm has been working on making frame-switching chainable [1]
which was originally going to be
driver.switchTo().frame("foo").frame("bar") and I presume hasn't been
made so yet because it hasn't been implemented across all drivers, and
it's an API change. It certainly looks a lot nicer, and I imagine in
5 years it will be an annoying part of the API not to have changed...

1: https://code.google.com/p/selenium/issues/detail?id=299

Michael Tamm

unread,
Jul 6, 2010, 5:57:31 PM7/6/10
to selenium-...@googlegroups.com
Yeah, I was struggeling with the same problem Jason mentioned in his first post,
but I did not dare to change API.

Nevertheless it would make things easier and more straight forward,
if we change the current frame handling in all drivers as Jason mentioned.

But, I still think backward compatibility is a good thing and I would like
to fall back to the current behaviour whenever we do not find a frame
from inside the current document/frame.

I guess the best thing to get started would be a couple of unit tests,
which we can all agree on, how WebDriver should behave. Maybe the
HTML in Jasons first post is a good starting point for testing the
tricky edge cases ...

Reagrds, Michael 

2010/7/5 Daniel Wagner-Hall <dawa...@gmail.com>
Reply all
Reply to author
Forward
0 new messages