rspec-html-matchers 0.8.0 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +39 -12
- data/README.md +13 -18
- data/features/step_definitions/steps.rb +3 -1
- data/features/support/env.rb +22 -3
- data/lib/rspec-html-matchers.rb +160 -356
- data/lib/rspec-html-matchers/have_tag.rb +274 -0
- data/lib/rspec-html-matchers/nokogiri_regexp_helper.rb +17 -0
- data/lib/rspec-html-matchers/nokogiri_text_helper.rb +24 -0
- data/lib/rspec-html-matchers/version.rb +5 -0
- data/spec/form_matchers_spec.rb +132 -130
- data/spec/have_empty_tag_spec.rb +6 -4
- data/spec/have_tag_spec.rb +221 -165
- data/spec/issues_spec.rb +27 -0
- data/spec/spec_helper.rb +3 -1
- data/spec/support/asset_helpers.rb +5 -5
- data/spec/support/raise_spec_error_helper.rb +9 -7
- metadata +58 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0f037ee7285bbe655173850423adeba9e9825641718cc372e89669a5d02284d0
|
4
|
+
data.tar.gz: fc31002e7b48380897520cb09e0e08ee00151311c847b260d75cad9c2fab81f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5b9f1f542091c493c69f402a46d54b6483a2f8c90e65c6fd8f7b038b14bc834cd76f8671e664323b37800f4a3e61afacf08d352963907c0873187521c8355cd
|
7
|
+
data.tar.gz: 5dd7980ad29b5ed66f3528366cc13b48199b809a0c025ed713cff6fb2f18f1a9323caa8c3bd6bc9145fea06d86c85c66b8763c560bb46377682c82d0dc7feff6
|
data/CHANGELOG.md
CHANGED
@@ -1,15 +1,42 @@
|
|
1
1
|
Changelog
|
2
2
|
=========
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
0.9.2
|
5
|
+
-----
|
6
|
+
|
7
|
+
* fixed have_empty_tag matcher on jruby
|
8
|
+
* added ruby 2.7 to build matrix (no official support until stable release though)
|
9
|
+
* added ruby 2.6 to build matrix ([#70](https://github.com/kucaahbe/rspec-html-matchers/pull/70))
|
10
|
+
|
11
|
+
infrastructure/misc:
|
12
|
+
|
13
|
+
* migrated to travis-ci.com instead of travis-ci.org (thanks [Hamada Takayuki](https://github.com/hamadata) for inspiration: [#70](https://github.com/kucaahbe/rspec-html-matchers/pull/70))
|
14
|
+
* refactor travis-ci build setup
|
15
|
+
* updated status badges to SVG (thanks to [Olle Jonsson](https://github.com/olleolleolle): [#71](https://github.com/kucaahbe/rspec-html-matchers/pull/71))
|
16
|
+
|
17
|
+
0.9.1
|
18
|
+
-----
|
19
|
+
|
20
|
+
* re-added ruby support back to 1.8.7 (supporting same versions as rspec 3)
|
21
|
+
* split lib in few files
|
22
|
+
|
23
|
+
0.9.0
|
24
|
+
-----
|
25
|
+
|
26
|
+
* fixed `with_tag` nesting (thanks to [randoum](https://github.com/randoum): [#59](https://github.com/kucaahbe/rspec-html-matchers/pull/59))
|
27
|
+
* added ~> 2.4 ruby support
|
28
|
+
* removed ~> 2 ruby support
|
29
|
+
|
30
|
+
0.8.2
|
31
|
+
-----
|
32
|
+
|
33
|
+
* fixed README (thanks to [Rodrigo Castro](https://github.com/roooodcastro))
|
34
|
+
* fixed deep nesting (thanks to [Misha Gorodnitzky](https://github.com/misaka))
|
35
|
+
|
36
|
+
0.8.1
|
37
|
+
-----
|
6
38
|
|
7
|
-
*
|
8
|
-
* add ability to have_form('/url', 'PUT') or have_form('/url', :PUT)
|
9
|
-
* inteligent check comments(make sure it is not searching inside comments)
|
10
|
-
* shouldn't show all markup in error message if it is too big
|
11
|
-
* order matching
|
12
|
-
* improve documentation, add more usage examples (look at changelog and code!)
|
39
|
+
* Rspec differ fix (thanks to [Misha Gorodnitzky](https://github.com/misaka))
|
13
40
|
|
14
41
|
0.8.0
|
15
42
|
-----
|
@@ -57,7 +84,7 @@ unreleased(TODO)
|
|
57
84
|
0.4.4
|
58
85
|
-----
|
59
86
|
|
60
|
-
* options for have_tag now support Regexp (thanks to [Ian C. Anderson](
|
87
|
+
* options for have_tag now support Regexp (thanks to [Ian C. Anderson](https://github.com/iancanderson))
|
61
88
|
|
62
89
|
0.4.3
|
63
90
|
-----
|
@@ -106,14 +133,14 @@ unreleased(TODO)
|
|
106
133
|
0.2.2
|
107
134
|
-----
|
108
135
|
|
109
|
-
* leading and trailing whitespaces are ignored in tags where they should be ignored(#11, and again thanks to [Simon Schoeters](
|
136
|
+
* leading and trailing whitespaces are ignored in tags where they should be ignored(#11, and again thanks to [Simon Schoeters](https://github.com/cimm))
|
110
137
|
* whitespaces ignoring as browser does in :text matching
|
111
138
|
* have_tag backwards compability(thanks to [Felix Tjandrawibawa](https://github.com/cemeng), #12)
|
112
139
|
|
113
140
|
0.2.1
|
114
141
|
-----
|
115
142
|
|
116
|
-
* make possible use non-string as :text option(#10, thanks for idea to [Simon Schoeters](
|
143
|
+
* make possible use non-string as :text option(#10, thanks for idea to [Simon Schoeters](https://github.com/cimm))
|
117
144
|
|
118
145
|
0.2.0
|
119
146
|
-----
|
@@ -132,7 +159,7 @@ unreleased(TODO)
|
|
132
159
|
0.0.6
|
133
160
|
-----
|
134
161
|
|
135
|
-
* allow for single quotes in content matchers (thanks to [Kelly Felkins](
|
162
|
+
* allow for single quotes in content matchers (thanks to [Kelly Felkins](https://github.com/kellyfelkins)).
|
136
163
|
|
137
164
|
0.0.5 (trial-trip)
|
138
165
|
------------------
|
data/README.md
CHANGED
@@ -1,20 +1,16 @@
|
|
1
|
-
rspec-html-matchers
|
2
|
-
===================
|
1
|
+
# rspec-html-matchers [![Gem Version](https://badge.fury.io/rb/rspec-html-matchers.svg)](https://badge.fury.io/rb/rspec-html-matchers) [![Build Status](https://travis-ci.com/kucaahbe/rspec-html-matchers.svg?branch=master)](https://travis-ci.com/kucaahbe/rspec-html-matchers)
|
3
2
|
|
4
3
|
[RSpec 3](https://www.relishapp.com/rspec) matchers for testing your html (for [RSpec 2](https://www.relishapp.com/rspec/rspec-core/v/2-99/docs) use 0.5.x version).
|
5
4
|
|
6
|
-
[![Gem Version](https://badge.fury.io/rb/rspec-html-matchers.png)](http://badge.fury.io/rb/rspec-html-matchers)
|
7
|
-
[![Build Status](https://travis-ci.org/kucaahbe/rspec-html-matchers.png)](http://travis-ci.org/kucaahbe/rspec-html-matchers)
|
8
|
-
|
9
5
|
Goals
|
10
6
|
-----
|
11
7
|
|
12
|
-
* for testing **
|
13
|
-
* [assert_select](
|
8
|
+
* designed for testing **complex** html output. If you plan to perform simple matching, consider using:
|
9
|
+
* [assert_select](https://api.rubyonrails.org/classes/ActionDispatch/Assertions/SelectorAssertions.html#method-i-assert_select)
|
14
10
|
* [matchers provided out of the box in rspec-rails](https://www.relishapp.com/rspec/rspec-rails/v/2-11/docs/view-specs/view-spec)
|
15
|
-
* [matchers provided by capybara](
|
11
|
+
* [matchers provided by capybara](https://rdoc.info/github/jnicklas/capybara/Capybara/Node/Matchers)
|
16
12
|
* developer-friendly output in error messages
|
17
|
-
* built on top of [nokogiri](
|
13
|
+
* built on top of [nokogiri](https://www.nokogiri.org/)
|
18
14
|
* has support for [capybara](https://github.com/jnicklas/capybara), see below
|
19
15
|
* syntax is similar to `have_tag` matcher from rspec-rails 1.x, but with own syntactic sugar
|
20
16
|
* framework agnostic, as input should be `String` (or capybara's page, see below)
|
@@ -45,7 +41,6 @@ describe "my view spec" do
|
|
45
41
|
it "has tags" do
|
46
42
|
expect(rendered).to have_tag('div')
|
47
43
|
end
|
48
|
-
|
49
44
|
end
|
50
45
|
```
|
51
46
|
|
@@ -55,7 +50,7 @@ Cucumber configuration:
|
|
55
50
|
World RSpecHtmlMatchers
|
56
51
|
```
|
57
52
|
|
58
|
-
as this gem requires **nokogiri**, here are [instructions for installing it](
|
53
|
+
as this gem requires **nokogiri**, here are [instructions for installing it](https://nokogiri.org/tutorials/installing_nokogiri.html).
|
59
54
|
|
60
55
|
Usage
|
61
56
|
-----
|
@@ -85,7 +80,7 @@ expect(rendered).to have_tag('form', :with => { :action => '/users', :method =>
|
|
85
80
|
end
|
86
81
|
```
|
87
82
|
|
88
|
-
Example above should be self-descriptive, if not, please refer to the [`have_tag`](
|
83
|
+
Example above should be self-descriptive, if not, please refer to the [`have_tag`](https://www.rubydoc.info/gems/rspec-html-matchers/RSpecHtmlMatchers%3Ahave_tag) documentation
|
89
84
|
|
90
85
|
Input can be any html string. Let's take a look at these examples:
|
91
86
|
|
@@ -152,7 +147,7 @@ Input can be any html string. Let's take a look at these examples:
|
|
152
147
|
expect('<p> Some content here</p>').to have_tag('p', :text => mymock.text)
|
153
148
|
# or
|
154
149
|
expect('<p> Some content here</p>').to have_tag('p') do
|
155
|
-
|
150
|
+
with_text mymock.text
|
156
151
|
end
|
157
152
|
|
158
153
|
# matching text content as it's seen by user:
|
@@ -193,7 +188,7 @@ where `page` is an instance of Capybara::Session
|
|
193
188
|
- with\_date\_field
|
194
189
|
|
195
190
|
and of course you can use the `without_` matchers,
|
196
|
-
for more info take a look at [documentation](
|
191
|
+
for more info take a look at [documentation](https://www.rubydoc.info/gems/rspec-html-matchers/RSpecHtmlMatchers)
|
197
192
|
|
198
193
|
### rspec 1 partial backwards compatibility:
|
199
194
|
|
@@ -204,7 +199,7 @@ expect(response).to have_tag('div', 'expected content')
|
|
204
199
|
expect(response).to have_tag('div', /regexp matching expected content/)
|
205
200
|
```
|
206
201
|
|
207
|
-
[RSpec 1 `have_tag` documentation](
|
202
|
+
[RSpec 1 `have_tag` documentation](https://old.rspec.info/rails/writing/views.html)
|
208
203
|
|
209
204
|
Matching Tag Attributes
|
210
205
|
-----------------------
|
@@ -218,7 +213,7 @@ expect(index).to have_tag("img[alt!='']")
|
|
218
213
|
More info
|
219
214
|
---------
|
220
215
|
|
221
|
-
You can find more on [documentation](
|
216
|
+
You can find more on [documentation](https://www.rubydoc.info/gems/rspec-html-matchers/RSpecHtmlMatchers)
|
222
217
|
|
223
218
|
Also, please read [CHANGELOG](https://github.com/kucaahbe/rspec-html-matchers/blob/master/CHANGELOG.md) and [issues](https://github.com/kucaahbe/rspec-html-matchers/issues), might be helpful.
|
224
219
|
|
@@ -234,8 +229,8 @@ Contribution
|
|
234
229
|
Contributors
|
235
230
|
============
|
236
231
|
|
237
|
-
- [Kelly Felkins](
|
238
|
-
- [Ryan Wilcox](
|
232
|
+
- [Kelly Felkins](https://github.com/kellyfelkins)
|
233
|
+
- [Ryan Wilcox](https://github.com/rwilcox)
|
239
234
|
- [Simon Schoeters](https://github.com/cimm)
|
240
235
|
- [Felix Tjandrawibawa](https://github.com/cemenghttps://github.com/cemeng)
|
241
236
|
- [Szymon Przybył](https://github.com/apocalyptiq)
|
data/features/support/env.rb
CHANGED
@@ -1,20 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# setup rspec matchers
|
2
4
|
require 'rspec/expectations'
|
3
5
|
World(RSpec::Matchers)
|
4
6
|
require 'sinatra/base'
|
5
7
|
require 'capybara/cucumber'
|
6
8
|
require 'rspec-html-matchers'
|
9
|
+
require 'webdrivers'
|
10
|
+
require 'selenium-webdriver'
|
7
11
|
|
8
12
|
World RSpecHtmlMatchers
|
9
13
|
|
10
|
-
|
11
|
-
$
|
14
|
+
# rubocop:disable Style/GlobalVars
|
15
|
+
$ASSETS_DIR = File.expand_path('../tmp', __FILE__)
|
16
|
+
$INDEX_HTML = File.join($ASSETS_DIR, 'index.html')
|
12
17
|
|
13
18
|
class SimpleApp < Sinatra::Base
|
14
19
|
set :public_folder, $ASSETS_DIR
|
15
20
|
end
|
16
21
|
|
17
|
-
Capybara.
|
22
|
+
Capybara.register_driver :headless_chrome do |app|
|
23
|
+
options = Selenium::WebDriver::Chrome::Options.new
|
24
|
+
options.add_argument('--headless')
|
25
|
+
options.add_argument('--disable-gpu')
|
26
|
+
options.add_argument('--window-size=800,600')
|
27
|
+
|
28
|
+
Capybara::Selenium::Driver.new(app, :browser => :chrome, :options => options)
|
29
|
+
end
|
30
|
+
|
31
|
+
Capybara.configure do |config|
|
32
|
+
config.default_max_wait_time = 15 if config.respond_to? :default_max_wait_time=
|
33
|
+
config.default_driver = :headless_chrome
|
34
|
+
end
|
35
|
+
|
18
36
|
Capybara.app = SimpleApp
|
19
37
|
|
20
38
|
Before do
|
@@ -24,3 +42,4 @@ end
|
|
24
42
|
After do
|
25
43
|
FileUtils.rm_rf $ASSETS_DIR
|
26
44
|
end
|
45
|
+
# rubocop:enable Style/GlobalVars
|
data/lib/rspec-html-matchers.rb
CHANGED
@@ -1,266 +1,30 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
1
|
# encoding: UTF-8
|
3
|
-
|
4
|
-
require 'nokogiri'
|
2
|
+
# frozen_string_literal: true
|
5
3
|
|
4
|
+
require 'rspec-html-matchers/nokogiri_regexp_helper'
|
5
|
+
require 'rspec-html-matchers/nokogiri_text_helper'
|
6
|
+
require 'rspec-html-matchers/have_tag'
|
7
|
+
|
8
|
+
# RSpec global configuration:
|
9
|
+
#
|
10
|
+
# RSpec.configure do |config|
|
11
|
+
# config.include RSpecHtmlMatchers
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# RSpec per-test configuration
|
15
|
+
#
|
16
|
+
# RSpec.describe "my view spec" do
|
17
|
+
# include RSpecHtmlMatchers
|
18
|
+
#
|
19
|
+
# it "has tags" do
|
20
|
+
# expect(rendered).to have_tag('div')
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# Cucumber configuration:
|
25
|
+
#
|
26
|
+
# World RSpecHtmlMatchers
|
6
27
|
module RSpecHtmlMatchers
|
7
|
-
|
8
|
-
# @api
|
9
|
-
# @private
|
10
|
-
# for nokogiri regexp matching
|
11
|
-
class NokogiriRegexpHelper
|
12
|
-
def initialize(regex)
|
13
|
-
@regex = regex
|
14
|
-
end
|
15
|
-
|
16
|
-
def regexp node_set
|
17
|
-
node_set.find_all { |node| node.content =~ @regex }
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
# @api
|
22
|
-
# @private
|
23
|
-
class NokogiriTextHelper
|
24
|
-
NON_BREAKING_SPACE = "\u00a0"
|
25
|
-
|
26
|
-
def initialize text, squeeze_text = false
|
27
|
-
@text = text
|
28
|
-
@squeeze_text = squeeze_text
|
29
|
-
end
|
30
|
-
|
31
|
-
def content node_set
|
32
|
-
node_set.find_all do |node|
|
33
|
-
actual_content = node.content.gsub(NON_BREAKING_SPACE, ' ')
|
34
|
-
actual_content = node.content.strip.squeeze(' ') if @squeeze_text
|
35
|
-
|
36
|
-
actual_content == @text
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
# @api
|
42
|
-
# @private
|
43
|
-
class HaveTag
|
44
|
-
attr_reader :failure_message, :failure_message_when_negated
|
45
|
-
attr_reader :parent_scope, :current_scope
|
46
|
-
|
47
|
-
DESCRIPTIONS = {
|
48
|
-
:have_at_least_1 => %Q|have at least 1 element matching "%s"|,
|
49
|
-
:have_n => %Q|have %i element(s) matching "%s"|
|
50
|
-
}
|
51
|
-
|
52
|
-
MESSAGES = {
|
53
|
-
:expected_tag => %Q|expected following:\n%s\nto #{DESCRIPTIONS[:have_at_least_1]}, found 0.|,
|
54
|
-
:unexpected_tag => %Q|expected following:\n%s\nto NOT have element matching "%s", found %s.|,
|
55
|
-
|
56
|
-
:expected_count => %Q|expected following:\n%s\nto #{DESCRIPTIONS[:have_n]}, found %s.|,
|
57
|
-
:unexpected_count => %Q|expected following:\n%s\nto NOT have %i element(s) matching "%s", but found.|,
|
58
|
-
|
59
|
-
:expected_btw_count => %Q|expected following:\n%s\nto have at least %i and at most %i element(s) matching "%s", found %i.|,
|
60
|
-
:unexpected_btw_count => %Q|expected following:\n%s\nto NOT have at least %i and at most %i element(s) matching "%s", but found %i.|,
|
61
|
-
|
62
|
-
:expected_at_most => %Q|expected following:\n%s\nto have at most %i element(s) matching "%s", found %i.|,
|
63
|
-
:unexpected_at_most => %Q|expected following:\n%s\nto NOT have at most %i element(s) matching "%s", but found %i.|,
|
64
|
-
|
65
|
-
:expected_at_least => %Q|expected following:\n%s\nto have at least %i element(s) matching "%s", found %i.|,
|
66
|
-
:unexpected_at_least => %Q|expected following:\n%s\nto NOT have at least %i element(s) matching "%s", but found %i.|,
|
67
|
-
|
68
|
-
:expected_regexp => %Q|%s regexp expected within "%s" in following template:\n%s|,
|
69
|
-
:unexpected_regexp => %Q|%s regexp unexpected within "%s" in following template:\n%s\nbut was found.|,
|
70
|
-
|
71
|
-
:expected_text => %Q|"%s" expected within "%s" in following template:\n%s|,
|
72
|
-
:unexpected_text => %Q|"%s" unexpected within "%s" in following template:\n%s\nbut was found.|,
|
73
|
-
|
74
|
-
:wrong_count_error => %Q|:count with :minimum or :maximum has no sence!|,
|
75
|
-
:min_max_error => %Q|:minimum should be less than :maximum!|,
|
76
|
-
:bad_range_error => %Q|Your :count range(%s) has no sence!|,
|
77
|
-
}
|
78
|
-
|
79
|
-
|
80
|
-
def initialize tag, options={}, &block
|
81
|
-
@tag, @options, @block = tag.to_s, options, block
|
82
|
-
|
83
|
-
if with_attrs = @options.delete(:with)
|
84
|
-
if classes = with_attrs.delete(:class)
|
85
|
-
@tag += '.' + classes_to_selector(classes)
|
86
|
-
end
|
87
|
-
selector = with_attrs.inject('') do |html_attrs_string, (k, v)|
|
88
|
-
html_attrs_string += "[#{k}='#{v}']"
|
89
|
-
html_attrs_string
|
90
|
-
end
|
91
|
-
@tag += selector
|
92
|
-
end
|
93
|
-
|
94
|
-
if without_attrs = @options.delete(:without)
|
95
|
-
if classes = without_attrs.delete(:class)
|
96
|
-
@tag += ":not(.#{classes_to_selector(classes)})"
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
validate_options!
|
101
|
-
set_options
|
102
|
-
end
|
103
|
-
|
104
|
-
def matches? document, &block
|
105
|
-
@block = block if block
|
106
|
-
|
107
|
-
document = document.html if defined?(Capybara::Session) && document.is_a?(Capybara::Session)
|
108
|
-
|
109
|
-
case document
|
110
|
-
when String
|
111
|
-
@parent_scope = @current_scope = Nokogiri::HTML(document).css(@tag)
|
112
|
-
@document = document
|
113
|
-
else
|
114
|
-
@parent_scope = document.current_scope
|
115
|
-
@current_scope = begin
|
116
|
-
document.parent_scope.css(@tag)
|
117
|
-
# on jruby this produce exception if css was not found:
|
118
|
-
# undefined method `decorate' for nil:NilClass
|
119
|
-
rescue NoMethodError
|
120
|
-
Nokogiri::XML::NodeSet.new(Nokogiri::XML::Document.new)
|
121
|
-
end
|
122
|
-
@document = @parent_scope.to_html
|
123
|
-
end
|
124
|
-
|
125
|
-
if tag_presents? and text_right? and count_right?
|
126
|
-
@current_scope = @parent_scope
|
127
|
-
@block.call if @block
|
128
|
-
true
|
129
|
-
else
|
130
|
-
false
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
def description
|
135
|
-
# TODO should it be more complicated?
|
136
|
-
if @options.has_key?(:count)
|
137
|
-
DESCRIPTIONS[:have_n] % [@options[:count],@tag]
|
138
|
-
else
|
139
|
-
DESCRIPTIONS[:have_at_least_1] % @tag
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
private
|
144
|
-
|
145
|
-
def classes_to_selector(classes)
|
146
|
-
case classes
|
147
|
-
when Array
|
148
|
-
classes.join('.')
|
149
|
-
when String
|
150
|
-
classes.gsub(/\s+/, '.')
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
def tag_presents?
|
155
|
-
if @current_scope.first
|
156
|
-
@count = @current_scope.count
|
157
|
-
@failure_message_when_negated = MESSAGES[:unexpected_tag] % [@document, @tag, @count]
|
158
|
-
true
|
159
|
-
else
|
160
|
-
@failure_message = MESSAGES[:expected_tag] % [@document, @tag]
|
161
|
-
false
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def count_right?
|
166
|
-
case @options[:count]
|
167
|
-
when Integer
|
168
|
-
((@failure_message_when_negated=MESSAGES[:unexpected_count] % [@document,@count,@tag]) && @count == @options[:count]) || (@failure_message=MESSAGES[:expected_count] % [@document,@options[:count],@tag,@count]; false)
|
169
|
-
when Range
|
170
|
-
((@failure_message_when_negated=MESSAGES[:unexpected_btw_count] % [@document,@options[:count].min,@options[:count].max,@tag,@count]) && @options[:count].member?(@count)) || (@failure_message=MESSAGES[:expected_btw_count] % [@document,@options[:count].min,@options[:count].max,@tag,@count]; false)
|
171
|
-
when nil
|
172
|
-
if @options[:maximum]
|
173
|
-
((@failure_message_when_negated=MESSAGES[:unexpected_at_most] % [@document,@options[:maximum],@tag,@count]) && @count <= @options[:maximum]) || (@failure_message=MESSAGES[:expected_at_most] % [@document,@options[:maximum],@tag,@count]; false)
|
174
|
-
elsif @options[:minimum]
|
175
|
-
((@failure_message_when_negated=MESSAGES[:unexpected_at_least] % [@document,@options[:minimum],@tag,@count]) && @count >= @options[:minimum]) || (@failure_message=MESSAGES[:expected_at_least] % [@document,@options[:minimum],@tag,@count]; false)
|
176
|
-
else
|
177
|
-
true
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
def text_right?
|
183
|
-
return true unless @options[:text]
|
184
|
-
|
185
|
-
case text=@options[:text]
|
186
|
-
when Regexp
|
187
|
-
new_scope = @current_scope.css(':regexp()',NokogiriRegexpHelper.new(text))
|
188
|
-
unless new_scope.empty?
|
189
|
-
@count = new_scope.count
|
190
|
-
@failure_message_when_negated = MESSAGES[:unexpected_regexp] % [text.inspect,@tag,@document]
|
191
|
-
true
|
192
|
-
else
|
193
|
-
@failure_message = MESSAGES[:expected_regexp] % [text.inspect,@tag,@document]
|
194
|
-
false
|
195
|
-
end
|
196
|
-
else
|
197
|
-
new_scope = @current_scope.css(':content()', NokogiriTextHelper.new(text, @options[:squeeze_text]))
|
198
|
-
unless new_scope.empty?
|
199
|
-
@count = new_scope.count
|
200
|
-
@failure_message_when_negated = MESSAGES[:unexpected_text] % [text,@tag,@document]
|
201
|
-
true
|
202
|
-
else
|
203
|
-
@failure_message = MESSAGES[:expected_text] % [text,@tag,@document]
|
204
|
-
false
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
protected
|
210
|
-
|
211
|
-
def validate_options!
|
212
|
-
validate_count_presence!
|
213
|
-
validate_count_when_set_min_max!
|
214
|
-
validate_count_when_set_range!
|
215
|
-
end
|
216
|
-
|
217
|
-
def validate_count_presence!
|
218
|
-
raise 'wrong :count specified' unless [Range, NilClass].include?(@options[:count].class) or @options[:count].is_a?(Integer)
|
219
|
-
|
220
|
-
[:min, :minimum, :max, :maximum].each do |key|
|
221
|
-
raise MESSAGES[:wrong_count_error] if @options.has_key?(key) and @options.has_key?(:count)
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
def validate_count_when_set_min_max!
|
226
|
-
begin
|
227
|
-
raise MESSAGES[:min_max_error] if @options[:minimum] > @options[:maximum]
|
228
|
-
rescue NoMethodError # nil > 4
|
229
|
-
rescue ArgumentError # 2 < nil
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
def validate_count_when_set_range!
|
234
|
-
begin
|
235
|
-
begin
|
236
|
-
raise MESSAGES[:bad_range_error] % [@options[:count].to_s] if count_is_range_but_no_min?
|
237
|
-
rescue ArgumentError, "comparison of String with" # if @options[:count] == 'a'..'z'
|
238
|
-
raise MESSAGES[:bad_range_error] % [@options[:count].to_s]
|
239
|
-
end
|
240
|
-
rescue TypeError # fix for 1.8.7 for 'rescue ArgumentError, "comparison of String with"' stroke
|
241
|
-
raise MESSAGES[:bad_range_error] % [@options[:count].to_s]
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
def count_is_range_but_no_min?
|
246
|
-
@options[:count] && @options[:count].is_a?(Range) &&
|
247
|
-
(@options[:count].min.nil? or @options[:count].min < 0)
|
248
|
-
end
|
249
|
-
|
250
|
-
def set_options
|
251
|
-
@options[:minimum] ||= @options.delete(:min)
|
252
|
-
@options[:maximum] ||= @options.delete(:max)
|
253
|
-
|
254
|
-
@options[:text] = @options[:text].to_s if @options.has_key?(:text) && !@options[:text].is_a?(Regexp)
|
255
|
-
|
256
|
-
if @options.has_key?(:seen) && !@options[:seen].is_a?(Regexp)
|
257
|
-
@options[:text] = @options[:seen].to_s
|
258
|
-
@options[:squeeze_text] = true
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
end
|
263
|
-
|
264
28
|
# tag assertion, this is the core of functionality, other matchers are shortcuts to this matcher
|
265
29
|
#
|
266
30
|
# @yield block where you should put with_tag, without_tag and/or other matchers
|
@@ -295,45 +59,60 @@ module RSpecHtmlMatchers
|
|
295
59
|
# </html>").to have_tag('body') { with_tag('h1', :text => 'some html document') }
|
296
60
|
# expect('<div class="one two">').to have_tag('div', :with => { :class => ['two', 'one'] })
|
297
61
|
# expect('<div class="one two">').to have_tag('div', :with => { :class => 'two one' })
|
298
|
-
def have_tag tag, options={}, &block
|
62
|
+
def have_tag tag, options = {}, &block
|
299
63
|
# for backwards compatibility with rpecs have tag:
|
300
|
-
options = { :text => options } if options.
|
64
|
+
options = { :text => options } if options.is_a?(String) || options.is_a?(Regexp)
|
301
65
|
@__current_scope_for_nokogiri_matcher = HaveTag.new(tag, options, &block)
|
302
66
|
end
|
303
67
|
|
304
|
-
|
305
|
-
|
68
|
+
# tests whether tag have any content inside
|
69
|
+
#
|
70
|
+
# @example
|
71
|
+
# expect('<div></div>').to have_empty_tag('div') # success
|
72
|
+
# expect('<div>hi</div>').to have_empty_tag('div') # fail
|
73
|
+
def have_empty_tag tag, options = {}
|
74
|
+
have_tag(tag, options.merge(:blank => true))
|
306
75
|
end
|
307
76
|
|
308
77
|
def with_text text
|
309
78
|
raise StandardError, 'this matcher should be used inside "have_tag" matcher block' unless defined?(@__current_scope_for_nokogiri_matcher)
|
310
79
|
raise ArgumentError, 'this matcher does not accept block' if block_given?
|
80
|
+
|
311
81
|
tag = @__current_scope_for_nokogiri_matcher.instance_variable_get(:@tag)
|
312
|
-
|
82
|
+
within_nested_tag do
|
83
|
+
expect(@__current_scope_for_nokogiri_matcher).to have_tag(tag, :text => text)
|
84
|
+
end
|
313
85
|
end
|
314
86
|
|
315
87
|
def without_text text
|
316
88
|
raise StandardError, 'this matcher should be used inside "have_tag" matcher block' unless defined?(@__current_scope_for_nokogiri_matcher)
|
317
89
|
raise ArgumentError, 'this matcher does not accept block' if block_given?
|
90
|
+
|
318
91
|
tag = @__current_scope_for_nokogiri_matcher.instance_variable_get(:@tag)
|
319
|
-
|
92
|
+
within_nested_tag do
|
93
|
+
expect(@__current_scope_for_nokogiri_matcher).to_not have_tag(tag, :text => text)
|
94
|
+
end
|
320
95
|
end
|
321
|
-
alias
|
96
|
+
alias but_without_text without_text
|
322
97
|
|
323
98
|
# with_tag matcher
|
324
99
|
# @yield block where you should put other with_tag or without_tag
|
325
100
|
# @see #have_tag
|
326
101
|
# @note this should be used within block of have_tag matcher
|
327
|
-
def with_tag tag, options={}, &block
|
328
|
-
|
102
|
+
def with_tag tag, options = {}, &block
|
103
|
+
within_nested_tag do
|
104
|
+
expect(@__current_scope_for_nokogiri_matcher).to have_tag(tag, options, &block)
|
105
|
+
end
|
329
106
|
end
|
330
107
|
|
331
108
|
# without_tag matcher
|
332
109
|
# @yield block where you should put other with_tag or without_tag
|
333
110
|
# @see #have_tag
|
334
111
|
# @note this should be used within block of have_tag matcher
|
335
|
-
def without_tag tag, options={}, &block
|
336
|
-
|
112
|
+
def without_tag tag, options = {}, &block
|
113
|
+
within_nested_tag do
|
114
|
+
expect(@__current_scope_for_nokogiri_matcher).to_not have_tag(tag, options, &block)
|
115
|
+
end
|
337
116
|
end
|
338
117
|
|
339
118
|
# form assertion
|
@@ -342,250 +121,275 @@ module RSpecHtmlMatchers
|
|
342
121
|
# have_tag 'form', :with => { :action => action_url, :method => method ... }
|
343
122
|
# @yield block with with_<field>, see below
|
344
123
|
# @see #have_tag
|
345
|
-
def have_form action_url, method, options={}, &block
|
124
|
+
def have_form action_url, method, options = {}, &block
|
346
125
|
options[:with] ||= {}
|
347
126
|
id = options[:with].delete(:id)
|
348
|
-
tag = 'form'; tag += '#'+id if id
|
127
|
+
tag = 'form'; tag += '#' + id if id
|
349
128
|
options[:with].merge!(:action => action_url)
|
350
129
|
options[:with].merge!(:method => method.to_s)
|
351
130
|
have_tag tag, options, &block
|
352
131
|
end
|
353
132
|
|
354
|
-
|
133
|
+
# @TODO fix code duplications
|
355
134
|
|
356
|
-
def with_hidden_field name, value=nil
|
357
|
-
options = form_tag_options('hidden',name,value)
|
135
|
+
def with_hidden_field name, value = nil
|
136
|
+
options = form_tag_options('hidden', name, value)
|
358
137
|
should_have_input(options)
|
359
138
|
end
|
360
139
|
|
361
|
-
def without_hidden_field name, value=nil
|
362
|
-
options = form_tag_options('hidden',name,value)
|
140
|
+
def without_hidden_field name, value = nil
|
141
|
+
options = form_tag_options('hidden', name, value)
|
363
142
|
should_not_have_input(options)
|
364
143
|
end
|
365
144
|
|
366
|
-
def with_text_field name, value=nil
|
367
|
-
options = form_tag_options('text',name,value)
|
145
|
+
def with_text_field name, value = nil
|
146
|
+
options = form_tag_options('text', name, value)
|
368
147
|
should_have_input(options)
|
369
148
|
end
|
370
149
|
|
371
|
-
def without_text_field name, value=nil
|
372
|
-
options = form_tag_options('text',name,value)
|
150
|
+
def without_text_field name, value = nil
|
151
|
+
options = form_tag_options('text', name, value)
|
373
152
|
should_not_have_input(options)
|
374
153
|
end
|
375
154
|
|
376
|
-
def with_email_field name, value=nil
|
377
|
-
options = form_tag_options('email',name,value)
|
155
|
+
def with_email_field name, value = nil
|
156
|
+
options = form_tag_options('email', name, value)
|
378
157
|
should_have_input(options)
|
379
158
|
end
|
380
159
|
|
381
|
-
def without_email_field name, value=nil
|
382
|
-
options = form_tag_options('email',name,value)
|
160
|
+
def without_email_field name, value = nil
|
161
|
+
options = form_tag_options('email', name, value)
|
383
162
|
should_not_have_input(options)
|
384
163
|
end
|
385
164
|
|
386
|
-
def with_url_field name, value=nil
|
387
|
-
options = form_tag_options('url',name,value)
|
165
|
+
def with_url_field name, value = nil
|
166
|
+
options = form_tag_options('url', name, value)
|
388
167
|
should_have_input(options)
|
389
168
|
end
|
390
169
|
|
391
|
-
def without_url_field name, value=nil
|
392
|
-
options = form_tag_options('url',name,value)
|
170
|
+
def without_url_field name, value = nil
|
171
|
+
options = form_tag_options('url', name, value)
|
393
172
|
should_not_have_input(options)
|
394
173
|
end
|
395
174
|
|
396
|
-
def with_number_field name, value=nil
|
397
|
-
options = form_tag_options('number',name,value)
|
175
|
+
def with_number_field name, value = nil
|
176
|
+
options = form_tag_options('number', name, value)
|
398
177
|
should_have_input(options)
|
399
178
|
end
|
400
179
|
|
401
|
-
def without_number_field name, value=nil
|
402
|
-
options = form_tag_options('number',name,value)
|
180
|
+
def without_number_field name, value = nil
|
181
|
+
options = form_tag_options('number', name, value)
|
403
182
|
should_not_have_input(options)
|
404
183
|
end
|
405
184
|
|
406
|
-
def with_range_field name, min, max, options={}
|
407
|
-
options = { :with => { :name => name, :type => 'range', :min => min.to_s, :max => max.to_s }.merge(options.delete(:with)||{}) }
|
185
|
+
def with_range_field name, min, max, options = {}
|
186
|
+
options = { :with => { :name => name, :type => 'range', :min => min.to_s, :max => max.to_s }.merge(options.delete(:with) || {}) }
|
408
187
|
should_have_input(options)
|
409
188
|
end
|
410
189
|
|
411
|
-
def without_range_field name, min=nil, max=nil, options={}
|
412
|
-
options = { :with => { :name => name, :type => 'range' }.merge(options.delete(:with)||{}) }
|
190
|
+
def without_range_field name, min = nil, max = nil, options = {}
|
191
|
+
options = { :with => { :name => name, :type => 'range' }.merge(options.delete(:with) || {}) }
|
413
192
|
options[:with].merge!(:min => min.to_s) if min
|
414
193
|
options[:with].merge!(:max => max.to_s) if max
|
415
194
|
should_not_have_input(options)
|
416
195
|
end
|
417
196
|
|
418
|
-
DATE_FIELD_TYPES = %w
|
197
|
+
DATE_FIELD_TYPES = %w[date month week time datetime datetime-local].freeze
|
419
198
|
|
420
|
-
def with_date_field date_field_type, name=nil, options={}
|
199
|
+
def with_date_field date_field_type, name = nil, options = {}
|
421
200
|
date_field_type = date_field_type.to_s
|
422
201
|
raise "unknown type `#{date_field_type}` for date picker" unless DATE_FIELD_TYPES.include?(date_field_type)
|
423
|
-
|
202
|
+
|
203
|
+
options = { :with => { :type => date_field_type.to_s }.merge(options.delete(:with) || {}) }
|
424
204
|
options[:with].merge!(:name => name.to_s) if name
|
425
205
|
should_have_input(options)
|
426
206
|
end
|
427
207
|
|
428
|
-
def without_date_field date_field_type, name=nil, options={}
|
208
|
+
def without_date_field date_field_type, name = nil, options = {}
|
429
209
|
date_field_type = date_field_type.to_s
|
430
210
|
raise "unknown type `#{date_field_type}` for date picker" unless DATE_FIELD_TYPES.include?(date_field_type)
|
431
|
-
|
211
|
+
|
212
|
+
options = { :with => { :type => date_field_type.to_s }.merge(options.delete(:with) || {}) }
|
432
213
|
options[:with].merge!(:name => name.to_s) if name
|
433
214
|
should_not_have_input(options)
|
434
215
|
end
|
435
216
|
|
436
|
-
def with_password_field name, value=nil
|
437
|
-
# TODO add ability to explicitly say that value should be empty
|
438
|
-
options = form_tag_options('password',name,value)
|
217
|
+
def with_password_field name, value = nil
|
218
|
+
# TODO: add ability to explicitly say that value should be empty
|
219
|
+
options = form_tag_options('password', name, value)
|
439
220
|
should_have_input(options)
|
440
221
|
end
|
441
222
|
|
442
|
-
def without_password_field name, value=nil
|
443
|
-
options = form_tag_options('password',name,value)
|
223
|
+
def without_password_field name, value = nil
|
224
|
+
options = form_tag_options('password', name, value)
|
444
225
|
should_not_have_input(options)
|
445
226
|
end
|
446
227
|
|
447
|
-
def with_file_field name, value=nil
|
448
|
-
options = form_tag_options('file',name,value)
|
228
|
+
def with_file_field name, value = nil
|
229
|
+
options = form_tag_options('file', name, value)
|
449
230
|
should_have_input(options)
|
450
231
|
end
|
451
232
|
|
452
|
-
def without_file_field name, value=nil
|
453
|
-
options = form_tag_options('file',name,value)
|
233
|
+
def without_file_field name, value = nil
|
234
|
+
options = form_tag_options('file', name, value)
|
454
235
|
should_not_have_input(options)
|
455
236
|
end
|
456
237
|
|
457
238
|
def with_text_area name
|
458
239
|
# TODO, should be: with_text_area name, text=nil
|
459
|
-
#options = form_tag_options('text',name,value)
|
240
|
+
# options = form_tag_options('text',name,value)
|
460
241
|
options = { :with => { :name => name } }
|
461
|
-
|
242
|
+
within_nested_tag do
|
243
|
+
expect(@__current_scope_for_nokogiri_matcher).to have_tag('textarea', options)
|
244
|
+
end
|
462
245
|
end
|
463
246
|
|
464
247
|
def without_text_area name
|
465
248
|
# TODO, should be: without_text_area name, text=nil
|
466
|
-
#options = form_tag_options('text',name,value)
|
249
|
+
# options = form_tag_options('text',name,value)
|
467
250
|
options = { :with => { :name => name } }
|
468
|
-
|
251
|
+
within_nested_tag do
|
252
|
+
expect(@__current_scope_for_nokogiri_matcher).to_not have_tag('textarea', options)
|
253
|
+
end
|
469
254
|
end
|
470
255
|
|
471
|
-
def with_checkbox name, value=nil
|
472
|
-
options = form_tag_options('checkbox',name,value)
|
256
|
+
def with_checkbox name, value = nil
|
257
|
+
options = form_tag_options('checkbox', name, value)
|
473
258
|
should_have_input(options)
|
474
259
|
end
|
475
260
|
|
476
|
-
def without_checkbox name, value=nil
|
477
|
-
options = form_tag_options('checkbox',name,value)
|
261
|
+
def without_checkbox name, value = nil
|
262
|
+
options = form_tag_options('checkbox', name, value)
|
478
263
|
should_not_have_input(options)
|
479
264
|
end
|
480
265
|
|
481
266
|
def with_radio_button name, value
|
482
|
-
options = form_tag_options('radio',name,value)
|
267
|
+
options = form_tag_options('radio', name, value)
|
483
268
|
should_have_input(options)
|
484
269
|
end
|
485
270
|
|
486
271
|
def without_radio_button name, value
|
487
|
-
options = form_tag_options('radio',name,value)
|
272
|
+
options = form_tag_options('radio', name, value)
|
488
273
|
should_not_have_input(options)
|
489
274
|
end
|
490
275
|
|
491
|
-
def with_select name, options={}, &block
|
276
|
+
def with_select name, options = {}, &block
|
492
277
|
options[:with] ||= {}
|
493
278
|
id = options[:with].delete(:id)
|
494
|
-
tag='select'; tag += '#'+id if id
|
279
|
+
tag = 'select'; tag += '#' + id if id
|
495
280
|
options[:with].merge!(:name => name)
|
496
|
-
|
281
|
+
within_nested_tag do
|
282
|
+
expect(@__current_scope_for_nokogiri_matcher).to have_tag(tag, options, &block)
|
283
|
+
end
|
497
284
|
end
|
498
285
|
|
499
|
-
def without_select name, options={}, &block
|
286
|
+
def without_select name, options = {}, &block
|
500
287
|
options[:with] ||= {}
|
501
288
|
id = options[:with].delete(:id)
|
502
|
-
tag='select'; tag += '#'+id if id
|
289
|
+
tag = 'select'; tag += '#' + id if id
|
503
290
|
options[:with].merge!(:name => name)
|
504
|
-
|
291
|
+
within_nested_tag do
|
292
|
+
expect(@__current_scope_for_nokogiri_matcher).to_not have_tag(tag, options, &block)
|
293
|
+
end
|
505
294
|
end
|
506
295
|
|
507
|
-
def with_option text, value=nil, options={}
|
296
|
+
def with_option text, value = nil, options = {}
|
508
297
|
options[:with] ||= {}
|
509
298
|
if value.is_a?(Hash)
|
510
299
|
options.merge!(value)
|
511
|
-
value=nil
|
300
|
+
value = nil
|
512
301
|
end
|
513
|
-
tag='option'
|
302
|
+
tag = 'option'
|
514
303
|
options[:with].merge!(:value => value.to_s) if value
|
515
|
-
if options[:selected]
|
516
|
-
options[:with].merge!(:selected => "selected")
|
517
|
-
end
|
304
|
+
options[:with].merge!(:selected => 'selected') if options[:selected]
|
518
305
|
options.delete(:selected)
|
519
306
|
options.merge!(:text => text) if text
|
520
|
-
|
307
|
+
within_nested_tag do
|
308
|
+
expect(@__current_scope_for_nokogiri_matcher).to have_tag(tag, options)
|
309
|
+
end
|
521
310
|
end
|
522
311
|
|
523
|
-
def without_option text, value=nil, options={}
|
312
|
+
def without_option text, value = nil, options = {}
|
524
313
|
options[:with] ||= {}
|
525
314
|
if value.is_a?(Hash)
|
526
315
|
options.merge!(value)
|
527
|
-
value=nil
|
316
|
+
value = nil
|
528
317
|
end
|
529
|
-
tag='option'
|
318
|
+
tag = 'option'
|
530
319
|
options[:with].merge!(:value => value.to_s) if value
|
531
|
-
if options[:selected]
|
532
|
-
options[:with].merge!(:selected => "selected")
|
533
|
-
end
|
320
|
+
options[:with].merge!(:selected => 'selected') if options[:selected]
|
534
321
|
options.delete(:selected)
|
535
322
|
options.merge!(:text => text) if text
|
536
|
-
|
323
|
+
within_nested_tag do
|
324
|
+
expect(@__current_scope_for_nokogiri_matcher).to_not have_tag(tag, options)
|
325
|
+
end
|
537
326
|
end
|
538
327
|
|
539
|
-
def with_button text, value=nil, options={}
|
328
|
+
def with_button text, value = nil, options = {}
|
540
329
|
options[:with] ||= {}
|
541
330
|
if value.is_a?(Hash)
|
542
331
|
options.merge!(value)
|
543
|
-
value=nil
|
332
|
+
value = nil
|
544
333
|
end
|
545
334
|
options[:with].merge!(:value => value.to_s) if value
|
546
335
|
options.merge!(:text => text) if text
|
547
|
-
|
336
|
+
within_nested_tag do
|
337
|
+
expect(@__current_scope_for_nokogiri_matcher).to have_tag('button', options)
|
338
|
+
end
|
548
339
|
end
|
549
340
|
|
550
|
-
def without_button text, value=nil, options={}
|
341
|
+
def without_button text, value = nil, options = {}
|
551
342
|
options[:with] ||= {}
|
552
343
|
if value.is_a?(Hash)
|
553
344
|
options.merge!(value)
|
554
|
-
value=nil
|
345
|
+
value = nil
|
555
346
|
end
|
556
347
|
options[:with].merge!(:value => value.to_s) if value
|
557
348
|
options.merge!(:text => text) if text
|
558
|
-
|
349
|
+
within_nested_tag do
|
350
|
+
expect(@__current_scope_for_nokogiri_matcher).to_not have_tag('button', options)
|
351
|
+
end
|
559
352
|
end
|
560
353
|
|
561
354
|
def with_submit value
|
562
355
|
options = { :with => { :type => 'submit', :value => value } }
|
563
|
-
#options = form_tag_options('text',name,value)
|
356
|
+
# options = form_tag_options('text',name,value)
|
564
357
|
should_have_input(options)
|
565
358
|
end
|
566
359
|
|
567
360
|
def without_submit value
|
568
|
-
#options = form_tag_options('text',name,value)
|
361
|
+
# options = form_tag_options('text',name,value)
|
569
362
|
options = { :with => { :type => 'submit', :value => value } }
|
570
363
|
should_not_have_input(options)
|
571
364
|
end
|
572
365
|
|
573
366
|
private
|
574
367
|
|
575
|
-
def should_have_input
|
576
|
-
|
368
|
+
def should_have_input options
|
369
|
+
within_nested_tag do
|
370
|
+
expect(@__current_scope_for_nokogiri_matcher).to have_tag('input', options)
|
371
|
+
end
|
577
372
|
end
|
578
373
|
|
579
|
-
def should_not_have_input
|
580
|
-
|
374
|
+
def should_not_have_input options
|
375
|
+
within_nested_tag do
|
376
|
+
expect(@__current_scope_for_nokogiri_matcher).to_not have_tag('input', options)
|
377
|
+
end
|
581
378
|
end
|
582
379
|
|
583
380
|
# form_tag in method name name mean smth. like input, submit, tags that should appear in a form
|
584
|
-
def form_tag_options form_tag_type, form_tag_name, form_tag_value=nil
|
381
|
+
def form_tag_options form_tag_type, form_tag_name, form_tag_value = nil
|
585
382
|
options = { :with => { :name => form_tag_name, :type => form_tag_type } }
|
586
383
|
# .to_s if value is a digit or smth. else, see issue#10
|
587
384
|
options[:with].merge!(:value => form_tag_value.to_s) if form_tag_value
|
588
|
-
|
385
|
+
options
|
589
386
|
end
|
590
387
|
|
388
|
+
def within_nested_tag &block
|
389
|
+
raise 'block needed' unless block_given?
|
390
|
+
|
391
|
+
parent_scope = @__current_scope_for_nokogiri_matcher
|
392
|
+
block.call
|
393
|
+
@__current_scope_for_nokogiri_matcher = parent_scope
|
394
|
+
end
|
591
395
|
end
|