Как щелкнуть ссылку внутри iframe, который находится внутри фрейма, с помощью Selenium Webdriver и Java - PullRequest
1 голос
/ 17 июня 2020

Я пытался автоматизировать несколько проверок вручную, используя огурец и селен , и пытался создать событие щелчка по пункту меню внутри iframe. Ниже приведен скелет источника.

<html>
<head>...</head>
<frameset rows="100%,*" border="0">
    <frame src="/XXXX/index.dsp" cd_frame_id_="03af6e390xxxxxxxxx0b209e24f67b9fab">
        <html>
            <body>  
                <iframe class="menuframe" name="menu" src="menu.dsp" scrolling="yes" seamless="seamless">
                    <html>
                    <head>..</head>
                    <body class="menu"...........>
                        <table class="menuTable".............>
                            <tbody>                                         
                                <tr>......</tr>
                                <tr>......</tr>
                                <tr>......</tr>

                                <tr manualhide="true" onclick="toggle(this, 'XXX_subMenu', 'XXXX_twistie');" onmouseover="this.className='cursor';" class="cursor">
                                    <td class="menusection menusection-collapsed" id="elmt_XXXX_subMenu">
                                        <img id="XXXX_twistie" src="/XXXX/images/collapsed_blue.png">
                                          &nbsp;XXXX  
                                    </td>
                                </tr>
                                <tr>......</tr>
                                <tr>......</tr>
                            </tbody>
                    </body>
                </iframe>

                <iframe class="contentframe" name="body" id="body" src="stats-general.dsp">
                .............
                </iframe>

            </body>
        </html>
    </frame>
</frameset>

Я пытаюсь нажать на указанное выше с id elmt_XXXX_subMenu.

Как я читал в нескольких блогах, это требуется для переключения на фрейм. Я пробовал следующее.

driver.switchTo().defaultContent();
// switch to frame
driver.switchTo().frame(0); 

// switch to menu iframe, It throws an exception
driver.switchTo().frame("menu"); 

// When replaced by following line also it throws same exception
// driver.switchTo().frame(driver.findElement(By.name("menu")));

Ниже представлена ​​трассировка стека.

 org.openqa.selenium.JavascriptException: javascript error: Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'.
  (Session info: chrome=83.0.4103.97)
Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03'
System info: host: 'XXXX', ip: 'XX.XX.XXX.XXX', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '1.8.0_221'
Driver info: org.openqa.selenium.chrome.ChromeDriver
Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 83.0.4103.97, chrome: {chromedriverVersion: 83.0.4103.39 (ccbf011cb2d2b..., userDataDir: C:\Users\XXXXXX~1\AppData\L...}, goog:chromeOptions: {debuggerAddress: localhost:58320}, javascriptEnabled: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: WINDOWS, platformName: WINDOWS, proxy: Proxy(), setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify, webauthn:virtualAuthenticators: true}
Session ID: f2e850e3e43d7782902297879bc70bc4
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:187)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:122)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:49)
    at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158)
    at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)
    at org.openqa.selenium.remote.RemoteWebDriver$RemoteTargetLocator.frame(RemoteWebDriver.java:892)
    at XXX.XXXX.XXXX.pages.TestPage.test(TestPage.java:40)
    at XXX.XXXX.XXXX.stepdefinitions.TestSteps.test_method(TestSteps.java:137)
    at ?.Then Check menu(basicChecks.feature:12)

Пожалуйста, предложите, если это неправильный способ? Заранее большое спасибо.

Обновление: Согласно ответу @DebanjanB, Пробовал использовать предложенный фрагмент (как селектор css, так и xpath),

new WebDriverWait(driver, 10).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.cssSelector("frame[src*='index']")));
new WebDriverWait(driver, 10).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.cssSelector("iframe.menuframe[name='menu']")));
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.cssSelector("td.menusection.menusection-collapsed#elmt_XXXX_subMenu"))).click();

Выдает то же самое исключение в строке 2

org.openqa.selenium.JavascriptException: javascript error: Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'.
  (Session info: chrome=83.0.4103.97)
Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03'
System info: host: 'XXXX', ip: 'XX.XX.XXX.XXX', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '1.8.0_221'
Driver info: org.openqa.selenium.chrome.ChromeDriver
Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 83.0.4103.97, chrome: {chromedriverVersion: 83.0.4103.39 (ccbf011cb2d2b..., userDataDir: C:\Users\XXXXXX~1\AppData\L...}, goog:chromeOptions: {debuggerAddress: localhost:58320}, javascriptEnabled: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: WINDOWS, platformName: WINDOWS, proxy: Proxy(), setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify, webauthn:virtualAuthenticators: true}
Session ID: 79f14698ee49ff2f4308b7f7930ee8b1
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:187)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:122)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:49)
    at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158)
    at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)
    at org.openqa.selenium.remote.RemoteWebDriver$RemoteTargetLocator.frame(RemoteWebDriver.java:892)
    at org.openqa.selenium.support.ui.ExpectedConditions$17.apply(ExpectedConditions.java:501)
    at org.openqa.selenium.support.ui.ExpectedConditions$17.apply(ExpectedConditions.java:497)
    at org.openqa.selenium.support.ui.FluentWait.until(FluentWait.java:249)
    at XXX.XXXX.XXXX.pages.TestPage.test(TestPage.java:26)
    at XXX.XXXX.XXXX.stepdefinitions.TestSteps.test_method(TestSteps.java:137)
    at ?.Then Check menu(basicChecks.feature:12)

Ответы [ 3 ]

1 голос
/ 17 июня 2020

To click() в элементе внутри <iframe>, который находится внутри <frame>, поэтому вам необходимо:

  • Induce WebDriverWait для первого frameToBeAvailableAndSwitchToIt .
  • Induce WebDriverWait для второго frameToBeAvailableAndSwitchToIt .
  • Вы можете использовать любую из следующих Стратегий локатора :

    • Использование cssSelector :

      new WebDriverWait(driver, 10).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.cssSelector("frame[src*='index']")));
      new WebDriverWait(driver, 10).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.cssSelector("iframe.menuframe[name='menu']")));
      new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.cssSelector("td.menusection.menusection-collapsed#elmt_XXXX_subMenu"))).click();
      
    • Использование xpath :

      new WebDriverWait(driver, 10).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.xpath("//frame[contains(@src, 'index')]")));
      new WebDriverWait(driver, 10).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.xpath("//iframe[@class='menuframe' and @name='menu']")));
      new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("//td[@class='menusection menusection-collapsed' and @id='elmt_XXXX_subMenu']"))).click();
      

Примечание : В соответствии с текущим HTML вы предоставили следующее <iframe> выглядит закрытым, что может не соответствовать действительности:

<iframe class="menuframe" name="menu" src="menu.dsp" scrolling="yes" seamless="seamless"></iframe>

Ссылка

Вы можете найти пару соответствующих обсуждений в:

0 голосов
/ 19 июня 2020

Мне удалось заставить его работать, переключая контент по индексу. Использование System.out.println(driver.getPageSource()); для записи источника страницы на консоль и проверки того, что я работаю в нужном месте. Я попытался найти iframe по тегу и напечатать их имя следующим образом.

List<WebElement> elements = DriverContext.driver.findElements(By.tagName("iframe"));
elements.forEach(element -> System.out.println(element.getAttribute("name"))); // printed 'menu' and 'body', perfect

Но, переключая содержимое на iframe с использованием имени, я пытался также использовать WebDriverWait,

driver.switchTo().frame(driver.findElement(By.name("menu")));

по любой причине , это не сработало и продолжало генерировать исключение, как в вопросе.

Использование индекса для переключения на iframe с последующим щелчком по элементу сработало.

driver.switchTo().frame(0); // switch to frame
driver.switchTo().frame(0); // switch to first iframe

driver.findElement(By.id("elmt_XXXX_subMenu")).click();

Кроме того, я использовал WebDriver - дождитесь загрузки страницы.

WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(webDriver -> ((JavascriptExecutor) driver).executeScript("return document.readyState").toString().equals("complete"));
0 голосов
/ 17 июня 2020

.frame() используется для переключения элемента на iframe и принимает элемент в качестве параметра, поэтому вам нужно передать элемент туда. Кроме того, элемент с «0» не является типом iframe, поэтому вам не нужна строка кода driver.switchTo().frame(0).

Вам просто нужно переключить драйвер на menu iframe, а затем щелкнуть элемент.

Для перехода на menu iframe необходимо использовать:

driver.switchTo().frame(driver.findElement(By.name("menu"))); 
...