Selenium 2.0a2のWebDriver
を使用すると、要素が表示されているかどうかを確認できません。
WebDriver.findElement
はWebElement
を返しますが、残念ながらisVisible
メソッドは提供していません。 WebElement.clear
またはWebElement.click
を使用してこれを回避できますが、どちらもElementNotVisibleException
をスローしますが、これは非常に汚い感じがします。
より良いアイデアはありますか?
element instanceof RenderedWebElement
は動作するはずです。
私は質問に答えるのが少し遅れていますが:
WebElement.isDisplayed()
を使用して、要素が表示されているかどうかを確認できるようになりました。
注:
要素が不可視になる理由はたくさんあります。 Seleniumはそれらのほとんどをカバーしようとしますが、期待どおりに動作しないEdgeのケースがあります。
たとえば、isDisplayed()
doesは、要素にdisplay: none
またはopacity: 0
が含まれる場合にfalse
を返しますが、少なくともmyテストでは、CSSの配置のために要素が別の要素で覆われているかどうかを確実に検出しません。
次の2つの提案方法があります。
次のようにisDisplayed()
を使用できます。
driver.findElement(By.id("idOfElement")).isDisplayed();
以下に示すようにメソッドを定義して呼び出すことができます:
public boolean isElementPresent(By by) {
try {
driver.findElement(by);
return true;
}
catch (org.openqa.Selenium.NoSuchElementException e) {
return false;
}
}
これで、以下のようにアサーションを実行して、要素が存在するかどうかを確認できます。
assertTrue(isElementPresent(By.id("idOfElement")));
C#を使用している場合は、driver.Displayedになります。私自身のプロジェクトの例を次に示します。
if (!driver.FindElement(By.Name("newtagfield")).Displayed) //if the tag options is not displayed
driver.FindElement(By.Id("expand-folder-tags")).Click(); //make sure the folder and tags options are visible
#visibilityOfElementLocated
を使用してくださいisDisplayed
などを使用した答えはどれも正しくありません。彼らはdisplay
プロパティがnone
ではないかどうかをチェックするだけで、要素が実際に見えるかどうかはチェックしません! Seleniumには、多数の静的ユーティリティメソッドが ExpectedConditions
クラスに追加されていました。この場合、そのうちの2つを使用できます。
使用法
@Test
// visibilityOfElementLocated has been statically imported
public demo(){
By searchButtonSelector = By.className("search_button");
WebDriverWait wait = new WebDriverWait(driver, 10);
driver.get(homeUrl);
WebElement searchButton = wait.until(
visibilityOfElementLocated
(searchButtonSelector));
//clicks the search button
searchButton.click();
ExpectedConditions
のユーティリティメソッドについて知る前に、これが私の答えでした。私はそれが上記の方法よりも多くのことを行うと思うので、それはまだ関連しているかもしれません。要素は高さと幅を持っていることだけをチェックします。
本質的に、これはJavaおよびfindElementBy*
メソッドとWebElement#isDisplayed
だけでは答えることができません。これらは要素が存在するかどうかしかわからないためです、実際に可視である場合ではありません。 OPはvisibleの意味を定義していませんが、通常は
opacity
> 0がありますdisplay
プロパティがnone
以外に設定されているvisibility
propはvisible
に設定されますほとんどの人は、それが実際にビューポート内にあるという要件も含みます(したがって、人はそれを見ることができます)。
何らかの理由で、この非常に通常の必要性は純粋なJava APIで満たされていませんが、その上に構築されるSeleniumのフロントエンドはしばしばisVisible
のバリエーションを実装します。そして、NodeフレームワークWebDriver.IOのソースを参照した後、 ソース のisVisible
が見つかりました。 5.0ベータでのisVisibleInViewport
のより適切な名前。
基本的に、クライアントで実行されるjavascriptに委任する呼び出しとしてカスタムコマンドを実装し、実際の作業を行います!これは「サーバー」ビットです。
export default function isDisplayedInViewport () {
return getBrowserObject(this).execute(isDisplayedInViewportScript, {
[ELEMENT_KEY]: this.elementId, // w3c compatible
ELEMENT: this.elementId // jsonwp compatible
})
}
興味深いのは、クライアントで実行するために送信されるJavaScriptです。
/**
* check if element is visible and within the viewport
* @param {HTMLElement} elem element to check
* @return {Boolean} true if element is within viewport
*/
export default function isDisplayedInViewport (elem) {
const dde = document.documentElement
let isWithinViewport = true
while (elem.parentNode && elem.parentNode.getBoundingClientRect) {
const elemDimension = elem.getBoundingClientRect()
const elemComputedStyle = window.getComputedStyle(elem)
const viewportDimension = {
width: dde.clientWidth,
height: dde.clientHeight
}
isWithinViewport = isWithinViewport &&
(elemComputedStyle.display !== 'none' &&
elemComputedStyle.visibility === 'visible' &&
parseFloat(elemComputedStyle.opacity, 10) > 0 &&
elemDimension.bottom > 0 &&
elemDimension.right > 0 &&
elemDimension.top < viewportDimension.height &&
elemDimension.left < viewportDimension.width)
elem = elem.parentNode
}
return isWithinViewport
}
このJSの部分は、実際に(ほとんど)そのままの形で独自のコードベースにコピーできます(export default
を削除し、非常緑ブラウザの場合はconst
をvar
に置き換えます)。それを使用するには、File
からクライアントで実行するためにSeleniumが送信できるString
に読み取ります。
検討する価値があるもう1つの興味深い関連スクリプトは、 selectByVisibleText です。
Seleniumを使用してJSを実行したことがない場合は、 これを少し覗いてみてください または JavaScriptExecutor API を参照できます。
通常、常に非ブロッキング非同期スクリプト( #executeAsyncScript を意味する)を使用するようにしてください。ただし、既に同期のブロッキングスクリプトがあるため、通常の同期呼び出しを使用することもできます。返されるオブジェクトは、多くのタイプのオブジェクトになる可能性があるため、適切にキャストしてください。これはそれを行う1つの方法です。
/**
* Demo of a Java version of webdriverio's isDisplayedInViewport
* https://github.com/webdriverio/webdriverio/blob/v5.0.0-beta.2/packages/webdriverio/src/commands/element/isDisplayedInViewport.js
* The super class GuiTest just deals with setup of the driver and such
*/
class VisibleDemoTest extends GuiTest {
public static String readScript(String name) {
try {
File f = new File("Selenium-scripts/" + name + ".js");
BufferedReader reader = new BufferedReader( new FileReader( file ) );
return reader.lines().collect(Collectors.joining(System.lineSeparator()));
} catch(IOError e){
throw new RuntimeError("No such Selenium script: " + f.getAbsolutePath());
}
}
public static Boolean isVisibleInViewport(RemoteElement e){
// according to the Webdriver spec a string that identifies an element
// should be deserialized into the corresponding web element,
// meaning the 'isDisplayedInViewport' function should receive the element,
// not just the string we passed to it originally - how this is done is not our concern
//
// This is probably when ELEMENT and ELEMENT_KEY refers to in the wd.io implementation
//
// Ref https://w3c.github.io/webdriver/#dfn-json-deserialize
return js.executeScript(readScript("isDisplayedInViewport"), e.getId());
}
public static Boolean isVisibleInViewport(String xPath){
driver().findElementByXPath("//button[@id='should_be_visible']");
}
@Test
public demo_isVisibleInViewport(){
// you can build all kinds of abstractions on top of the base method
// to make it more Selenium-ish using retries with timeouts, etc
assertTrue(isVisibleInViewport("//button[@id='should_be_visible']"));
assertFalse(isVisibleInViewport("//button[@id='should_be_hidden']"));
}
}
Driver.FindElement
はHTMLソースのみをチェックするため、要素が表示されているかどうかを確認することが重要です。ただし、ポップアップコードはページhtmlにあり、表示されない可能性があります。したがって、Driver.FindElement
関数はfalse positiveを返します(テストは失敗します)
Eleが表示されていることを確認します。
public static boolean isElementVisible(final By by)
throws InterruptedException {
boolean value = false;
if (driver.findElements(by).size() > 0) {
value = true;
}
return value;
}