Capybara and div contentEditable

Jeffrey Qua
3 min readMar 27, 2017

--

At Glassbreakers, we use Rspec/Capybara for our testing framework.

One recent front-end issue that we just encountered was figuring out how to deal with filling in forms that aren’t input fields. The code change required changing it over from an input field, either an <input type="text”> or a textarea element into contentEditable divs (ie: <div contentEditable="true">). This was done in order to create text fields that are more dynamic.

Design context

Our existing textfields use textarea elements. By default, a textarea element’s height is set (automatically by the browser if not given parameters) and does not size up and down (unless manipulated by CSS). So any text that goes beyond the set height will become hidden, and a scrollbar is added to scroll through the textarea content.

Existing type field — textarea’s by default have set heights
Existing type field with response — the textarea will hide any overflowing text and create a scrollbar

This change was about changing the textarea box into a dynamic auto-height text field that sizes up with the amount of content inside the field. We want to minimize empty space being taken up from textfields that are not in use yet. This unfortunately isn’t how the HTML textarea element works.

This is a mockup of the design we want, where we have a single line text area that will size up once we have content that fills in.

Dynamic text field height based on content in field

Our solution is to convert the fields into <div contentEditable="true"> fields as div elements size up based on the content in the element.

We had a textarea element already on the feature and our existing tests were using the fill_in Capybara method.

fill_in(:comment_body, with: “aaa”)

However with a change to a contentEditable div, this test method no longer works as it is not supported and this is where we started running into problems.

It took a while trying to look up how to deal with this change.

Using set to fill in the field

find(“.comments__textarea”).set(“aaa”)

The first option was to try using the set method. Although it achieves the purpose of filling in the content of the div, it does not trigger JavaScript, and bypasses any validation and dynamic behavior — which in our case is to show and hide the Send button only when it is necessary.

Simulating keystrokes

find(“.comments__textarea”).base.send_keys(“aaa”)

Eventually, we found the send_keys method. It can be used to simulate keystrokes, and perfect in our case, because we can’t use fill_in and set does not trigger JavaScript. It requires usage of the native or in our case, thebase method at first.

This was able to achieve the functionality that fill_in was able to do but for non-text class="input" and non-textarea fields.

There aren’t that many references I could find dealing with this issue, but much thanks to the few Stackoverflow posts out there who pointed us in the right direction.

--

--