rspec2-rails-views-matchers 0.0.1

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.
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
+