rspec-html-matchers 0.3.5 → 0.4.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.
- 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
|
+
[](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
|