rspec-html-matchers 0.3.5 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -2
- data/CHANGELOG.md +19 -1
- data/README.md +115 -84
- data/Rakefile +5 -6
- data/features/support/env.rb +1 -1
- data/lib/rspec-html-matchers.rb +112 -81
- data/rspec-html-matchers.gemspec +2 -1
- data/{assets → spec/assets}/form.html +0 -0
- data/{assets → spec/assets}/ordered_list.html +0 -0
- data/{assets → spec/assets}/paragraphs.html +0 -0
- data/spec/assets/quotes.html +15 -0
- data/{assets → spec/assets}/search_and_submit.html +0 -0
- data/{assets → spec/assets}/special.html +0 -0
- data/spec/matchers/form_matchers_spec.rb +3 -2
- data/spec/matchers/have_tag_spec.rb +223 -97
- data/spec/spec_helper.rb +21 -4
- metadata +36 -11
- data/assets/quotes.html +0 -26
- data/mikhalok.jpg +0 -0
- data/spec/support/helpers.rb +0 -11
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -4,8 +4,26 @@ Changelog
|
|
4
4
|
unreleased(TODO)
|
5
5
|
----------------
|
6
6
|
|
7
|
-
* improve documentation(look at changelog and code!)
|
8
7
|
* add :without to have\_tag? like have_tag('div', :without => { :class => 'test' })
|
8
|
+
* with_tag should raise error when used outside have_tag
|
9
|
+
* add ability to have_form('/url', 'PUT') or have_form('/url', :PUT)
|
10
|
+
* inteligent check comments(make sure it is not searching inside comments)
|
11
|
+
* shouldn't show all markup in error message if it is too big
|
12
|
+
|
13
|
+
0.5.0(TODO)
|
14
|
+
-----------
|
15
|
+
|
16
|
+
* order matching
|
17
|
+
* improve documentation, add more usage examples (look at changelog and code!)
|
18
|
+
|
19
|
+
0.4.0
|
20
|
+
-----
|
21
|
+
|
22
|
+
* added with_text matcher
|
23
|
+
* some code refactoring, but a lot of refactoring left for future
|
24
|
+
* rewritten README, added more usage examples
|
25
|
+
* removed dealing with whitespaces (#11), too much magic for usage (#16)
|
26
|
+
* some attempt to improve documentation
|
9
27
|
|
10
28
|
0.3.5
|
11
29
|
-----
|
data/README.md
CHANGED
@@ -1,40 +1,40 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
rspec-html-matchers
|
2
|
+
===================
|
3
3
|
|
4
|
-
[
|
4
|
+
[RSpec 2](https://www.relishapp.com/rspec) matchers for testing your html.
|
5
5
|
|
6
|
-
|
7
|
-
===
|
6
|
+
[![Build Status](http://travis-ci.org/kucaahbe/rspec-html-matchers.png)](http://travis-ci.org/kucaahbe/rspec-html-matchers)
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
* and assert\_select seems is something strange to you
|
12
|
-
* have_tag in [rspec-rails](http://github.com/rspec/rspec-rails) are deprecated now
|
13
|
-
* you need a user-firendly output in your error messages
|
8
|
+
Goals
|
9
|
+
-----
|
14
10
|
|
15
|
-
|
16
|
-
|
11
|
+
* for testing **complicated** html output, for simple matching consider use:
|
12
|
+
* [assert_select](http://api.rubyonrails.org/classes/ActionDispatch/Assertions/SelectorAssertions.html#method-i-assert_select)
|
13
|
+
* [matchers provided out of the box in rspec-rails](https://www.relishapp.com/rspec/rspec-rails/v/2-11/docs/view-specs/view-spec)
|
14
|
+
* [matchers provided by capybara](http://rdoc.info/github/jnicklas/capybara/Capybara/Node/Matchers)
|
15
|
+
* developer-firendly output in error messages
|
16
|
+
* built on top of [nokogiri](nokogiri.org)
|
17
|
+
* has support for [capybara](https://github.com/jnicklas/capybara), see below
|
18
|
+
* syntax is similar to [have_tag](http://old.rspec.info/rails/writing/views.html) matcher from old-school rspec-rails, but with own syntactic sugar
|
19
|
+
* framework agnostic, as input should be String(or capybara's page, see below)
|
17
20
|
|
18
21
|
Install
|
19
22
|
-------
|
20
23
|
|
21
|
-
Add to your Gemfile
|
24
|
+
Add to your Gemfile in the `:test` group:
|
22
25
|
|
23
26
|
```ruby
|
24
|
-
|
25
|
-
gem 'rspec-html-matchers'
|
26
|
-
end
|
27
|
+
gem 'rspec-html-matchers'
|
27
28
|
```
|
28
29
|
|
29
|
-
|
30
|
+
as this gem requires **nokogiri**, here [instructions for installing it](http://nokogiri.org/tutorials/installing_nokogiri.html).
|
30
31
|
|
31
32
|
Usage
|
32
33
|
-----
|
33
34
|
|
34
|
-
|
35
|
+
so perharps your code produces following output:
|
35
36
|
|
36
|
-
```
|
37
|
-
view=<<-HTML
|
37
|
+
```html
|
38
38
|
<h1>Simple Form</h1>
|
39
39
|
<form action="/users" method="post">
|
40
40
|
<p>
|
@@ -44,9 +44,12 @@ view=<<-HTML
|
|
44
44
|
<input type="submit" id="special_submit" />
|
45
45
|
</p>
|
46
46
|
</form>
|
47
|
-
|
47
|
+
```
|
48
|
+
|
49
|
+
so you test it with following:
|
48
50
|
|
49
|
-
|
51
|
+
```ruby
|
52
|
+
rendered.should have_tag('form', :with => { :action => '/users', :method => 'post' }) do
|
50
53
|
with_tag "input", :with => { :name => "user[email]", :type => 'email' }
|
51
54
|
with_tag "input#special_submit", :count => 1
|
52
55
|
without_tag "h1", :text => 'unneeded tag'
|
@@ -54,76 +57,103 @@ view.should have_tag('form', :with => { :action => '/users', :method => 'post' }
|
|
54
57
|
end
|
55
58
|
```
|
56
59
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
'<p class="qwe rty" id="qwerty">Paragraph</p>'.should have_tag('p
|
66
|
-
|
67
|
-
'<p class="qwe rty" id="qwerty"
|
68
|
-
'<p class="qwe rty" id="qwerty"
|
69
|
-
|
70
|
-
|
71
|
-
'<p class="qwe rty" id="qwerty"><strong>Para</strong>graph</p>'.should have_tag('p')
|
72
|
-
|
73
|
-
|
74
|
-
'<p class="qwe rty" id="qwerty"><strong>Para</strong>graph</p>'.should have_tag('p
|
75
|
-
|
76
|
-
end
|
77
|
-
'<p class="qwe rty" id="qwerty"><strong>Para</strong>graph</p>'.should have_tag('p
|
78
|
-
|
79
|
-
end
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
'<p class="qwe rty" id="qwerty">Paragraph</p>'.should have_tag('p', :with => { :class =>
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
60
|
+
Example about should be self-descriptive, but if not refer to [have_tag](http://rdoc.info/github/kucaahbe/rspec-html-matchers/RSpec/Matchers:have_tag) documentation
|
61
|
+
|
62
|
+
Input could be any html string. Let's take a look at these examples:
|
63
|
+
|
64
|
+
* matching tags by css:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
# simple examples:
|
68
|
+
'<p class="qwe rty" id="qwerty">Paragraph</p>'.should have_tag('p')
|
69
|
+
'<p class="qwe rty" id="qwerty">Paragraph</p>'.should have_tag(:p)
|
70
|
+
'<p class="qwe rty" id="qwerty">Paragraph</p>'.should have_tag('p#qwerty')
|
71
|
+
'<p class="qwe rty" id="qwerty">Paragraph</p>'.should have_tag('p.qwe.rty')
|
72
|
+
# more complicated examples:
|
73
|
+
'<p class="qwe rty" id="qwerty"><strong>Para</strong>graph</p>'.should have_tag('p strong')
|
74
|
+
'<p class="qwe rty" id="qwerty"><strong>Para</strong>graph</p>'.should have_tag('p#qwerty strong')
|
75
|
+
'<p class="qwe rty" id="qwerty"><strong>Para</strong>graph</p>'.should have_tag('p.qwe.rty strong')
|
76
|
+
# or you can use another syntax for examples above
|
77
|
+
'<p class="qwe rty" id="qwerty"><strong>Para</strong>graph</p>'.should have_tag('p') do
|
78
|
+
with_tag('strong')
|
79
|
+
end
|
80
|
+
'<p class="qwe rty" id="qwerty"><strong>Para</strong>graph</p>'.should have_tag('p#qwerty') do
|
81
|
+
with_tag('strong')
|
82
|
+
end
|
83
|
+
'<p class="qwe rty" id="qwerty"><strong>Para</strong>graph</p>'.should have_tag('p.qwe.rty') do
|
84
|
+
with_tag('strong')
|
85
|
+
end
|
86
|
+
```
|
87
|
+
|
88
|
+
* special case for classes matching:
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
# all of this are equivalent:
|
92
|
+
'<p class="qwe rty" id="qwerty">Paragraph</p>'.should have_tag('p', :with => { :class => 'qwe rty' })
|
93
|
+
'<p class="qwe rty" id="qwerty">Paragraph</p>'.should have_tag('p', :with => { :class => 'rty qwe' })
|
94
|
+
'<p class="qwe rty" id="qwerty">Paragraph</p>'.should have_tag('p', :with => { :class => ['rty', 'qwe'] })
|
95
|
+
'<p class="qwe rty" id="qwerty">Paragraph</p>'.should have_tag('p', :with => { :class => ['qwe', 'rty'] })
|
96
|
+
```
|
97
|
+
|
98
|
+
* content matching:
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
'<p> Some content here</p>'.should have_tag('p', :text => ' Some content here')
|
102
|
+
# or
|
103
|
+
'<p> Some content here</p>'.should have_tag('p') do
|
104
|
+
with_text ' Some content here'
|
105
|
+
end
|
106
|
+
|
107
|
+
'<p> Some content here</p>'.should have_tag('p', :text => /Some content here/)
|
108
|
+
# or
|
109
|
+
'<p> Some content here</p>'.should have_tag('p') do
|
110
|
+
with_text /Some content here/
|
111
|
+
end
|
112
|
+
|
113
|
+
# mymock.text == 'Some content here'
|
114
|
+
'<p> Some content here</p>'.should have_tag('p', :content => mymock.text)
|
115
|
+
# or
|
116
|
+
'<p> Some content here</p>'.should have_tag('p') do
|
117
|
+
with_content mymock.text
|
118
|
+
end
|
119
|
+
```
|
120
|
+
|
121
|
+
* usage with capybara and cucumber:
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
page.should have_tag( ... )
|
125
|
+
```
|
95
126
|
|
96
127
|
where `page` is an instance of Capybara::Session
|
97
128
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
- [
|
102
|
-
- [with\
|
103
|
-
- [with\
|
104
|
-
- [with\
|
105
|
-
- [with\
|
106
|
-
- [with\
|
107
|
-
- [with\
|
108
|
-
- [with\
|
109
|
-
- [with\
|
110
|
-
- [with\
|
111
|
-
- [with\
|
112
|
-
- [with\_text\
|
113
|
-
- [with\
|
114
|
-
- [with\
|
115
|
-
- [with\
|
116
|
-
- [with\
|
117
|
-
- [with\_date\_field](http://rdoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers:with_date_field)
|
129
|
+
* also included shorthand matchers for form inputs:
|
130
|
+
|
131
|
+
- [have\_form](http://rdoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers:have_form)
|
132
|
+
- [with\_checkbox](http://rdoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers:with_checkbox)
|
133
|
+
- [with\_email\_field](http://rdoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers:with_email_field)
|
134
|
+
- [with\_file\_field](http://rdoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers:with_file_field)
|
135
|
+
- [with\_hidden\_field](http://rdoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers:with_hidden_field)
|
136
|
+
- [with\_option](http://rdoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers:with_option)
|
137
|
+
- [with\_password_field](http://rdoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers:with_password_field)
|
138
|
+
- [with\_radio\_button](http://rdoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers:with_radio_button)
|
139
|
+
- [with\_button](http://rdoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers:with_button)
|
140
|
+
- [with\_select](http://rdoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers:with_select)
|
141
|
+
- [with\_submit](http://rdoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers:with_submit)
|
142
|
+
- [with\_text\_area](http://rdoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers:with_text_area)
|
143
|
+
- [with\_text\_field](http://rdoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers:with_text_field)
|
144
|
+
- [with\_url\_field](http://rdoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers:with_url_field)
|
145
|
+
- [with\_number\_field](http://rdoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers:with_number_field)
|
146
|
+
- [with\_range\_field](http://rdoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers:with_range_field)
|
147
|
+
- [with\_date\_field](http://rdoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers:with_date_field)
|
118
148
|
|
119
149
|
and of course you can use the `without_` matchers (see the documentation).
|
120
150
|
|
121
151
|
More info
|
122
152
|
---------
|
123
153
|
|
124
|
-
You can find more on [RubyDoc](http://rubydoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers), take a look at
|
154
|
+
You can find more on [RubyDoc](http://rubydoc.info/github/kucaahbe/rspec-html-matchers/master/RSpec/Matchers), take a look at [have_tag](http://rdoc.info/github/kucaahbe/rspec-html-matchers/RSpec/Matchers#have_tag-instance_method) method.
|
125
155
|
|
126
|
-
Also, please read
|
156
|
+
Also, please read [CHANGELOG](https://github.com/kucaahbe/rspec-html-matchers/blob/master/CHANGELOG.md), it might be helpful.
|
127
157
|
|
128
158
|
Contribution
|
129
159
|
============
|
@@ -131,7 +161,8 @@ Contribution
|
|
131
161
|
1. Fork the repository
|
132
162
|
2. Add tests for your feature
|
133
163
|
3. Write the code
|
134
|
-
4.
|
164
|
+
4. Add documentation for your contribution
|
165
|
+
5. Send a pull request
|
135
166
|
|
136
167
|
Contributors
|
137
168
|
============
|
@@ -141,7 +172,7 @@ Contributors
|
|
141
172
|
- [Simon Schoeters](https://github.com/cimm)
|
142
173
|
- [Felix Tjandrawibawa](https://github.com/cemenghttps://github.com/cemeng)
|
143
174
|
- [Szymon Przybył](https://github.com/apocalyptiq)
|
144
|
-
- [Howard Wilson]
|
175
|
+
- [Howard Wilson](https://github.com/watsonbox)
|
145
176
|
|
146
177
|
MIT Licensed
|
147
178
|
============
|
data/Rakefile
CHANGED
@@ -3,19 +3,18 @@ require 'rspec/core/rake_task'
|
|
3
3
|
require 'cucumber/rake/task'
|
4
4
|
Bundler::GemHelper.install_tasks
|
5
5
|
|
6
|
-
gemspec = eval(File.read(Dir["*.gemspec"].first))
|
7
|
-
|
8
6
|
task :default => [:spec, :cucumber]
|
9
7
|
|
10
|
-
RSpec::Core::RakeTask.new(:spec) do |t|
|
11
|
-
t.rspec_opts='--tag ~wip'
|
12
|
-
end
|
13
|
-
|
14
8
|
desc "Validate the gemspec"
|
15
9
|
task :gemspec do
|
10
|
+
gemspec = eval(File.read(Dir["*.gemspec"].first))
|
16
11
|
gemspec.validate && puts('gemspec valid')
|
17
12
|
end
|
18
13
|
|
14
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
15
|
+
t.rspec_opts='--tag ~wip'
|
16
|
+
end
|
17
|
+
|
19
18
|
namespace :spec do
|
20
19
|
RSpec::Core::RakeTask.new(:wip) do |t|
|
21
20
|
t.rspec_opts='--tag wip'
|
data/features/support/env.rb
CHANGED
@@ -2,7 +2,7 @@ require 'sinatra/base'
|
|
2
2
|
require 'capybara/cucumber'
|
3
3
|
require 'rspec-html-matchers'
|
4
4
|
|
5
|
-
$ASSETS_DIR = File.
|
5
|
+
$ASSETS_DIR = File.expand_path('../../../spec/assets',__FILE__)
|
6
6
|
$INDEX_HTML = File.join($ASSETS_DIR,'index.html')
|
7
7
|
|
8
8
|
class SimpleApp < Sinatra::Base
|
data/lib/rspec-html-matchers.rb
CHANGED
@@ -4,6 +4,43 @@ require 'nokogiri'
|
|
4
4
|
module RSpec
|
5
5
|
module Matchers
|
6
6
|
|
7
|
+
# @api
|
8
|
+
# @private
|
9
|
+
# for nokogiri regexp matching
|
10
|
+
class NokogiriRegexpHelper
|
11
|
+
def initialize(regex)
|
12
|
+
@regex = regex
|
13
|
+
end
|
14
|
+
|
15
|
+
def regexp node_set
|
16
|
+
node_set.find_all { |node| node.content =~ @regex }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# @api
|
21
|
+
# @private
|
22
|
+
class NokogiriTextHelper
|
23
|
+
def initialize text
|
24
|
+
@text = text
|
25
|
+
end
|
26
|
+
|
27
|
+
def content node_set
|
28
|
+
match_text = @text.gsub(/\\000027/, "'")
|
29
|
+
node_set.find_all do |node|
|
30
|
+
actual_content = node.content
|
31
|
+
# remove non-breaking spaces:
|
32
|
+
case RUBY_VERSION
|
33
|
+
when /^1\.9/
|
34
|
+
actual_content.gsub!(/\u00a0/, ' ')
|
35
|
+
when /^1\.8/
|
36
|
+
actual_content.gsub!("\302\240", ' ')
|
37
|
+
end
|
38
|
+
|
39
|
+
actual_content == match_text
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
7
44
|
# @api
|
8
45
|
# @private
|
9
46
|
class NokogiriMatcher
|
@@ -30,8 +67,6 @@ module RSpec
|
|
30
67
|
MIN_MAX_ERROR_MSG = %Q|:minimum shold be less than :maximum!|
|
31
68
|
BAD_RANGE_ERROR_MSG = %Q|Your :count range(%s) has no sence!|
|
32
69
|
|
33
|
-
PRESERVE_WHITESPACE_TAGS = %w( pre textarea )
|
34
|
-
|
35
70
|
def initialize tag, options={}, &block
|
36
71
|
@tag, @options, @block = tag.to_s, options, block
|
37
72
|
|
@@ -68,7 +103,7 @@ module RSpec
|
|
68
103
|
@document = @parent_scope.to_html
|
69
104
|
end
|
70
105
|
|
71
|
-
if tag_presents? and
|
106
|
+
if tag_presents? and text_right? and count_right?
|
72
107
|
@current_scope = @parent_scope
|
73
108
|
@block.call if @block
|
74
109
|
true
|
@@ -116,20 +151,12 @@ module RSpec
|
|
116
151
|
end
|
117
152
|
end
|
118
153
|
|
119
|
-
def
|
154
|
+
def text_right?
|
120
155
|
return true unless @options[:text]
|
121
156
|
|
122
157
|
case text=@options[:text]
|
123
158
|
when Regexp
|
124
|
-
new_scope = @current_scope.css(
|
125
|
-
def initialize(regex)
|
126
|
-
@regex = regex
|
127
|
-
end
|
128
|
-
|
129
|
-
def regexp node_set
|
130
|
-
node_set.find_all { |node| node.content =~ @regex }
|
131
|
-
end
|
132
|
-
}.new(text))
|
159
|
+
new_scope = @current_scope.css(':regexp()',NokogiriRegexpHelper.new(text))
|
133
160
|
unless new_scope.empty?
|
134
161
|
@count = new_scope.count
|
135
162
|
@negative_failure_message = REGEXP_FOUND_MSG % [text.inspect,@tag,@document]
|
@@ -139,23 +166,7 @@ module RSpec
|
|
139
166
|
false
|
140
167
|
end
|
141
168
|
else
|
142
|
-
|
143
|
-
new_scope = @current_scope.css(":content('#{css_param}')",Class.new {
|
144
|
-
def content node_set, text
|
145
|
-
match_text = text.gsub(/\\000027/, "'")
|
146
|
-
node_set.find_all do |node|
|
147
|
-
actual_content = if PRESERVE_WHITESPACE_TAGS.include?(node.name)
|
148
|
-
node.content
|
149
|
-
else
|
150
|
-
node.content.strip.squeeze(' ')
|
151
|
-
end
|
152
|
-
# remove non-braking spaces:
|
153
|
-
actual_content.gsub!("\u00a0", ' ')
|
154
|
-
actual_content.gsub!("\302\240", ' ')
|
155
|
-
actual_content == match_text
|
156
|
-
end
|
157
|
-
end
|
158
|
-
}.new)
|
169
|
+
new_scope = @current_scope.css(':content()',NokogiriTextHelper.new(text))
|
159
170
|
unless new_scope.empty?
|
160
171
|
@count = new_scope.count
|
161
172
|
@negative_failure_message = TEXT_FOUND_MSG % [text,@tag,@document]
|
@@ -200,20 +211,20 @@ module RSpec
|
|
200
211
|
|
201
212
|
end
|
202
213
|
|
203
|
-
#
|
214
|
+
# tag assertion, this is the core of functionality, other matchers are shortcuts to this matcher
|
204
215
|
#
|
205
|
-
# @yield block where you should put with_tag
|
216
|
+
# @yield block where you should put with_tag, without_tag and/or other matchers
|
206
217
|
#
|
207
|
-
# @param [String] tag css selector for tag you want to match
|
218
|
+
# @param [String] tag css selector for tag you want to match, e.g. 'div', 'section#my', 'article.red'
|
208
219
|
# @param [Hash] options options hash(see below)
|
209
|
-
# @option options [Hash] :with hash with
|
210
|
-
# @option options [Fixnum] :count
|
211
|
-
# @option options [Range] :count count of
|
220
|
+
# @option options [Hash] :with hash with html attributes, within this, *:class* option have special meaning, you may specify it as array of expected classes or string of classes separated by spaces, order does not matter
|
221
|
+
# @option options [Fixnum] :count for tag count matching(*ATTENTION:* do not use :count with :minimum(:min) or :maximum(:max))
|
222
|
+
# @option options [Range] :count not strict tag count matching, count of tags should be in specified range
|
212
223
|
# @option options [Fixnum] :minimum minimum count of elements to match
|
213
224
|
# @option options [Fixnum] :min same as :minimum
|
214
225
|
# @option options [Fixnum] :maximum maximum count of elements to match
|
215
226
|
# @option options [Fixnum] :max same as :maximum
|
216
|
-
#
|
227
|
+
# @option options [String/Regexp] :text to match tag content, could be either String or Regexp
|
217
228
|
#
|
218
229
|
# @example
|
219
230
|
# rendered.should have_tag('div')
|
@@ -221,7 +232,7 @@ module RSpec
|
|
221
232
|
# rendered.should have_tag('div#footer')
|
222
233
|
# rendered.should have_tag('input#email', :with => { :name => 'user[email]', :type => 'email' } )
|
223
234
|
# rendered.should have_tag('div', :count => 3) # matches exactly 3 'div' tags
|
224
|
-
# rendered.should have_tag('div', :count => 3..7) #
|
235
|
+
# rendered.should have_tag('div', :count => 3..7) # shortcut for have_tag('div', :minimum => 3, :maximum => 7)
|
225
236
|
# rendered.should have_tag('div', :minimum => 3) # matches more(or equal) than 3 'div' tags
|
226
237
|
# rendered.should have_tag('div', :maximum => 3) # matches less(or equal) than 3 'div' tags
|
227
238
|
# rendered.should have_tag('p', :text => 'some content') # will match "<p>some content</p>"
|
@@ -235,14 +246,28 @@ module RSpec
|
|
235
246
|
# '<div class="one two">'.should have_tag('div', :with => { :class => ['two', 'one'] })
|
236
247
|
# '<div class="one two">'.should have_tag('div', :with => { :class => 'two one' })
|
237
248
|
def have_tag tag, options={}, &block
|
238
|
-
|
239
|
-
|
240
|
-
end
|
249
|
+
# for backwards compatibility with rpecs have tag:
|
250
|
+
options = { :text => options } if options.kind_of? String
|
241
251
|
@__current_scope_for_nokogiri_matcher = NokogiriMatcher.new(tag, options, &block)
|
242
252
|
end
|
243
253
|
|
254
|
+
def with_text text
|
255
|
+
raise StandardError, 'this matcher should be used inside "have_tag" matcher block' unless defined?(@__current_scope_for_nokogiri_matcher)
|
256
|
+
raise ArgumentError, 'this matcher does not accept block' if block_given?
|
257
|
+
tag = @__current_scope_for_nokogiri_matcher.instance_variable_get(:@tag)
|
258
|
+
@__current_scope_for_nokogiri_matcher.should have_tag(tag, :text => text)
|
259
|
+
end
|
260
|
+
|
261
|
+
def without_text text
|
262
|
+
raise StandardError, 'this matcher should be used inside "have_tag" matcher block' unless defined?(@__current_scope_for_nokogiri_matcher)
|
263
|
+
raise ArgumentError, 'this matcher does not accept block' if block_given?
|
264
|
+
tag = @__current_scope_for_nokogiri_matcher.instance_variable_get(:@tag)
|
265
|
+
@__current_scope_for_nokogiri_matcher.should_not have_tag(tag, :text => text)
|
266
|
+
end
|
267
|
+
alias :but_without_text :without_text
|
268
|
+
|
244
269
|
# with_tag matcher
|
245
|
-
# @yield
|
270
|
+
# @yield block where you should put other with_tag or without_tag
|
246
271
|
# @see #have_tag
|
247
272
|
# @note this should be used within block of have_tag matcher
|
248
273
|
def with_tag tag, options={}, &block
|
@@ -250,13 +275,19 @@ module RSpec
|
|
250
275
|
end
|
251
276
|
|
252
277
|
# without_tag matcher
|
253
|
-
# @yield
|
278
|
+
# @yield block where you should put other with_tag or without_tag
|
254
279
|
# @see #have_tag
|
255
280
|
# @note this should be used within block of have_tag matcher
|
256
281
|
def without_tag tag, options={}, &block
|
257
282
|
@__current_scope_for_nokogiri_matcher.should_not have_tag(tag, options, &block)
|
258
283
|
end
|
259
284
|
|
285
|
+
# form assertion
|
286
|
+
#
|
287
|
+
# it is a shortcut to
|
288
|
+
# have_tag 'form', :with => { :action => action_url, :method => method ... }
|
289
|
+
# @yield block with with_<field>, see below
|
290
|
+
# @see #have_tag
|
260
291
|
def have_form action_url, method, options={}, &block
|
261
292
|
options[:with] ||= {}
|
262
293
|
id = options[:with].delete(:id)
|
@@ -266,63 +297,55 @@ module RSpec
|
|
266
297
|
have_tag tag, options, &block
|
267
298
|
end
|
268
299
|
|
300
|
+
#TODO fix code duplications
|
301
|
+
|
269
302
|
def with_hidden_field name, value=nil
|
270
|
-
options =
|
271
|
-
options[:with].merge!(:value => value) if value
|
303
|
+
options = form_tag_options('hidden',name,value)
|
272
304
|
should_have_input(options)
|
273
305
|
end
|
274
306
|
|
275
307
|
def without_hidden_field name, value=nil
|
276
|
-
options =
|
277
|
-
options[:with].merge!(:value => value) if value
|
308
|
+
options = form_tag_options('hidden',name,value)
|
278
309
|
should_not_have_input(options)
|
279
310
|
end
|
280
311
|
|
281
312
|
def with_text_field name, value=nil
|
282
|
-
options =
|
283
|
-
options[:with].merge!(:value => value) if value
|
313
|
+
options = form_tag_options('text',name,value)
|
284
314
|
should_have_input(options)
|
285
315
|
end
|
286
316
|
|
287
317
|
def without_text_field name, value=nil
|
288
|
-
options =
|
289
|
-
options[:with].merge!(:value => value) if value
|
318
|
+
options = form_tag_options('text',name,value)
|
290
319
|
should_not_have_input(options)
|
291
320
|
end
|
292
321
|
|
293
322
|
def with_email_field name, value=nil
|
294
|
-
options =
|
295
|
-
options[:with].merge!(:value => value) if value
|
323
|
+
options = form_tag_options('email',name,value)
|
296
324
|
should_have_input(options)
|
297
325
|
end
|
298
326
|
|
299
327
|
def without_email_field name, value=nil
|
300
|
-
options =
|
301
|
-
options[:with].merge!(:value => value) if value
|
328
|
+
options = form_tag_options('email',name,value)
|
302
329
|
should_not_have_input(options)
|
303
330
|
end
|
304
331
|
|
305
332
|
def with_url_field name, value=nil
|
306
|
-
options =
|
307
|
-
options[:with].merge!(:value => value) if value
|
333
|
+
options = form_tag_options('url',name,value)
|
308
334
|
should_have_input(options)
|
309
335
|
end
|
310
336
|
|
311
337
|
def without_url_field name, value=nil
|
312
|
-
options =
|
313
|
-
options[:with].merge!(:value => value) if value
|
338
|
+
options = form_tag_options('url',name,value)
|
314
339
|
should_not_have_input(options)
|
315
340
|
end
|
316
341
|
|
317
342
|
def with_number_field name, value=nil
|
318
|
-
options =
|
319
|
-
options[:with].merge!(:value => value.to_s) if value
|
343
|
+
options = form_tag_options('number',name,value)
|
320
344
|
should_have_input(options)
|
321
345
|
end
|
322
346
|
|
323
347
|
def without_number_field name, value=nil
|
324
|
-
options =
|
325
|
-
options[:with].merge!(:value => value.to_s) if value
|
348
|
+
options = form_tag_options('number',name,value)
|
326
349
|
should_not_have_input(options)
|
327
350
|
end
|
328
351
|
|
@@ -356,57 +379,55 @@ module RSpec
|
|
356
379
|
should_not_have_input(options)
|
357
380
|
end
|
358
381
|
|
359
|
-
def with_password_field name
|
360
|
-
options =
|
382
|
+
def with_password_field name, value=nil
|
383
|
+
options = form_tag_options('password',name,value)
|
361
384
|
should_have_input(options)
|
362
385
|
end
|
363
386
|
|
364
|
-
def without_password_field name
|
365
|
-
options =
|
387
|
+
def without_password_field name, value=nil
|
388
|
+
options = form_tag_options('password',name,value)
|
366
389
|
should_not_have_input(options)
|
367
390
|
end
|
368
391
|
|
369
|
-
def with_file_field name
|
370
|
-
options =
|
392
|
+
def with_file_field name, value=nil
|
393
|
+
options = form_tag_options('file',name,value)
|
371
394
|
should_have_input(options)
|
372
395
|
end
|
373
396
|
|
374
|
-
def without_file_field name
|
375
|
-
options =
|
397
|
+
def without_file_field name, value=nil
|
398
|
+
options = form_tag_options('file',name,value)
|
376
399
|
should_not_have_input(options)
|
377
400
|
end
|
378
401
|
|
379
|
-
def with_text_area name
|
402
|
+
def with_text_area name#TODO, text=nil
|
403
|
+
#options = form_tag_options('text',name,value)
|
380
404
|
options = { :with => { :name => name } }
|
381
405
|
@__current_scope_for_nokogiri_matcher.should have_tag('textarea', options)
|
382
406
|
end
|
383
407
|
|
384
|
-
def without_text_area name
|
408
|
+
def without_text_area name#TODO, text=nil
|
409
|
+
#options = form_tag_options('text',name,value)
|
385
410
|
options = { :with => { :name => name } }
|
386
411
|
@__current_scope_for_nokogiri_matcher.should_not have_tag('textarea', options)
|
387
412
|
end
|
388
413
|
|
389
414
|
def with_checkbox name, value=nil
|
390
|
-
options =
|
391
|
-
options[:with].merge!(:value => value) if value
|
415
|
+
options = form_tag_options('checkbox',name,value)
|
392
416
|
should_have_input(options)
|
393
417
|
end
|
394
418
|
|
395
419
|
def without_checkbox name, value=nil
|
396
|
-
options =
|
397
|
-
options[:with].merge!(:value => value) if value
|
420
|
+
options = form_tag_options('checkbox',name,value)
|
398
421
|
should_not_have_input(options)
|
399
422
|
end
|
400
423
|
|
401
424
|
def with_radio_button name, value
|
402
|
-
options =
|
403
|
-
options[:with].merge!(:value => value)
|
425
|
+
options = form_tag_options('radio',name,value)
|
404
426
|
should_have_input(options)
|
405
427
|
end
|
406
428
|
|
407
429
|
def without_radio_button name, value
|
408
|
-
options =
|
409
|
-
options[:with].merge!(:value => value)
|
430
|
+
options = form_tag_options('radio',name,value)
|
410
431
|
should_not_have_input(options)
|
411
432
|
end
|
412
433
|
|
@@ -482,10 +503,12 @@ module RSpec
|
|
482
503
|
|
483
504
|
def with_submit value
|
484
505
|
options = { :with => { :type => 'submit', :value => value } }
|
506
|
+
#options = form_tag_options('text',name,value)
|
485
507
|
should_have_input(options)
|
486
508
|
end
|
487
509
|
|
488
510
|
def without_submit value
|
511
|
+
#options = form_tag_options('text',name,value)
|
489
512
|
options = { :with => { :type => 'submit', :value => value } }
|
490
513
|
should_not_have_input(options)
|
491
514
|
end
|
@@ -500,5 +523,13 @@ module RSpec
|
|
500
523
|
@__current_scope_for_nokogiri_matcher.should_not have_tag('input', options)
|
501
524
|
end
|
502
525
|
|
526
|
+
# form_tag in method name name mean smth. like input, submit, tags that should appear in a form
|
527
|
+
def form_tag_options form_tag_type, form_tag_name, form_tag_value=nil
|
528
|
+
options = { :with => { :name => form_tag_name, :type => form_tag_type } }
|
529
|
+
# .to_s if value is a digit or smth. else, see issue#10
|
530
|
+
options[:with].merge!(:value => form_tag_value.to_s) if form_tag_value
|
531
|
+
return options
|
532
|
+
end
|
533
|
+
|
503
534
|
end
|
504
535
|
end
|