Selenium подождите, пока он не станет активным, но все еще не доступен - PullRequest
0 голосов
/ 11 июля 2020

Я пишу программу, использующую Selenium в Java для очистки веб-сайта (я бы поделился веб-сайтом, но вам нужна учетная запись, поэтому я не думаю, что это будет полезно). Я использую драйвер chrome. Я застреваю, пытаясь понять, как нажать кнопку «Выполнить сейчас» на странице (фрагмент кода html ниже). Selenium жалуется, что кнопка не нажимается, хотя я явно жду, пока кнопка не станет активной.

Вот мой код:

public String getReport() {
    wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//*[@id='QTF_AdminTab']/a")));
    driver.get("theurl");
    wait.until(ExpectedConditions.urlToBe("theurl"));

    String oldtab = driver.getWindowHandle();
    wait.until(ExpectedConditions.elementToBeClickable(By.xpath("/html/body/div[1]/div[2]/div/div[1]/div/div/div[1]/div[4]/button[@class='_widget-form-run mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--primary']/span")));
    driver.findElement(By.xpath("/html/body/div[1]/div[2]/div/div[1]/div/div/div[1]/div[4]/button[@class='_widget-form-run mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--primary']/span")).click();
    //... I don't think the rest is relevant since the above line (line 114 in the log) is the one causing the trouble 
}

Мой xpath поднимается до , так как Оператор журнала говорит что-то, на что нужно щелкнуть. Если я удалю span из xpath, ничего не изменится.

Вот журнал:

Starting ChromeDriver 83.0.4103.39 (ccbf011cb2d2b19b506d844400483861342c20cd-refs/branch-heads/4103@{#416}) on port 41202
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
Jul 10, 2020 5:36:00 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: W3C
Exception in thread "main" org.openqa.selenium.ElementClickInterceptedException: element click intercepted: Element <span class="mdl-button__ripple-container">...</span> is not 
clickable at point (796, 183). Other element would receive the click: <span class="mdl-button__ripple-container">...</span>
  (Session info: chrome=83.0.4103.116)
Build info: version: '4.0.0-alpha-6', revision: '5f43a29cfc'
System info: host: '______', ip: '_______', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '11.0.7'
Driver info: org.openqa.selenium.chrome.ChromeDriver
Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 83.0.4103.116, chrome: {chromedriverVersion: 83.0.4103.39 (ccbf011cb2d2b..., userDataDir: C:\Users\______\AppData\Loca...}, goog:chromeOptions: {debuggerAddress: localhost:56109}, 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: e2b8ff1a23cd9b0932c00af2b1ffd2b5
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
        at org.openqa.selenium.remote.codec.w3c.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:196)
        at org.openqa.selenium.remote.codec.w3c.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:129)
        at org.openqa.selenium.remote.codec.w3c.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:53)
        at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:160)
        at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83)
        at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:582)
        at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:316)
        at org.openqa.selenium.remote.RemoteWebElement.click(RemoteWebElement.java:85)
        at reliant.abusescanner.PCCclient.getReport(PCCclient.java:114)
        at reliant.abusescanner.Main.main(Main.java:72)

Вот код html для кнопки:

<div class="flex-actions">
                <button class="_widget-form-run mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--primary" data-upgraded=",MaterialButton,MaterialRipple">Run now<span class="mdl-button__ripple-container"><span class="mdl-ripple"></span></span></button>
                <!--<button class="_component-save mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--secondary" style="display:none">Save</button>-->
                <button class="_component-saveAs mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--secondary" style="" data-upgraded=",MaterialButton,MaterialRipple">Save As<span class="mdl-button__ripple-container"><span class="mdl-ripple"></span></span></button>
                <!--<button class="_component-delete mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--secondary" disabled>Delete</button>-->

                <button class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--secondary configMenuBtn" id="demo-menu-lower-right" data-upgraded=",MaterialButton,MaterialRipple">
                    More Actions <i class="material-icons configMenuList">arrow_drop_down</i>
                <span class="mdl-button__ripple-container"><span class="mdl-ripple"></span></span></button>
                <div class="mdl-menu__container is-upgraded"><div class="mdl-menu__outline mdl-menu--bottom-right"></div><ul class="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect mdl-js-ripple-effect--ignore-events" for="demo-menu-lower-right" data-upgraded=",MaterialMenu,MaterialRipple">
                    
                    <li class="mdl-menu__item _component-save mdl-js-ripple-effect" tabindex="-1" data-upgraded=",MaterialRipple" style="display: none;">Save<span class="mdl-menu__item-ripple-container"><span class="mdl-ripple"></span></span></li>
                    <li disabled="disabled" class="mdl-menu__item _component-delete mdl-js-ripple-effect" tabindex="-1" data-upgraded=",MaterialRipple">Delete<span class="mdl-menu__item-ripple-container"><span class="mdl-ripple"></span></span></li>
                </ul></div>
            </div>

Вот гораздо больший сегмент кода html (который включает вышеперечисленное), на случай, если это поможет вам ответить на вопрос:

<div class="mdl-body">
    <div class="onboarding-report-section">
        Reduce the time it takes to setup and run a report.
        <a href="#" class="_onboarding-report-setup-details">Click here to learn more</a>
    </div>
    
    <h1>24 Hour Summary Report</h1>
    <div class="_form"><div class="_widget-root mdl-form">
        
            <div class="_widget-section mdl-form-section">
                <div class="_widget-fields"><div class="_form-field-save_config mdl-field saveConfigurationComponent">
        <div class="mdl-field-input">
            <div class="mdl-form-label flex-label">My saved settings</div>
            <div class="_publishOverlayPlaceholder"></div>
            <div class="_component-dropdown flex-dropdown"><span class="_catalyst-flyoutList-select dropdown-anchor-input " tabindex="0" style="width:300px;">
        <span class="dropdown-legend"></span>
        <span class="dropdown-label">
            
                    
                        
                            Unsaved
                            
                        
                    
                    
                    
            
        </span>
        <i class="material-icons dropdown-arrow">arrow_drop_down</i>
    </span></div>
            <div class="flex-actions">
                <button class="_widget-form-run mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--primary" data-upgraded=",MaterialButton,MaterialRipple">Run now<span class="mdl-button__ripple-container"><span class="mdl-ripple"></span></span></button>
                <!--<button class="_component-save mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--secondary" style="display:none">Save</button>-->
                <button class="_component-saveAs mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--secondary" style="" data-upgraded=",MaterialButton,MaterialRipple">Save As<span class="mdl-button__ripple-container"><span class="mdl-ripple"></span></span></button>
                <!--<button class="_component-delete mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--secondary" disabled>Delete</button>-->

                <button class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--secondary configMenuBtn" id="demo-menu-lower-right" data-upgraded=",MaterialButton,MaterialRipple">
                    More Actions <i class="material-icons configMenuList">arrow_drop_down</i>
                <span class="mdl-button__ripple-container"><span class="mdl-ripple"></span></span></button>
                <div class="mdl-menu__container is-upgraded"><div class="mdl-menu__outline mdl-menu--bottom-right"></div><ul class="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect mdl-js-ripple-effect--ignore-events" for="demo-menu-lower-right" data-upgraded=",MaterialMenu,MaterialRipple">
                    
                    <li class="mdl-menu__item _component-save mdl-js-ripple-effect" tabindex="-1" data-upgraded=",MaterialRipple" style="display: none;">Save<span class="mdl-menu__item-ripple-container"><span class="mdl-ripple"></span></span></li>
                    <li disabled="disabled" class="mdl-menu__item _component-delete mdl-js-ripple-effect" tabindex="-1" data-upgraded=",MaterialRipple">Delete<span class="mdl-menu__item-ripple-container"><span class="mdl-ripple"></span></span></li>
                </ul></div>
            </div>
        </div>
        <div class="_setting-instructions"></div>
        <div class="_component-field-error mdl-field-errors"></div>
    </div></div>
            </div>
        
            <div class="_widget-section mdl-form-section">
                <div class="_widget-fields"><div class="_form-field-dateEnding mdl-field">
        <div class="mdl-field-input datePickerComponent unSavedConfigField">
            <div class="mdl-field-header">
                <div class="mdl-form-label">Date (Ending)<span class="unSavedConfiglabelDisplay">(Date (Ending) won't be saved in the setting)</span></div>
                
             </div>
            <span class="_toggleRange" style="display: none;">From </span>
            <input class="_fromDate catalyst-datepicker" style="margin-right:25px;">
            <span class="_toggleRange" style="display: none;">
                To <input class="_toDate catalyst-datepicker">
            <input type="hidden" value="2020-07-10" name="end_date"></span>
        <input type="hidden" value="2020-07-10" name="start_date"></div>
        <div class="_component-field-error mdl-field-errors"></div>
    </div><div class="_form-field-unit mdl-field">
        <div class="mdl-field-input genericComponent">
         <div class="mdl-field-header">
            <div class="mdl-form-label">Unit</div>
            
         </div>
            
            <div class="_dropdown"><span class="_catalyst-flyoutList-select dropdown-anchor-input " tabindex="0" style="width:315px;">
        <span class="dropdown-legend"></span>
        <span class="dropdown-label">
            
                    
                        
                            All
                            
                        
                    
                    
                    
            
        </span>
        <i class="material-icons dropdown-arrow">arrow_drop_down</i>
    </span></div>
        </div>
        <div class="_component-field-error mdl-field-errors"></div>
    </div><div class="_form-field-floor mdl-field">
        <div class="mdl-field-input genericComponent">
         <div class="mdl-field-header">
            <div class="mdl-form-label">Floor</div>
            
         </div>
            
            <div class="_dropdown"><span class="_catalyst-flyoutList-select dropdown-anchor-input " tabindex="0" style="width:315px;">
        <span class="dropdown-legend"></span>
        <span class="dropdown-label">
            
                    
                        
                            All
                            
                        
                    
                    
                    
            
        </span>
        <i class="material-icons dropdown-arrow">arrow_drop_down</i>
    </span></div>
        </div>
        <div class="_component-field-error mdl-field-errors"></div>
    </div><div class="_form-field-timeEnding mdl-field">
        <div class="mdl-field-input hourMinuteTimeComponent">
            <div class="mdl-field-header">
                <div class="mdl-form-label">Ending Time</div>
            </div>
            <div class="_nestedContent">
                <div class="_nestedHours"><span class="_catalyst-flyoutList-select dropdown-anchor-input " tabindex="0" style="width:50px;">
        <span class="dropdown-legend"></span>
        <span class="dropdown-label">
            
                    
                        
                            13
                            
                        
                    
                    
                    
            
        </span>
        <i class="material-icons dropdown-arrow">arrow_drop_down</i>
    </span></div>
                <div class="_nestedMinutes"><span class="_catalyst-flyoutList-select dropdown-anchor-input " tabindex="0" style="width:50px;">
        <span class="dropdown-legend"></span>
        <span class="dropdown-label">
            
                    
                        
                            00
                            
                        
                    
                    
                    
            
        </span>
        <i class="material-icons dropdown-arrow">arrow_drop_down</i>
    </span></div>
            </div>
        </div>
        <div class="_component-field-error mdl-field-errors"></div>
    </div><div class="_form-field-summaryInterval mdl-field">
        <div class="catalyst-field-input">
            <div class="mdl-field-header">
                <div class="mdl-form-label">Summary Interval</div>
                
            </div>
            
            

            

            

            
                
                    
                        
                            <label class="_mdl-radio mdl-radio mdl-js-radio mdl-js-ripple-effect mdl-js-ripple-effect--ignore-events is-upgraded" for="formObj_summaryInterval_8" data-upgraded=",MaterialRadio,MaterialRipple">
        <input type="radio" class="mdl-radio__button" id="formObj_summaryInterval_8" name="summaryInterval" value="8">
        <span class="mdl-radio__label">Last 8 hours</span>
    <span class="mdl-radio__outer-circle"></span><span class="mdl-radio__inner-circle"></span><span class="mdl-radio__ripple-container mdl-js-ripple-effect mdl-ripple--center" data-upgraded=",MaterialRipple"><span class="mdl-ripple"></span></span></label>
                        
                    
                        
                            <label class="_mdl-radio mdl-radio mdl-js-radio mdl-js-ripple-effect mdl-js-ripple-effect--ignore-events is-upgraded is-checked" for="formObj_summaryInterval_24" data-upgraded=",MaterialRadio,MaterialRipple">
        <input type="radio" class="mdl-radio__button" id="formObj_summaryInterval_24" name="summaryInterval" value="24">
        <span class="mdl-radio__label">Last 24 hours</span>
    <span class="mdl-radio__outer-circle"></span><span class="mdl-radio__inner-circle"></span><span class="mdl-radio__ripple-container mdl-js-ripple-effect mdl-ripple--center" data-upgraded=",MaterialRipple"><span class="mdl-ripple"></span></span></label>
                        
                    
                        
                            <label class="_mdl-radio mdl-radio mdl-js-radio mdl-js-ripple-effect mdl-js-ripple-effect--ignore-events is-upgraded" for="formObj_summaryInterval_72" data-upgraded=",MaterialRadio,MaterialRipple">
        <input type="radio" class="mdl-radio__button" id="formObj_summaryInterval_72" name="summaryInterval" value="72">
        <span class="mdl-radio__label">Last 72 hours</span>
    <span class="mdl-radio__outer-circle"></span><span class="mdl-radio__inner-circle"></span><span class="mdl-radio__ripple-container mdl-js-ripple-effect mdl-ripple--center" data-upgraded=",MaterialRipple"><span class="mdl-ripple"></span></span></label>
                        
                    
                
            

        </div>
        <div class="_component-field-error mdl-field-errors"></div>
    </div><div class="_form-field-includeDraftProgressNotes mdl-field">
        <div class="catalyst-field-input">
            <div class="mdl-field-header">
                <div class="mdl-form-label">Include draft progress notes on report</div>
                
            </div>
            
            

            

            

            
                
                    
                        
                            <label class="_mdl-radio mdl-radio mdl-js-radio mdl-js-ripple-effect mdl-js-ripple-effect--ignore-events is-upgraded is-checked" for="formObj_includeDraftProgressNotes_true" data-upgraded=",MaterialRadio,MaterialRipple">
        <input type="radio" class="mdl-radio__button" id="formObj_includeDraftProgressNotes_true" name="includeDraftProgressNotes" value="true">
        <span class="mdl-radio__label">Yes</span>
    <span class="mdl-radio__outer-circle"></span><span class="mdl-radio__inner-circle"></span><span class="mdl-radio__ripple-container mdl-js-ripple-effect mdl-ripple--center" data-upgraded=",MaterialRipple"><span class="mdl-ripple"></span></span></label>
                        
                    
                        
                            <label class="_mdl-radio mdl-radio mdl-js-radio mdl-js-ripple-effect mdl-js-ripple-effect--ignore-events is-upgraded" for="formObj_includeDraftProgressNotes_false" data-upgraded=",MaterialRadio,MaterialRipple">
        <input type="radio" class="mdl-radio__button" id="formObj_includeDraftProgressNotes_false" name="includeDraftProgressNotes" value="false">
        <span class="mdl-radio__label">No</span>
    <span class="mdl-radio__outer-circle"></span><span class="mdl-radio__inner-circle"></span><span class="mdl-radio__ripple-container mdl-js-ripple-effect mdl-ripple--center" data-upgraded=",MaterialRipple"><span class="mdl-ripple"></span></span></label>
                        
                    
                
            

        </div>
        <div class="_component-field-error mdl-field-errors"></div>
    </div><div class="_form-field-sortBy mdl-field">
        <div class="catalyst-field-input">
            <div class="mdl-field-header">
                <div class="mdl-form-label">Sort Residents By</div>
                
            </div>
            
            

            

            

            
                
                    
                        
                            <label class="_mdl-radio mdl-radio mdl-js-radio mdl-js-ripple-effect mdl-js-ripple-effect--ignore-events is-upgraded" for="formObj_sortBy_-1" data-upgraded=",MaterialRadio,MaterialRipple">
        <input type="radio" class="mdl-radio__button" id="formObj_sortBy_-1" name="sortBy" value="-1">
        <span class="mdl-radio__label">Last Name</span>
    <span class="mdl-radio__outer-circle"></span><span class="mdl-radio__inner-circle"></span><span class="mdl-radio__ripple-container mdl-js-ripple-effect mdl-ripple--center" data-upgraded=",MaterialRipple"><span class="mdl-ripple"></span></span></label>
                        
                    
                        
                            <label class="_mdl-radio mdl-radio mdl-js-radio mdl-js-ripple-effect mdl-js-ripple-effect--ignore-events is-upgraded is-checked" for="formObj_sortBy_1" data-upgraded=",MaterialRadio,MaterialRipple">
        <input type="radio" class="mdl-radio__button" id="formObj_sortBy_1" name="sortBy" value="1">
        <span class="mdl-radio__label">Location</span>
    <span class="mdl-radio__outer-circle"></span><span class="mdl-radio__inner-circle"></span><span class="mdl-radio__ripple-container mdl-js-ripple-effect mdl-ripple--center" data-upgraded=",MaterialRipple"><span class="mdl-ripple"></span></span></label>
                        
                    
                
            

        </div>
        <div class="_component-field-error mdl-field-errors"></div>
    </div></div>
            </div>
        
    </div></div>
    <div class="_meadcoSection"></div>

</div>

Пожалуйста, дайте мне знать, если есть что-нибудь Я могу сделать, чтобы на этот вопрос было легче ответить. Заранее спасибо!

Edit: Я подверг цензуре некоторую личную информацию (с «____»). Надеюсь, все в порядке

Ответы [ 3 ]

1 голос
/ 11 июля 2020

Если вы посмотрите на метод elementToBeClickable(..), вы увидите, что «кликабельный» означает «видимый и активный».

Сообщение, которое вы видите, означает, что какой-то элемент перекрывает ваш целевой. Изменение XPath не поможет.

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

PS - wait.until(..) возвращает элемент, который был обнаружен условием, так что нет необходимости искать его снова. Вы можете сделать что-то вроде:

WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("/blah blah"));
1 голос
/ 14 июля 2020

Метод принимает веб-элемент в качестве параметра.

Список cccc = driver.findElements (By.xpath ("// div [contains (@ id, 'loadmask')]")) ;

Это проверяет, завершена ли загрузка какого-то JavaScript WebElement. Он сохраняет все элементы, которые, как говорилось в ошибке, получат щелчок, в моем случае в сообщении было что-то с loadmask. В вашем он будет около <span class="mdl-button__ripple-container">

boolean pageload = wait.until(ExpectedConditions.invisibilityOfAllElements(cccc));

Проверяет, невидим ли элемент списка cccc

if (pageload) {
            wait.until(ExpectedConditions.elementToBeClickable(element));
        }

// Если элемент не виден, он ждет, пока элемент, указанный в параметре, является кликабельным

Несколько шагов по устранению неполадок;

Вы можете приостановить ваш дом (Google it) до того, как ваш элемент будет нажат, и посмотреть, что происходит в ваших спецификациях c кейс. В моем случае виновником была эта маска загрузки элемента, которая была загружена JS, что привело к сбою моего теста. Итак, я вошел и остановил dom прямо перед моим фактическим щелчком и посмотрел, что происходит. Вы можете попробовать это и посмотреть, поможет ли это.

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

https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html

0 голосов
/ 11 июля 2020

Ожидание может быть сложным, просто для устранения неполадок используйте thread.sleep (15000) и посмотрите, доступен ли элемент для клика. когда у меня была аналогичная ошибка - другой элемент получал щелчок: это означало, что страница все еще загружалась, я решил свою проблему, реализовав эти два метода в зависимости от этой проблемы, однако я всегда мог щелкнуть элемент без них пользовательские методы с помощью thread.sleep (15000), поэтому я предлагаю сначала попробовать, чтобы выделить проблему, вот как выглядел мой метод ожидания:

publi c void isDisplayed (элемент WebElement) {попробуйте {

        WebDriverWait wait = new WebDriverWait(driver, 90);

        List<WebElement> cccc = driver.findElements(By.xpath("//div[contains(@id,'loadmask')]"));

        boolean pageload = wait.until(ExpectedConditions.invisibilityOfAllElements(cccc));

        // boolean pageload=
        // wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//div[contains(@id,'loadmask-')]")));

        System.out.println(a);
        if (pageload) {
            wait.until(ExpectedConditions.elementToBeClickable(element));
        }

    } catch (org.openqa.selenium.NoSuchElementException exception) {

    }
}

// второй метод

public void elementwaitClick(WebElement waitForelement) {

    WebDriverWait wait = new WebDriverWait(driver, 30);
    WebElement element = wait.until(ExpectedConditions.elementToBeClickable(waitForelement));
    element.click();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...