rspec-html-matchers 0.8.1 → 0.9.4
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +45 -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 +290 -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 +9 -7
- data/spec/have_tag_spec.rb +270 -166
- data/spec/issues_spec.rb +17 -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: c80050c4efaf8917fde81c8f5b139f846731b679f1a9001fec4a3e49690451b3
|
4
|
+
data.tar.gz: bc7e5523735f253a51fff1055e364f1189d7daa5dcedacf388612c4a57889e5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2febc5b59c123bd2e9232aecfb7839a047f29dbd0b30c0958378523bc04f3c119ad60923a7535def8c2748bb5f92793b47707a9db16ff864dc20696f7e8985d0
|
7
|
+
data.tar.gz: 38c6bf3867215196fd61a4877f8cabbd6bade0dc66ae4ae1edb00945b9d0ac6deecdbcdc0101530255347f6647c1e619f540a4cfe3fb6ca84d807fbf735b7ac6
|
data/CHANGELOG.md
CHANGED
@@ -1,15 +1,48 @@
|
|
1
1
|
Changelog
|
2
2
|
=========
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
0.9.4
|
5
|
+
-----
|
6
|
+
* html/body matching from now is forbidden ([#75](https://github.com/kucaahbe/rspec-html-matchers/pull/75))
|
7
|
+
* make ruby 2.7 possible to fail on CI
|
8
|
+
|
9
|
+
0.9.3
|
10
|
+
-----
|
11
|
+
* fix for :seen option ([#73](https://github.com/kucaahbe/rspec-html-matchers/issues/73))
|
12
|
+
* fix for html/body matching ([#62](https://github.com/kucaahbe/rspec-html-matchers/issues/62))
|
13
|
+
* a bit of linting and refactoring
|
14
|
+
|
15
|
+
0.9.2
|
16
|
+
-----
|
17
|
+
|
18
|
+
* fixed have_empty_tag matcher on jruby
|
19
|
+
* added ruby 2.7 to build matrix (no official support until stable release though)
|
20
|
+
* added ruby 2.6 to build matrix ([#70](https://github.com/kucaahbe/rspec-html-matchers/pull/70))
|
21
|
+
|
22
|
+
infrastructure/misc:
|
23
|
+
|
24
|
+
* 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))
|
25
|
+
* refactor travis-ci build setup
|
26
|
+
* updated status badges to SVG (thanks to [Olle Jonsson](https://github.com/olleolleolle): [#71](https://github.com/kucaahbe/rspec-html-matchers/pull/71))
|
27
|
+
|
28
|
+
0.9.1
|
29
|
+
-----
|
30
|
+
|
31
|
+
* re-added ruby support back to 1.8.7 (supporting same versions as rspec 3)
|
32
|
+
* split lib in few files
|
33
|
+
|
34
|
+
0.9.0
|
35
|
+
-----
|
36
|
+
|
37
|
+
* fixed `with_tag` nesting (thanks to [randoum](https://github.com/randoum): [#59](https://github.com/kucaahbe/rspec-html-matchers/pull/59))
|
38
|
+
* added ~> 2.4 ruby support
|
39
|
+
* removed ~> 2 ruby support
|
40
|
+
|
41
|
+
0.8.2
|
42
|
+
-----
|
6
43
|
|
7
|
-
*
|
8
|
-
*
|
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!)
|
44
|
+
* fixed README (thanks to [Rodrigo Castro](https://github.com/roooodcastro))
|
45
|
+
* fixed deep nesting (thanks to [Misha Gorodnitzky](https://github.com/misaka))
|
13
46
|
|
14
47
|
0.8.1
|
15
48
|
-----
|
@@ -62,7 +95,7 @@ unreleased(TODO)
|
|
62
95
|
0.4.4
|
63
96
|
-----
|
64
97
|
|
65
|
-
* options for have_tag now support Regexp (thanks to [Ian C. Anderson](
|
98
|
+
* options for have_tag now support Regexp (thanks to [Ian C. Anderson](https://github.com/iancanderson))
|
66
99
|
|
67
100
|
0.4.3
|
68
101
|
-----
|
@@ -111,14 +144,14 @@ unreleased(TODO)
|
|
111
144
|
0.2.2
|
112
145
|
-----
|
113
146
|
|
114
|
-
* leading and trailing whitespaces are ignored in tags where they should be ignored(#11, and again thanks to [Simon Schoeters](
|
147
|
+
* leading and trailing whitespaces are ignored in tags where they should be ignored(#11, and again thanks to [Simon Schoeters](https://github.com/cimm))
|
115
148
|
* whitespaces ignoring as browser does in :text matching
|
116
149
|
* have_tag backwards compability(thanks to [Felix Tjandrawibawa](https://github.com/cemeng), #12)
|
117
150
|
|
118
151
|
0.2.1
|
119
152
|
-----
|
120
153
|
|
121
|
-
* make possible use non-string as :text option(#10, thanks for idea to [Simon Schoeters](
|
154
|
+
* make possible use non-string as :text option(#10, thanks for idea to [Simon Schoeters](https://github.com/cimm))
|
122
155
|
|
123
156
|
0.2.0
|
124
157
|
-----
|
@@ -137,7 +170,7 @@ unreleased(TODO)
|
|
137
170
|
0.0.6
|
138
171
|
-----
|
139
172
|
|
140
|
-
* allow for single quotes in content matchers (thanks to [Kelly Felkins](
|
173
|
+
* allow for single quotes in content matchers (thanks to [Kelly Felkins](https://github.com/kellyfelkins)).
|
141
174
|
|
142
175
|
0.0.5 (trial-trip)
|
143
176
|
------------------
|
data/README.md
CHANGED
@@ -1,20 +1,16 @@
|
|
1
|
-
rspec-html-matchers
|
2
|
-
===================
|
1
|
+
# rspec-html-matchers [](https://badge.fury.io/rb/rspec-html-matchers) [](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
|
-
[](http://badge.fury.io/rb/rspec-html-matchers)
|
7
|
-
[](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
|