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.