rspec-tag_matchers 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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