调整浏览器窗口大小(Chrome)后无法从元素获取文本

时间:2019-06-10 13:51:09

标签: java selenium webdriver resize window

  1. 在Chrome中加载网址https://sfo-demo.herokuapp.com/model-portfolio
  2. 能够看到2个标签(3个根据您的偏好设置的投资组合建议 和15种其他投资组合可供选择)
  3. 在这两个元素上执行的Gettext获取相同的文本(显示)
  4. 将窗口调整为667、375 (d.manage()。window()。setSize(new Dimension(667,375));)
  5. 这两个标签的文本已更改。现在,在这两个元素上执行的gettext()不会获取任何文本

3 个答案:

答案 0 :(得分:1)

调整大小 667, 375 的窗口时,您看到的元素来自移动视图,并且位于不同的位置在DOM Tree中。因此,您需要使用其他Locator Strategy,如下所示:

  • 代码块:

    ChromeOptions chromeOptions = new ChromeOptions();
    chromeOptions.addArguments("start-maximized");
    chromeOptions.addArguments("disable-infobars");
    chromeOptions.addArguments("--disable-extensions"); 
    WebDriver driver = new ChromeDriver(chromeOptions); 
    driver.get("https://sfo-demo.herokuapp.com/model-portfolio");
    System.out.println("Elements in list with full screen:");
    System.out.println(new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("ul.model-portfolio-navs.hidden-sm.hidden-xs a"))).stream().map(element->element.getAttribute("innerHTML")).collect(Collectors.toList()));
    driver.manage().window().setSize(new Dimension(667, 375));
    System.out.println("Elements in list with window resized:");
    System.out.println(new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("ul.model-portfolio-navs.mobile.hidden-md.hidden-lg a"))).stream().map(element->element.getAttribute("innerHTML")).collect(Collectors.toList()));
    
  • 控制台输出:

    Elements in list with full screen:
    [
                3 Portfolio recommendations based on your preferences
              , 
                15 other portfolio choices available
              ]
    Elements in list with window resized:
    [Recommended (3), Others (15)]
    

答案 1 :(得分:1)

调整窗口大小时,DOM元素会过时,您需要再执行一次WebDriver.findElements()函数来获取更新的元素。

您可以在两种情况下使用相同的XPath locator来实现兼容性。

示例代码:

ChromeDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get("https://sfo-demo.herokuapp.com/model-portfolio");

List<String> textBeforeResize = driver.findElements(By.xpath("//a[@data-toggle='tab']"))
        .stream()
        .map(WebElement::getText)
        .collect(Collectors.toList());

System.out.println("Before:");
textBeforeResize.forEach(System.out::println);

driver.manage().window().setSize(new Dimension(667, 375));

System.out.println("After:");
List<String> textAfterResize = driver.findElements(By.xpath("//a[@data-toggle='tab']"))
        .stream()
        .map(WebElement::getText)
        .collect(Collectors.toList());

textAfterResize.forEach(System.out::println);

演示:

enter image description here

答案 2 :(得分:0)

同意以上两个答案。使用绝对xpath定位不同的元素位置:

package arun;

import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import webdriverFactoryPatternUsingSupplier.*;

public class Q56527756 {

    WebDriver driver = DriverFactory.getDriver(DriverType.CHROME);

    @Test
    public void demo() throws InterruptedException {

        driver.get("https://sfo-demo.herokuapp.com/model-portfolio");
        clickableByXpath("//*[@id=\"page-top\"]/div[3]/div[1]/nav/div[1]/a/img", 5);

        WebElement no1 = byXpath("//*[@id=\"page-top\"]/div[3]/section/div[2]/div[3]/ul[1]/li[1]/a");
        WebElement no2 = byXpath("//*[@id=\"page-top\"]/div[3]/section/div[2]/div[3]/ul[1]/li[2]/a");

        String firstElementFirstTry = no1.getText();
        String secondElementFirstTry = no2.getText();
        System.out.println(firstElementFirstTry);
        System.out.println(secondElementFirstTry);

        driver.manage().window().setSize(new Dimension(667, 375));

        // there are elementes fitting to no1's and no'2 xpath, but those are not the same, have no text

        // after resize your two elements are moved in 'ul' level
        WebElement no3 = byXpath("//*[@id=\"page-top\"]/div[3]/section/div[2]/div[3]/ul[2]/li[1]/a");
        WebElement no4 = byXpath("//*[@id=\"page-top\"]/div[3]/section/div[2]/div[3]/ul[2]/li[2]/a");

        String firstElementSecondTry = no3.getText();
        String secondElementSecondTry = no4.getText();
        System.out.println(firstElementSecondTry);
        System.out.println(secondElementSecondTry);

        driver.close();
        driver.quit();

    }

    // custom wait method
    public WebDriverWait waitSec(WebDriver driver, int sec) {
        return new WebDriverWait(driver, sec);
    } 

    public WebElement byXpath(String xpath) {
        WebElement element = driver.findElement(By.xpath(xpath));
        return element;
    }    

    public WebElement clickableByXpath(String xpath, int sec) {
           WebElement element = waitSec(driver, sec).until(ExpectedConditions.elementToBeClickable(By.xpath(xpath)));
           return element;
    }

}

输出:

Starting ChromeDriver 74.0.3729.6 (255758eccf3d244491b8a1317aa76e1ce10d57e9-refs/branch-heads/3729@{#29}) on port 15890
Only local connections are allowed.
Please protect ports used by ChromeDriver and related test frameworks to prevent access by malicious code.
[1560178038.495][WARNING]: This version of ChromeDriver has not been tested with Chrome version 75.
Čer 10, 2019 4:47:19 ODP. org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: OSS
3 Portfolio recommendations based on your preferences
15 other portfolio choices available
Recommended (3)
Others (15)

还有工厂,如果您想自己尝试(只需编辑路径):

package webdriverFactoryPatternUsingSupplier;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.openqa.selenium.firefox.internal.ProfilesIni;

public class DriverFactory {

    private static final Map<DriverType, Supplier<WebDriver>> driverMap = new HashMap<>();

    public static String chromedriverPath = "C:\\Users\\pburgr\\Desktop\\selenium-tests\\GCH_driver\\chromedriver.exe";
    public static String chromeProfilePath = "C:\\Users\\pburgr\\AppData\\Local\\Google\\Chrome\\User Data";

    public static String geckodriverPath = "C:\\Users\\pburgr\\Desktop\\selenium-tests\\FF_driver_0_23\\geckodriver.exe";

    public static WebDriver driver;

    //chrome driver supplier
    private static final Supplier<WebDriver> chromeDriverSupplier = () -> {

        System.setProperty("webdriver.chrome.driver", chromedriverPath);
        ChromeOptions options = new ChromeOptions();
        options.addArguments("user-data-dir=" + chromeProfilePath);
        driver = new ChromeDriver(options);
        driver.manage().window().maximize();
        System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
        return driver;
    };

    //firefox driver supplier
    private static final Supplier<WebDriver> firefoxDriverSupplier = () -> {

        FirefoxOptions options = new FirefoxOptions();
        ProfilesIni allProfiles = new ProfilesIni();         
        FirefoxProfile selenium_profile = allProfiles.getProfile("selenium_profile");
        options.setProfile(selenium_profile);
        options.setBinary("C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe");
        System.setProperty("webdriver.gecko.driver", geckodriverPath);
        driver = new FirefoxDriver(options);
        driver.manage().window().maximize();
        return driver;
    };

    //add more suppliers here

    //add all the drivers into a map
    static{
        driverMap.put(DriverType.CHROME, chromeDriverSupplier);
        driverMap.put(DriverType.FIREFOX, firefoxDriverSupplier);
    }

    //return a new driver from the map
    public static final WebDriver getDriver(DriverType type){
        return driverMap.get(type).get();
    }

}

和枚举:

package webdriverFactoryPatternUsingSupplier;

    public enum DriverType {
        CHROME,
        FIREFOX,
        // SAFARI,  not implemented
        // IE;      not implemented
    }