我目前有很多情况需要验证页面(及其所有元素)是否正确显示。 WebElement的isDisplayed()
方法似乎是一种逻辑方式,但是我想准确理解这个方法正在做什么来确定元素是否“显示”。 javadoc并未阐明该方法的内部工作原理,而网上的其他信息似乎最多也是稀疏的。
如果有人能详细说明这种方法是如何运作的,我将非常感激。
答案 0 :(得分:28)
我相信Selenium可以解决是否显示元素的问题。如果它不起作用,您可以提出错误和/或修复您看到的任何问题并提供补丁。
这就是该方法的作用(取自当前的Selenium source code):
/**
* Determines whether an element is what a user would call "shown". This means
* that the element is shown in the viewport of the browser, and only has
* height and width greater than 0px, and that its visibility is not "hidden"
* and its display property is not "none".
* Options and Optgroup elements are treated as special cases: they are
* considered shown iff they have a enclosing select element that is shown.
*
* @param {!Element} elem The element to consider.
* @param {boolean=} opt_ignoreOpacity Whether to ignore the element's opacity
* when determining whether it is shown; defaults to false.
* @return {boolean} Whether or not the element is visible.
*/
bot.dom.isShown = function(elem, opt_ignoreOpacity) {
if (!bot.dom.isElement(elem)) {
throw new Error('Argument to isShown must be of type Element');
}
// Option or optgroup is shown iff enclosing select is shown (ignoring the
// select's opacity).
if (bot.dom.isElement(elem, goog.dom.TagName.OPTION) ||
bot.dom.isElement(elem, goog.dom.TagName.OPTGROUP)) {
var select = /**@type {Element}*/ (goog.dom.getAncestor(elem, function(e) {
return bot.dom.isElement(e, goog.dom.TagName.SELECT);
}));
return !!select && bot.dom.isShown(select, /*ignoreOpacity=*/true);
}
// Image map elements are shown if image that uses it is shown, and
// the area of the element is positive.
var imageMap = bot.dom.maybeFindImageMap_(elem);
if (imageMap) {
return !!imageMap.image &&
imageMap.rect.width > 0 && imageMap.rect.height > 0 &&
bot.dom.isShown(imageMap.image, opt_ignoreOpacity);
}
// Any hidden input is not shown.
if (bot.dom.isElement(elem, goog.dom.TagName.INPUT) &&
elem.type.toLowerCase() == 'hidden') {
return false;
}
// Any NOSCRIPT element is not shown.
if (bot.dom.isElement(elem, goog.dom.TagName.NOSCRIPT)) {
return false;
}
// Any element with hidden visibility is not shown.
if (bot.dom.getEffectiveStyle(elem, 'visibility') == 'hidden') {
return false;
}
// Any element with a display style equal to 'none' or that has an ancestor
// with display style equal to 'none' is not shown.
function displayed(e) {
if (bot.dom.getEffectiveStyle(e, 'display') == 'none') {
return false;
}
var parent = bot.dom.getParentElement(e);
return !parent || displayed(parent);
}
if (!displayed(elem)) {
return false;
}
// Any transparent element is not shown.
if (!opt_ignoreOpacity && bot.dom.getOpacity(elem) == 0) {
return false;
}
// Any element with the hidden attribute or has an ancestor with the hidden
// attribute is not shown
function isHidden(e) {
//IE does not support hidden attribute yet
if (goog.userAgent.IE) {
return true;
}
if (e.hasAttribute) {
if (e.hasAttribute('hidden')){
return false;
}
} else {
return true;
}
var parent = bot.dom.getParentElement(e);
return !parent || isHidden(parent);
}
if (!isHidden(elem)) {
return false;
}
// Any element without positive size dimensions is not shown.
function positiveSize(e) {
var rect = bot.dom.getClientRect(e);
if (rect.height > 0 && rect.width > 0) {
return true;
}
// A vertical or horizontal SVG Path element will report zero width or
// height but is "shown" if it has a positive stroke-width.
if (bot.dom.isElement(e, 'PATH') && (rect.height > 0 || rect.width > 0)) {
var strokeWidth = bot.dom.getEffectiveStyle(e, 'stroke-width');
return !!strokeWidth && (parseInt(strokeWidth, 10) > 0);
}
// Zero-sized elements should still be considered to have positive size
// if they have a child element or text node with positive size, unless
// the element has an 'overflow' style of 'hidden'.
return bot.dom.getEffectiveStyle(e, 'overflow') != 'hidden' &&
goog.array.some(e.childNodes, function(n) {
return n.nodeType == goog.dom.NodeType.TEXT ||
(bot.dom.isElement(n) && positiveSize(n));
});
}
if (!positiveSize(elem)) {
return false;
}
// Elements that are hidden by overflow are not shown.
if (bot.dom.getOverflowState(elem) == bot.dom.OverflowState.HIDDEN) {
return false;
}
不确定它真的需要更多解释,评论很清楚。如果您想要添加更多信息,请与我们联系。
答案 1 :(得分:23)
WebDriver有自己的W3C specification。
关于determining visibility的部分就是您的目标。
我会警告说“显示”是一个如此广泛的术语,因此有很多场景。因此,可能存在WebDriver未考虑的情况。
重要的是,至关重要实际上,要记住“显示”或“可见”的内容具有许多含义。 (与完全加载的页面相同,也有很多含义。)
还记得Selenium是entirely open source.没有什么能阻止你重新检查存储库并在本地检查它。
答案 2 :(得分:0)
根据 documentation isDisplayed()
方法确定 WebElement 是否显示并返回 boolean
显示与否。此方法避免了必须解析元素的 style
属性的问题。
此实现符合 WebDriver Level 2 W3C Working Draft 中提到的规范:
<块引用>虽然 WebDriver 没有定义一个原语来确定 可见性 element 在 viewport, 我们承认它对许多用户来说是一个重要的功能。在这里,我们 包括一个推荐的方法,它将给出一个简化的 元素可见性的近似值,但请注意它 仅依赖于树遍历,并且只覆盖可见性的一个子集 检查。
元素的可见性取决于感知可见的内容 到人眼。在这种情况下,元素的显示性不 与 visibility 或 display 样式 属性。
建议实现者确定元素的方法 可见性最初是由 Selenium 项目开发的,并且是 基于对元素性质的粗略近似和 树中的关系。一般要考虑一个元素 如果它的任何部分在边界内的画布上绘制,则可见 视口。
显示的元素算法是一个布尔状态,其中 true
表示显示该元素,false
表示
元素不显示。要计算元素上的状态,请调用
Call(bot.dom.isShown, null, element)
。如果这样做不会产生
错误,返回此函数调用的返回值。否则
返回错误代码为未知错误的错误。
此函数通常暴露给具有以下 URI 模板的 GET
请求:
/session/{session id}/element/{element id}/displayed