twalpole / apparition

Capybara driver for Chrome using CDP
MIT License
363 stars 46 forks source link

property(:validity) is always nil #20

Closed TylerRick closed 5 years ago

TylerRick commented 5 years ago

When using a Selenium driver, I'm able to check the validity state of an input with element.native.property(:validity). But with Apparition driver, property(:validity) always returns nil. Why is that? And can it be fixed?

Example

As an example, I have an input in my tests that I wanted to test transitioned from "valid"=>false to "valid"=>true after changing the input in a certain way.

This is what it returned when it was invalid:

element.native.property(:validity)={"badInput"=>false, "customError"=>false, "patternMismatch"=>false, "rangeOverflow"=>false, "rangeUnderflow"=>false, "stepMismatch"=>false, "tooLong"=>false, "tooShort"=>false, "typeMismatch"=>false, "valid"=>false, "valueMissing"=>true}

This is what it returned when it was invalid:

element.native.property(:validity)={"badInput"=>false, "customError"=>false, "patternMismatch"=>false, "rangeOverflow"=>false, "rangeUnderflow"=>false, "stepMismatch"=>false, "tooLong"=>false, "tooShort"=>false, "typeMismatch"=>false, "valid"=>true, "valueMissing"=>false}    

I can't figure out how to do this with apparition since it always returns nil.

validationMessage property is available

Interestingly, I noticed that the validationMessage property is available for the same element, so as a workaround I was able to check whether validationMessage was present? or not (seems to return "" when input is valid).

I'm curious why apparition has is able to get validationMessage but not validity. In the developer tools console, you can see that the validity property does exist and is not null.

Some related test helpers

  def element_validity(element)
    element.native.property(:validity).with_indifferent_access
  end

  def element_validitation_message(element)
    element.native.property(:validationMessage)
  end

  def element_valid?(element)
    if selenium?
      element_validity(element)[:valid]
    else
      element_validitation_message(element).blank?
    end
  end

  def expect_invalid(element)
    #expect_validity_match(element, valid: false)
    expect(element_valid?(element)).to eq false
  end

  def expect_valid(element)
    #expect_validity_match(element, valid: true)
    expect(element_valid?(element)).to eq true
  end

  def expect_validity_match(element, expected)
    raise NotImplementedError unless selenium?
    expect(element_validity(element)).to include expected
  end
twalpole commented 5 years ago

Using element.native for normal things is generally a bad idea - since it makes your tests driver specific. Also the way you're writing your helpers is going to produce race conditions. You'll be much better off just using the CSS pseudo selectors :valid and :invalid -

def expect_valid(element)
    expect(element).to match_css('*:valid')
end
twalpole commented 5 years ago

As to why it always returns nil for this - it's because validity returns a ValidityState object which Apparition doesn't know how to deal with, I need to look at that.

twalpole commented 5 years ago

Fixed nil response via 72233c0262f6430caf88fbfea643c6ae32ea017f - however you're still going to be better off longterm just using the :valid/:invalid CSS pseudo selectors rather than directly accessing the validity property.

twalpole commented 5 years ago

Also, the next Capybara release will have a :valid node filter option on the :field and :fillable_field selectors