org.openqa.selenium.StaleElementReferenceException: 元素未附加到页面文档

org.openqa.selenium.StaleElementReferenceException: element is not attached to the page document

我正在尝试测试 GeeksForGeeks UI。当我单击教程下拉菜单,然后单击 select 语言和 select Java,它链接到一个新页面并发生以下错误 org.openqa.selenium.StaleElementReferenceException。我该如何解决这个问题?我已经尝试了 Whosebug 中所有可能的解决方案。

public class SeleniumTest {

    public static WebDriver driver;

    @BeforeClass
    public static void setupClass() {
        System.setProperty("webdriver.chrome.driver", "driver/chromedriver.exe");
    }

    @Before
    public void setup() {
        driver = new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
    }

    @After
    public void after() {
        driver.close();
    }

    @Test
    public void testGeeksForGeeksR() throws InterruptedException {
        driver.get("https://www.geeksforgeeks.org/");
        WebElement tutorialsMenu = driver.findElement(By.className("header-main__list-item"));
        tutorialsMenu.click();
        List<WebElement> tutorialsList = tutorialsMenu.findElements(By.tagName("li"));
        for (WebElement li : tutorialsList) {
            if (li.getText().equals("Languages")) {
                li.click();
                List<WebElement> languages = driver.findElements(By.tagName("a"));
                for (WebElement a : languages) {
                    if (a.getText().equals("Java")) {
                        WebDriverWait wait = new WebDriverWait(driver, 20);
                        wait.until(ExpectedConditions.elementToBeClickable(a));
                        a.click();
                        WebElement title = driver.findElement(By.className("entry-title"));
                        assertEquals("Java Programming Language", title.getText());

                    }
                }
            }
        }
        Thread.sleep(6000);
    }

}

解决方案:

@Test
    public void testGeeksForGeeksR() throws InterruptedException {
        driver.get("https://www.geeksforgeeks.org/");
        WebElement tutorialsMenu = driver.findElement(By.className("header-main__list-item"));
        tutorialsMenu.click();
        List<WebElement> tutorialsList = tutorialsMenu.findElements(By.tagName("li"));
        WebElement javaLanguage = null;
        for (WebElement li : tutorialsList) {
            if (li.getText().equals("Languages")) {
                li.click();
                List<WebElement> languages = driver.findElements(By.tagName("a"));
                for (WebElement a : languages) {
                    if (a.getText().equals("Java")) {
                        javaLanguage = a;
                        break;
                    }
                }
            }
        }
        javaLanguage.click();
        driver.switchTo().activeElement();
        WebElement title = driver.findElement(By.className("entry-title"));
        assertEquals("Java Programming Language", title.getText());
        Thread.sleep(3000);
    }

单击带有 Java 文本的 a 元素后,将打开 Java Programming Language 页面。
此时所有上一页收集到的元素引用都变成了Stale.
通常,每个 Selenium WebElement 对象实际上是对物理 Web 元素对象的引用(指针)。
因此,当您打开另一个网页或刷新现有页面(在那里重新加载网络元素)时,对前一个网页上的网络元素的所有引用都不再有效。
在 Selenium 术语中,这种情况称为 Stale Element.
回到您的特定代码流。
看起来您的目标是打开 Java Programming Language 页面。如果是这样,您在这里所缺少的就是在该页面打开后退出循环并完成测试。
如果您希望继续从主页面的菜单中打开另一个教程,您将必须从您打开的内部页面返回,然后再次获取您希望在那里使用的所有元素。