Rails

CapybaraでCSSの要素の値をテストする

CapybaraでCSSの要素をテストしなければいけない機会がありました。

ただCapybaraとCSSのことを調べてみてもセレクターに関することばかりで、CSSの値をテストする方法は見つかりませんでした。なので記事を残しておこうと思います。

今回は入力された行数によってtextareaの高さ(height)が自動で大きくなる機能が正常に動いているかをテストします。 テキストエリアに文字を入力する前のtextareaheightと文字を入力した後のtextareaのheightを比較します。

CapybaraでCSSの要素をテストする

仕様の確認

最初にも書きましたが、今回はtextareの高さが自動で大きくなることを確認するテストを書いていきます。
このtextarea は16行以上入力すると自動で高さが大きくなります。

Image from Gyazo

textarea が可変しない状態(バグ)はこんな感じです。

Image from Gyazo

実装していく

先に完成形のテストをお見せします。
これがいいコードとは思いませんが、今回の目的を達成することはできます。

test 'automatically resizes textarea of a new report' do
    visit_with_auth '/reports/new', 'komagata'
    fill_in('report[description]', with: 'test')
    height = find('#report_description').style('height')['height'][/\d+/].to_i

    fill_in('report[description]', with: "\n1\n2\n3\n4\n5\n6\7\n8\n9\n10\n11\n12\n13\n14\n15")
    after_height = find('#report_description').style('height')['height'][/\d+/].to_i

    assert height <  after_height
  end

文字入力前のtextareaのheightを取得する

まずはtextarea があるページに移動して適当な文字をtextarea に入力する

# textareaがあるページに移動
visit_with_auth '/reports/new', 'komagata'
# textarea に適当な文字(今回は'test') を入力する  
fill_in('report[description]', with: 'test')

次にtextareaのheight を取得します。

find メソッドを使ってtextarea の要素を取得します。
* #report_description はtextareaのclassです。

find('#report_description')
=> #<Capybara::Node::Element tag="textarea" path="/HTML/BODY/DIV/MAIN/DIV/DIV/FORM/DIV/DIV/DIV/DIV/DIV/TEXTAREA">

Capybara::Node::Element は要素を表示することができます。
参考:class: Capybara::Node::Element

今回はCSSの要素を取得したいので style を指定します。
このようにstyle を指定する場合、引数が必要です。今回はheight を引数に入れます。

find('#report_description').style('height")
=> {"height"=>"352px"}

これでheight の値を取得できました。
戻り値を見る限り、ハッシュの形式になっているようです。なので352pxだけ取り出します。

find('#report_description').style('height')['height']
=> "352px"

これでheight の値だけ取り出せました。 でもこれだと"352px" という文字列が戻り値になっています。このままではtextarea の高さを比較することができません。 正規表現を使って352だけ取り出します。

find('#report_description').style('height')['height'][/\d+/]
=> "352"

/\d+/ で数字だけを取り出せました。
ただまだ文字列になっているので、これをinteger に変換します。

find('#report_description').style('height')['height'][/\d+/].to_i
=> 352

これでheight の値を取得できました。

文字入力前と後のtextareaのheightを比較する

height を取得する式を変数に入れます

height = find('#report_description').style('height')['height'][/\d+/].to_i

文字入力前のtextareaheightを取得できたら、textareaが自動で大きなる(はずの)ように文字を入力していきます。
今回でいえば15行以上になるように文字を入力します。

fill_in('report[description]', with: "\n1\n2\n3\n4\n5\n6\7\n8\n9\n10\n11\n12\n13\n14\n15")

次はもう一度textareaheight を取得します。
文字を入力した後なのでtexrareaheight が大きくなっているはずです。

after_height = find('#report_description').style('height')['height'][/\d+/].to_i
=> 373

先ほどは352px だったので想定通りheightが大きくなっています。
最後にtextareaの高さを比較してテストの判定をしていきます。

assert height < after_height

今回の方法だけが正しい方法ではないと思うので、他の方法があれば教えてもらいたいです🙏
最後まで読んでいただきありがとうございました。