Handling InnerFrames with Selenium

后端 未结 1 854
无人及你
无人及你 2021-01-25 02:28

I have to test an \"old fashioned\" web application which uses inner frames.Just like:


....



        
相关标签:
1条回答
  • 2021-01-25 02:48

    No, there isn't.

    In fact, handling iframe elements with Selenium is very tricky.

    You have three options for switching into a frame:

    1. Using its index (0, 1, ..., N-1)
    2. Using its name or ID (as you did in the example above)
    3. Using a WebElement object that you obtain from the DOM

    But you have only one option for switching out:

    1. driver.switchTo().defaultContent()

    And once you've switched out of a frame, you in fact switched out "all the way up".

    So if you thought you were recursing the frames with a simple DFS, it is most likely you were wrong.

    The way I found to do it is by "leaving bread crumbs". In other words, before switching into a frame, I "memorize" the entire path from the root of the DOM to that frame.

    After switching out, because I'm "back in the root", I perform the entire path to the frame (except for switching into that frame of course), and then continue to the frame next to it.

    Be aware that once you've switched into a frame, all previous WebElement objects you were storing have become "stale", so you would have to find them again after switching out.

    P.S.: I found that almost all websites store advertisements inside iframe tags, so I doubt it's an "old fashion" thing.

    Anyway, here is the code that I used (in Java):

    private void searchFrames(List<Integer> route)
    {
        doWhateverYouWannaDoHere();
        if (route.size() < MAX_DEPTH)
        {
            int numOfFrames = webDriver.findElements(By.tagName("iframe")).size();
            for (int i=0; i<numOfFrames; i++)
            {
                try
                {
                    webDriver.switchTo().frame(i);
                    List<Integer> newRoute = new ArrayList<Integer>(route);
                    newRoute.add(i);
                    searchFrames(newRoute);
                    webDriver.switchTo().defaultContent();
                    for (int j : route)
                        webDriver.switchTo().frame(j);
                }
                catch (NoSuchFrameException error)
                {
                    break;
                }
                catch (Exception error)
                {
                }
            }
        }
    }
    

    In order to start the procedure, call searchFrames(new ArrayList<Integer>()).

    Hope it helps...

    UPDATE:

    This method performs the desired action not only inside each frame, but also in the DOM itself. If you want to avoid the DOM itself, then move the call to method 'doWhateverYouWannaDoHere' after the first line in the try clause, i.e., after webDriver.switchTo().frame(i).

    0 讨论(0)
提交回复
热议问题