5

I've run into an interesting problem with Capybara and Selenium. I have some Capybara request specs which require javascript to be enabled while a form is being completed. One of the forms is a textarea which used the Redactor Rich Text Editor.

<div class="control-group">
<%= f.label :description, "Description", class: "control-label" %>
    <div class="controls">
        <%= f.text_area :description, rows: 10, class: "redactor"%>
    </div>
</div>

When the test runs and Selenium fires (in both FF and Chrome drivers), Selenium fails on the following command:

`fill_in "Description", with: "some description"`

The error it returns is:

Selenium::WebDriver::Error::InvalidElementStateError:
   Element is not currently interactable and may not be manipulated

It seems that Selenium can't recognize the Rich Text Editor/Textarea any more. If I remove the class="redactor" which is what triggers the Redactor JS to render against the Description text area it works fine.

So my question is, 1. Is there a workaround to fill it out? 2. Alternatively, could I somehow disable the redactor js just for this test?

cman77
  • 1,753
  • 1
  • 22
  • 48

3 Answers3

4

You may want to consider using Redactor's API for filling editor fields:

def fill_in_redactor(options)
  if options[:in]
    node = "('#{options[:in]}')"
  else
    node = "('.redactor')"
  end

  page.execute_script( "$#{node}.redactor('set', '#{options[:with]}')" )

end

If no :in option is passed, it will find the first field with the .redactor class. Otherwise, it assumes the :in value is a valid css finder value.

This avoids having to manually fill in the hidden text_area field.

Tom H
  • 207
  • 2
  • 13
  • +1 to this method, worth noting that the API has changed to be `.redactor('code.set', '#{options[:with]}')` – efatsi Oct 26 '15 at 17:25
4

As narath mentioned, Capybara now supports contenteditable divs. I was able to write:

find('.redactor_editor').set('text')

fill_in wasn't working for me for some reason though.

Joseph Siefers
  • 1,282
  • 1
  • 12
  • 23
3

It looks like capybara will include the ability to fill_in contenteditable divs (see https://github.com/jnicklas/capybara/pull/911).

In the meantime I use the following: (you need to have :js => true for your scenario)

# fill_in_redactor :in => find(".text1"), :with => "Hello world"
def fill_in_redactor(options)
  if options[:in]
    parent = "('#{options[:in]}').find"
  else
    parent = ""
  end

  page.execute_script( "$#{parent}('.redactor_editor').html('#{options[:with]}')" )
  page.execute_script( "$#{parent}('.redactor').html('#{options[:with]}')" )
end

def no_redactor
  page.execute_script("$('.redactor').destroyEditor();");
end
narath
  • 66
  • 4
  • Thanks - yes this seems to be correct, I came up with this while awaiting an answer `page.execute_script('$("#job_description").val("some text here")')` which seems to be a similar approach. I like your idea of making it a utility method - i'll definitely do that! Thank you! – cman77 Jan 25 '13 at 21:24
  • I didn't downvote this answer because it was a reasonable assumption at the time. However, that pull request has not been accepted and the discussion indicated it won't ever be. – IAmNaN Aug 30 '13 at 06:28