rspec-html-matchers 0.7.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,240 +1,30 @@
1
1
  # encoding: UTF-8
2
- require 'rspec'
3
- require 'nokogiri'
4
-
2
+ # frozen_string_literal: true
3
+
4
+ require 'rspec-html-matchers/nokogiri_regexp_helper'
5
+ require 'rspec-html-matchers/nokogiri_text_helper'
6
+ require 'rspec-html-matchers/have_tag'
7
+
8
+ # RSpec global configuration:
9
+ #
10
+ # RSpec.configure do |config|
11
+ # config.include RSpecHtmlMatchers
12
+ # end
13
+ #
14
+ # RSpec per-test configuration
15
+ #
16
+ # RSpec.describe "my view spec" do
17
+ # include RSpecHtmlMatchers
18
+ #
19
+ # it "has tags" do
20
+ # expect(rendered).to have_tag('div')
21
+ # end
22
+ # end
23
+ #
24
+ # Cucumber configuration:
25
+ #
26
+ # World RSpecHtmlMatchers
5
27
  module RSpecHtmlMatchers
6
-
7
- # @api
8
- # @private
9
- # for nokogiri regexp matching
10
- class NokogiriRegexpHelper
11
- def initialize(regex)
12
- @regex = regex
13
- end
14
-
15
- def regexp node_set
16
- node_set.find_all { |node| node.content =~ @regex }
17
- end
18
- end
19
-
20
- # @api
21
- # @private
22
- class NokogiriTextHelper
23
- NON_BREAKING_SPACE = "\u00a0"
24
-
25
- def initialize text
26
- @text = text
27
- end
28
-
29
- def content node_set
30
- node_set.find_all do |node|
31
- actual_content = node.content.gsub(NON_BREAKING_SPACE, ' ')
32
-
33
- actual_content == @text
34
- end
35
- end
36
- end
37
-
38
- # @api
39
- # @private
40
- class HaveTag
41
- attr_reader :failure_message, :failure_message_when_negated
42
- attr_reader :parent_scope, :current_scope
43
-
44
- DESCRIPTIONS = {
45
- :have_at_least_1 => %Q|have at least 1 element matching "%s"|,
46
- :have_n => %Q|have %i element(s) matching "%s"|
47
- }
48
-
49
- MESSAGES = {
50
- :expected_tag => %Q|expected following:\n%s\nto #{DESCRIPTIONS[:have_at_least_1]}, found 0.|,
51
- :unexpected_tag => %Q|expected following:\n%s\nto NOT have element matching "%s", found %s.|,
52
-
53
- :expected_count => %Q|expected following:\n%s\nto #{DESCRIPTIONS[:have_n]}, found %s.|,
54
- :unexpected_count => %Q|expected following:\n%s\nto NOT have %i element(s) matching "%s", but found.|,
55
-
56
- :expected_btw_count => %Q|expected following:\n%s\nto have at least %i and at most %i element(s) matching "%s", found %i.|,
57
- :unexpected_btw_count => %Q|expected following:\n%s\nto NOT have at least %i and at most %i element(s) matching "%s", but found %i.|,
58
-
59
- :expected_at_most => %Q|expected following:\n%s\nto have at most %i element(s) matching "%s", found %i.|,
60
- :unexpected_at_most => %Q|expected following:\n%s\nto NOT have at most %i element(s) matching "%s", but found %i.|,
61
-
62
- :expected_at_least => %Q|expected following:\n%s\nto have at least %i element(s) matching "%s", found %i.|,
63
- :unexpected_at_least => %Q|expected following:\n%s\nto NOT have at least %i element(s) matching "%s", but found %i.|,
64
-
65
- :expected_regexp => %Q|%s regexp expected within "%s" in following template:\n%s|,
66
- :unexpected_regexp => %Q|%s regexp unexpected within "%s" in following template:\n%s\nbut was found.|,
67
-
68
- :expected_text => %Q|"%s" expected within "%s" in following template:\n%s|,
69
- :unexpected_text => %Q|"%s" unexpected within "%s" in following template:\n%s\nbut was found.|,
70
-
71
- :wrong_count_error => %Q|:count with :minimum or :maximum has no sence!|,
72
- :min_max_error => %Q|:minimum should be less than :maximum!|,
73
- :bad_range_error => %Q|Your :count range(%s) has no sence!|,
74
- }
75
-
76
-
77
- def initialize tag, options={}, &block
78
- @tag, @options, @block = tag.to_s, options, block
79
-
80
- if with_attrs = @options.delete(:with)
81
- if classes = with_attrs.delete(:class)
82
- @tag << '.' + classes_to_selector(classes)
83
- end
84
- selector = with_attrs.inject('') do |html_attrs_string, (k, v)|
85
- html_attrs_string << "[#{k}='#{v}']"
86
- html_attrs_string
87
- end
88
- @tag << selector
89
- end
90
-
91
- if without_attrs = @options.delete(:without)
92
- if classes = without_attrs.delete(:class)
93
- @tag << ":not(.#{classes_to_selector(classes)})"
94
- end
95
- end
96
-
97
- validate_options!
98
- end
99
-
100
- def matches? document, &block
101
- @block = block if block
102
-
103
- document = document.html if defined?(Capybara::Session) && document.is_a?(Capybara::Session)
104
-
105
- case document
106
- when String
107
- @parent_scope = @current_scope = Nokogiri::HTML(document).css(@tag)
108
- @document = document
109
- else
110
- @parent_scope = document.current_scope
111
- @current_scope = begin
112
- document.parent_scope.css(@tag)
113
- # on jruby this produce exception if css was not found:
114
- # undefined method `decorate' for nil:NilClass
115
- rescue NoMethodError
116
- Nokogiri::XML::NodeSet.new(Nokogiri::XML::Document.new)
117
- end
118
- @document = @parent_scope.to_html
119
- end
120
-
121
- if tag_presents? and text_right? and count_right?
122
- @current_scope = @parent_scope
123
- @block.call if @block
124
- true
125
- else
126
- false
127
- end
128
- end
129
-
130
- def description
131
- # TODO should it be more complicated?
132
- if @options.has_key?(:count)
133
- DESCRIPTIONS[:have_n] % [@options[:count],@tag]
134
- else
135
- DESCRIPTIONS[:have_at_least_1] % @tag
136
- end
137
- end
138
-
139
- private
140
-
141
- def classes_to_selector(classes)
142
- case classes
143
- when Array
144
- classes.join('.')
145
- when String
146
- classes.gsub(/\s+/, '.')
147
- end
148
- end
149
-
150
- def tag_presents?
151
- if @current_scope.first
152
- @count = @current_scope.count
153
- @failure_message_when_negated = MESSAGES[:unexpected_tag] % [@document, @tag, @count]
154
- true
155
- else
156
- @failure_message = MESSAGES[:expected_tag] % [@document, @tag]
157
- false
158
- end
159
- end
160
-
161
- def count_right?
162
- case @options[:count]
163
- when Integer
164
- ((@failure_message_when_negated=MESSAGES[:unexpected_count] % [@document,@count,@tag]) && @count == @options[:count]) || (@failure_message=MESSAGES[:expected_count] % [@document,@options[:count],@tag,@count]; false)
165
- when Range
166
- ((@failure_message_when_negated=MESSAGES[:unexpected_btw_count] % [@document,@options[:count].min,@options[:count].max,@tag,@count]) && @options[:count].member?(@count)) || (@failure_message=MESSAGES[:expected_btw_count] % [@document,@options[:count].min,@options[:count].max,@tag,@count]; false)
167
- when nil
168
- if @options[:maximum]
169
- ((@failure_message_when_negated=MESSAGES[:unexpected_at_most] % [@document,@options[:maximum],@tag,@count]) && @count <= @options[:maximum]) || (@failure_message=MESSAGES[:expected_at_most] % [@document,@options[:maximum],@tag,@count]; false)
170
- elsif @options[:minimum]
171
- ((@failure_message_when_negated=MESSAGES[:unexpected_at_least] % [@document,@options[:minimum],@tag,@count]) && @count >= @options[:minimum]) || (@failure_message=MESSAGES[:expected_at_least] % [@document,@options[:minimum],@tag,@count]; false)
172
- else
173
- true
174
- end
175
- end
176
- end
177
-
178
- def text_right?
179
- return true unless @options[:text]
180
-
181
- case text=@options[:text]
182
- when Regexp
183
- new_scope = @current_scope.css(':regexp()',NokogiriRegexpHelper.new(text))
184
- unless new_scope.empty?
185
- @count = new_scope.count
186
- @failure_message_when_negated = MESSAGES[:unexpected_regexp] % [text.inspect,@tag,@document]
187
- true
188
- else
189
- @failure_message = MESSAGES[:expected_regexp] % [text.inspect,@tag,@document]
190
- false
191
- end
192
- else
193
- new_scope = @current_scope.css(':content()',NokogiriTextHelper.new(text))
194
- unless new_scope.empty?
195
- @count = new_scope.count
196
- @failure_message_when_negated = MESSAGES[:unexpected_text] % [text,@tag,@document]
197
- true
198
- else
199
- @failure_message = MESSAGES[:expected_text] % [text,@tag,@document]
200
- false
201
- end
202
- end
203
- end
204
-
205
- protected
206
-
207
- def validate_options!
208
- raise 'wrong :count specified' unless [Range, NilClass].include?(@options[:count].class) or @options[:count].is_a?(Integer)
209
-
210
- [:min, :minimum, :max, :maximum].each do |key|
211
- raise MESSAGES[:wrong_count_error] if @options.has_key?(key) and @options.has_key?(:count)
212
- end
213
-
214
- begin
215
- raise MESSAGES[:min_max_error] if @options[:minimum] > @options[:maximum]
216
- rescue NoMethodError # nil > 4
217
- rescue ArgumentError # 2 < nil
218
- end
219
-
220
- begin
221
- begin
222
- raise MESSAGES[:bad_range_error] % [@options[:count].to_s] if @options[:count] && @options[:count].is_a?(Range) && (@options[:count].min.nil? or @options[:count].min < 0)
223
- rescue ArgumentError, "comparison of String with" # if @options[:count] == 'a'..'z'
224
- raise MESSAGES[:bad_range_error] % [@options[:count].to_s]
225
- end
226
- rescue TypeError # fix for 1.8.7 for 'rescue ArgumentError, "comparison of String with"' stroke
227
- raise MESSAGES[:bad_range_error] % [@options[:count].to_s]
228
- end
229
-
230
- @options[:minimum] ||= @options.delete(:min)
231
- @options[:maximum] ||= @options.delete(:max)
232
-
233
- @options[:text] = @options[:text].to_s if @options.has_key?(:text) && !@options[:text].is_a?(Regexp)
234
- end
235
-
236
- end
237
-
238
28
  # tag assertion, this is the core of functionality, other matchers are shortcuts to this matcher
239
29
  #
240
30
  # @yield block where you should put with_tag, without_tag and/or other matchers
@@ -269,41 +59,60 @@ module RSpecHtmlMatchers
269
59
  # </html>").to have_tag('body') { with_tag('h1', :text => 'some html document') }
270
60
  # expect('<div class="one two">').to have_tag('div', :with => { :class => ['two', 'one'] })
271
61
  # expect('<div class="one two">').to have_tag('div', :with => { :class => 'two one' })
272
- def have_tag tag, options={}, &block
62
+ def have_tag tag, options = {}, &block
273
63
  # for backwards compatibility with rpecs have tag:
274
- options = { :text => options } if options.kind_of?(String) || options.kind_of?(Regexp)
64
+ options = { :text => options } if options.is_a?(String) || options.is_a?(Regexp)
275
65
  @__current_scope_for_nokogiri_matcher = HaveTag.new(tag, options, &block)
276
66
  end
277
67
 
68
+ # tests whether tag have any content inside
69
+ #
70
+ # @example
71
+ # expect('<div></div>').to have_empty_tag('div') # success
72
+ # expect('<div>hi</div>').to have_empty_tag('div') # fail
73
+ def have_empty_tag tag, options = {}
74
+ have_tag(tag, options.merge(:blank => true))
75
+ end
76
+
278
77
  def with_text text
279
78
  raise StandardError, 'this matcher should be used inside "have_tag" matcher block' unless defined?(@__current_scope_for_nokogiri_matcher)
280
79
  raise ArgumentError, 'this matcher does not accept block' if block_given?
80
+
281
81
  tag = @__current_scope_for_nokogiri_matcher.instance_variable_get(:@tag)
282
- expect(@__current_scope_for_nokogiri_matcher).to have_tag(tag, :text => text)
82
+ within_nested_tag do
83
+ expect(@__current_scope_for_nokogiri_matcher).to have_tag(tag, :text => text)
84
+ end
283
85
  end
284
86
 
285
87
  def without_text text
286
88
  raise StandardError, 'this matcher should be used inside "have_tag" matcher block' unless defined?(@__current_scope_for_nokogiri_matcher)
287
89
  raise ArgumentError, 'this matcher does not accept block' if block_given?
90
+
288
91
  tag = @__current_scope_for_nokogiri_matcher.instance_variable_get(:@tag)
289
- expect(@__current_scope_for_nokogiri_matcher).to_not have_tag(tag, :text => text)
92
+ within_nested_tag do
93
+ expect(@__current_scope_for_nokogiri_matcher).to_not have_tag(tag, :text => text)
94
+ end
290
95
  end
291
- alias :but_without_text :without_text
96
+ alias but_without_text without_text
292
97
 
293
98
  # with_tag matcher
294
99
  # @yield block where you should put other with_tag or without_tag
295
100
  # @see #have_tag
296
101
  # @note this should be used within block of have_tag matcher
297
- def with_tag tag, options={}, &block
298
- expect(@__current_scope_for_nokogiri_matcher).to have_tag(tag, options, &block)
102
+ def with_tag tag, options = {}, &block
103
+ within_nested_tag do
104
+ expect(@__current_scope_for_nokogiri_matcher).to have_tag(tag, options, &block)
105
+ end
299
106
  end
300
107
 
301
108
  # without_tag matcher
302
109
  # @yield block where you should put other with_tag or without_tag
303
110
  # @see #have_tag
304
111
  # @note this should be used within block of have_tag matcher
305
- def without_tag tag, options={}, &block
306
- expect(@__current_scope_for_nokogiri_matcher).to_not have_tag(tag, options, &block)
112
+ def without_tag tag, options = {}, &block
113
+ within_nested_tag do
114
+ expect(@__current_scope_for_nokogiri_matcher).to_not have_tag(tag, options, &block)
115
+ end
307
116
  end
308
117
 
309
118
  # form assertion
@@ -312,248 +121,275 @@ module RSpecHtmlMatchers
312
121
  # have_tag 'form', :with => { :action => action_url, :method => method ... }
313
122
  # @yield block with with_<field>, see below
314
123
  # @see #have_tag
315
- def have_form action_url, method, options={}, &block
124
+ def have_form action_url, method, options = {}, &block
316
125
  options[:with] ||= {}
317
126
  id = options[:with].delete(:id)
318
- tag = 'form'; tag << '#'+id if id
127
+ tag = 'form'; tag += '#' + id if id
319
128
  options[:with].merge!(:action => action_url)
320
129
  options[:with].merge!(:method => method.to_s)
321
130
  have_tag tag, options, &block
322
131
  end
323
132
 
324
- #TODO fix code duplications
133
+ # @TODO fix code duplications
325
134
 
326
- def with_hidden_field name, value=nil
327
- options = form_tag_options('hidden',name,value)
135
+ def with_hidden_field name, value = nil
136
+ options = form_tag_options('hidden', name, value)
328
137
  should_have_input(options)
329
138
  end
330
139
 
331
- def without_hidden_field name, value=nil
332
- options = form_tag_options('hidden',name,value)
140
+ def without_hidden_field name, value = nil
141
+ options = form_tag_options('hidden', name, value)
333
142
  should_not_have_input(options)
334
143
  end
335
144
 
336
- def with_text_field name, value=nil
337
- options = form_tag_options('text',name,value)
145
+ def with_text_field name, value = nil
146
+ options = form_tag_options('text', name, value)
338
147
  should_have_input(options)
339
148
  end
340
149
 
341
- def without_text_field name, value=nil
342
- options = form_tag_options('text',name,value)
150
+ def without_text_field name, value = nil
151
+ options = form_tag_options('text', name, value)
343
152
  should_not_have_input(options)
344
153
  end
345
154
 
346
- def with_email_field name, value=nil
347
- options = form_tag_options('email',name,value)
155
+ def with_email_field name, value = nil
156
+ options = form_tag_options('email', name, value)
348
157
  should_have_input(options)
349
158
  end
350
159
 
351
- def without_email_field name, value=nil
352
- options = form_tag_options('email',name,value)
160
+ def without_email_field name, value = nil
161
+ options = form_tag_options('email', name, value)
353
162
  should_not_have_input(options)
354
163
  end
355
164
 
356
- def with_url_field name, value=nil
357
- options = form_tag_options('url',name,value)
165
+ def with_url_field name, value = nil
166
+ options = form_tag_options('url', name, value)
358
167
  should_have_input(options)
359
168
  end
360
169
 
361
- def without_url_field name, value=nil
362
- options = form_tag_options('url',name,value)
170
+ def without_url_field name, value = nil
171
+ options = form_tag_options('url', name, value)
363
172
  should_not_have_input(options)
364
173
  end
365
174
 
366
- def with_number_field name, value=nil
367
- options = form_tag_options('number',name,value)
175
+ def with_number_field name, value = nil
176
+ options = form_tag_options('number', name, value)
368
177
  should_have_input(options)
369
178
  end
370
179
 
371
- def without_number_field name, value=nil
372
- options = form_tag_options('number',name,value)
180
+ def without_number_field name, value = nil
181
+ options = form_tag_options('number', name, value)
373
182
  should_not_have_input(options)
374
183
  end
375
184
 
376
- def with_range_field name, min, max, options={}
377
- options = { :with => { :name => name, :type => 'range', :min => min.to_s, :max => max.to_s }.merge(options.delete(:with)||{}) }
185
+ def with_range_field name, min, max, options = {}
186
+ options = { :with => { :name => name, :type => 'range', :min => min.to_s, :max => max.to_s }.merge(options.delete(:with) || {}) }
378
187
  should_have_input(options)
379
188
  end
380
189
 
381
- def without_range_field name, min=nil, max=nil, options={}
382
- options = { :with => { :name => name, :type => 'range' }.merge(options.delete(:with)||{}) }
190
+ def without_range_field name, min = nil, max = nil, options = {}
191
+ options = { :with => { :name => name, :type => 'range' }.merge(options.delete(:with) || {}) }
383
192
  options[:with].merge!(:min => min.to_s) if min
384
193
  options[:with].merge!(:max => max.to_s) if max
385
194
  should_not_have_input(options)
386
195
  end
387
196
 
388
- DATE_FIELD_TYPES = %w( date month week time datetime datetime-local )
197
+ DATE_FIELD_TYPES = %w[date month week time datetime datetime-local].freeze
389
198
 
390
- def with_date_field date_field_type, name=nil, options={}
199
+ def with_date_field date_field_type, name = nil, options = {}
391
200
  date_field_type = date_field_type.to_s
392
201
  raise "unknown type `#{date_field_type}` for date picker" unless DATE_FIELD_TYPES.include?(date_field_type)
393
- options = { :with => { :type => date_field_type.to_s }.merge(options.delete(:with)||{}) }
202
+
203
+ options = { :with => { :type => date_field_type.to_s }.merge(options.delete(:with) || {}) }
394
204
  options[:with].merge!(:name => name.to_s) if name
395
205
  should_have_input(options)
396
206
  end
397
207
 
398
- def without_date_field date_field_type, name=nil, options={}
208
+ def without_date_field date_field_type, name = nil, options = {}
399
209
  date_field_type = date_field_type.to_s
400
210
  raise "unknown type `#{date_field_type}` for date picker" unless DATE_FIELD_TYPES.include?(date_field_type)
401
- options = { :with => { :type => date_field_type.to_s }.merge(options.delete(:with)||{}) }
211
+
212
+ options = { :with => { :type => date_field_type.to_s }.merge(options.delete(:with) || {}) }
402
213
  options[:with].merge!(:name => name.to_s) if name
403
214
  should_not_have_input(options)
404
215
  end
405
216
 
406
- # TODO add ability to explicitly say that value should be empty
407
- def with_password_field name, value=nil
408
- options = form_tag_options('password',name,value)
217
+ def with_password_field name, value = nil
218
+ # TODO: add ability to explicitly say that value should be empty
219
+ options = form_tag_options('password', name, value)
409
220
  should_have_input(options)
410
221
  end
411
222
 
412
- def without_password_field name, value=nil
413
- options = form_tag_options('password',name,value)
223
+ def without_password_field name, value = nil
224
+ options = form_tag_options('password', name, value)
414
225
  should_not_have_input(options)
415
226
  end
416
227
 
417
- def with_file_field name, value=nil
418
- options = form_tag_options('file',name,value)
228
+ def with_file_field name, value = nil
229
+ options = form_tag_options('file', name, value)
419
230
  should_have_input(options)
420
231
  end
421
232
 
422
- def without_file_field name, value=nil
423
- options = form_tag_options('file',name,value)
233
+ def without_file_field name, value = nil
234
+ options = form_tag_options('file', name, value)
424
235
  should_not_have_input(options)
425
236
  end
426
237
 
427
- def with_text_area name#TODO, text=nil
428
- #options = form_tag_options('text',name,value)
238
+ def with_text_area name
239
+ # TODO, should be: with_text_area name, text=nil
240
+ # options = form_tag_options('text',name,value)
429
241
  options = { :with => { :name => name } }
430
- expect(@__current_scope_for_nokogiri_matcher).to have_tag('textarea', options)
242
+ within_nested_tag do
243
+ expect(@__current_scope_for_nokogiri_matcher).to have_tag('textarea', options)
244
+ end
431
245
  end
432
246
 
433
- def without_text_area name#TODO, text=nil
434
- #options = form_tag_options('text',name,value)
247
+ def without_text_area name
248
+ # TODO, should be: without_text_area name, text=nil
249
+ # options = form_tag_options('text',name,value)
435
250
  options = { :with => { :name => name } }
436
- expect(@__current_scope_for_nokogiri_matcher).to_not have_tag('textarea', options)
251
+ within_nested_tag do
252
+ expect(@__current_scope_for_nokogiri_matcher).to_not have_tag('textarea', options)
253
+ end
437
254
  end
438
255
 
439
- def with_checkbox name, value=nil
440
- options = form_tag_options('checkbox',name,value)
256
+ def with_checkbox name, value = nil
257
+ options = form_tag_options('checkbox', name, value)
441
258
  should_have_input(options)
442
259
  end
443
260
 
444
- def without_checkbox name, value=nil
445
- options = form_tag_options('checkbox',name,value)
261
+ def without_checkbox name, value = nil
262
+ options = form_tag_options('checkbox', name, value)
446
263
  should_not_have_input(options)
447
264
  end
448
265
 
449
266
  def with_radio_button name, value
450
- options = form_tag_options('radio',name,value)
267
+ options = form_tag_options('radio', name, value)
451
268
  should_have_input(options)
452
269
  end
453
270
 
454
271
  def without_radio_button name, value
455
- options = form_tag_options('radio',name,value)
272
+ options = form_tag_options('radio', name, value)
456
273
  should_not_have_input(options)
457
274
  end
458
275
 
459
- def with_select name, options={}, &block
276
+ def with_select name, options = {}, &block
460
277
  options[:with] ||= {}
461
278
  id = options[:with].delete(:id)
462
- tag='select'; tag << '#'+id if id
279
+ tag = 'select'; tag += '#' + id if id
463
280
  options[:with].merge!(:name => name)
464
- expect(@__current_scope_for_nokogiri_matcher).to have_tag(tag, options, &block)
281
+ within_nested_tag do
282
+ expect(@__current_scope_for_nokogiri_matcher).to have_tag(tag, options, &block)
283
+ end
465
284
  end
466
285
 
467
- def without_select name, options={}, &block
286
+ def without_select name, options = {}, &block
468
287
  options[:with] ||= {}
469
288
  id = options[:with].delete(:id)
470
- tag='select'; tag << '#'+id if id
289
+ tag = 'select'; tag += '#' + id if id
471
290
  options[:with].merge!(:name => name)
472
- expect(@__current_scope_for_nokogiri_matcher).to_not have_tag(tag, options, &block)
291
+ within_nested_tag do
292
+ expect(@__current_scope_for_nokogiri_matcher).to_not have_tag(tag, options, &block)
293
+ end
473
294
  end
474
295
 
475
- def with_option text, value=nil, options={}
296
+ def with_option text, value = nil, options = {}
476
297
  options[:with] ||= {}
477
298
  if value.is_a?(Hash)
478
299
  options.merge!(value)
479
- value=nil
300
+ value = nil
480
301
  end
481
- tag='option'
302
+ tag = 'option'
482
303
  options[:with].merge!(:value => value.to_s) if value
483
- if options[:selected]
484
- options[:with].merge!(:selected => "selected")
485
- end
304
+ options[:with].merge!(:selected => 'selected') if options[:selected]
486
305
  options.delete(:selected)
487
306
  options.merge!(:text => text) if text
488
- expect(@__current_scope_for_nokogiri_matcher).to have_tag(tag, options)
307
+ within_nested_tag do
308
+ expect(@__current_scope_for_nokogiri_matcher).to have_tag(tag, options)
309
+ end
489
310
  end
490
311
 
491
- def without_option text, value=nil, options={}
312
+ def without_option text, value = nil, options = {}
492
313
  options[:with] ||= {}
493
314
  if value.is_a?(Hash)
494
315
  options.merge!(value)
495
- value=nil
316
+ value = nil
496
317
  end
497
- tag='option'
318
+ tag = 'option'
498
319
  options[:with].merge!(:value => value.to_s) if value
499
- if options[:selected]
500
- options[:with].merge!(:selected => "selected")
501
- end
320
+ options[:with].merge!(:selected => 'selected') if options[:selected]
502
321
  options.delete(:selected)
503
322
  options.merge!(:text => text) if text
504
- expect(@__current_scope_for_nokogiri_matcher).to_not have_tag(tag, options)
323
+ within_nested_tag do
324
+ expect(@__current_scope_for_nokogiri_matcher).to_not have_tag(tag, options)
325
+ end
505
326
  end
506
327
 
507
- def with_button text, value=nil, options={}
328
+ def with_button text, value = nil, options = {}
508
329
  options[:with] ||= {}
509
330
  if value.is_a?(Hash)
510
331
  options.merge!(value)
511
- value=nil
332
+ value = nil
512
333
  end
513
334
  options[:with].merge!(:value => value.to_s) if value
514
335
  options.merge!(:text => text) if text
515
- expect(@__current_scope_for_nokogiri_matcher).to have_tag('button', options)
336
+ within_nested_tag do
337
+ expect(@__current_scope_for_nokogiri_matcher).to have_tag('button', options)
338
+ end
516
339
  end
517
340
 
518
- def without_button text, value=nil, options={}
341
+ def without_button text, value = nil, options = {}
519
342
  options[:with] ||= {}
520
343
  if value.is_a?(Hash)
521
344
  options.merge!(value)
522
- value=nil
345
+ value = nil
523
346
  end
524
347
  options[:with].merge!(:value => value.to_s) if value
525
348
  options.merge!(:text => text) if text
526
- expect(@__current_scope_for_nokogiri_matcher).to_not have_tag('button', options)
349
+ within_nested_tag do
350
+ expect(@__current_scope_for_nokogiri_matcher).to_not have_tag('button', options)
351
+ end
527
352
  end
528
353
 
529
354
  def with_submit value
530
355
  options = { :with => { :type => 'submit', :value => value } }
531
- #options = form_tag_options('text',name,value)
356
+ # options = form_tag_options('text',name,value)
532
357
  should_have_input(options)
533
358
  end
534
359
 
535
360
  def without_submit value
536
- #options = form_tag_options('text',name,value)
361
+ # options = form_tag_options('text',name,value)
537
362
  options = { :with => { :type => 'submit', :value => value } }
538
363
  should_not_have_input(options)
539
364
  end
540
365
 
541
366
  private
542
367
 
543
- def should_have_input(options)
544
- expect(@__current_scope_for_nokogiri_matcher).to have_tag('input', options)
368
+ def should_have_input options
369
+ within_nested_tag do
370
+ expect(@__current_scope_for_nokogiri_matcher).to have_tag('input', options)
371
+ end
545
372
  end
546
373
 
547
- def should_not_have_input(options)
548
- expect(@__current_scope_for_nokogiri_matcher).to_not have_tag('input', options)
374
+ def should_not_have_input options
375
+ within_nested_tag do
376
+ expect(@__current_scope_for_nokogiri_matcher).to_not have_tag('input', options)
377
+ end
549
378
  end
550
379
 
551
380
  # form_tag in method name name mean smth. like input, submit, tags that should appear in a form
552
- def form_tag_options form_tag_type, form_tag_name, form_tag_value=nil
381
+ def form_tag_options form_tag_type, form_tag_name, form_tag_value = nil
553
382
  options = { :with => { :name => form_tag_name, :type => form_tag_type } }
554
383
  # .to_s if value is a digit or smth. else, see issue#10
555
384
  options[:with].merge!(:value => form_tag_value.to_s) if form_tag_value
556
- return options
385
+ options
557
386
  end
558
387
 
388
+ def within_nested_tag &block
389
+ raise 'block needed' unless block_given?
390
+
391
+ parent_scope = @__current_scope_for_nokogiri_matcher
392
+ block.call
393
+ @__current_scope_for_nokogiri_matcher = parent_scope
394
+ end
559
395
  end