Ошибка «Элемент принадлежит другому фрейму» при переключении на фрейм в Serenity BDD

У меня есть набор тестов, в котором использовался Thycidides/jbehave, и он работал нормально (хотя и против более старой версии FireFox, потому что разработка переключилась на Sernity BDD). Теперь я перешел на новый Serenity BDD (все еще jbehave) и обновил FireFox, но внезапно столкнулся с ошибкой при попытке переключиться на фрейм на определенной странице/тесте.

На нашем сайте МНОГО фреймов, но переключение фреймов работает на всех страницах/тестах, за исключением одной страницы/теста (который, похоже, имеет ту же структуру фреймов, что и другие рабочие тесты). Когда я пытаюсь переключиться на определенный фрейм (который, как я знаю, там есть), я получаю «Элемент принадлежит другому фрейму, чем текущий — переключитесь на содержащий его фрейм, чтобы использовать его» (и ссылку на stale_element_reference) (SerenityManagedException. detachedCopyOf), что не имеет особого смысла в том, что я пытаюсь сделать. Я написал некоторый альтернативный код, который запускал все кадры, чтобы убедиться, что кадр, на который я переключался, присутствует и есть.

"Базовая" структура фрейма:

<html>
    <head>      
    </head>
    <frameset cols="5,*" border="0" frameborder="no" framespacing="0">
        <frameset rows="145,*" border="0" frameborder="no" framespacing="0">
            <frame name="kalender" src="../calendar/Month.jsp" marginwidth="0" marginheight="0" noresize="" scrolling="no">
            <frame name="dagskalender" src="../calendar/NewTimeReg.jsp" marginwidth="10" marginheight="20" noresize="" scrolling="no">
        </frameset>
        <frameset rows="50,*,1" border="0" frameborder="NO" framespacing="0">
            <frameset cols="63,175,*,35" border="0" frameborder="NO" framespacing="0">
                <frame name="dagbund" src="Mail.jsp" marginwidth="0" marginheight="0" noresize="" scrolling="NO">
                <frame name="soeg" src="../search/main/Cont.jsp" marginwidth="0" marginheight="0" noresize="" scrolling="no">
                <frame name="topbar" src="TopBarMid.jsp" marginwidth="0" marginheight="0" noresize="" scrolling="no">
                <frame name="topbarende" src="TopBarRight.jsp" marginwidth="0" marginheight="0" noresize="" scrolling="no">
            </frameset>
            <frame name="main" src="../startpage/Fram.jsp?null" marginwidth="0" marginheight="0" noresize="">
            <frameset cols="33%,33%,33%,*" border="0" frameborder="NO" framespacing="0">
                <frame name="skjult" src="Blank.jsp" marginwidth="0" marginheight="0" noresize="" scrolling="no">
                <frame name="skjult2" src="Blank2.jsp" marginwidth="0" marginheight="0" noresize="" scrolling="no">
                <frame name="skjult3" src="Blank3.jsp" marginwidth="0" marginheight="0" noresize="" scrolling="no">
                <frame name="AppletLoader" src="" marginwidth="0" marginheight="0" noresize="" scrolling="no">
            </frameset>   
        </frameset>
    </frameset>   

</html>

Я пытаюсь переключиться на «основной» фрейм, поэтому я сначала переключаюсь на содержимое по умолчанию, а затем пытаюсь переключиться на «основной»

getDriver().switchTo().defaultContent();

String SAML = System.getProperty("login.user.saml").toString();
if(SAML.equalsIgnoreCase("false")) // some sites have a extra parent frame
{
    staticlogger.info( "Switching to 'system' frame..." );  
    getDriver().switchTo().frame("system"); //disable step if SAML-login
}       
staticlogger.info( "Switching to 'main' frame..." );
getDriver().switchTo().frame("main");   

staticlogger.info("Переключение на основной кадр..." ); является последним, который выполняется, поэтому он терпит неудачу в getDriver().switchTo().frame("main");

Приведенный ниже код находит «основной», что означает, что он должен присутствовать в активном фрейме и также переключаться, потому что findElements возвращается только из активного фрейма:

List<WebElement> ele = getDriver().findElements(By.tagName("frame"));
        for(WebElement el : ele)
        {
            staticlogger.info( "Frame: " + el.getAttribute("name") + " ID: " + el.getAttribute("id"));
            if(el.getAttribute("name").equalsIgnoreCase("main"))
            {
                staticlogger.info( "Switching to 'main' frame..." );    
                getDriver().switchTo().frame(el);
            }

        }

У кого-нибудь есть идея или обходной путь для решения этой ошибки? Невозможно опубликовать полный HTML-код сайтов, поскольку они содержат конфиденциальные данные/код.


person user2505096    schedule 25.05.2016    source источник
comment
Выдает ли ту же ошибку при переключении на имя фрейма = kalendar?   -  person Zeeshan Siddiqui    schedule 25.05.2016
comment
Я проверю это, но не думаю, потому что сайты с родительским фреймом «система» без проблем переключаются на этот фрейм перед переключением на неудавшийся «основной».   -  person user2505096    schedule 25.05.2016
comment
Я могу переключиться на кадр «календарь» без каких-либо исключений   -  person user2505096    schedule 25.05.2016
comment
Примечание: в альтернативном коде внизу я все еще получаю ту же ошибку в getDriver().switchTo().frame(el);   -  person user2505096    schedule 25.05.2016
comment
Иерархия наборов фреймов следующая... ‹frameset ROOT› ‹frameset A› ‹frame name=kalender› ‹frame name=dagskalender› ‹/frameset› ‹frameset B› ‹frameset B1› ‹frame name=dagbund› ‹frame name=soeg › ‹frame name=topbar› ‹frame name=topbarende› ‹/frameset› ‹frame name=main› ‹frameset B2› ‹frame name=skjult› ‹frame name=skjult2› ‹frame name=skjult3› ‹frame name=AppletLoader › ‹/frameset› ‹/frameset› ‹/frameset› Я думаю, вам следует последовательно переключаться с ROOT › B › main вместо переключения на ROOT › main.   -  person Zeeshan Siddiqui    schedule 25.05.2016
comment
Проблема может заключаться в том, что main находится на 2 уровня глубже корневого набора фреймов. Возможно, вы захотите переключиться на подродительский набор фреймов, поскольку switchTo работает только с непосредственными дочерними фреймами.   -  person Zeeshan Siddiqui    schedule 25.05.2016
comment
Если мне нужно сначала переключиться на наборы фреймов, просто странно, что это работает для других фреймов, таких как календарь, который также находится внутри наборов фреймов (и работает для того же кода в другом месте). Я не думаю, что набор фреймов считается уровнем для селена как таковым. Это не просто контейнер?   -  person user2505096    schedule 26.05.2016


Ответы (1)


Я нашел обходной путь

После долгих проб и ошибок я нашел следующие проблемы и обходные пути:

  1. Исключение переключения кадров на самом деле является StaleElementReferenceException, поэтому сообщение об ошибке «Элемент принадлежит другому кадру, отличному от текущего — переключитесь на содержащий его кадр, чтобы использовать его» вводит в заблуждение.

  2. Если я проигнорирую исключение, а не сломаю его, я смогу получить доступ к элементам внутри фрейма, как и хотел. Похоже, он переключился на «основной» кадр независимо от исключения

  3. После игнорирования исключения я получил новую ошибку при попытке отправить ключи элементу внутри фрейма. Исключением является 'Permission denied to access property "__raven__"' Из того, что я мог найти в Google, кажется, что это исключение может быть связано с jQuery, но у меня есть serenity.jquery.integration=false в serenity.properties.

  4. Еще раз я мог бы продолжить тест, игнорируя исключение, и желаемое значение sendKeys все еще вводится в поле, вызвавшее исключение.

  5. После пропуска первой ошибки __raven__ я получаю еще одну позже (между двумя ошибками - использование sendKey/findElement, которое не вызывает исключения) при использовании findElements, которые я также могу обойти, игнорируя ошибку.

Кто-нибудь знает, почему возникают эти 2 исключения?

Хотя тест теперь работает, это довольно грязный способ его проведения, поэтому хотелось бы, чтобы проблемы были решены, если это возможно.

Новый код для "рабочего" переключателя кадров:

String SAML = System.getProperty("login.user.saml").toString();

  getDriver().switchTo().defaultContent();

  if(SAML.equalsIgnoreCase("false"))


  {

   staticlogger.info( "Switching to 'system' frame..." ); 

   getDriver().switchTo().frame("system"); //disable step if SAML-login

  }  

  staticlogger.info( "Switching to 'main' frame..." );

  getDriver().manage().timeouts().implicitlyWait( 2, TimeUnit.SECONDS );

  try

  {

   getDriver().switchTo().frame("main"); 

  }

  catch ( StaleElementReferenceException ser ) 

  {      

     staticlogger.info( "WARNING: Stale 'main' frame");      

  } 

  catch ( NoSuchFrameException nsf ) 

  {      

     staticlogger.info( "ERROR: No 'main' frame found");             



  } catch ( Exception e ) 

  {

      staticlogger.info( "ERROR: " + e.getMessage() );

  }

  getDriver().manage().timeouts().implicitlyWait( DEFAULT_IMPLICIT_WAIT, TimeUnit.SECONDS );


  staticlogger.info( "Done switching to 'main' frame..." );

Workaround for __raven__

long startTime = System.currentTimeMillis();

driver.manage().timeouts().implicitlyWait( 250, TimeUnit.MILLISECONDS );

WebElement we = null;

boolean unfound = true;

int tries = 0;

while ( unfound && tries < 8 ) {

  tries += 1;

  try {

    we = driver.findElement( locator );

    unfound = false; // FOUND IT

  } catch ( StaleElementReferenceException ser ) {      

    staticlogger.info( "Try [" + tries + "] - ERROR: Stale element. " + locator.toString() );

    unfound = true;

  } catch ( NoSuchElementException nse ) {      

    staticlogger.info( "Try [" + tries + "] - ERROR: No such element. " + locator.toString() );

    unfound = true;

  } catch ( Exception e ) {

    staticlogger.info( "Try [" + tries + "] - " + e.getMessage() );

  }

} 

long endTime = System.currentTimeMillis();

long totalTime = endTime - startTime;

if (we != null)   

 staticlogger.info("Try [" + tries + "] - Found element after " + totalTime + " milliseconds.");

else    

 staticlogger.info("Element NOT found after looking for " + totalTime + " milliseconds.");     

driver.manage().timeouts().implicitlyWait( DEFAULT_IMPLICIT_WAIT, TimeUnit.SECONDS );
return we;
person user2505096    schedule 27.05.2016