1

問題の Web ページは SPA です。複数の div「ボード」が内部にある単一の大きな div として説明できます。親 div に webkit 変換を適用することでスクロールして表示されます。

残念ながら、スクロールしすぎると、WebDriver によって返される要素は「無効」になります。WebElement プロパティの「表示」は false で、Text プロパティは空白で、要素に対してクリック/アクションを実行できません。ただし、その時点でページに表示されており、完全に機能しています。

問題を調査している間、私は小さなテスト Web ページを作成して、これがどのような条件で発生するかを確認しました。

機能を示す JSFiddle サンプル ページへのリンク

注意: この Web サイトでは IFrame を使用していないことに注意してください。JSFiddle は機能を示すためだけのものです。

<html><head>
<script type="text/javascript" src="jquery-1.8.3.js"></script>
<style type="text/css">
    .board-nav {
        font-size: 12px;
        color: #1b1a1a;
        margin-right: 10px;
        vertical-align: middle;
    }

    .scroller{
        -webkit-transition: -webkit-transform 0ms; transition: -webkit-transform 0ms; 
        -webkit-transform-origin: 0px 0px; 
        -webkit-transform: translate(0px, 0px) scale(1) translateZ(0px);
        transition-property: transform; 
        transform-origin: 0px 0px 0px; 
        transform: translate(0px, 0px) scale(1) translateZ(0px);
        height: 4000px;
    }
</style>
<script type="text/javascript">
 var boardPositions = [0, -878, -1748, -2598, -3468];
var $scroller = null;
function changeBoard(event) {
    var newValue = 'translate(0px, ' + boardPositions[event.target.id] + 'px) scale(1) translateZ(0px)';
    
    $('.scroller').css('-webkit-transform',newValue);
    $('.scroller').css('transform', newValue);
}

$(document).ready( function(){
    var $boards = $('.board-nav'); 
    $boards.on('click', changeBoard);
});

</script>
</head><body>
<div>
    <div class="board-nav" id="0">Info</div>
    <div class="board-nav" id="1">Board1</div>
    <div class="board-nav" id="2">Board2</div>
    <div class="board-nav" id="3">Board3</div>
    <div class="board-nav" id="4">Board4</div>
</div>
<div id="content" style="width:1612px; height:864px; position:absolute; left:58px;         overflow:hidden">
    <div class="scroller">
        <ul class="vertical">
            <li class="v" id="li0">
                <div class="target"><span>Info</span></div>
            </li>
        <li class="v" id="li1">
            <div class="target"><span>Board1</span></div>
        </li>
        <li class="v" id="li2">
            <div class="target"><span>Board2</span></div>
        </li>
        <li class="v" id="li3">
            <div class="target"><span>Board3</span></div>
        </li>
        <li class="v" id="li4">
            <div class="target"><span>Board4</span></div>
        </li>
    </ul>
    </div>
</div>
</body></html>

親の div Y の位置が -2000 付近を下回るとすぐに、このようにすべての子要素が「無効」になるようです。これより前 (たとえば -1900 前後) には、要素はすべての情報が有効な状態で返されます。ボード 3 からボード 2 に戻ると、すべての要素が再び正しく返されます。ボード 3 に戻る - すべてのボードを「無効」にします。したがって、これはブラウザの WebDriver の制限のようです。

WebDriver C# テスト コード:

 var driver = new FirefoxDriver();
 driver.Manage().Window.Maximize();
 driver.Navigate().GoToUrl("testpage.html");

 var elements = driver.FindElements(By.ClassName("v"));
 return elements[3].FindElement(By.TagName("span")).Text;

Firefox はこれを最もよく処理します - あきらめる前に、少なくとも Info/Board1/Board2 を表示します。Chrome はどのボードも処理せず、すべてのボードに対して同じ Displayed = false、空の Text を返します。

だから私の質問は - これを回避する方法はありますか? Board1/Info が表示されている間、他のボードのテキストが正しいことをテストできますが、最後の 2 つのボードと対話することはできません。

答え:

親divの「scroller」要素に高さ属性を追加することで問題を解決しました-私の推測では、WebDriverは親divの高さを判断できなかったため、特定の場所を超えて表示されなくなったと想定しています。

上記のコードと JSFiddle をソリューションで更新しました

4

1 に答える 1

4

これはFirefoxとIEで発生すると思いますが、Chromeでは発生しませんか? その場合、同様の問題が発生しています。Chrome は WebDriver W3C 標準を気にせず、わずかに異なる方法で可視性を決定しているのではないかと思います。

この回答があなたの質問に関連していない場合でも、検索エンジンでこれを見つけた人にとって有益であることを願っています.

私が直面している問題は、Selenium が要素を非表示として返すことですが、実際のエンド ユーザーは問題なくアクションを表示および実行できます。ここでの最善の解決策は、サイトのソース コードを変更して、SeleniumFirefoxDriverInternetExplorerDriver満足させることです。これは要素の位置と重なりに関連しているため、再現と修正がかなり難しいようです。

ただし、それとは別に、Selenium を介したいくつかの回避策とハックが役立つ場合があります。

  • これらの目に見えない要素element.GetAttribute("textContent")の代わりに使用しますelement.Text
 return elements[3].FindElement(By.TagName("span")).GetAttribute("textContent");
  • 通常のクリックの代わりに、アクション クリックまたは JavaScript クリックを使用します。たとえば、このメソッドが何度も必要な場合は、 または のいずれかの拡張メソッドを作成することをお勧めしIWebElementますIWebDriver
// example of JavaScriptClick extension method for IWebDriver
// use as driver.JavaScriptClick(element);
// or you can make it IWebElement's extension and pass in IWebDriver
// or just create a normal method and pass in both driver and element
public static void JavaScriptClick(this IWebDriver driver, IWebElement element) {
    IJavaScriptExecutor executor = driver as IJavaScriptExecutor;
    executor.ExecuteScript("arguments[0].click();", element);
}

public static void ActionsClick(this IWebDriver driver, IWebElement element) {
    new Actions(driver).Click(element).Perform();
}

関連読書:

于 2013-09-04T04:54:33.650 に答える