teampoltergeist / poltergeist

A PhantomJS driver for Capybara

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Read javascript property and not html attribute

synth opened this issue · comments

I have a form in which I'm disabling all inputs under certain use cases with the following js:

$(".disable-entire-form input, .disable-entire-form select, .disable-entire-form textarea")
    .prop('disabled', true).prop('readonly', true);

The following test passes, but its a false positive (since el[:readonly] == "" and !!el[:readonly] == true) and the inverse test (where expect(...).to be(false)) fails.

        page.all(:css, "input").each do |el|
          expect(el.readonly?).to be true
          expect(el.disabled?).to be true
        end

        page.all(:css, "select").each do |el|
          expect(el.readonly?).to be true
          expect(el.disabled?).to be true
        end

        page.all(:css, "textarea").each do |el|
          expect(el.readonly?).to be true
          expect(el.disabled?).to be true
        end

The reason is because el.readonly? is checking the html attribute not the javascript property.

Don't we always want to check the property and not the attribute where possible?

There is this issue here which talks about Selenium doing the right thing (even though the OP thinks its a bug).

Is there a way to get Poltergeist to read the js prop instead of the html attribute?

As seen here - https://github.com/teampoltergeist/poltergeist/blob/master/lib/capybara/poltergeist/node.rb#L66 - Poltergeist should already be defaulting to the property over attribute. If it's not, please provide a small self contained example that shows the issue you're having.

Additionally the test you show would probably be better written as

expect(page).not_to have_field(readonly: false)
expect(page).not_to have_field(disabled: false)

or

expect(page).to have_no_field(readonly: false)
expect(page).to have_no_field(disabled: false)

FYI - here's a gist showing that it works correctly - https://gist.github.com/twalpole/412a87b4ba980023ec0a4a3520de107f

Well, in my example when you do page.all, the object that is yielded is a Node::Element, not just a Node. Maybe that's the issue?

The reason why I wrote it the way above is because my code is actually not so simple. The CSS selector is a bit more specific than every single field on the page, it's just fields within one specific form on the page.

Is there a way to use your style with a more specific selector? Perhaps using a within block?

I will try when I get back to a computer.

@synth Capybara::Poltergeist::Node is stored as the base member of Capybara::Node::Element and [] on the Element just calls base[] so it is correct that you would have a Capybara::Node::Element.

As for the style I suggested, it will work fine inside a within block (thereby scoping the check to only inside that form) or by calling it on the form element rather than page

form = find('form#my_form')
# either 
within(form) do
  expect(page).not_to have_field(readonly: false)
  expect(page).not_to have_field(disabled: false)
end
# or
expect(form).not_to have_field(readonly: false)
expect(form).not_to have_field(disabled: false)

Of course, this does all assume you're running current versions of Poltergeist and Capybara. The behavior around properties vs attributes changed to match selenium in Poltergeist 1.8 which was released over a year ago (1.14 is current)- hopefully you're not running something that old and reporting an issue on it.

Thanks, using v1.13. When I have a moment, I"ll create a bare test app and let you know if there is issue with the syntax I was using. I will move my code to more semantic form you recommend.

Closing until proof of the issue is provided. We can reopen if/when it is.