capybara 3.30.0 → 3.31.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +21 -0
  3. data/README.md +1 -1
  4. data/lib/capybara/dsl.rb +10 -2
  5. data/lib/capybara/minitest.rb +18 -4
  6. data/lib/capybara/node/element.rb +11 -8
  7. data/lib/capybara/node/finders.rb +5 -1
  8. data/lib/capybara/node/matchers.rb +24 -15
  9. data/lib/capybara/node/simple.rb +1 -1
  10. data/lib/capybara/queries/base_query.rb +2 -1
  11. data/lib/capybara/rack_test/node.rb +34 -9
  12. data/lib/capybara/result.rb +24 -4
  13. data/lib/capybara/rspec/matchers.rb +27 -27
  14. data/lib/capybara/rspec/matchers/base.rb +12 -6
  15. data/lib/capybara/rspec/matchers/count_sugar.rb +2 -1
  16. data/lib/capybara/rspec/matchers/have_ancestor.rb +4 -3
  17. data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
  18. data/lib/capybara/rspec/matchers/have_selector.rb +15 -7
  19. data/lib/capybara/rspec/matchers/have_sibling.rb +3 -3
  20. data/lib/capybara/rspec/matchers/have_text.rb +2 -2
  21. data/lib/capybara/rspec/matchers/have_title.rb +2 -2
  22. data/lib/capybara/rspec/matchers/match_selector.rb +3 -3
  23. data/lib/capybara/rspec/matchers/match_style.rb +2 -2
  24. data/lib/capybara/rspec/matchers/spatial_sugar.rb +2 -1
  25. data/lib/capybara/selector.rb +2 -0
  26. data/lib/capybara/selector/definition/label.rb +1 -1
  27. data/lib/capybara/selector/definition/select.rb +31 -12
  28. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +1 -1
  29. data/lib/capybara/selenium/extensions/html5_drag.rb +24 -8
  30. data/lib/capybara/selenium/node.rb +23 -6
  31. data/lib/capybara/selenium/nodes/chrome_node.rb +4 -2
  32. data/lib/capybara/selenium/nodes/edge_node.rb +1 -1
  33. data/lib/capybara/selenium/nodes/firefox_node.rb +1 -1
  34. data/lib/capybara/session.rb +30 -15
  35. data/lib/capybara/spec/public/test.js +40 -6
  36. data/lib/capybara/spec/session/all_spec.rb +45 -5
  37. data/lib/capybara/spec/session/assert_text_spec.rb +5 -5
  38. data/lib/capybara/spec/session/fill_in_spec.rb +20 -0
  39. data/lib/capybara/spec/session/has_css_spec.rb +3 -3
  40. data/lib/capybara/spec/session/has_select_spec.rb +28 -0
  41. data/lib/capybara/spec/session/has_text_spec.rb +5 -1
  42. data/lib/capybara/spec/session/node_spec.rb +92 -3
  43. data/lib/capybara/spec/views/form.erb +6 -1
  44. data/lib/capybara/version.rb +1 -1
  45. data/spec/rack_test_spec.rb +0 -1
  46. data/spec/result_spec.rb +4 -0
  47. data/spec/selenium_spec_chrome.rb +2 -1
  48. metadata +2 -2
@@ -15,45 +15,45 @@ module Capybara
15
15
  # RSpec matcher for whether the element(s) matching a given selector exist.
16
16
  #
17
17
  # @see Capybara::Node::Matchers#assert_selector
18
- def have_selector(*args, &optional_filter_block)
19
- Matchers::HaveSelector.new(*args, &optional_filter_block)
18
+ def have_selector(*args, **kw_args, &optional_filter_block)
19
+ Matchers::HaveSelector.new(*args, **kw_args, &optional_filter_block)
20
20
  end
21
21
 
22
22
  # RSpec matcher for whether the element(s) matching a group of selectors exist.
23
23
  #
24
24
  # @see Capybara::Node::Matchers#assert_all_of_selectors
25
- def have_all_of_selectors(*args, &optional_filter_block)
26
- Matchers::HaveAllSelectors.new(*args, &optional_filter_block)
25
+ def have_all_of_selectors(*args, **kw_args, &optional_filter_block)
26
+ Matchers::HaveAllSelectors.new(*args, **kw_args, &optional_filter_block)
27
27
  end
28
28
 
29
29
  # RSpec matcher for whether no element(s) matching a group of selectors exist.
30
30
  #
31
31
  # @see Capybara::Node::Matchers#assert_none_of_selectors
32
- def have_none_of_selectors(*args, &optional_filter_block)
33
- Matchers::HaveNoSelectors.new(*args, &optional_filter_block)
32
+ def have_none_of_selectors(*args, **kw_args, &optional_filter_block)
33
+ Matchers::HaveNoSelectors.new(*args, **kw_args, &optional_filter_block)
34
34
  end
35
35
 
36
36
  # RSpec matcher for whether the element(s) matching any of a group of selectors exist.
37
37
  #
38
38
  # @see Capybara::Node::Matchers#assert_any_of_selectors
39
- def have_any_of_selectors(*args, &optional_filter_block)
40
- Matchers::HaveAnySelectors.new(*args, &optional_filter_block)
39
+ def have_any_of_selectors(*args, **kw_args, &optional_filter_block)
40
+ Matchers::HaveAnySelectors.new(*args, **kw_args, &optional_filter_block)
41
41
  end
42
42
 
43
43
  # RSpec matcher for whether the current element matches a given selector.
44
44
  #
45
45
  # @see Capybara::Node::Matchers#assert_matches_selector
46
- def match_selector(*args, &optional_filter_block)
47
- Matchers::MatchSelector.new(*args, &optional_filter_block)
46
+ def match_selector(*args, **kw_args, &optional_filter_block)
47
+ Matchers::MatchSelector.new(*args, **kw_args, &optional_filter_block)
48
48
  end
49
49
 
50
50
  %i[css xpath].each do |selector|
51
51
  define_method "have_#{selector}" do |expr, **options, &optional_filter_block|
52
- Matchers::HaveSelector.new(selector, expr, options, &optional_filter_block)
52
+ Matchers::HaveSelector.new(selector, expr, **options, &optional_filter_block)
53
53
  end
54
54
 
55
55
  define_method "match_#{selector}" do |expr, **options, &optional_filter_block|
56
- Matchers::MatchSelector.new(selector, expr, options, &optional_filter_block)
56
+ Matchers::MatchSelector.new(selector, expr, **options, &optional_filter_block)
57
57
  end
58
58
  end
59
59
 
@@ -79,7 +79,7 @@ module Capybara
79
79
 
80
80
  %i[link button field select table].each do |selector|
81
81
  define_method "have_#{selector}" do |locator = nil, **options, &optional_filter_block|
82
- Matchers::HaveSelector.new(selector, locator, options, &optional_filter_block)
82
+ Matchers::HaveSelector.new(selector, locator, **options, &optional_filter_block)
83
83
  end
84
84
  end
85
85
 
@@ -110,7 +110,7 @@ module Capybara
110
110
 
111
111
  %i[checked unchecked].each do |state|
112
112
  define_method "have_#{state}_field" do |locator = nil, **options, &optional_filter_block|
113
- Matchers::HaveSelector.new(:field, locator, options.merge(state => true), &optional_filter_block)
113
+ Matchers::HaveSelector.new(:field, locator, **options.merge(state => true), &optional_filter_block)
114
114
  end
115
115
  end
116
116
 
@@ -127,27 +127,27 @@ module Capybara
127
127
  # RSpec matcher for text content.
128
128
  #
129
129
  # @see Capybara::Node::Matchers#assert_text
130
- def have_text(*args)
131
- Matchers::HaveText.new(*args)
130
+ def have_text(text_or_type, *args, **options)
131
+ Matchers::HaveText.new(text_or_type, *args, **options)
132
132
  end
133
133
  alias_method :have_content, :have_text
134
134
 
135
135
  def have_title(title, **options)
136
- Matchers::HaveTitle.new(title, options)
136
+ Matchers::HaveTitle.new(title, **options)
137
137
  end
138
138
 
139
139
  # RSpec matcher for the current path.
140
140
  #
141
141
  # @see Capybara::SessionMatchers#assert_current_path
142
142
  def have_current_path(path, **options)
143
- Matchers::HaveCurrentPath.new(path, options)
143
+ Matchers::HaveCurrentPath.new(path, **options)
144
144
  end
145
145
 
146
146
  # RSpec matcher for element style.
147
147
  #
148
148
  # @see Capybara::Node::Matchers#matches_style?
149
149
  def match_style(styles, **options)
150
- Matchers::MatchStyle.new(styles, options)
150
+ Matchers::MatchStyle.new(styles, **options)
151
151
  end
152
152
 
153
153
  ##
@@ -161,30 +161,30 @@ module Capybara
161
161
  %w[selector css xpath text title current_path link button
162
162
  field checked_field unchecked_field select table
163
163
  sibling ancestor].each do |matcher_type|
164
- define_method "have_no_#{matcher_type}" do |*args, &optional_filter_block|
165
- Matchers::NegatedMatcher.new(send("have_#{matcher_type}", *args, &optional_filter_block))
164
+ define_method "have_no_#{matcher_type}" do |*args, **kw_args, &optional_filter_block|
165
+ Matchers::NegatedMatcher.new(send("have_#{matcher_type}", *args, **kw_args, &optional_filter_block))
166
166
  end
167
167
  end
168
168
  alias_method :have_no_content, :have_no_text
169
169
 
170
170
  %w[selector css xpath].each do |matcher_type|
171
- define_method "not_match_#{matcher_type}" do |*args, &optional_filter_block|
172
- Matchers::NegatedMatcher.new(send("match_#{matcher_type}", *args, &optional_filter_block))
171
+ define_method "not_match_#{matcher_type}" do |*args, **kw_args, &optional_filter_block|
172
+ Matchers::NegatedMatcher.new(send("match_#{matcher_type}", *args, **kw_args, &optional_filter_block))
173
173
  end
174
174
  end
175
175
 
176
176
  # RSpec matcher for whether sibling element(s) matching a given selector exist.
177
177
  #
178
178
  # @see Capybara::Node::Matchers#assert_sibling
179
- def have_sibling(*args, &optional_filter_block)
180
- Matchers::HaveSibling.new(*args, &optional_filter_block)
179
+ def have_sibling(*args, **kw_args, &optional_filter_block)
180
+ Matchers::HaveSibling.new(*args, **kw_args, &optional_filter_block)
181
181
  end
182
182
 
183
183
  # RSpec matcher for whether ancestor element(s) matching a given selector exist.
184
184
  #
185
185
  # @see Capybara::Node::Matchers#assert_ancestor
186
- def have_ancestor(*args, &optional_filter_block)
187
- Matchers::HaveAncestor.new(*args, &optional_filter_block)
186
+ def have_ancestor(*args, **kw_args, &optional_filter_block)
187
+ Matchers::HaveAncestor.new(*args, **kw_args, &optional_filter_block)
188
188
  end
189
189
 
190
190
  ##
@@ -12,22 +12,28 @@ module Capybara
12
12
 
13
13
  attr_reader :failure_message, :failure_message_when_negated
14
14
 
15
- def initialize(*args, &filter_block)
15
+ def initialize(*args, **kw_args, &filter_block)
16
16
  @args = args.dup
17
+ @kw_args = kw_args || {}
17
18
  @filter_block = filter_block
18
19
  end
19
20
 
20
21
  private
21
22
 
22
23
  def session_query_args
23
- if @args.last.is_a? Hash
24
- @args.last[:session_options] = session_options
25
- else
26
- @args.push(session_options: session_options)
27
- end
24
+ # if @args.last.is_a? Hash
25
+ # @args.last[:session_options] = session_options
26
+ # else
27
+ # @args.push(session_options: session_options)
28
+ # end
28
29
  @args
29
30
  end
30
31
 
32
+ def session_query_options
33
+ @kw_args[:session_options] = session_options
34
+ @kw_args
35
+ end
36
+
31
37
  def session_options
32
38
  @context_el ||= nil
33
39
  if @context_el.respond_to? :session_options
@@ -29,7 +29,8 @@ module Capybara
29
29
  private
30
30
 
31
31
  def options
32
- (@args.last.is_a?(Hash) ? @args : @args.push({})).last
32
+ # (@args.last.is_a?(Hash) ? @args : @args.push({})).last
33
+ @kw_args
33
34
  end
34
35
  end
35
36
  end
@@ -7,11 +7,11 @@ module Capybara
7
7
  module Matchers
8
8
  class HaveAncestor < CountableWrappedElementMatcher
9
9
  def element_matches?(el)
10
- el.assert_ancestor(*@args, &@filter_block)
10
+ el.assert_ancestor(*@args, **session_query_options, &@filter_block)
11
11
  end
12
12
 
13
13
  def element_does_not_match?(el)
14
- el.assert_no_ancestor(*@args, &@filter_block)
14
+ el.assert_no_ancestor(*@args, **session_query_options, &@filter_block)
15
15
  end
16
16
 
17
17
  def description
@@ -19,7 +19,8 @@ module Capybara
19
19
  end
20
20
 
21
21
  def query
22
- @query ||= Capybara::Queries::AncestorQuery.new(*session_query_args, &@filter_block)
22
+ # @query ||= Capybara::Queries::AncestorQuery.new(*session_query_args, &@filter_block)
23
+ @query ||= Capybara::Queries::AncestorQuery.new(*session_query_args, **session_query_options, &@filter_block)
23
24
  end
24
25
  end
25
26
  end
@@ -7,11 +7,11 @@ module Capybara
7
7
  module Matchers
8
8
  class HaveCurrentPath < WrappedElementMatcher
9
9
  def element_matches?(el)
10
- el.assert_current_path(*@args)
10
+ el.assert_current_path(current_path, **@kw_args)
11
11
  end
12
12
 
13
13
  def element_does_not_match?(el)
14
- el.assert_no_current_path(*@args)
14
+ el.assert_no_current_path(current_path, **@kw_args)
15
15
  end
16
16
 
17
17
  def description
@@ -6,12 +6,20 @@ module Capybara
6
6
  module RSpecMatchers
7
7
  module Matchers
8
8
  class HaveSelector < CountableWrappedElementMatcher
9
+ def initialize(*args, **kw_args, &filter_block)
10
+ super
11
+ if (RUBY_VERSION >= '2.7') && (@args.size < 2) && @kw_args.keys.any?(String) # rubocop:disable Style/GuardClause
12
+ @args.push(@kw_args)
13
+ @kw_args = {}
14
+ end
15
+ end
16
+
9
17
  def element_matches?(el)
10
- el.assert_selector(*@args, &@filter_block)
18
+ el.assert_selector(*@args, **session_query_options, &@filter_block)
11
19
  end
12
20
 
13
21
  def element_does_not_match?(el)
14
- el.assert_no_selector(*@args, &@filter_block)
22
+ el.assert_no_selector(*@args, **session_query_options, &@filter_block)
15
23
  end
16
24
 
17
25
  def description
@@ -19,13 +27,13 @@ module Capybara
19
27
  end
20
28
 
21
29
  def query
22
- @query ||= Capybara::Queries::SelectorQuery.new(*session_query_args, &@filter_block)
30
+ @query ||= Capybara::Queries::SelectorQuery.new(*session_query_args, **session_query_options, &@filter_block)
23
31
  end
24
32
  end
25
33
 
26
34
  class HaveAllSelectors < WrappedElementMatcher
27
35
  def element_matches?(el)
28
- el.assert_all_of_selectors(*@args, &@filter_block)
36
+ el.assert_all_of_selectors(*@args, **session_query_options, &@filter_block)
29
37
  end
30
38
 
31
39
  def does_not_match?(_actual)
@@ -39,7 +47,7 @@ module Capybara
39
47
 
40
48
  class HaveNoSelectors < WrappedElementMatcher
41
49
  def element_matches?(el)
42
- el.assert_none_of_selectors(*@args, &@filter_block)
50
+ el.assert_none_of_selectors(*@args, **session_query_options, &@filter_block)
43
51
  end
44
52
 
45
53
  def does_not_match?(_actual)
@@ -53,11 +61,11 @@ module Capybara
53
61
 
54
62
  class HaveAnySelectors < WrappedElementMatcher
55
63
  def element_matches?(el)
56
- el.assert_any_of_selectors(*@args, &@filter_block)
64
+ el.assert_any_of_selectors(*@args, **session_query_options, &@filter_block)
57
65
  end
58
66
 
59
67
  def does_not_match?(_actual)
60
- el.assert_none_of_selectors(*@args, &@filter_block)
68
+ el.assert_none_of_selectors(*@args, **session_query_options, &@filter_block)
61
69
  end
62
70
 
63
71
  def description
@@ -7,11 +7,11 @@ module Capybara
7
7
  module Matchers
8
8
  class HaveSibling < CountableWrappedElementMatcher
9
9
  def element_matches?(el)
10
- el.assert_sibling(*@args, &@filter_block)
10
+ el.assert_sibling(*@args, **session_query_options, &@filter_block)
11
11
  end
12
12
 
13
13
  def element_does_not_match?(el)
14
- el.assert_no_sibling(*@args, &@filter_block)
14
+ el.assert_no_sibling(*@args, **session_query_options, &@filter_block)
15
15
  end
16
16
 
17
17
  def description
@@ -19,7 +19,7 @@ module Capybara
19
19
  end
20
20
 
21
21
  def query
22
- @query ||= Capybara::Queries::SiblingQuery.new(*session_query_args, &@filter_block)
22
+ @query ||= Capybara::Queries::SiblingQuery.new(*session_query_args, **session_query_options, &@filter_block)
23
23
  end
24
24
  end
25
25
  end
@@ -7,11 +7,11 @@ module Capybara
7
7
  module Matchers
8
8
  class HaveText < CountableWrappedElementMatcher
9
9
  def element_matches?(el)
10
- el.assert_text(*@args)
10
+ el.assert_text(*@args, **@kw_args)
11
11
  end
12
12
 
13
13
  def element_does_not_match?(el)
14
- el.assert_no_text(*@args)
14
+ el.assert_no_text(*@args, **@kw_args)
15
15
  end
16
16
 
17
17
  def description
@@ -7,11 +7,11 @@ module Capybara
7
7
  module Matchers
8
8
  class HaveTitle < WrappedElementMatcher
9
9
  def element_matches?(el)
10
- el.assert_title(*@args)
10
+ el.assert_title(*@args, **@kw_args)
11
11
  end
12
12
 
13
13
  def element_does_not_match?(el)
14
- el.assert_no_title(*@args)
14
+ el.assert_no_title(*@args, **@kw_args)
15
15
  end
16
16
 
17
17
  def description
@@ -7,11 +7,11 @@ module Capybara
7
7
  module Matchers
8
8
  class MatchSelector < HaveSelector
9
9
  def element_matches?(el)
10
- el.assert_matches_selector(*@args, &@filter_block)
10
+ el.assert_matches_selector(*@args, **session_query_options, &@filter_block)
11
11
  end
12
12
 
13
13
  def element_does_not_match?(el)
14
- el.assert_not_matches_selector(*@args, &@filter_block)
14
+ el.assert_not_matches_selector(*@args, **session_query_options, &@filter_block)
15
15
  end
16
16
 
17
17
  def description
@@ -19,7 +19,7 @@ module Capybara
19
19
  end
20
20
 
21
21
  def query
22
- @query ||= Capybara::Queries::MatchQuery.new(*session_query_args, &@filter_block)
22
+ @query ||= Capybara::Queries::MatchQuery.new(*session_query_args, **session_query_options, &@filter_block)
23
23
  end
24
24
  end
25
25
  end
@@ -7,7 +7,7 @@ module Capybara
7
7
  module Matchers
8
8
  class MatchStyle < WrappedElementMatcher
9
9
  def element_matches?(el)
10
- el.assert_matches_style(*@args)
10
+ el.assert_matches_style(*@args, **@kw_args)
11
11
  end
12
12
 
13
13
  def does_not_match?(_actual)
@@ -28,7 +28,7 @@ module Capybara
28
28
  ##
29
29
  # @deprecated
30
30
  class HaveStyle < MatchStyle
31
- def initialize(*args, &filter_block)
31
+ def initialize(*args, **kw_args, &filter_block)
32
32
  warn 'HaveStyle matcher is deprecated, please use the MatchStyle matcher instead'
33
33
  super
34
34
  end
@@ -31,7 +31,8 @@ module Capybara
31
31
  private
32
32
 
33
33
  def options
34
- (@args.last.is_a?(Hash) ? @args : @args.push({})).last
34
+ # (@args.last.is_a?(Hash) ? @args : @args.push({})).last
35
+ @kw_args
35
36
  end
36
37
  end
37
38
  end
@@ -108,6 +108,8 @@ require 'capybara/selector/definition'
108
108
  # * :disabled (Boolean, :all) - Match disabled field? (Default: false)
109
109
  # * :multiple (Boolean) - Match fields that accept multiple values
110
110
  # * :options (Array<String>) - Exact match options
111
+ # * :enabled_options (Array<String>) - Exact match enabled options
112
+ # * :disabled_options (Array<String>) - Exact match disabled options
111
113
  # * :with_options (Array<String>) - Partial match options
112
114
  # * :selected (String, Array<String>) - Match the selection(s)
113
115
  # * :with_selected (String, Array<String>) - Partial match the selection(s)
@@ -2,7 +2,7 @@
2
2
 
3
3
  Capybara.add_selector(:label, locator_type: [String, Symbol]) do
4
4
  label 'label'
5
- xpath(:for) do |locator, options|
5
+ xpath(:for) do |locator, **options|
6
6
  xpath = XPath.descendant(:label)
7
7
  unless locator.nil?
8
8
  locator_matchers = XPath.string.n.is(locator.to_s) | (XPath.attr(:id) == locator.to_s)
@@ -11,16 +11,26 @@ Capybara.add_selector(:select, locator_type: [String, Symbol]) do
11
11
  filter_set(:_field, %i[disabled multiple name placeholder])
12
12
 
13
13
  node_filter(:options) do |node, options|
14
- actual = if node.visible?
15
- node.all(:xpath, './/option', wait: false).map(&:text)
16
- else
17
- node.all(:xpath, './/option', visible: false, wait: false).map { |option| option.text(:all) }
18
- end
14
+ actual = options_text(node)
19
15
  (options.sort == actual.sort).tap do |res|
20
16
  add_error("Expected options #{options.inspect} found #{actual.inspect}") unless res
21
17
  end
22
18
  end
23
19
 
20
+ node_filter(:enabled_options) do |node, options|
21
+ actual = options_text(node) { |o| !o.disabled? }
22
+ (options.sort == actual.sort).tap do |res|
23
+ add_error("Expected enabled options #{options.inspect} found #{actual.inspect}") unless res
24
+ end
25
+ end
26
+
27
+ node_filter(:disabled_options) do |node, options|
28
+ actual = options_text(node, &:disabled?)
29
+ (options.sort == actual.sort).tap do |res|
30
+ add_error("Expected disabled options #{options.inspect} found #{actual.inspect}") unless res
31
+ end
32
+ end
33
+
24
34
  expression_filter(:with_options) do |expr, options|
25
35
  options.inject(expr) do |xpath, option|
26
36
  xpath[expression_for(:option, option)]
@@ -28,18 +38,14 @@ Capybara.add_selector(:select, locator_type: [String, Symbol]) do
28
38
  end
29
39
 
30
40
  node_filter(:selected) do |node, selected|
31
- actual = node.all(:xpath, './/option', visible: false, wait: false)
32
- .select(&:selected?)
33
- .map { |option| option.text(:all) }
41
+ actual = options_text(node, visible: false, &:selected?)
34
42
  (Array(selected).sort == actual.sort).tap do |res|
35
43
  add_error("Expected #{selected.inspect} to be selected found #{actual.inspect}") unless res
36
44
  end
37
45
  end
38
46
 
39
47
  node_filter(:with_selected) do |node, selected|
40
- actual = node.all(:xpath, './/option', visible: false, wait: false)
41
- .select(&:selected?)
42
- .map { |option| option.text(:all) }
48
+ actual = options_text(node, visible: false, &:selected?)
43
49
  (Array(selected) - actual).empty?.tap do |res|
44
50
  add_error("Expected at least #{selected.inspect} to be selected found #{actual.inspect}") unless res
45
51
  end
@@ -51,12 +57,25 @@ Capybara.add_selector(:select, locator_type: [String, Symbol]) do
51
57
  desc
52
58
  end
53
59
 
54
- describe_node_filters do |options: nil, selected: nil, with_selected: nil, disabled: nil, **|
60
+ describe_node_filters do |
61
+ options: nil, disabled_options: nil, enabled_options: nil,
62
+ selected: nil, with_selected: nil,
63
+ disabled: nil, **|
55
64
  desc = +''
56
65
  desc << " with options #{options.inspect}" if options
66
+ desc << " with disabled options #{disabled_options.inspect}}" if disabled_options
67
+ desc << " with enabled options #{enabled_options.inspect}" if enabled_options
57
68
  desc << " with #{selected.inspect} selected" if selected
58
69
  desc << " with at least #{with_selected.inspect} selected" if with_selected
59
70
  desc << ' which is disabled' if disabled
60
71
  desc
61
72
  end
73
+
74
+ def options_text(node, **opts, &filter_block)
75
+ opts[:wait] = false
76
+ opts[:visible] = false unless node.visible?
77
+ node.all(:xpath, './/option', **opts, &filter_block).map do |o|
78
+ o.text((:all if opts[:visible] == false))
79
+ end
80
+ end
62
81
  end