rspec2-rails-views-matchers 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ html
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rspec2-rails-views-matchers.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,26 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rspec2-rails-views-matchers (0.0.1)
5
+ nokogiri (~> 1.4.4)
6
+ rspec (>= 2.0.0)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ diff-lcs (1.1.2)
12
+ nokogiri (1.4.4)
13
+ rspec (2.4.0)
14
+ rspec-core (~> 2.4.0)
15
+ rspec-expectations (~> 2.4.0)
16
+ rspec-mocks (~> 2.4.0)
17
+ rspec-core (2.4.0)
18
+ rspec-expectations (2.4.0)
19
+ diff-lcs (~> 1.1.2)
20
+ rspec-mocks (2.4.0)
21
+
22
+ PLATFORMS
23
+ ruby
24
+
25
+ DEPENDENCIES
26
+ rspec2-rails-views-matchers!
data/README.rdoc ADDED
@@ -0,0 +1,24 @@
1
+ = Why?
2
+
3
+ * you need to test some complex views
4
+ * and you want to use rspec2
5
+ * and assert\_select seems is something strange to you
6
+ * rspec-rails[https://github.com/rspec/rspec-rails] for some reason does not provide instruments for testing views
7
+ * you need user-firendly output in error messages
8
+
9
+ == Install
10
+
11
+ add to your Gemfile(in group :test :) ):
12
+
13
+ gem 'rspec2-rails-views-matchers'
14
+
15
+ == Usage
16
+
17
+ descriptive code:
18
+
19
+ rendered.should have_tag('form',:with => {:action => user_path, :method => 'post'}) {
20
+ with_tag "input", :with => { :name => "user[email]", :type => 'email' }
21
+ with_tag "input", :with => { :name => "user[password]", :type => 'password'}
22
+ with_tag "input", :with => { :name => "user[password_confirmation]", :type => 'password' }
23
+ with_tag "input#special_submit"
24
+ }
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'bundler'
2
+ require 'rspec/core/rake_task'
3
+ require 'rake/rdoctask'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ task :default => :spec
7
+
8
+ RSpec::Core::RakeTask.new
9
+
10
+ Rake::RDocTask.new(:rdoc) do |rd|
11
+ rd.main = "README.rdoc"
12
+ rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
13
+ rd.options << "--all"
14
+ end
@@ -0,0 +1 @@
1
+ require 'rspec/rails/views/matchers/have_tag'
@@ -0,0 +1,117 @@
1
+ require 'nokogiri'
2
+
3
+ module RSpec
4
+ module Matchers
5
+
6
+ class NokogiriMatcher#:nodoc:
7
+ attr_reader :failure_message
8
+ attr_reader :parent_scope, :current_scope
9
+
10
+ def initialize tag, options={}, &block
11
+ @tag, @options, @block = tag, options, block
12
+
13
+ if attrs = @options.delete(:with)
14
+ html_attrs_string=''
15
+ attrs.each_pair { |k,v| html_attrs_string << %Q{[#{k.to_s}='#{v.to_s}']} }
16
+ @tag << html_attrs_string
17
+ end
18
+
19
+ # TODO add min and max processing
20
+ @options[:minimum] ||= @options.delete(:min)
21
+ @options[:maximum] ||= @options.delete(:max)
22
+ end
23
+
24
+ def matches?(document)
25
+
26
+ case document
27
+ when String
28
+ @parent_scope = @current_scope = Nokogiri::HTML(document).css(@tag)
29
+ @document = document
30
+ else
31
+ @parent_scope = document.current_scope
32
+ @current_scope = document.parent_scope.css(@tag)
33
+ @document = @parent_scope.to_html
34
+ end
35
+
36
+ if tag_presents? and count_right? and content_right?
37
+ @current_scope = @parent_scope
38
+ @block.call if @block
39
+ true
40
+ else
41
+ false
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def tag_presents?
48
+ if @current_scope.first
49
+ @count = @current_scope.count
50
+ true
51
+ else
52
+ @failure_message = %Q{expected following:\n#{@document}\nto have at least 1 element matching "#{@tag}", found 0.}
53
+ false
54
+ end
55
+ end
56
+
57
+ def count_right?
58
+ case @options[:count]
59
+ when Integer
60
+ @count == @options[:count] || (@failure_message=%Q{expected following:\n#{@document}\nto have #{@options[:count]} element(s) matching "#{@tag}", found #{@count}.}; false)
61
+ when Range
62
+ @options[:count].member?(@count) || (@failure_message=%Q{expected following:\n#{@document}\nto have at least #{@options[:count].min} and at most #{@options[:count].max} element(s) matching "#{@tag}", found #{@count}.}; false)
63
+ when nil
64
+ if @options[:maximum]
65
+ @count <= @options[:maximum] || (@failure_message=%Q{expected following:\n#{@document}\nto have at most #{@options[:maximum]} element(s) matching "#{@tag}", found #{@count}.}; false)
66
+ elsif @options[:minimum]
67
+ @count >= @options[:minimum] || (@failure_message=%Q{expected following:\n#{@document}\nto have at least #{@options[:minimum]} element(s) matching "#{@tag}", found #{@count}.}; false)
68
+ else
69
+ true
70
+ end
71
+ else
72
+ @failure_message = 'wrong count specified'
73
+ return false
74
+ end
75
+ end
76
+
77
+ def content_right?
78
+ return true unless @options[:text]
79
+
80
+ case text=@options[:text]
81
+ when Regexp
82
+ if @current_scope.any? {|node| node.content =~ text }
83
+ true
84
+ else
85
+ @failure_message=%Q{#{text.inspect} regexp expected within "#{@tag}" in following template:\n#{@document}}
86
+ false
87
+ end
88
+ else
89
+ if @current_scope.any? {|node| node.content == text }
90
+ true
91
+ else
92
+ @failure_message=%Q{"#{text}" expected within "#{@tag}" in following template:\n#{@document}}
93
+ false
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ # :call-seq:
100
+ # rendered.should have_tag(tag,options={},&block)
101
+ # rendered.should have_tag(tag,options={},&block) { with_tag(other_tag) }
102
+ # string.should have_tag(tag,options={},&block)
103
+ #
104
+ def have_tag tag,options={}, &block
105
+ @__current_scope_for_nokogiri_matcher = NokogiriMatcher.new(tag, options, &block)
106
+ end
107
+
108
+ def with_tag tag, options={}, &block
109
+ @__current_scope_for_nokogiri_matcher.should have_tag(tag, options, &block)
110
+ end
111
+
112
+ def without_tag tag, options={}, &block
113
+ @__current_scope_for_nokogiri_matcher.should_not have_tag(tag, options, &block)
114
+ end
115
+
116
+ end
117
+ end
@@ -0,0 +1,9 @@
1
+ module RSpec#:nodoc:
2
+ module Rails#:nodoc:
3
+ module Views#:nodoc:
4
+ module Matchers#:nodoc:
5
+ VERSION = "0.0.1"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1 @@
1
+ require 'rspec/rails/views/matchers'
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rspec/rails/views/matchers/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rspec2-rails-views-matchers"
7
+ s.version = RSpec::Rails::Views::Matchers::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["kucaahbe"]
10
+ s.email = ["kucaahbe@ukr.net"]
11
+ s.homepage = ""
12
+ s.summary = %q{collection of rspec2 views matchers for rails}
13
+ s.description = s.summary
14
+
15
+ s.rubyforge_project = "rspec2-rails-views-matchers"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency 'rspec', '>= 2.0.0'
23
+ s.add_dependency 'nokogiri', '~> 1.4.4'
24
+ end
@@ -0,0 +1,246 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'have_tag' do
4
+
5
+ it "should have message for should_not"
6
+ it "should have #description method"
7
+
8
+ context "through css selector" do
9
+
10
+ before :each do
11
+ render_html <<HTML
12
+ <div>
13
+ some content
14
+ <div id="div">some other div</div>
15
+ <p class="paragraph">la<strong>lala</strong></p>
16
+ </div>
17
+ <form id="some_form">
18
+ <input id="search" type="text" />
19
+ <input type="submit" value="Save" />
20
+ </form>
21
+ HTML
22
+ end
23
+
24
+ it "should find tags" do
25
+ rendered.should have_tag('div')
26
+ rendered.should have_tag('div#div')
27
+ rendered.should have_tag('p.paragraph')
28
+ rendered.should have_tag('div p strong')
29
+ end
30
+
31
+ it "should not find tags" do
32
+ rendered.should_not have_tag('span')
33
+ rendered.should_not have_tag('span#id')
34
+ rendered.should_not have_tag('span#class')
35
+ rendered.should_not have_tag('div div span')
36
+ end
37
+
38
+ it "should not find tags and display appropriate message" do
39
+ expect { rendered.should have_tag('span') }.should raise_spec_error(
40
+ %Q{expected following:\n#{rendered}\nto have at least 1 element matching "span", found 0.}
41
+ )
42
+ expect { rendered.should have_tag('span#some_id') }.should raise_spec_error(
43
+ %Q{expected following:\n#{rendered}\nto have at least 1 element matching "span#some_id", found 0.}
44
+ )
45
+ expect { rendered.should have_tag('span.some_class') }.should raise_spec_error(
46
+ %Q{expected following:\n#{rendered}\nto have at least 1 element matching "span.some_class", found 0.}
47
+ )
48
+ end
49
+
50
+ context "with additional HTML attributes(:with option)" do
51
+
52
+ it "should find tags" do
53
+ rendered.should have_tag('input#search',:with => {:type => "text"})
54
+ rendered.should have_tag('input',:with => {:type => "submit", :value => "Save"})
55
+ end
56
+
57
+ it "should not find tags" do
58
+ rendered.should_not have_tag('input#search',:with => {:type => "some_other_type"})
59
+ end
60
+
61
+ it "should not find tags and display appropriate message" do
62
+ expect { rendered.should have_tag('input#search',:with => {:type => "some_other_type"}) }.should raise_spec_error(
63
+ %Q{expected following:\n#{rendered}\nto have at least 1 element matching "input#search[type='some_other_type']", found 0.}
64
+ )
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+
71
+ context "by count" do
72
+
73
+ before :each do
74
+ render_html <<HTML
75
+ <p>tag one</p>
76
+ <p>tag two</p>
77
+ <p>tag three</p>
78
+ HTML
79
+ end
80
+
81
+ it "should find tags" do
82
+ rendered.should have_tag('p', :count => 3)
83
+ rendered.should have_tag('p', :count => 2..3)
84
+ end
85
+
86
+ it "should find tags when :minimum specified" do
87
+ rendered.should have_tag('p', :min => 3)
88
+ rendered.should have_tag('p', :minimum => 2)
89
+ end
90
+
91
+ it "should find tags when :maximum specified" do
92
+ rendered.should have_tag('p', :max => 4)
93
+ rendered.should have_tag('p', :maximum => 3)
94
+ end
95
+
96
+ it "should not find tags(with :count, :minimum or :maximum specified)" do
97
+ rendered.should_not have_tag('p', :count => 10)
98
+ rendered.should_not have_tag('p', :count => 4..8)
99
+ rendered.should_not have_tag('p', :min => 11)
100
+ rendered.should_not have_tag('p', :minimum => 10)
101
+ rendered.should_not have_tag('p', :max => 2)
102
+ rendered.should_not have_tag('p', :maximum => 2)
103
+ end
104
+
105
+ it "should not find tags and display appropriate message(with :count)" do
106
+ expect { rendered.should have_tag('p', :count => 10) }.should raise_spec_error(
107
+ %Q{expected following:\n#{rendered}\nto have 10 element(s) matching "p", found 3.}
108
+ )
109
+
110
+ expect { rendered.should have_tag('p', :count => 4..8) }.should raise_spec_error(
111
+ %Q{expected following:\n#{rendered}\nto have at least 4 and at most 8 element(s) matching "p", found 3.}
112
+ )
113
+ end
114
+
115
+ it "should not find tags and display appropriate message(with :minimum)" do
116
+ expect { rendered.should have_tag('p', :min => 100) }.should raise_spec_error(
117
+ %Q{expected following:\n#{rendered}\nto have at least 100 element(s) matching "p", found 3.}
118
+ )
119
+ expect { rendered.should have_tag('p', :minimum => 100) }.should raise_spec_error(
120
+ %Q{expected following:\n#{rendered}\nto have at least 100 element(s) matching "p", found 3.}
121
+ )
122
+ end
123
+
124
+ it "should not find tags and display appropriate message(with :maximum)" do
125
+ expect { rendered.should have_tag('p', :max => 2) }.should raise_spec_error(
126
+ %Q{expected following:\n#{rendered}\nto have at most 2 element(s) matching "p", found 3.}
127
+ )
128
+ expect { rendered.should have_tag('p', :maximum => 2) }.should raise_spec_error(
129
+ %Q{expected following:\n#{rendered}\nto have at most 2 element(s) matching "p", found 3.}
130
+ )
131
+ end
132
+
133
+ it "should raise error when wrong params specified" do
134
+ pending(:TODO)
135
+ wrong_params_error_msg_1 = 'TODO1'
136
+ expect { rendered.should have_tag('div', :count => 2, :minimum => 1 ) }.should raise_error(wrong_params_error_msg_1)
137
+ expect { rendered.should have_tag('div', :count => 2, :min => 1 ) }.should raise_error(wrong_params_error_msg_1)
138
+ expect { rendered.should have_tag('div', :count => 2, :maximum => 1 ) }.should raise_error(wrong_params_error_msg_1)
139
+ expect { rendered.should have_tag('div', :count => 2, :max => 1 ) }.should raise_error(wrong_params_error_msg_1)
140
+
141
+ wrong_params_error_msg_2 = 'TODO2'
142
+ expect { rendered.should have_tag('div', :minimum => 2, :maximum => 1 ) }.should raise_error(wrong_params_error_msg_2)
143
+
144
+ [ 4..1, -2..6, 'a'..'z', 3..-9 ].each do |range|
145
+ expect { rendered.should have_tag('div', :count => range ) }.should raise_error("Your :count range(#{range.to_s}) has no sence!")
146
+ end
147
+ end
148
+
149
+ end
150
+
151
+ context "with content specified" do
152
+
153
+ before :each do
154
+ render_html <<HTML
155
+ <div>sample text</div>
156
+ <p>one </p>
157
+ <p> two</p>
158
+ <p> three </p>
159
+ HTML
160
+ end
161
+
162
+ it "should find tags" do
163
+ rendered.should have_tag('div', :text => 'sample text')
164
+ rendered.should have_tag('p', :text => 'one ' )
165
+ rendered.should have_tag('div', :text => /SAMPLE/i )
166
+ end
167
+
168
+ it "should not find tags" do
169
+ rendered.should_not have_tag('p', :text => 'text does not present')
170
+ rendered.should_not have_tag('strong', :text => 'text does not present')
171
+ rendered.should_not have_tag('p', :text => /text does not present/)
172
+ rendered.should_not have_tag('strong', :text => /text does not present/)
173
+ end
174
+
175
+ it "should not find tags and display appropriate message" do
176
+ # TODO make diffable,maybe...
177
+ expect { rendered.should have_tag('div', :text => 'SAMPLE text') }.should raise_spec_error(
178
+ %Q{"SAMPLE text" expected within "div" in following template:\n#{rendered}}
179
+ )
180
+ expect { rendered.should have_tag('div', :text => /SAMPLE tekzt/i) }.should raise_spec_error(
181
+ %Q{/SAMPLE tekzt/i regexp expected within "div" in following template:\n#{rendered}}
182
+ )
183
+ end
184
+
185
+ end
186
+
187
+ context "nested matching:" do
188
+ before :each do
189
+ @ordered_list =<<OL
190
+ <ol class="menu">
191
+ <li>list item 1</li>
192
+ <li>list item 2</li>
193
+ <li>list item 3</li>
194
+ </ol>
195
+ OL
196
+ render_html <<HTML
197
+ <html>
198
+ <body>
199
+ #{@ordered_list}
200
+ </body>
201
+ </html>
202
+ HTML
203
+ end
204
+
205
+ it "should find tags" do
206
+ rendered.should have_tag('ol') {
207
+ with_tag('li', :text => 'list item 1')
208
+ with_tag('li', :text => 'list item 2')
209
+ with_tag('li', :text => 'list item 3')
210
+ with_tag('li', :count => 3)
211
+ with_tag('li', :count => 2..3)
212
+ with_tag('li', :min => 2)
213
+ with_tag('li', :max => 6)
214
+ }
215
+ end
216
+
217
+ it "should not find tags" do
218
+ rendered.should have_tag('ol') {
219
+ without_tag('div')
220
+ without_tag('li', :count => 2)
221
+ without_tag('li', :count => 4..8)
222
+ without_tag('li', :min => 100)
223
+ without_tag('li', :max => 2)
224
+ without_tag('li', :text => 'blabla')
225
+ without_tag('li', :text => /list item (?!\d)/)
226
+ }
227
+ end
228
+
229
+ it "should not find tags and display appropriate message" do
230
+ ordered_list_regexp = @ordered_list.gsub(/(\n?\s{2,}|\n\s?)/,'\n*\s*')
231
+ expect {
232
+ rendered.should have_tag('ol') { with_tag('li'); with_tag('div') }
233
+ }.should raise_spec_error(/expected following:#{ordered_list_regexp}to have at least 1 element matching "div", found 0/)
234
+
235
+ expect {
236
+ rendered.should have_tag('ol') { with_tag('li'); with_tag('li', :count => 10) }
237
+ }.should raise_spec_error(/expected following:#{ordered_list_regexp}to have 10 element\(s\) matching "li", found 3/)
238
+
239
+ expect {
240
+ rendered.should have_tag('ol') { with_tag('li'); with_tag('li', :text => /SAMPLE text/i) }
241
+ }.should raise_spec_error(/\/SAMPLE text\/i regexp expected within "li" in following template:#{ordered_list_regexp}/)
242
+ end
243
+
244
+ end
245
+
246
+ end
@@ -0,0 +1,19 @@
1
+ require 'rspec/rails/views/matchers'
2
+
3
+ # Requires supporting files with custom matchers and macros, etc,
4
+ # # in ./support/ and its subdirectories.
5
+ Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
6
+
7
+ module RenderedHelper
8
+ def render_html html
9
+ @rendered = html
10
+ end
11
+
12
+ def rendered
13
+ @rendered
14
+ end
15
+ end
16
+
17
+ RSpec.configure do |config|
18
+ config.include RenderedHelper
19
+ end
@@ -0,0 +1,3 @@
1
+ def raise_spec_error msg
2
+ raise_error RSpec::Expectations::ExpectationNotMetError, msg
3
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rspec2-rails-views-matchers
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - kucaahbe
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-21 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rspec
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 15
30
+ segments:
31
+ - 2
32
+ - 0
33
+ - 0
34
+ version: 2.0.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: nokogiri
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 15
46
+ segments:
47
+ - 1
48
+ - 4
49
+ - 4
50
+ version: 1.4.4
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ description: collection of rspec2 views matchers for rails
54
+ email:
55
+ - kucaahbe@ukr.net
56
+ executables: []
57
+
58
+ extensions: []
59
+
60
+ extra_rdoc_files: []
61
+
62
+ files:
63
+ - .gitignore
64
+ - .rspec
65
+ - Gemfile
66
+ - Gemfile.lock
67
+ - README.rdoc
68
+ - Rakefile
69
+ - lib/rspec/rails/views/matchers.rb
70
+ - lib/rspec/rails/views/matchers/have_tag.rb
71
+ - lib/rspec/rails/views/matchers/version.rb
72
+ - lib/rspec2-rails-views-matchers.rb
73
+ - rspec2-rails-views-matchers.gemspec
74
+ - spec/matchers/have_tag_spec.rb
75
+ - spec/spec_helper.rb
76
+ - spec/support/spec_error.rb
77
+ has_rdoc: true
78
+ homepage: ""
79
+ licenses: []
80
+
81
+ post_install_message:
82
+ rdoc_options: []
83
+
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ hash: 3
92
+ segments:
93
+ - 0
94
+ version: "0"
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ hash: 3
101
+ segments:
102
+ - 0
103
+ version: "0"
104
+ requirements: []
105
+
106
+ rubyforge_project: rspec2-rails-views-matchers
107
+ rubygems_version: 1.5.0
108
+ signing_key:
109
+ specification_version: 3
110
+ summary: collection of rspec2 views matchers for rails
111
+ test_files: []
112
+