rspec-html-matchers 0.9.2 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/README.md +6 -3
- data/features/step_definitions/steps.rb +3 -1
- data/features/support/env.rb +6 -2
- data/lib/rspec-html-matchers/have_tag.rb +157 -133
- data/lib/rspec-html-matchers/nokogiri_regexp_helper.rb +3 -5
- data/lib/rspec-html-matchers/nokogiri_text_helper.rb +3 -5
- data/lib/rspec-html-matchers/version.rb +3 -1
- data/lib/rspec-html-matchers.rb +103 -88
- data/spec/form_matchers_spec.rb +128 -126
- data/spec/have_empty_tag_spec.rb +8 -6
- data/spec/have_tag_spec.rb +202 -166
- data/spec/issues_spec.rb +17 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/support/asset_helpers.rb +5 -5
- data/spec/support/raise_spec_error_helper.rb +9 -7
- metadata +25 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1240c0b682d8f66bf9058191105b0264804359ab93edc3217251ebd28c76b8c9
|
4
|
+
data.tar.gz: a287233a778683a27fb2a22dfa5f4947707f442826c6780b0554ec9061127100
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce5b239fe81a0deae7783c2698f5eecd173e24c903c1248774d2a7143b10d9d0841c05f16c36761e6844aa2dc8fc9c877ffcfdfb490cacb1522dbb9bd727e796
|
7
|
+
data.tar.gz: 20f258033ce55b259f5ff97d054f2a151e50a7365bb44853047c10f171f0b9c6007aff944a01b015d5bd4f26cae9f556cafbf5e9e78db90887744e480cd48d94
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,25 @@
|
|
1
1
|
Changelog
|
2
2
|
=========
|
3
3
|
|
4
|
+
0.10.0
|
5
|
+
------
|
6
|
+
|
7
|
+
* relax rspec dependecy upper limit
|
8
|
+
* add ruby 3.0 to test matrix
|
9
|
+
* add ruby 3.1 to test matrix
|
10
|
+
* remove 1.8 ruby from test matrix, this is the first step to remove it's support completely
|
11
|
+
|
12
|
+
0.9.4
|
13
|
+
-----
|
14
|
+
* html/body matching from now is forbidden ([#75](https://github.com/kucaahbe/rspec-html-matchers/pull/75))
|
15
|
+
* make ruby 2.7 possible to fail on CI
|
16
|
+
|
17
|
+
0.9.3
|
18
|
+
-----
|
19
|
+
* fix for :seen option ([#73](https://github.com/kucaahbe/rspec-html-matchers/issues/73))
|
20
|
+
* fix for html/body matching ([#62](https://github.com/kucaahbe/rspec-html-matchers/issues/62))
|
21
|
+
* a bit of linting and refactoring
|
22
|
+
|
4
23
|
0.9.2
|
5
24
|
-----
|
6
25
|
|
data/README.md
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
-
# rspec-html-matchers [](https://badge.fury.io/rb/rspec-html-matchers)
|
1
|
+
# rspec-html-matchers [](https://badge.fury.io/rb/rspec-html-matchers)
|
2
2
|
|
3
|
-
[RSpec
|
3
|
+
[RSpec](https://www.relishapp.com/rspec) matchers for testing your html (for [RSpec 2](https://www.relishapp.com/rspec/rspec-core/v/2-99/docs) use 0.5.x version).
|
4
|
+
|
5
|
+
[](https://github.com/kucaahbe/rspec-html-matchers/actions/workflows/rspec-mri.yml)
|
6
|
+
[](https://github.com/kucaahbe/rspec-html-matchers/actions/workflows/rspec-jruby.yml)
|
7
|
+
[](https://github.com/kucaahbe/rspec-html-matchers/actions/workflows/cucumber-mri.yml)
|
4
8
|
|
5
9
|
Goals
|
6
10
|
-----
|
@@ -41,7 +45,6 @@ describe "my view spec" do
|
|
41
45
|
it "has tags" do
|
42
46
|
expect(rendered).to have_tag('div')
|
43
47
|
end
|
44
|
-
|
45
48
|
end
|
46
49
|
```
|
47
50
|
|
data/features/support/env.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# setup rspec matchers
|
2
4
|
require 'rspec/expectations'
|
3
5
|
World(RSpec::Matchers)
|
@@ -9,8 +11,9 @@ require 'selenium-webdriver'
|
|
9
11
|
|
10
12
|
World RSpecHtmlMatchers
|
11
13
|
|
12
|
-
|
13
|
-
$
|
14
|
+
# rubocop:disable Style/GlobalVars
|
15
|
+
$ASSETS_DIR = File.expand_path('../tmp', __FILE__)
|
16
|
+
$INDEX_HTML = File.join($ASSETS_DIR, 'index.html')
|
14
17
|
|
15
18
|
class SimpleApp < Sinatra::Base
|
16
19
|
set :public_folder, $ASSETS_DIR
|
@@ -39,3 +42,4 @@ end
|
|
39
42
|
After do
|
40
43
|
FileUtils.rm_rf $ASSETS_DIR
|
41
44
|
end
|
45
|
+
# rubocop:enable Style/GlobalVars
|
@@ -1,52 +1,51 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
1
|
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
4
|
+
require 'nokogiri'
|
5
5
|
|
6
|
+
module RSpecHtmlMatchers
|
6
7
|
# @api
|
7
8
|
# @private
|
8
|
-
class HaveTag
|
9
|
-
attr_reader :failure_message, :failure_message_when_negated
|
10
|
-
attr_reader :parent_scope, :current_scope
|
11
|
-
|
9
|
+
class HaveTag # rubocop:disable Metrics/ClassLength
|
12
10
|
DESCRIPTIONS = {
|
13
|
-
|
14
|
-
|
15
|
-
}
|
11
|
+
:have_at_least_1 => %(have at least 1 element matching "%s"),
|
12
|
+
:have_n => %(have %i element(s) matching "%s"),
|
13
|
+
}.freeze
|
16
14
|
|
17
15
|
MESSAGES = {
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
:expected_count => %Q|expected following:\n%s\nto #{DESCRIPTIONS[:have_n]}, found %s.|,
|
22
|
-
:unexpected_count => %Q|expected following:\n%s\nto NOT have %i element(s) matching "%s", but found.|,
|
16
|
+
:expected_tag => %(expected following:\n%s\nto #{DESCRIPTIONS[:have_at_least_1]}, found 0.),
|
17
|
+
:unexpected_tag => %(expected following:\n%s\nto NOT have element matching "%s", found %s.),
|
23
18
|
|
24
|
-
|
25
|
-
|
19
|
+
:expected_count => %(expected following:\n%s\nto #{DESCRIPTIONS[:have_n]}, found %s.),
|
20
|
+
:unexpected_count => %(expected following:\n%s\nto NOT have %i element(s) matching "%s", but found.),
|
26
21
|
|
27
|
-
|
28
|
-
|
22
|
+
:expected_btw_count => %(expected following:\n%s\nto have at least %i and at most %i element(s) matching "%s", found %i.),
|
23
|
+
:unexpected_btw_count => %(expected following:\n%s\nto NOT have at least %i and at most %i element(s) matching "%s", but found %i.),
|
29
24
|
|
30
|
-
|
31
|
-
|
25
|
+
:expected_at_most => %(expected following:\n%s\nto have at most %i element(s) matching "%s", found %i.),
|
26
|
+
:unexpected_at_most => %(expected following:\n%s\nto NOT have at most %i element(s) matching "%s", but found %i.),
|
32
27
|
|
33
|
-
|
34
|
-
|
28
|
+
:expected_at_least => %(expected following:\n%s\nto have at least %i element(s) matching "%s", found %i.),
|
29
|
+
:unexpected_at_least => %(expected following:\n%s\nto NOT have at least %i element(s) matching "%s", but found %i.),
|
35
30
|
|
36
|
-
|
37
|
-
|
31
|
+
:expected_blank => %(expected following template to contain empty tag %s:\n%s),
|
32
|
+
:unexpected_blank => %(expected following template to contain tag %s with other tags:\n%s),
|
38
33
|
|
39
|
-
|
40
|
-
|
34
|
+
:expected_regexp => %(%s regexp expected within "%s" in following template:\n%s),
|
35
|
+
:unexpected_regexp => %(%s regexp unexpected within "%s" in following template:\n%s\nbut was found.),
|
41
36
|
|
42
|
-
|
43
|
-
|
44
|
-
:bad_range_error => %Q|Your :count range(%s) has no sence!|,
|
45
|
-
}
|
37
|
+
:expected_text => %("%s" expected within "%s" in following template:\n%s),
|
38
|
+
:unexpected_text => %("%s" unexpected within "%s" in following template:\n%s\nbut was found.),
|
46
39
|
|
40
|
+
:wrong_count_error => %(:count with :minimum or :maximum has no sence!),
|
41
|
+
:min_max_error => %(:minimum should be less than :maximum!),
|
42
|
+
:bad_range_error => %(Your :count range(%s) has no sence!),
|
43
|
+
}.freeze
|
47
44
|
|
48
|
-
def initialize tag, options={}, &block
|
49
|
-
@tag
|
45
|
+
def initialize tag, options = {}, &block
|
46
|
+
@tag = tag.to_s
|
47
|
+
@options = options
|
48
|
+
@block = block
|
50
49
|
|
51
50
|
if with_attrs = @options.delete(:with)
|
52
51
|
if classes = with_attrs.delete(:class)
|
@@ -66,30 +65,35 @@ module RSpecHtmlMatchers
|
|
66
65
|
end
|
67
66
|
|
68
67
|
validate_options!
|
69
|
-
|
68
|
+
organize_options!
|
70
69
|
end
|
71
70
|
|
72
|
-
|
71
|
+
attr_reader :failure_message
|
72
|
+
attr_reader :failure_message_when_negated
|
73
|
+
attr_reader :current_scope
|
74
|
+
|
75
|
+
def matches? src, &block
|
73
76
|
@block = block if block
|
74
77
|
|
75
|
-
|
78
|
+
src = src.html if defined?(Capybara::Session) && src.is_a?(Capybara::Session)
|
76
79
|
|
77
|
-
case
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
80
|
+
case src
|
81
|
+
when String
|
82
|
+
parent_scope = Nokogiri::HTML(src)
|
83
|
+
@document = src
|
84
|
+
else
|
85
|
+
parent_scope = src.current_scope
|
86
|
+
@document = parent_scope.to_html
|
84
87
|
end
|
88
|
+
|
85
89
|
@current_scope = begin
|
86
|
-
|
90
|
+
parent_scope.css(tag)
|
87
91
|
# on jruby this produce exception if css was not found:
|
88
92
|
# undefined method `decorate' for nil:NilClass
|
89
93
|
rescue NoMethodError
|
90
94
|
Nokogiri::XML::NodeSet.new(Nokogiri::XML::Document.new)
|
91
95
|
end
|
92
|
-
if tag_presents?
|
96
|
+
if tag_presents? && proper_content? && count_right?
|
93
97
|
@block.call(self) if @block
|
94
98
|
true
|
95
99
|
else
|
@@ -97,60 +101,74 @@ module RSpecHtmlMatchers
|
|
97
101
|
end
|
98
102
|
end
|
99
103
|
|
100
|
-
def document
|
101
|
-
@document
|
102
|
-
end
|
103
|
-
|
104
104
|
def description
|
105
|
-
# TODO should it be more complicated?
|
106
|
-
if
|
107
|
-
DESCRIPTIONS[:have_n]
|
105
|
+
# TODO: should it be more complicated?
|
106
|
+
if options.key?(:count)
|
107
|
+
format(DESCRIPTIONS[:have_n], options[:count], tag)
|
108
108
|
else
|
109
|
-
DESCRIPTIONS[:have_at_least_1] %
|
109
|
+
DESCRIPTIONS[:have_at_least_1] % tag
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|
113
113
|
private
|
114
114
|
|
115
|
-
|
115
|
+
attr_reader :tag
|
116
|
+
attr_reader :options
|
117
|
+
attr_reader :document
|
118
|
+
|
119
|
+
def classes_to_selector classes
|
116
120
|
case classes
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
+
when Array
|
122
|
+
classes.join('.')
|
123
|
+
when String
|
124
|
+
classes.gsub(/\s+/, '.')
|
121
125
|
end
|
122
126
|
end
|
123
127
|
|
124
128
|
def tag_presents?
|
125
|
-
if
|
126
|
-
@count =
|
127
|
-
|
128
|
-
true
|
129
|
+
if current_scope.first
|
130
|
+
@count = current_scope.count
|
131
|
+
match_succeeded! :unexpected_tag, document, tag, @count
|
129
132
|
else
|
130
|
-
|
131
|
-
false
|
133
|
+
match_failed! :expected_tag, document, tag
|
132
134
|
end
|
133
135
|
end
|
134
136
|
|
135
|
-
def count_right?
|
136
|
-
case
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
137
|
+
def count_right? # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
138
|
+
case options[:count]
|
139
|
+
when Integer
|
140
|
+
if @count == options[:count]
|
141
|
+
match_succeeded! :unexpected_count, document, @count, tag
|
142
|
+
else
|
143
|
+
match_failed! :expected_count, document, options[:count], tag, @count
|
144
|
+
end
|
145
|
+
when Range
|
146
|
+
if options[:count].member? @count
|
147
|
+
match_succeeded! :unexpected_btw_count, document, options[:count].min, options[:count].max, tag, @count
|
148
|
+
else
|
149
|
+
match_failed! :expected_btw_count, document, options[:count].min, options[:count].max, tag, @count
|
150
|
+
end
|
151
|
+
when nil
|
152
|
+
if options[:maximum]
|
153
|
+
if @count <= options[:maximum]
|
154
|
+
match_succeeded! :unexpected_at_most, document, options[:maximum], tag, @count
|
155
|
+
else
|
156
|
+
match_failed! :expected_at_most, document, options[:maximum], tag, @count
|
157
|
+
end
|
158
|
+
elsif options[:minimum]
|
159
|
+
if @count >= options[:minimum]
|
160
|
+
match_succeeded! :unexpected_at_least, document, options[:minimum], tag, @count
|
146
161
|
else
|
147
|
-
|
162
|
+
match_failed! :expected_at_least, document, options[:minimum], tag, @count
|
148
163
|
end
|
164
|
+
else
|
165
|
+
true
|
166
|
+
end
|
149
167
|
end
|
150
168
|
end
|
151
169
|
|
152
170
|
def proper_content?
|
153
|
-
if
|
171
|
+
if options.key?(:blank)
|
154
172
|
maybe_empty?
|
155
173
|
else
|
156
174
|
text_right?
|
@@ -158,109 +176,115 @@ module RSpecHtmlMatchers
|
|
158
176
|
end
|
159
177
|
|
160
178
|
def maybe_empty?
|
161
|
-
if
|
162
|
-
|
163
|
-
@failure_message = MESSAGES[:expected_blank] % [@tag, @document]
|
179
|
+
if options[:blank] && current_scope.children.empty?
|
180
|
+
match_succeeded! :unexpected_blank, tag, document
|
164
181
|
else
|
165
|
-
|
166
|
-
@failure_message = MESSAGES[:unexpected_blank] % [@tag, @document]
|
167
|
-
end
|
168
|
-
|
169
|
-
if @options[:blank]
|
170
|
-
@current_scope.children.empty?
|
171
|
-
else
|
172
|
-
!@current_scope.children.empty?
|
182
|
+
match_failed! :expected_blank, tag, document
|
173
183
|
end
|
174
184
|
end
|
175
185
|
|
176
186
|
def text_right?
|
177
|
-
return true unless
|
178
|
-
|
179
|
-
case text
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
@failure_message_when_negated = MESSAGES[:unexpected_regexp] % [text.inspect,@tag,@document]
|
185
|
-
true
|
186
|
-
else
|
187
|
-
@failure_message = MESSAGES[:expected_regexp] % [text.inspect,@tag,@document]
|
188
|
-
false
|
189
|
-
end
|
187
|
+
return true unless options[:text]
|
188
|
+
|
189
|
+
case text = options[:text]
|
190
|
+
when Regexp
|
191
|
+
new_scope = current_scope.css(':regexp()', NokogiriRegexpHelper.new(text))
|
192
|
+
if new_scope.empty?
|
193
|
+
match_failed! :expected_regexp, text.inspect, tag, document
|
190
194
|
else
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
195
|
+
@count = new_scope.count
|
196
|
+
match_succeeded! :unexpected_regexp, text.inspect, tag, document
|
197
|
+
end
|
198
|
+
else
|
199
|
+
new_scope = current_scope.css(':content()', NokogiriTextHelper.new(text, options[:squeeze_text]))
|
200
|
+
if new_scope.empty?
|
201
|
+
match_failed! :expected_text, text, tag, document
|
202
|
+
else
|
203
|
+
@count = new_scope.count
|
204
|
+
match_succeeded! :unexpected_text, text, tag, document
|
205
|
+
end
|
200
206
|
end
|
201
207
|
end
|
202
208
|
|
203
|
-
protected
|
204
|
-
|
205
209
|
def validate_options!
|
210
|
+
validate_html_body_tags!
|
206
211
|
validate_text_options!
|
207
212
|
validate_count_presence!
|
208
213
|
validate_count_when_set_min_max!
|
209
214
|
validate_count_when_set_range!
|
210
215
|
end
|
211
216
|
|
217
|
+
# here is a demo:
|
218
|
+
# irb(main):009:0> Nokogiri::HTML('<p>asd</p>').xpath('//html')
|
219
|
+
# => [#<Nokogiri::XML::Element:0x3fea02cd3f58 name="html" children=[#<Nokogiri::XML::Element:0x3fea02cd37c4 name="body" children=[#<Nokogiri::XML::Element:0x3fea02cd34e0 name="p" children=[#<Nokogiri::XML::Text:0x3fea02cd3134 "asd">]>]>]>]
|
220
|
+
# irb(main):010:0> Nokogiri::HTML('<p>asd</p>').xpath('//body')
|
221
|
+
# => [#<Nokogiri::XML::Element:0x3fea02ce3df4 name="body" children=[#<Nokogiri::XML::Element:0x3fea02ce3a70 name="p" children=[#<Nokogiri::XML::Text:0x3fea02ce350c "asd">]>]>]
|
222
|
+
# irb(main):011:0> Nokogiri::HTML('<p>asd</p>').xpath('//p')
|
223
|
+
# => [#<Nokogiri::XML::Element:0x3fea02cf3754 name="p" children=[#<Nokogiri::XML::Text:0x3fea02cf2f98 "asd">]>]
|
224
|
+
# irb(main):012:0> Nokogiri::HTML('<p>asd</p>').xpath('//a')
|
225
|
+
# => []
|
226
|
+
def validate_html_body_tags!
|
227
|
+
if %w[html body].include?(tag) && options.empty?
|
228
|
+
raise ArgumentError, 'matching <html> and <body> tags without specifying additional options does not work, see: https://github.com/kucaahbe/rspec-html-matchers/pull/75'
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
212
232
|
def validate_text_options!
|
213
233
|
# TODO: test these options validations
|
214
|
-
if
|
215
|
-
raise ':text option is not accepted when :blank => true'
|
234
|
+
if options.key?(:blank) && options[:blank] && options.key?(:text) # rubocop:disable Style/GuardClause, Style/IfUnlessModifier
|
235
|
+
raise ':text option is not accepted when :blank => true'
|
216
236
|
end
|
217
237
|
end
|
218
238
|
|
219
239
|
def validate_count_presence!
|
220
|
-
raise 'wrong :count specified' unless [Range, NilClass].include?(
|
240
|
+
raise 'wrong :count specified' unless [Range, NilClass].include?(options[:count].class) || options[:count].is_a?(Integer)
|
221
241
|
|
222
242
|
[:min, :minimum, :max, :maximum].each do |key|
|
223
|
-
raise MESSAGES[:wrong_count_error] if
|
243
|
+
raise MESSAGES[:wrong_count_error] if options.key?(key) && options.key?(:count)
|
224
244
|
end
|
225
245
|
end
|
226
246
|
|
227
247
|
def validate_count_when_set_min_max!
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
rescue ArgumentError # 2 < nil
|
232
|
-
end
|
248
|
+
raise MESSAGES[:min_max_error] if options[:minimum] > options[:maximum]
|
249
|
+
rescue NoMethodError # nil > 4 # rubocop:disable Lint/HandleExceptions
|
250
|
+
rescue ArgumentError # 2 < nil # rubocop:disable Lint/HandleExceptions
|
233
251
|
end
|
234
252
|
|
235
253
|
def validate_count_when_set_range!
|
236
254
|
begin
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
raise MESSAGES[:bad_range_error] % [@options[:count].to_s]
|
241
|
-
end
|
242
|
-
rescue TypeError # fix for 1.8.7 for 'rescue ArgumentError, "comparison of String with"' stroke
|
243
|
-
raise MESSAGES[:bad_range_error] % [@options[:count].to_s]
|
255
|
+
raise format(MESSAGES[:bad_range_error], options[:count].to_s) if count_is_range_but_no_min?
|
256
|
+
rescue ArgumentError, 'comparison of String with' # if options[:count] == 'a'..'z' # rubocop:disable Lint/RescueType
|
257
|
+
raise format(MESSAGES[:bad_range_error], options[:count].to_s)
|
244
258
|
end
|
259
|
+
rescue TypeError # fix for 1.8.7 for 'rescue ArgumentError, "comparison of String with"' stroke
|
260
|
+
raise format(MESSAGES[:bad_range_error], options[:count].to_s)
|
245
261
|
end
|
246
262
|
|
247
263
|
def count_is_range_but_no_min?
|
248
|
-
|
249
|
-
|
264
|
+
options[:count].is_a?(Range) &&
|
265
|
+
(options[:count].min.nil? || (options[:count].min < 0))
|
250
266
|
end
|
251
267
|
|
252
|
-
def
|
268
|
+
def organize_options!
|
253
269
|
@options[:minimum] ||= @options.delete(:min)
|
254
270
|
@options[:maximum] ||= @options.delete(:max)
|
255
271
|
|
256
|
-
@options[:text] = @options[:text].to_s if @options.
|
272
|
+
@options[:text] = @options[:text].to_s if @options.key?(:text) && !@options[:text].is_a?(Regexp)
|
257
273
|
|
258
|
-
if @options.
|
274
|
+
if @options.key?(:seen) && !@options[:seen].is_a?(Regexp) # rubocop:disable Style/GuardClause
|
259
275
|
@options[:text] = @options[:seen].to_s
|
260
276
|
@options[:squeeze_text] = true
|
261
277
|
end
|
262
278
|
end
|
263
279
|
|
264
|
-
|
280
|
+
def match_succeeded! message, *args
|
281
|
+
@failure_message_when_negated = format MESSAGES[message], *args
|
282
|
+
true
|
283
|
+
end
|
265
284
|
|
285
|
+
def match_failed! message, *args
|
286
|
+
@failure_message = format MESSAGES[message], *args
|
287
|
+
false
|
288
|
+
end
|
289
|
+
end
|
266
290
|
end
|
@@ -1,13 +1,12 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
1
|
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RSpecHtmlMatchers
|
5
|
-
|
6
5
|
# @api
|
7
6
|
# @private
|
8
7
|
# for nokogiri regexp matching
|
9
8
|
class NokogiriRegexpHelper
|
10
|
-
def initialize
|
9
|
+
def initialize regex
|
11
10
|
@regex = regex
|
12
11
|
end
|
13
12
|
|
@@ -15,5 +14,4 @@ module RSpecHtmlMatchers
|
|
15
14
|
node_set.find_all { |node| node.content =~ @regex }
|
16
15
|
end
|
17
16
|
end
|
18
|
-
|
19
|
-
end
|
17
|
+
end
|
@@ -1,8 +1,7 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
1
|
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RSpecHtmlMatchers
|
5
|
-
|
6
5
|
# @api
|
7
6
|
# @private
|
8
7
|
class NokogiriTextHelper
|
@@ -16,11 +15,10 @@ module RSpecHtmlMatchers
|
|
16
15
|
def content node_set
|
17
16
|
node_set.find_all do |node|
|
18
17
|
actual_content = node.content.gsub(NON_BREAKING_SPACE, ' ')
|
19
|
-
actual_content = node.content.
|
18
|
+
actual_content = node.content.gsub(/\s+/, ' ').strip if @squeeze_text
|
20
19
|
|
21
20
|
actual_content == @text
|
22
21
|
end
|
23
22
|
end
|
24
23
|
end
|
25
|
-
|
26
|
-
end
|
24
|
+
end
|