このエラーの原因であると思われる別の質問を作成しました: Selenium Firefoxドライバーは、親がオーバーフローしたときにモーダルが表示されないと見なすのはなぜですか?
Seleniumバージョン2.33.0
Firefoxドライバー
エラーの原因となるコード:
_ System.Threading.Thread.Sleep(5000);
var dimentions = driver.Manage().Window.Size;
var field = driver.FindElement(By.Id("addEmployees-password")); //displayed is true
field.Click(); //works fine
var element = driver.FindElement(By.Id(buttonName)); //displayed is false
element.Click(); //errors out
_
クリックしようとしているボタン:
_<div id="addEmployees" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="addEmployeesLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3>Add Employee</h3>
</div>
<div class="modal-body">
<p class="alert alert-info">
<input name="addEmployees-username" id="addEmployees-username" />
<input name="addEmployees-password" id="addEmployees-password" type="password" />
<input name="addEmployees-employee" id="addEmployees-employee" />
</p>
</div>
<div class="modal-footer">
<button name="addEmployees-add" id="addEmployees-add" type="button" class="btn" data-ng-click="submit()">Add</button>
</div>
</div>
_
FindElements
に変更すると、要素が1つ取得されるため、ページには他に何もありません。FindElement
、たとえば_addEmployees-employee
_の場合、_addEmployees-employee
_はdisplayed
です。一方のフィールドが表示され、もう一方のフィールドが表示されないと見なすことができるのはどうしてですか?
右下に追加ボタンがあるモーダル、他のすべての要素が表示されます= true
ウィンドウサイズはdriver.Manage().Window.Size;
あたり1200x645です
要素の場所は次のとおりです:driver.FindElement(By.Id(buttonName)).Location
あたり800x355y
要素の寸法は次のとおりです:driver.FindElement(By.Id(buttonName)).Size
あたり51x30
パスワード要素の場所は次のとおりです:driver.FindElement(By.Id("addEmployees-password")).Size
あたり552x233y
Selenium WebDriverは、不透明度!= 0、可視性= true、高さ> 0をチェックし、問題の現在の要素に!= noneを表示するだけでなく、DOMの祖先チェーンを検索して、親要素がないことを確認します。これらのチェッカーと一致します。 ([〜#〜] update [〜#〜]すべてのバインディングが参照するJSONワイヤーコードを確認した後、SWDには- オーバーフロー!=非表示 、 as同様に少数その他ケース 。)
@Brianが示唆するように、コードを再構築する前に2つのことを行います。
「div.modal_footer」要素に、SWDが表示されていないと見なす理由がないことを確認してください。
Javascriptを挿入して、ブラウザで問題の要素を強調表示し、正しい要素を選択したことが確実にわかるようにします。 this Gist を開始点として使用できます。ボタンが黄色の境界線で強調表示されている場合は、適切な要素が選択されていることがわかります。そうでない場合は、選択された要素がDOMの他の場所にあることを意味します。この場合、予想どおりに一意のIDがない可能性があり、DOMの操作が非常に混乱します。
私が推測しなければならないとしたら、2番目はあなたが遭遇しているものだと思います。これは私にも起こりました。開発者が要素IDを再利用し、どの要素を見つけるかで競合が発生しました。
ブライアンの応答は正しかった:Thread.Sleep()に対して明示的な待機を使用する。 Sleep()は一般的に脆弱であり、不必要に5秒を失っています。さらに、自動テストでは本当に腐った練習にすぎません。 (それを学ぶのに長い時間がかかったので、あなただけではありません。)
暗黙の待機は避けてください。これらは通常、DOMに追加される新しいアイテムに対して機能し、モーダルなどがアクティブになるための遷移に対しては機能しません。
明示的な待機には、これらの問題を乗り越えることができる一連のExpectedConditions( Javadoxで詳しく説明されています )があります。次のアクションに必要な状態に一致するExpectedConditionを使用します。
また、 このトピックに関するIan Roseのすばらしいブログ投稿 も参照してください。
チャットでこれについて話し合った後、(少なくとも今のところ)最善の解決策は、ボタンをモーダルのフッターから本体に移動することだと思います。
これはあなたが望むものです(今のところ):
<div class="modal-body">
<p class="alert alert-info">
<input name="addEmployees-username" id="addEmployees-username" />
<input name="addEmployees-password" id="addEmployees-password" type="password" />
<input name="addEmployees-employee" id="addEmployees-employee" />
<button name="addEmployees-add" id="addEmployees-add" type="button" class="btn" data-ng-click="submit()">Add</button>
</p>
</div>
そしてこれではありません:
<div class="modal-body">
<p class="alert alert-info">
<input name="addEmployees-username" id="addEmployees-username" />
<input name="addEmployees-password" id="addEmployees-password" type="password" />
<input name="addEmployees-employee" id="addEmployees-employee" />
</p>
</div>
<div class="modal-footer">
<button name="addEmployees-add" id="addEmployees-add" type="button" class="btn" data-ng-click="submit()">Add</button>
</div>
同じ要素が表示されないため、操作できないという問題がありました。それはちょうど解決されました。 Seleniumスタンドアロンサーバーを更新しました。以前のバージョンは2.33.0
そして今は2.35.0
私の場合、要素はすでにページに存在していましたが、無効になっているため、これは機能しませんでした(python):
_wait.until(lambda driver: driver.find_element_by_id("myBtn"))
driver.find_element_by_id("myBtn").click()
_
エラーで失敗しました:
_“Element is not currently visible and so may not be interacted with"
_
問題を解決するには、要素が表示されるまで数秒(time.sleep(5)
)待たなければなりませんでした。
JavaScriptを使用して要素を有効にすることもできます。apython例:
_driver.execute_script("document.getElementById('myBtn').disabled='' ")
driver.execute_script("document.getElementById('myBtn').click() ")
_