A Quick Frame-switching Trick

Back in my day (pre-AJAX, etc.)… a common design layout method was to use frames to load navigate around. And there are a lot of sites from that era still operating just fine behind corporate firewalls that haven’t been refreshed.

Nor should the be, really.

But this does pose a bit of a problem, well, more nuisance, when dealing with WebDriver since you have to switch context to a frame before it can be used. This means crawling through frames. A lot. Using Page Objects though, we can hide all of this chaos using something like this towards the top of your PO heirarchy.

def switch_to_frame(self, frame_name=None):
  if not frame_name:
    self.driver.switch_to_default_context()
    return

  if frame_name == "main_frame":
    self.switch_to_default_context()
    f = self.driver.find_element(By.CSS_SELECTOR, 'frame[name="main_frame"]')
    self.driver.switch_to_frame(f)
  elif frame_name == "top_frame":
    self.switch_to_frame('main_frame')
    f = self.driver.find_element(By.CSS_SELECTOR, 'frame[name="top_frame"]')
    self.driver.switch_to_frame(f)
  elif frame_name == "search_frame":
    self.switch_to_frame('main_frame')
    f = self.driver.find_element(By.CSS_SELECTOR, 'frame[name="search_frame"]')
    self.driver.switch_to_frame(f)
  else:
    raise UnknownFrameException('% is not a known frame.' % frame_name)

I’ve had to use this pattern a couple times recently and I employ it even if there is only one frame to switch to in the app since there is only one … until a second appears and its easier to add to an existing method than refactor a whole bunch of page objects.

Its also been pretty bomb-proof on Firefox, but I have one client where the level of nesting is pretty impressive and we can make it hang Chrome predictably. I suspect that is more due to a bug[s] in the chomedriver than anything else since doing the script manually works just fine.

Comments 4

  1. Brian wrote:

    We implemented this method, using very similar code to switch to iframes. Unfortunately, Selenium now seems to have a bug with holding on to the iframe context and is causing too many failures. Hope it gets fixed soon!

    See http://code.google.com/p/selenium/issues/detail?id=4876&sort=-opened&colspec=ID%20Stars%20Type%20Status%20Priority%20Milestone%20Owner%20Summary%20Opened

    Posted 03 Jan 2013 at 5:47 pm
  2. Michael Yang wrote:

    This trick is working only when the ‘name’ attribute is given for the frame, thus having high reliance on how the app is implemented. Many apps don’t have frame name available in some MVC frameworks.

    For a general approach, to switch to frames reliably by any elements (including the frame itself), you can create a chain of indexes for all frames in the page object, e.g. 0->1->1 switch to first frame and then second, and then second further. Building up the chain happens only once for each page object, so not much performance concerns. I’ve been adopting this approach against many pages that have several levels of nested frames. It switches quickly and is very robust.

    Posted 04 Jan 2013 at 11:14 am
  3. adam wrote:

    Well, this example uses ‘name’ — the reality is that it is dependent on the frame. In the real code some have name, some have xpath, some have css, etc.

    Posted 04 Jan 2013 at 11:22 am
  4. Michael Yang wrote:

    I see your point now.

    You are actually talking about the advantages brought by page object to switch to frames with one entry call. Agreed! I was concerning specifically about dealing with frames switch in general cases.

    Posted 04 Jan 2013 at 11:51 am

Post a Comment

Your email is never published nor shared. Required fields are marked *