CSSセレクターのcontains()pseudoクラスを理解するのに苦労している理由は、そのように機能しますか?
-
27-10-2019 - |
質問
私はセレンとキュウリを備えたCSSセレクターを使用しています。ロケーターが機能しない場合は、Chrome開発者ツールのコンソールを使用してテストします。私は理解していない行動に遭遇し続けます(なぜそれがしていることをするのではなく、私がする必要があることではないのです...)。これらのロケーターを見てください:
div.view_header ~ div input.my_button
div:contains(My Header Title) ~ div input.my_button
div:contains(My Header Title) ~ div div div input.my_button
私のDOMでは、それらのロケーターのそれぞれの最初の部分を一致させる要素は同じです...
<div class="view_header foo"> My Header Title </div>
問題は、上記のロケーター#1&#3のみが実際に何でも一致することです。なぜこれが真実なのか誰か知っていますか。気付いた div:contains(foo)
実際にFOOを含むDIVだけでなく、すべての親が同様に一致しますが、ロケーター要素の残りの部分が機能するように整理する必要があるように思えます。
「my_button」がクリックしていることを確認する方法についての洞察とおそらく提案を探しています。それらを区別する方法は、ロケーターの一見過剰なDOM構造を排除して、再利用可能になる可能性が高くなるように、ヘッダーが下にあるヘッダーによるものです。
<head>
<body class="bp">
<div style="left: -100em; position: absolute; width: 100em;"></div>
<input class="refresh_marker" type="text" value="no" style="display:none">
<div class="container">
<div id="nav_bar">
<div id="user_bar">
<div id="wrapper" style="border-radius: 10px 10px 10px 10px;">
<div class="content">
<div class="page_title"> Title </div>
<div></div>
<a class="change_tracker_link"> </a>
<div class="breadcrumb_trail">
<style type="text/css">
<div id="dialog_no_new_assoc" class="hide" title="No Associations Selected"></div>
<div class="organizer_widget root_organizer" title="WorkflowItem" style="">
<input id="data_classifier" type="hidden" value="Workflow::WorkflowItem">
<input id="data_id" type="hidden" value="34">
<input id="data_getter" type="hidden">
<input id="collection_vertex_id" type="hidden" value="4cb1ecc300fa5f77844b1e87431d0a25390c1c77">
<input id="view-name" type="hidden" value="EnterPaperInformation">
<div class="object organizer">
<div class="clear"></div>
<div class="interior">
<form method="POST" enctype="multipart/form-data">
<input type="hidden" value="4cb1ecc300fa5f77844b1e87431d0a25390c1c77" name="vertex_id">
<input type="submit" value="Save" style="display: none;" name="submit_form">
<div class="organizer_header view_header"> My Header Title </div>
<div class="organizer_widget" title="Citation" style="">
<input id="data_classifier" type="hidden" value="Bibliography::Citation">
<input id="data_id" type="hidden" value="10">
<input id="data_getter" type="hidden" value="citation">
<input id="collection_vertex_id" type="hidden" value="5376dcc81102a5d76bf829513b096be8f67e560d">
<input id="view-name" type="hidden" value="CitationEntrySummary">
<div id="citation" class="object organizer">
<div class="clear"></div>
<div class="interior">
<div id="Citation___id_widget" class="widget_row numeric">
<div id="Citation___title_widget" class="widget_row string">
<div id="Citation___abbreviated_title_widget" class="widget_row string">
<div id="Citation___authors_display_string_widget" class="widget_row string">
<div id="Citation___language_widget" class="widget_row choice">
<div id="Citation___link_widget" class="widget_row link">
<input type="hidden" value="Bibliography::JournalArticle___10" name="check_5376dcc81102a5d76bf829513b096be8f67e560d[]">
<input id="ba_citation" class="my_button" type="button" value="Break Associations" name="break_assoc_5376dcc81102a5d76bf829513b096be8f67e560d">
<div class="clear"></div>
<input type="hidden" value="5376dcc81102a5d76bf829513b096be8f67e560d" name="vertices[]">
</div>
...
解決
この種のトラブルに巻き込まれているときに私がする通常のことは、仕様を見ることです。
おそらくご存知のように、 何もありません :contains()
現在の仕様 したがって、特定のブラウザ/パーサーの文書化されていない、前に科されていない機能に依存しています。それ したほうがいい 作業ですが、そうではありません - 明らかに実装は完了しませんでした。そして今、擬似クラスはなくなりました。
に行ってもらえますか xpath 代わりは?内部セレンメソッドまたは JavaScript. 。このXPathは、CSSセレクター番号2と同じです。
//div[contains(text(),'My Header Title')]/following-sibling::div//input[contains(@class,'my_button')]
編集
あなたのコメントの後、私たちがSelenium RCについて話していることを示した後、したがって、私はより深く掘りました。
私はあなたの模範を取り、HTMLを撮影し、隠された(一見)不必要な要素からそれを剥ぎ取り、これに残されました。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script src="sizzle.js" type="text/javascript"></script>
</head>
<body class="bp">
<div class="container">
<div id="nav_bar">
<div id="user_bar">
<div id="wrapper" style="border-radius: 10px 10px 10px 10px;">
<div class="content">
<div class="breadcrumb_trail">
<div class="organizer_widget root_organizer" title="WorkflowItem" style="">
<div class="object organizer">
<div class="interior">
<form method="POST" enctype="multipart/form-data">
<div class="organizer_header view_header"> My Header Title </div>
<div class="organizer_widget" title="Citation" style="">
<div id="citation" class="object organizer">
<div class="clear"></div>
<div class="interior">
<div id="Citation___id_widget" class="widget_row numeric">
<div id="Citation___title_widget" class="widget_row string">
<div id="Citation___abbreviated_title_widget" class="widget_row string">
<div id="Citation___authors_display_string_widget" class="widget_row string">
<div id="Citation___language_widget" class="widget_row choice">
<div id="Citation___link_widget" class="widget_row link">
<input id="ba_citation" class="my_button" type="button" value="Break Associations" name="break_assoc_5376dcc81102a5d76bf829513b096be8f67e560d" />
<div class="clear"></div>
</div></div></div></div></div></div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
ダウンロードしました 最新のシズル そして、私は取得しました 現在のリリースでセレンが実際に使用しているシズルのバージョン.
これら2つは非常に異なっていることがわかりました。
例 contains
現在のシズルの実装:
return ~( elem.textContent || elem.innerText || getText( elem ) ).indexOf( match[3] );
および実装Seleniumが使用します。
return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
テストドキュメントで両方の実装を試しましたが、ここで結果を見ることができます(クリックして拡大してください):
Selenium's Sizzle- 4つのうち1つを一致させます
結果はそれをすべて言います。 Seleniumは、のハンドリングに何らかの形で不完全な古いバージョンのSizzleを使用しています :contains()
擬似クラス。現在のSizzleバージョンはバグに苦しむことはなく、すべての要素をうまく見つけることができます。
今、あなたはこれらのいずれかを行うことができます:
- セレンバグを提出します。
- XPathを回避策として使用します。
- 切り替えます
sizzle.js
Seleniumパッケージにファイルします。
他のヒント
#Selenium #Webdriver handle only HTML elements but with using java script executor It's possible to handle #pseudo elements in selenium #webdriver.
Ex: :after , :before etc
String script = "return window.getComputedStyle(document.querySelector('Enter root classname here'),':after / :before').getPropertyValue('content')";
Thread.sleep(3000);
JavascriptExecutor js = (JavascriptExecutor) driver;
String content = (String) js.executeScript(script);
System.out.println(content);