Skip to content

Commit

Permalink
Add :valid node filter to :field and :fillable_field selectors
Browse files Browse the repository at this point in the history
  • Loading branch information
twalpole committed Jul 31, 2019
1 parent 2541eb4 commit 90ab5b6
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 3 deletions.
1 change: 1 addition & 0 deletions History.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion lib/capybara/selector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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] }
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/capybara/selector/definition/fillable_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 18 additions & 0 deletions lib/capybara/spec/session/has_field_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion lib/capybara/spec/views/form.erb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

<h1>Form</h1>

<form action="/form" method="post">
<form action="/form" method="post" novalidate>

<p>
<label for="form_title">Title</label>
Expand Down Expand Up @@ -460,6 +460,11 @@ New line after and before textarea tag
<input id="readonly" name="form[readonly_test]" readonly/>
<input id="not_readonly" name="form[readonly_test]" />
</p>

<p>
<input id="required" name="form[required]" required />
<input id="length" name="form[length]" minlength="4" maxlength="4" />
</p>
</form>

<input type="text" name="form[outside_input]" value="outside_input" form="form1"/>
Expand Down

0 comments on commit 90ab5b6

Please sign in to comment.