【Rails/RSpec】element has zero size エラーへの対処法


概要

RSpecを用いて結合テストコードを実行していた際"element has zero size"というエラーにぶつかりました。
パッと見で「クリックした要素のサイズがゼロだからか…」と思い、仮説と検証を行いました。

もしかしたらFontAwesomeを使っている方には同じ現象が起こるかもしれないので、ここで仮説と検証のプロセスを共有します。


環境

  • macOS Catalina 10.15.6
  • ruby 2.6.5
  • Rails 6.0.3.4
  • MySQL : 5.6.47
  • Bootstrap : 4.3.1


今回のコード

今回は「ユーザーが投稿したタスク内で、コミットを記録していくアプリ」のテストをします。
テスト内容は「投稿したコミットを編集する」です。

app/spec/system/commits_spec.rb
require 'rails_helper'

RSpec.describe "コミット編集", type: :system do
  before do
    @commit = FactoryBot.create(:commit)
    # user > task > commit の順にネスト
  end

  context 'コミット編集ができるとき' do
    it '正しい情報が入力されれば更新される' do
      # ログイン (サポートモジュールで実装済み)
      sign_in(@commit.task.user)
      # マイページのタスクをクリック
      find_link(href: "/tasks/#{@commit.task.id}").click
      # コミット編集ボタンをクリック
      find_link(href: "/tasks/#{@commit.task.id}/commits/#{@commit.id}/edit").click
      => エラー!
    end
  end
end

テストコードを実行すると、ターミナルに下記のエラー文が表示されました。

1) コミット編集 コミット編集ができるとき 正しい情報が入力されれば更新される
Failure/Error: find_link(href: "/tasks/#{@commit.task.id}/commits/#{@commit.id}/edit").click
Selenium::WebDriver::Error::ElementNotInteractableError:
element not interactable: element has zero size

続いて、このエラー文から仮説と検証を行います。


仮説と検証

エラー文から仮説設定

Failure/Error: find_link(href: "/tasks/***/edit).click
=> find_linkのところでエラー

Selenium::WebDriver::Error::ElementNotInteractableError:
element not interactable: element has zero size
=> 「要素のサイズがゼロだよ」

▶【仮説】find_linkで指定したリンクのサイズがゼロだからクリックできなかった?


検証ツールでリンクを確認

Chromeの検証ツールで、ターゲットにしたリンクを確認します。

find_link(href: "/tasks/#{@commit.task.id}/commits/#{@commit.id}/edit").clickで検索しクリックしたリンクは、下記のaタグです。

確かに、a 0x17.27の「高さゼロの要素」をクリックしようとしていたことがわかります。

高さがゼロでは、幅があろうと存在しない判定になるようですね。初めて知りました。


状況整理

今クリックをしたいのは、右側の青い編集アイコンです。

これをfind_link().clickでクリックしようとしましたが、検証ツールで確認したところ、サイズがないaタグなのでクリックできないという結果になっています。

ちなみにこのaタグ部分がビューファイルでどう記述されているか見てみましょう。

app/views/commits/_commit.html.erb
<%# 必要部分を抜粋 %>
<%= link_to edit_task_commit_path(commit.task, commit) do %>
  <i class="fas fa-edit"></i>
<% end %>

編集アイコン<i class="fas fa-edit"></i>が、実際にリンクとして表示されている文字です。

つまり「リンクをクリック」するにはこのアイコンをクリックすれば良さそうです。

このアイコンですが、実はページ内の他の部分でも使っているので、個別にid属性を付与してクリックしてみましょう


コードを変更▶検証

画像のように、クリックしたい要素にid属性(data-linkId属性)を付与しました。

app/views/commits/_commit.html.erb
<%# 必要部分を抜粋 %>
<%= link_to edit_task_commit_path(commit.task, commit) do %>
  <i class="fas fa-edit" data-linkId="commit-edit"></i>
<% end %>

するとHTMLは次のように表示されます。

svg要素(アイコン)にdata-linkIdを付与できました。
data-linkId="commit-edit"の部分です。

これをfindで取得してクリックしてみます。

app/spec/system/commits_spec.rb
require 'rails_helper'

RSpec.describe "コミット編集", type: :system do
  before do
    @commit = FactoryBot.create(:commit)
    # user > task > commit の順にネスト
  end

  context 'コミット編集ができるとき' do
    it '正しい情報が入力されれば更新される' do
      # ログイン
      sign_in(@commit.task.user)
      # マイページのタスクをクリック
      find_link(href: "/tasks/#{@commit.task.id}").click
      # コミット編集ボタンをクリック
      - find_link(href: "/tasks/#{@commit.task.id}/commits/#{@commit.id}/edit").click
       find("svg[data-linkId='commit-edit']").click
    end
  end
end

この変更により、

クリック前の画面から

クリック後の画面へ遷移できました!


まとめ

  • RSpecでのテスト時、サイズがゼロの要素をクリックしようとしていた
  • 指定すべきリンクは、aタグでなくその中のアイコンだった
  • アイコン要素にidを付与したことで、find().clickでクリックを実行できた