diff --git a/History.md b/History.md index 42995cd2bf..1dd27fc2b5 100644 --- a/History.md +++ b/History.md @@ -5,6 +5,7 @@ Release date: unreleased * Allow forcing HTML5 or legacy dragging via the `:html5` option to `drag_to` when using Selenium with Chrome or Firefox * Autodetection of drag type interprets not seeing the mousedown event as legacy. +* HTML5 form validation `:valid` node filter added to `:field` and `:fillable_field` selectors # Version 3.27.0 Release date: 2019-07-28 diff --git a/lib/capybara/selector.rb b/lib/capybara/selector.rb index 2b0c0892ca..ce19d5dd1c 100644 --- a/lib/capybara/selector.rb +++ b/lib/capybara/selector.rb @@ -34,6 +34,7 @@ # * :unchecked (Boolean) - Match unchecked fields? # * :disabled (Boolean, :all) - Match disabled field? (Default: false) # * :multiple (Boolean) - Match fields that accept multiple values +# * :valid (Boolean) - Match fields that are valid/invalid according to HTML5 form validation # # * **:fieldset** - Select fieldset elements # * Locator: Matches id, {Capybara.configure test_id}, or contents of wrapped legend @@ -72,6 +73,7 @@ # * :type (String) - Matches the type attribute of the field or element type for 'textarea' # * :disabled (Boolean, :all) - Match disabled field? (Default: false) # * :multiple (Boolean) - Match fields that accept multiple values +# * :valid (Boolean) - Match fields that are valid/invalid according to HTML5 form validation # # * **:radio_button** - Find radio buttons # * Locator: Match id, {Capybara.configure test_id} attribute, name, or associated label text @@ -166,6 +168,7 @@ class Capybara::Selector; end node_filter(:checked, :boolean) { |node, value| !(value ^ node.checked?) } node_filter(:unchecked, :boolean) { |node, value| (value ^ node.checked?) } node_filter(:disabled, :boolean, default: false, skip_if: :all) { |node, value| !(value ^ node.disabled?) } + node_filter(:valid, :boolean) { |node, value| node.evaluate_script('this.validity.valid') == value } expression_filter(:name) { |xpath, val| xpath[XPath.attr(:name) == val] } expression_filter(:placeholder) { |xpath, val| xpath[XPath.attr(:placeholder) == val] } @@ -182,12 +185,14 @@ class Capybara::Selector; end desc end - describe(:node_filters) do |checked: nil, unchecked: nil, disabled: nil, **| + describe(:node_filters) do |checked: nil, unchecked: nil, disabled: nil, valid: nil, **| desc, states = +'', [] states << 'checked' if checked || (unchecked == false) states << 'not checked' if unchecked || (checked == false) states << 'disabled' if disabled == true desc << " that is #{states.join(' and ')}" unless states.empty? + desc << ' that is valid' if valid == true + desc << ' that is invalid' if valid == false desc end end diff --git a/lib/capybara/selector/definition/fillable_field.rb b/lib/capybara/selector/definition/fillable_field.rb index 98a49ff94c..eba9baaad6 100644 --- a/lib/capybara/selector/definition/fillable_field.rb +++ b/lib/capybara/selector/definition/fillable_field.rb @@ -18,7 +18,7 @@ end end - filter_set(:_field, %i[disabled multiple name placeholder]) + filter_set(:_field, %i[disabled multiple name placeholder valid]) node_filter(:with) do |node, with| val = node.value diff --git a/lib/capybara/spec/session/has_field_spec.rb b/lib/capybara/spec/session/has_field_spec.rb index 0530af77ca..8a3e24544d 100644 --- a/lib/capybara/spec/session/has_field_spec.rb +++ b/lib/capybara/spec/session/has_field_spec.rb @@ -93,6 +93,24 @@ expect(@session).not_to have_field('Html5 Multiple Email', multiple: false) end end + + context 'with valid', requires: [:js] do + it 'should be true if field is valid' do + @session.fill_in 'required', with: 'something' + @session.fill_in 'length', with: 'abcd' + + expect(@session).to have_field('required', valid: true) + expect(@session).to have_field('length', valid: true) + end + + it 'should be false if field is invalid' do + expect(@session).not_to have_field('required', valid: true) + expect(@session).to have_field('required', valid: false) + + @session.fill_in 'length', with: 'abc' + expect(@session).not_to have_field('length', valid: true) + end + end end Capybara::SpecHelper.spec '#has_no_field' do diff --git a/lib/capybara/spec/views/form.erb b/lib/capybara/spec/views/form.erb index 118d72ef99..03369d5b19 100644 --- a/lib/capybara/spec/views/form.erb +++ b/lib/capybara/spec/views/form.erb @@ -1,7 +1,7 @@

Form

-
+

@@ -460,6 +460,11 @@ New line after and before textarea tag

+ +

+ + +