Selenium-Java-geckodriver:测试执行停止并出现 Java 脚本错误 "document.getElementById(...) is null"
Selenium-Java-geckodriver : Test Execution halts with JavaScript error as "document.getElementById(...) is null"
我遇到这个问题已经有一段时间了。浏览了 SO 和其他论坛上的很多主题,但仍然一无所知。
在 Eclipse Neon v2 IDE 中使用 Selenium 3.4.0、geckodriver v0.16.1 和 Mozilla Firefox 53.0 在 Web 应用程序上自动化简单流程时 IDE,我在控制台上间歇性地遇到错误,如下所示:
JavaScript error: https://www.url.com/my, line 1715: TypeError: document.getElementById(...) is null
尽管使用 chromedriver v2.29/Google Chrome 58.0 或使用 Python 我没有遇到任何此类问题。
一旦出现此错误,测试执行将停止并最终显示 TimeoutException
如下:
Exception in thread "main" org.openqa.selenium.TimeoutException: Timeout loading page after 300000ms
URL的网站是:https://www.shareinvestor.com/my
HTML DOM 是:
<div id="sic_sitemap">
<div id="sic_container">
<div id="sic_header">
<h1 id="sic_siteTitle">
<div id="sic_headerMembershipLink">
<a id="sic_mobileEdition" href="/mobile">
<div id="sic_loginContainer" class="sic_logIn" style="">
<div class="sic_login-wrap">
<div class="sic_logIn-subscribe">
<div class="sic_logIn-bg">
<a href="/user/login.html">
</div>
</div>
</div>
</div>
<div id="sic_subHeader">
<div id="sic_mainNav" class="sic_withRightCorner">
<div id="sic_sideBar" class="sic_expanded { selected_market_suffix: 'MY'}">
<div class="sic_superBanner sic_superBannerTop">
<div id="sic_content" class="sic_collapsed">
<div id="sic_footer" class="si_fixed">
</div>
截至目前,我已经尝试了以下选项但无济于事:
- Java 点击
- JavascriptExecutor 点击
- 点击操作
这是我的代码:
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.remote.DesiredCapabilities;
public class 78644072022 {
public static void main(String[] args) {
System.setProperty("webdriver.gecko.driver", "C:\Utility\BrowserDrivers\geckodriver.exe");
DesiredCapabilities dc = DesiredCapabilities.firefox();
dc.setCapability("marionette", true);
WebDriver driver = new FirefoxDriver(dc);
driver.manage().window().maximize();
driver.get("https://www.shareinvestor.com/my");
WebElement login_button = driver.findElement(By.xpath("//div[@id='sic_loginContainer']/div/div[@class='sic_logIn-bg']/a"));
//Java Click
login_button.click();
//JavascriptExecutor Click
/*JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript("arguments[0].click();", login_button);*/
//Actions Click
/*Actions act = new Actions(driver);
act.moveToElement(login_button).click().build().perform();*/
driver.findElement(By.xpath("//input[@id='sic_login_header_username']")).sendKeys("debanjan");
driver.findElement(By.xpath("//input[@id='sic_login_header_password']")).sendKeys("5786");
driver.findElement(By.xpath("//input[@id='sic_login_submit']")).click();
}
}
我正在寻找 Java geckodriver 的解决方案来克服错误 JavaScript error:TypeError: document.getElementById(...) is null
在其中一个 SO threads 中,我看到了这样的解决方案:
You need to do a null check in updateHTML like this:
function updateHTML(elmId, value) {
var elem = document.getElementById(elmId);
if(typeof elem !== 'undefined' && elem !== null) {
document.getElementById(elmId).innerHTML = value;
}
}
我们可以实现吗?
任何建议和指示都会有所帮助。
我想我已经设法在您的脚本中找到引起这种骚动的原因。
我检查了你的 HTML ,似乎 javascript 方法 function showRemaining()
导致了这个问题;因为 showRemaining()
包含此语句
document.getElementById('countdown').innerHTML = '';
它尝试将 id 为 countdown
的元素的 innerHTML 属性设置为 ''.
但是您网页上的任何地方都不存在倒计时,因此出现错误。
TypeError: document.getElementById(...) is null
不知何故,selenium 无法忽略此错误。所以我认为让开发人员修复它应该对你有所帮助。
更新:
基本上,您需要使用隐式等待等待所有元素加载,一旦所有元素都加载完毕,您的 Javascript 错误就会得到解决,最终与网页的交互不会受到 javascript 的阻碍错误:
driver.get("https://www.shareinvestor.com/my");
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.manage().window().maximize();
/*String script = "function updateHTML(countdown, value) {" +
"var elem = document.getElementById('countdown');"+
"if(typeof elem !== 'undefined' && elem !== null) {"+
" document.getElementById('countdown').innerHTML = value;"+
"}"+
"}";
((JavascriptExecutor) driver).executeScript(script);*/
WebElement login_button = driver.findElement(By.xpath("//div[@id='sic_loginContainer']/div/div[@class='sic_logIn-bg']/a"));
login_button.click();
driver.findElement(By.xpath("//input[@id='sic_login_header_username']")).sendKeys("debanjan");
driver.findElement(By.xpath("//input[@id='sic_login_header_password']")).sendKeys("5786");
driver.findElement(By.xpath("//input[@id='sic_login_submit']")).click();
login_button
的 XPath 似乎不正确:
By.xpath("//div[@id='sic_loginContainer']/div/div[@class='sic_logIn-bg']/a");
应该是:
By.xpath("//div[@id='sic_loginContainer']/div/div/div[@class='sic_logIn-bg']/a");
这可以解释 TimeoutException
,因为 Selenium 无法找到不存在的元素。 编辑:我的错误,你应该看到 NoSuchElementException
如果找不到元素。
至于 JavaScript 错误,除非您尝试使用 Selenium 访问由 JavaScript 代码(id='countdown'
元素)操作的 Web 元素,否则 Selenium 应该忽略错误。否则,可能会出现其他 Selenium 错误,例如 StaleElementReferenceException
,但情况似乎并非如此。
I am looking for a Java Solution with geckodriver to overcome the error JavaScript error:TypeError: document.getElementById(...) is null
为了回答您的问题,我认为您无法通过 Java/Selenium 对此 "fix" 做任何事情。这是一个 JavaScript 错误,源自您尝试访问的网站。您可能需要考虑 contacting 他们的支持团队,也许他们的开发人员之一可以查看此问题。
与其点击登录按钮,不如考虑直接导航到登录页面?
driver.get("https://www.shareinvestor.com/user/login.html");
首先,那些java脚本错误不会由于任何硒代码而触发。当然超时已经被selenium触发了(这个以后再说)
无论您使用何种浏览器启动 URL,您都会遇到 java 脚本错误。但是在壁虎的情况下,您会在 eclipse 控制台中收到通知,但在 Chrome 的情况下不会。如果您需要在 chrome 中查看 java 脚本错误,只需在 chrome 中启动 url 并转到 devtools/console(F12)。您也可以在 firefox 控制台中看到相同的内容。
- Chrome 图片:
其次,我们收到超时异常,因为该站点加载时间确实太长了。我已经等了 7 分钟,页面仍在加载中。除非页面已完全启动,否则 Selenium 不会执行其脚本。结果我们收到超时异常(不确定允许的默认页面启动时间)。我想直接绕过登录页面(“https://www.shareinvestor.com/user/login.html”),而且完全加载也不需要任何有限的时间。
Intepolation:那些 java 脚本错误不是自动化的问题,但那些页面加载确实是。此站点似乎不太适合自动化解决此问题。
Update1: 否则我们也可以通过另一个线程停止页面加载,例如使用 Action class.
发送 "esc" 键序列
Update2: 我今天尝试了同样的代码,它工作正常。下面是我试过的代码片段(完全没有变化)
public static void main(String[] args) throws InterruptedException
{
System.setProperty("webdriver.gecko.driver", "F:\Softwares\Selenium\Webdriver\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
driver.get("https://www.shareinvestor.com/my");
WebElement login_button = driver.findElement(By.xpath("//div[@id='sic_loginContainer']/div/div[@class='sic_logIn-bg']/a"));
//Java Click
login_button.click();
System.out.println("In Login PAge");
driver.findElement(By.xpath("//input[@id='sic_login_header_username']")).sendKeys("debanjan");
driver.findElement(By.xpath("//input[@id='sic_login_header_password']")).sendKeys("5786");
System.out.println("Entered password");
driver.findElement(By.xpath("//input[@id='sic_login_submit']")).click();
}
Selenium 版本 - 3.4.0
Gecko 驱动程序 - v0.16.1(我的是 32 位)
Mozilla - 51.0.1(更新=>也在 53.02 上运行)
希望对您有所帮助。谢谢
这是因为您的应用程序 HTML 页面使用了异步 javascript 并且它使用了一些在执行时不可用的变量引用。我们遇到了同样的问题,并要求开发人员在 HTML 中遵循 javascript 的一些最佳实践,例如将脚本标记放在页面末尾。我检查了站点的 HTML 页面源代码,它在代码之间包含许多脚本标记。这将阻止 DOM 渲染。更好的办法是让开发人员遵循一些最佳实践,在 HTML 中包含脚本标签。您参考 link Where should I put <script> tags in HTML markup? 以获得最佳实践。
我遇到这个问题已经有一段时间了。浏览了 SO 和其他论坛上的很多主题,但仍然一无所知。
在 Eclipse Neon v2 IDE 中使用 Selenium 3.4.0、geckodriver v0.16.1 和 Mozilla Firefox 53.0 在 Web 应用程序上自动化简单流程时 IDE,我在控制台上间歇性地遇到错误,如下所示:
JavaScript error: https://www.url.com/my, line 1715: TypeError: document.getElementById(...) is null
尽管使用 chromedriver v2.29/Google Chrome 58.0 或使用 Python 我没有遇到任何此类问题。
一旦出现此错误,测试执行将停止并最终显示 TimeoutException
如下:
Exception in thread "main" org.openqa.selenium.TimeoutException: Timeout loading page after 300000ms
URL的网站是:https://www.shareinvestor.com/my
HTML DOM 是:
<div id="sic_sitemap">
<div id="sic_container">
<div id="sic_header">
<h1 id="sic_siteTitle">
<div id="sic_headerMembershipLink">
<a id="sic_mobileEdition" href="/mobile">
<div id="sic_loginContainer" class="sic_logIn" style="">
<div class="sic_login-wrap">
<div class="sic_logIn-subscribe">
<div class="sic_logIn-bg">
<a href="/user/login.html">
</div>
</div>
</div>
</div>
<div id="sic_subHeader">
<div id="sic_mainNav" class="sic_withRightCorner">
<div id="sic_sideBar" class="sic_expanded { selected_market_suffix: 'MY'}">
<div class="sic_superBanner sic_superBannerTop">
<div id="sic_content" class="sic_collapsed">
<div id="sic_footer" class="si_fixed">
</div>
截至目前,我已经尝试了以下选项但无济于事:
- Java 点击
- JavascriptExecutor 点击
- 点击操作
这是我的代码:
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.remote.DesiredCapabilities;
public class 78644072022 {
public static void main(String[] args) {
System.setProperty("webdriver.gecko.driver", "C:\Utility\BrowserDrivers\geckodriver.exe");
DesiredCapabilities dc = DesiredCapabilities.firefox();
dc.setCapability("marionette", true);
WebDriver driver = new FirefoxDriver(dc);
driver.manage().window().maximize();
driver.get("https://www.shareinvestor.com/my");
WebElement login_button = driver.findElement(By.xpath("//div[@id='sic_loginContainer']/div/div[@class='sic_logIn-bg']/a"));
//Java Click
login_button.click();
//JavascriptExecutor Click
/*JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript("arguments[0].click();", login_button);*/
//Actions Click
/*Actions act = new Actions(driver);
act.moveToElement(login_button).click().build().perform();*/
driver.findElement(By.xpath("//input[@id='sic_login_header_username']")).sendKeys("debanjan");
driver.findElement(By.xpath("//input[@id='sic_login_header_password']")).sendKeys("5786");
driver.findElement(By.xpath("//input[@id='sic_login_submit']")).click();
}
}
我正在寻找 Java geckodriver 的解决方案来克服错误 JavaScript error:TypeError: document.getElementById(...) is null
在其中一个 SO threads 中,我看到了这样的解决方案:
You need to do a null check in updateHTML like this:
function updateHTML(elmId, value) {
var elem = document.getElementById(elmId);
if(typeof elem !== 'undefined' && elem !== null) {
document.getElementById(elmId).innerHTML = value;
}
}
我们可以实现吗? 任何建议和指示都会有所帮助。
我想我已经设法在您的脚本中找到引起这种骚动的原因。
我检查了你的 HTML ,似乎 javascript 方法 function showRemaining()
导致了这个问题;因为 showRemaining()
包含此语句
document.getElementById('countdown').innerHTML = '';
它尝试将 id 为 countdown
的元素的 innerHTML 属性设置为 ''.
但是您网页上的任何地方都不存在倒计时,因此出现错误。
TypeError: document.getElementById(...) is null
不知何故,selenium 无法忽略此错误。所以我认为让开发人员修复它应该对你有所帮助。
更新:
基本上,您需要使用隐式等待等待所有元素加载,一旦所有元素都加载完毕,您的 Javascript 错误就会得到解决,最终与网页的交互不会受到 javascript 的阻碍错误:
driver.get("https://www.shareinvestor.com/my");
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.manage().window().maximize();
/*String script = "function updateHTML(countdown, value) {" +
"var elem = document.getElementById('countdown');"+
"if(typeof elem !== 'undefined' && elem !== null) {"+
" document.getElementById('countdown').innerHTML = value;"+
"}"+
"}";
((JavascriptExecutor) driver).executeScript(script);*/
WebElement login_button = driver.findElement(By.xpath("//div[@id='sic_loginContainer']/div/div[@class='sic_logIn-bg']/a"));
login_button.click();
driver.findElement(By.xpath("//input[@id='sic_login_header_username']")).sendKeys("debanjan");
driver.findElement(By.xpath("//input[@id='sic_login_header_password']")).sendKeys("5786");
driver.findElement(By.xpath("//input[@id='sic_login_submit']")).click();
login_button
的 XPath 似乎不正确:
By.xpath("//div[@id='sic_loginContainer']/div/div[@class='sic_logIn-bg']/a");
应该是:
By.xpath("//div[@id='sic_loginContainer']/div/div/div[@class='sic_logIn-bg']/a");
这可以解释 编辑:我的错误,你应该看到 TimeoutException
,因为 Selenium 无法找到不存在的元素。NoSuchElementException
如果找不到元素。
至于 JavaScript 错误,除非您尝试使用 Selenium 访问由 JavaScript 代码(id='countdown'
元素)操作的 Web 元素,否则 Selenium 应该忽略错误。否则,可能会出现其他 Selenium 错误,例如 StaleElementReferenceException
,但情况似乎并非如此。
I am looking for a Java Solution with geckodriver to overcome the error JavaScript error:TypeError: document.getElementById(...) is null
为了回答您的问题,我认为您无法通过 Java/Selenium 对此 "fix" 做任何事情。这是一个 JavaScript 错误,源自您尝试访问的网站。您可能需要考虑 contacting 他们的支持团队,也许他们的开发人员之一可以查看此问题。
与其点击登录按钮,不如考虑直接导航到登录页面?
driver.get("https://www.shareinvestor.com/user/login.html");
首先,那些java脚本错误不会由于任何硒代码而触发。当然超时已经被selenium触发了(这个以后再说)
无论您使用何种浏览器启动 URL,您都会遇到 java 脚本错误。但是在壁虎的情况下,您会在 eclipse 控制台中收到通知,但在 Chrome 的情况下不会。如果您需要在 chrome 中查看 java 脚本错误,只需在 chrome 中启动 url 并转到 devtools/console(F12)。您也可以在 firefox 控制台中看到相同的内容。
- Chrome 图片:
其次,我们收到超时异常,因为该站点加载时间确实太长了。我已经等了 7 分钟,页面仍在加载中。除非页面已完全启动,否则 Selenium 不会执行其脚本。结果我们收到超时异常(不确定允许的默认页面启动时间)。我想直接绕过登录页面(“https://www.shareinvestor.com/user/login.html”),而且完全加载也不需要任何有限的时间。
Intepolation:那些 java 脚本错误不是自动化的问题,但那些页面加载确实是。此站点似乎不太适合自动化解决此问题。
Update1: 否则我们也可以通过另一个线程停止页面加载,例如使用 Action class.
发送 "esc" 键序列Update2: 我今天尝试了同样的代码,它工作正常。下面是我试过的代码片段(完全没有变化)
public static void main(String[] args) throws InterruptedException
{
System.setProperty("webdriver.gecko.driver", "F:\Softwares\Selenium\Webdriver\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
driver.get("https://www.shareinvestor.com/my");
WebElement login_button = driver.findElement(By.xpath("//div[@id='sic_loginContainer']/div/div[@class='sic_logIn-bg']/a"));
//Java Click
login_button.click();
System.out.println("In Login PAge");
driver.findElement(By.xpath("//input[@id='sic_login_header_username']")).sendKeys("debanjan");
driver.findElement(By.xpath("//input[@id='sic_login_header_password']")).sendKeys("5786");
System.out.println("Entered password");
driver.findElement(By.xpath("//input[@id='sic_login_submit']")).click();
}
Selenium 版本 - 3.4.0
Gecko 驱动程序 - v0.16.1(我的是 32 位)
Mozilla - 51.0.1(更新=>也在 53.02 上运行)
希望对您有所帮助。谢谢
这是因为您的应用程序 HTML 页面使用了异步 javascript 并且它使用了一些在执行时不可用的变量引用。我们遇到了同样的问题,并要求开发人员在 HTML 中遵循 javascript 的一些最佳实践,例如将脚本标记放在页面末尾。我检查了站点的 HTML 页面源代码,它在代码之间包含许多脚本标记。这将阻止 DOM 渲染。更好的办法是让开发人员遵循一些最佳实践,在 HTML 中包含脚本标签。您参考 link Where should I put <script> tags in HTML markup? 以获得最佳实践。