2012年6月13日水曜日

Symfonyのlimeで使えるCSSセレクタのまとめ

Symfony でユニットテストやファンクショナルテストをする際、組み込みのテストフレームワークである lime を使うことが多いと思います。

しかしながら lime はネット上の情報源が少なく、特にテスト駆動開発をしようと思うと結構苦労します。結局 Symfony パッケージ内部のソースコードを見て調べることもあるでしょう。

ファンクショナルテストにはレスポンス内容を検査する sfTesterResponse::checkElement() メソッドの使用頻度が多いので、sfTesterResponse::checkElement() で使えるCSSセレクタをソースコードを見て調べてみました。対象バージョンはSymfony 1.4 です。

sfTesterResponse::checkElement() から CSSセレクタによってノードを選択する際、最終的に sfDomCssSelector::getElementsForNode() およびsfDomCssSelector::matchCustomSelector()
が呼び出されています。その中で正規表現を用いて CSSセレクタの機能を実現しているようです。

以下、ソースに記述のあったCSSセレクタを列挙します。

IDセレクタ及びクラスセレクタ

#id
指定されたIDを持つ
.class
指定されたクラスを持つ

属性セレクタ

[attr]
attr 属性を持つ
[attr=”val”]
attr 属性を持ち、値が val に一致する
[attre^=”val”]
attr 属性を持ち、値が val で始まる
[attr$=”val”]
attr 属性を持ち、値が val で終わる
[attr*=”val”]
attr 属性を持ち、値に val が含まれる
[attr~=”val”]
attr 属性を持ち、値をスペースで区切ったうちの1つに val が一致する
[attr|=”val”]
attr 属性を持ち、値が val または val- で始まる

範囲を限定するセレクタ

elem
要素セレクタ(elem 要素)
elem1 elem2
子孫セレクタ(elem1 要素の孫要素である elem2 要素)
elem1 > elem2
子セレクタ(elem1 要素の直下の子要素である elem2 要素)
element1 + element2
兄弟セレクタ(elem1 要素の直後の兄弟要素である elem2 要素)

擬似クラス

:contains(“val”)
文字列 val を含むもの
:nth-child(n)
親要素のn番目の子要素であるもの(n は 1 から始まる番号)
:first-child
親要素の最初の子要素であるもの
:last-child
親要素の最後の要素であるもの
:lt(n)
インデックス番号 n より前の要素(n は 0 から始まる番号、n 自体は含まない)
:gt(n)
インデックス番号 n より後の要素(n は 0 から始まる番号、n 自体は含まない)
:nth(n) または :eq(n)
インデックス番号 n の要素(n は 0 から始まる番号)
:odd
奇数番目の要素
:even
偶数番目の要素
:first
最初の要素
:last
最後の要素

注意点

lime の CSSセレクタには ID セレクタ及びクラスセレクタと属性セレクタを同時に使うと意図通りマッチしないというバグがあります(Symfony1.4.10で確認)。
これを回避するには、 ID 指定やクラス指定も属性セレクタと同様に [id=”foo”] や [class=”bar”] の形式にします。

例:
input#foo[checked] → 意図通りマッチしません。
input[id=”foo”][checked] → 意図通りマッチします。
input.bar[checked] → 意図通りマッチしません。
input[class=”bar”][cheched] → 意図通りマッチします。

ハマりやすいポイントだと思いますので注意してください。(私はハマりました・・・)

また、擬似クラス指定の :nth-child(n) の引数に指定できるのは整数のみです。

それから属性指定の [attr|=”val”] は本来 attr 属性の値が val そのものか、val- で始まるものを指定するはずですが、ソースコードを見る限り val で始まるものも許容しています。

参考

http://simonwillison.net/static/2003/getElementsBySelector.html
http://trac.symfony-project.org/ticket/6691

0 件のコメント:

コメントを投稿