rspec-tag_matchers 0.1.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.
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe RSpec::TagMatchers::HasSelect do
4
+ include RSpec::TagMatchers
5
+
6
+ describe "matching select tags" do
7
+ context "have_select" do
8
+ subject { have_select }
9
+ it { should_not match("<input />") }
10
+ it { should match("<select />") }
11
+ it { should match("<SELECT />") }
12
+ it { should_not match("<selector />") }
13
+ it { should_not match("select") }
14
+ end
15
+ end
16
+
17
+ describe "matching input names" do
18
+ context "have_select.for(:user => :role)" do
19
+ subject { have_select.for(:user => :role) }
20
+ it { should_not match("<select />") }
21
+ it { should_not match("<select name='user' />") }
22
+ it { should match("<select name='user[role]' />") }
23
+ it { should_not match("<select name='user[role][admin]' />") }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,294 @@
1
+ require 'spec_helper'
2
+
3
+ describe RSpec::TagMatchers::HasTag do
4
+ include RSpec::TagMatchers
5
+
6
+ describe "inputs" do
7
+ let(:string) { "<foo></foo>" }
8
+ let(:document) { Nokogiri::HTML::Document.parse(string) }
9
+ let(:node_set) { document.css("foo") }
10
+
11
+ subject { have_tag(:foo) }
12
+
13
+ it "should match against String" do
14
+ subject.should match(string)
15
+ end
16
+
17
+ it "should match against Nokogiri::XML::NodeSet" do
18
+ subject.should match(node_set)
19
+ end
20
+ end
21
+
22
+ describe "tag name matching" do
23
+ context "matches with symbol" do
24
+ context 'have_tag(:foo)' do
25
+ subject { have_tag(:foo) }
26
+ it { should match("<foo></foo>") }
27
+ it { should match("<foo bar='baz'></foo>") }
28
+ it { should match("<FOO></FOO>") }
29
+ it { should_not match("<foobar></foobar>") }
30
+ it { should_not match("<bar></bar>") }
31
+ it { should_not match("foo") }
32
+ end
33
+
34
+ context 'have_tag(:bar)' do
35
+ subject { have_tag(:bar) }
36
+ it { should match("<bar></bar>") }
37
+ it { should_not match("<foo></foo>") }
38
+ end
39
+ end
40
+
41
+ context "matches with string" do
42
+ context 'have_tag("foo")' do
43
+ subject { have_tag("foo") }
44
+ it { should match("<foo></foo>") }
45
+ it { should match("<foo bar='1'></foo>") }
46
+ it { should match("<FOO></FOO>") }
47
+ it { should_not match("<foobar></foobar>") }
48
+ it { should_not match("<bar></bar>") }
49
+ it { should_not match("foo") }
50
+ end
51
+
52
+ context 'have_tag("bar")' do
53
+ subject { have_tag("bar") }
54
+ it { should match("<bar></bar>") }
55
+ it { should_not match("<foo></foo>") }
56
+ end
57
+ end
58
+ end
59
+
60
+ describe "attribute value matching" do
61
+ context "true matches presence of attribute" do
62
+ context 'have_tag(:foo).with_attribute(:bar => true)' do
63
+ subject { have_tag(:foo).with_attribute(:bar => true) }
64
+ it { should_not match("<foo></foo>") }
65
+ it { should match("<foo bar='baz'></foo>") }
66
+ it { should match("<foo bar='qux'></foo>") }
67
+ it { should match("<foo bar></foo>") }
68
+ it { should_not match("<foo qux='baz'></foo>") }
69
+ it { should_not match("<foo>bar</foo>") }
70
+ it { should_not match("<foo></foo><qux bar='baz'></qux>") }
71
+ end
72
+
73
+ context 'have_tag(:foo).with_attribute(:qux => true)' do
74
+ subject { have_tag(:foo).with_attribute(:qux => true) }
75
+ it { should_not match("<foo></foo>") }
76
+ it { should_not match("<foo bar='baz'></foo>") }
77
+ it { should match("<foo qux='baz'></foo>") }
78
+ it { should match("<foo qux></foo>") }
79
+ it { should_not match("<foo></foo><qux bar='baz'></qux>") }
80
+ end
81
+ end
82
+
83
+ context "false matches absence of attribute" do
84
+ context 'have_tag(:foo).with_attribute(:bar => false)' do
85
+ subject { have_tag(:foo).with_attribute(:bar => false) }
86
+ it { should match("<foo></foo>") }
87
+ it { should_not match("<foo bar='baz'></foo>") }
88
+ it { should_not match("<foo bar='qux'></foo>") }
89
+ it { should_not match("<foo bar></foo>") }
90
+ it { should match("<foo qux='baz'></foo>") }
91
+ end
92
+
93
+ context 'have_tag(:foo).with_attribute(:qux => false)' do
94
+ subject { have_tag(:foo).with_attribute(:qux => false) }
95
+ it { should match("<foo></foo>") }
96
+ it { should match("<foo bar='baz'></foo>") }
97
+ it { should_not match("<foo qux='baz'></foo>") }
98
+ it { should_not match("<foo qux></foo>") }
99
+ end
100
+ end
101
+
102
+ context "string matches exactly" do
103
+ context 'have_tag(:foo).with_attribute(:bar => "baz")' do
104
+ subject { have_tag(:foo).with_attribute(:bar => "baz") }
105
+ it { should_not match("<foo></foo>") }
106
+ it { should match("<foo bar='baz'></foo>") }
107
+ it { should_not match("<foo bar='qux'></foo>") }
108
+ it { should_not match("<foo bar='BAZ'></foo>") }
109
+ it { should_not match("<foo bar='baza'></foo>") }
110
+ it { should_not match("<foo bar='abaz'</foo>") }
111
+ it { should_not match("<foo qux='baz'></foo>") }
112
+ end
113
+
114
+ context 'have_tag(:foo).with_attribute(:bar => "qux")' do
115
+ subject { have_tag(:foo).with_attribute(:bar => "qux") }
116
+ it { should_not match("<foo></foo>") }
117
+ it { should_not match("<foo bar='baz'></foo>") }
118
+ it { should match("<foo bar='qux'></foo>") }
119
+ it { should_not match("<foo qux='baz'></foo>") }
120
+ end
121
+
122
+ context 'have_tag(:foo).with_attribute(:qux => "baz")' do
123
+ subject { have_tag(:foo).with_attribute(:qux => "baz") }
124
+ it { should_not match("<foo></foo>") }
125
+ it { should_not match("<foo bar='baz'></foo>") }
126
+ it { should_not match("<foo bar='qux'></foo>") }
127
+ it { should match("<foo qux='baz'></foo>") }
128
+ end
129
+ end
130
+
131
+ context "symbol matches ignoring case" do
132
+ context 'have_tag(:foo).with_attribute(:bar => :baz)' do
133
+ subject { have_tag(:foo).with_attribute(:bar => :baz) }
134
+ it { should_not match("<foo></foo>") }
135
+ it { should match("<foo bar='baz'></foo>") }
136
+ it { should match("<foo bar='BAZ'></foo>") }
137
+ it { should_not match("<foo bar='qux'></foo>") }
138
+ it { should_not match("<foo bar='baza'></foo>") }
139
+ it { should_not match("<foo bar='abaz'</foo>") }
140
+ it { should_not match("<foo qux='baz'></foo>") }
141
+ end
142
+
143
+ context 'have_tag(:foo).with_attribute(:bar => :qux)' do
144
+ subject { have_tag(:foo).with_attribute(:bar => :qux) }
145
+ it { should_not match("<foo></foo>") }
146
+ it { should_not match("<foo bar='baz'></foo>") }
147
+ it { should match("<foo bar='qux'></foo>") }
148
+ it { should_not match("<foo qux='baz'></foo>") }
149
+ end
150
+
151
+ context 'have_tag(:foo).with_attribute(:qux => :baz)' do
152
+ subject { have_tag(:foo).with_attribute(:qux => :baz) }
153
+ it { should_not match("<foo></foo>") }
154
+ it { should_not match("<foo bar='baz'></foo>") }
155
+ it { should_not match("<foo bar='qux'></foo>") }
156
+ it { should match("<foo qux='baz'></foo>") }
157
+ end
158
+ end
159
+
160
+ context "regex matches with regex" do
161
+ context 'have_tag(:foo).with_attribute(:bar => /baz/)' do
162
+ subject { have_tag(:foo).with_attribute(:bar => /baz/) }
163
+ it { should_not match("<foo></foo>") }
164
+ it { should match("<foo bar='baz'></foo>") }
165
+ it { should_not match("<foo bar='BAZ'></foo>") }
166
+ it { should_not match("<foo bar='qux'></foo>") }
167
+ it { should match("<foo bar='baza'></foo>") }
168
+ it { should match("<foo bar='abaz'</foo>") }
169
+ it { should_not match("<foo qux='baz'></foo>") }
170
+ end
171
+
172
+ context 'have_tag(:foo).with_attribute(:bar => /qux/)' do
173
+ subject { have_tag(:foo).with_attribute(:bar => /qux/) }
174
+ it { should_not match("<foo></foo>") }
175
+ it { should_not match("<foo bar='baz'></foo>") }
176
+ it { should match("<foo bar='qux'></foo>") }
177
+ it { should_not match("<foo qux='baz'></foo>") }
178
+ end
179
+
180
+ context 'have_tag(:foo).with_attribute(:qux => /baz/)' do
181
+ subject { have_tag(:foo).with_attribute(:qux => /baz/) }
182
+ it { should_not match("<foo></foo>") }
183
+ it { should_not match("<foo bar='baz'></foo>") }
184
+ it { should_not match("<foo bar='qux'></foo>") }
185
+ it { should match("<foo qux='baz'></foo>") }
186
+ end
187
+ end
188
+
189
+ context "matches multiple attributes" do
190
+ context 'have_tag(:foo).with_attribute(:bar => true, :baz => true)' do
191
+ subject { have_tag(:foo).with_attribute(:bar => true, :baz => true) }
192
+ it { should match("<foo bar='1' baz='2'></foo>") }
193
+ it { should_not match("<foo bar='1'></foo>") }
194
+ it { should_not match("<foo baz='2'></foo>") }
195
+ it { should_not match("<foo></foo>") }
196
+ end
197
+ end
198
+ end
199
+
200
+ describe "extra criteria" do
201
+ context "as symbol" do
202
+ context "have_tag(:foo).with_criteria(:custom_filter)" do
203
+ subject { have_tag(:foo).with_criteria(:custom_filter) }
204
+
205
+ it "should call custom_filter with Nokogiri::XML::Element as argument" do
206
+ RSpec::TagMatchers::HasTag.any_instance.should_receive(:custom_filter).with(an_instance_of(Nokogiri::XML::Element))
207
+ subject.matches?("<foo></foo>")
208
+ end
209
+
210
+ context "when custom_filter returns true" do
211
+ before { RSpec::TagMatchers::HasTag.any_instance.stub(:custom_filter) { true } }
212
+ it { should match("<foo></foo>") }
213
+ it { should_not match("<bar></bar>") }
214
+ end
215
+
216
+ context "when custom_filter returns false" do
217
+ before { RSpec::TagMatchers::HasTag.any_instance.stub(:custom_filter) { false } }
218
+ it { should_not match("<foo></foo>") }
219
+ it { should_not match("<bar></bar>") }
220
+ end
221
+ end
222
+ end
223
+
224
+ context "as block" do
225
+ context "have_tag(:foo).with_criteria { |element| ... }" do
226
+ let!(:block) { lambda { |element| true } }
227
+ subject { have_tag(:foo).with_criteria { |element| block.call(element) } }
228
+
229
+ it "should call the block with Nokogiri::XML::Element as argument" do
230
+ block.should_receive(:call).with(an_instance_of(Nokogiri::XML::Element))
231
+ subject.matches?("<foo></foo>")
232
+ end
233
+
234
+ context "when block returns true" do
235
+ before { block.stub(:call) { true } }
236
+ it { should match("<foo></foo>") }
237
+ it { should_not match("<bar></bar>") }
238
+ end
239
+
240
+ context "when block returns false" do
241
+ before { block.stub(:call) { false } }
242
+ it { should_not match("<foo></foo>") }
243
+ it { should_not match("<bar></bar>") }
244
+ end
245
+ end
246
+ end
247
+
248
+ context "multiple criteria" do
249
+ context "have_tag(:foo).with_criteria(:filter_1).with_criteria(:filter_2)" do
250
+ subject { have_tag(:foo).with_criteria(:filter_1).with_criteria(:filter_2) }
251
+
252
+ context "both filters return true" do
253
+ before do
254
+ RSpec::TagMatchers::HasTag.any_instance.stub(:filter_1) { true }
255
+ RSpec::TagMatchers::HasTag.any_instance.stub(:filter_2) { true }
256
+ end
257
+
258
+ it { should match("<foo></foo>") }
259
+ it { should_not match("<bar></bar>") }
260
+ end
261
+
262
+ context "filter_1 returns false" do
263
+ before do
264
+ RSpec::TagMatchers::HasTag.any_instance.stub(:filter_1) { false }
265
+ RSpec::TagMatchers::HasTag.any_instance.stub(:filter_2) { true }
266
+ end
267
+
268
+ it { should_not match("<foo></foo>") }
269
+ it { should_not match("<bar></bar>") }
270
+ end
271
+
272
+ context "filter_2 returns false" do
273
+ before do
274
+ RSpec::TagMatchers::HasTag.any_instance.stub(:filter_1) { true }
275
+ RSpec::TagMatchers::HasTag.any_instance.stub(:filter_2) { false }
276
+ end
277
+
278
+ it { should_not match("<foo></foo>") }
279
+ it { should_not match("<bar></bar>") }
280
+ end
281
+
282
+ context "both filters return false" do
283
+ before do
284
+ RSpec::TagMatchers::HasTag.any_instance.stub(:filter_1) { false }
285
+ RSpec::TagMatchers::HasTag.any_instance.stub(:filter_2) { false }
286
+ end
287
+
288
+ it { should_not match("<foo></foo>") }
289
+ it { should_not match("<bar></bar>") }
290
+ end
291
+ end
292
+ end
293
+ end
294
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe RSpec::TagMatchers::HasTimeSelect do
4
+ include RSpec::TagMatchers
5
+
6
+ let(:start_time_hour) { "<select name='event[start_time(4i)]'></select>" }
7
+ let(:start_time_minute) { "<select name='event[start_time(5i)]'></select>" }
8
+ let(:start_time_second) { "<select name='event[start_time(6i)]'></select>" }
9
+
10
+ let(:end_time_hour) { "<select name='event[end_time(4i)]'></select>" }
11
+ let(:end_time_minute) { "<select name='event[end_time(5i)]'></select>" }
12
+ let(:end_time_second) { "<select name='event[end_time(6i)]'></select>" }
13
+
14
+ let(:start_time_with_hour_and_minute) { start_time_hour + start_time_minute }
15
+ let(:start_time_with_hour_minute_and_second) { start_time_hour + start_time_minute + start_time_second }
16
+
17
+ let(:end_time_with_hour_and_minute) { end_time_hour + end_time_minute }
18
+ let(:end_time_with_hour_minute_and_second) { end_time_hour + end_time_minute + end_time_second }
19
+
20
+ describe "time select matching" do
21
+ context "have_time_select" do
22
+ subject { have_time_select }
23
+
24
+ it { should match(start_time_with_hour_and_minute) }
25
+ it { should match(start_time_with_hour_minute_and_second) }
26
+ it { should_not match(start_time_hour) }
27
+ it { should_not match(start_time_minute) }
28
+ it { should_not match(start_time_second) }
29
+
30
+ it { should match(end_time_with_hour_and_minute) }
31
+ it { should match(end_time_with_hour_minute_and_second) }
32
+ it { should_not match(end_time_hour) }
33
+ it { should_not match(end_time_minute) }
34
+ it { should_not match(end_time_second) }
35
+ end
36
+ end
37
+
38
+ describe "matching input names" do
39
+ context "have_time_select.for(:event => :start_time)" do
40
+ subject { have_time_select.for(:event => :start_time) }
41
+
42
+ it { should match(start_time_with_hour_and_minute) }
43
+ it { should match(start_time_with_hour_minute_and_second) }
44
+
45
+ it { should_not match(end_time_with_hour_and_minute) }
46
+ it { should_not match(end_time_with_hour_minute_and_second) }
47
+ end
48
+
49
+ context "have_time_select.for(:event => :end_time)" do
50
+ subject { have_time_select.for(:event => :end_time) }
51
+
52
+ it { should match(end_time_with_hour_and_minute) }
53
+ it { should match(end_time_with_hour_minute_and_second) }
54
+
55
+ it { should_not match(start_time_with_hour_and_minute) }
56
+ it { should_not match(start_time_with_hour_minute_and_second) }
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,139 @@
1
+ require 'spec_helper'
2
+
3
+ describe RSpec::TagMatchers::MultipleInputMatcher do
4
+ let(:foo_matcher) { mock("'foo' input matcher") }
5
+ let(:bar_matcher) { mock("'bar' input matcher") }
6
+ let(:html) { "<input name='foo' /><input name='bar' />" }
7
+
8
+ let(:multiple_matcher) do
9
+ RSpec::TagMatchers::MultipleInputMatcher.new(2 => foo_matcher, 3 => bar_matcher)
10
+ end
11
+
12
+ before do
13
+ # prevent unexpected messages from causing test failures
14
+ foo_matcher.stub(:with_attribute).with(:name => /\(2i\)/)
15
+ bar_matcher.stub(:with_attribute).with(:name => /\(3i\)/)
16
+ end
17
+
18
+ describe "#initialize" do
19
+ it "should add criteria for input indices" do
20
+ foo_matcher.should_receive(:with_attribute).with(:name => /\(2i\)/)
21
+ bar_matcher.should_receive(:with_attribute).with(:name => /\(3i\)/)
22
+ multiple_matcher
23
+ end
24
+ end
25
+
26
+ describe "#for" do
27
+ it "should add indices, e.g., '(2i)', to last part of each input's name" do
28
+ foo_matcher.should_receive(:for).with("example", "foobar(2i)")
29
+ bar_matcher.should_receive(:for).with("example", "foobar(3i)")
30
+ multiple_matcher.for("example" => "foobar")
31
+ end
32
+
33
+ it "should return self" do
34
+ foo_matcher.should_receive(:for)
35
+ bar_matcher.should_receive(:for)
36
+ multiple_matcher.for("example" => "foobar").should == multiple_matcher
37
+ end
38
+ end
39
+
40
+ describe "#matches?" do
41
+ context "all matchers pass" do
42
+ before do
43
+ foo_matcher.should_receive(:matches?).with(html).and_return(true)
44
+ bar_matcher.should_receive(:matches?).with(html).and_return(true)
45
+ end
46
+
47
+ subject { multiple_matcher.matches?(html) }
48
+ it { should be_true }
49
+ end
50
+
51
+ context "some matchers fail" do
52
+ before do
53
+ foo_matcher.should_receive(:matches?).with(html).and_return(false)
54
+ bar_matcher.should_receive(:matches?).with(html).and_return(true)
55
+ end
56
+
57
+ subject { multiple_matcher.matches?(html) }
58
+ it { should be_false }
59
+ end
60
+
61
+ context "all matchers fail" do
62
+ before do
63
+ foo_matcher.should_receive(:matches?).with(html).and_return(false)
64
+ bar_matcher.should_receive(:matches?).with(html).and_return(false)
65
+ end
66
+
67
+ subject { multiple_matcher.matches?(html) }
68
+ it { should be_false }
69
+ end
70
+ end
71
+
72
+ describe "#failure_message" do
73
+ let(:failure_message_for_foo) { "failure message for foo" }
74
+ let(:failure_message_for_bar) { "failure message for bar" }
75
+
76
+ context "foo_matcher fails" do
77
+ before do
78
+ foo_matcher.should_receive(:matches?).with(html).and_return(false)
79
+ bar_matcher.should_receive(:matches?).with(html).and_return(true)
80
+ multiple_matcher.matches?(html)
81
+
82
+ foo_matcher.should_receive(:failure_message).and_return(failure_message_for_foo)
83
+ end
84
+
85
+ subject { multiple_matcher.failure_message }
86
+ it { should == failure_message_for_foo }
87
+ end
88
+
89
+ context "bar_matcher fails" do
90
+ before do
91
+ foo_matcher.should_receive(:matches?).with(html).and_return(true)
92
+ bar_matcher.should_receive(:matches?).with(html).and_return(false)
93
+ multiple_matcher.matches?(html)
94
+
95
+ bar_matcher.should_receive(:failure_message).and_return(failure_message_for_bar)
96
+ end
97
+
98
+ subject { multiple_matcher.failure_message }
99
+ it { should == failure_message_for_bar }
100
+ end
101
+
102
+ context "all matchers fail" do
103
+ before do
104
+ foo_matcher.should_receive(:matches?).with(html).and_return(false)
105
+ bar_matcher.should_receive(:matches?).with(html).and_return(false)
106
+ multiple_matcher.matches?(html)
107
+
108
+ foo_matcher.should_receive(:failure_message).and_return(failure_message_for_foo)
109
+ bar_matcher.should_receive(:failure_message).and_return(failure_message_for_bar)
110
+ end
111
+
112
+ subject { multiple_matcher.failure_message }
113
+ it { should include(failure_message_for_foo) }
114
+ it { should include(failure_message_for_bar) }
115
+ it { should include(" and ") }
116
+ end
117
+ end
118
+
119
+ describe "#negative_failure_message" do
120
+ let(:negative_failure_message_for_foo) { "negative failure message for foo" }
121
+ let(:negative_failure_message_for_bar) { "negative failure message for bar" }
122
+
123
+ context "all matchers pass" do
124
+ before do
125
+ foo_matcher.should_receive(:matches?).with(html).and_return(true)
126
+ bar_matcher.should_receive(:matches?).with(html).and_return(true)
127
+ multiple_matcher.matches?(html)
128
+
129
+ foo_matcher.should_receive(:negative_failure_message).and_return(negative_failure_message_for_foo)
130
+ bar_matcher.should_receive(:negative_failure_message).and_return(negative_failure_message_for_bar)
131
+ end
132
+
133
+ subject { multiple_matcher.negative_failure_message }
134
+ it { should include(negative_failure_message_for_foo) }
135
+ it { should include(negative_failure_message_for_bar) }
136
+ it { should include(" and ") }
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,18 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'rspec-tag_matchers'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
13
+
14
+ RSpec::Matchers.define :match do |rendered|
15
+ match do |matcher|
16
+ matcher.matches?(rendered)
17
+ end
18
+ end