rspec-html 0.3.2 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.ruby-version +1 -1
- data/Gemfile +7 -5
- data/Gemfile.lock +58 -18
- data/LICENSE.txt +1 -1
- data/Makefile +9 -0
- data/README.md +6 -200
- data/lib/rspec/html/version.rb +1 -1
- data/lib/rspec_html/element.rb +1 -0
- data/lib/rspec_html/search.rb +10 -4
- data/rspec-documentation/pages/000-Introduction.md +38 -0
- data/rspec-documentation/pages/010-Usage/010-The document Object.md +13 -0
- data/rspec-documentation/pages/010-Usage/020-Selectors.md +45 -0
- data/rspec-documentation/pages/010-Usage/030-Matchers/010-match_text.md +27 -0
- data/rspec-documentation/pages/010-Usage/030-Matchers/020-contain_tag.md +15 -0
- data/rspec-documentation/pages/010-Usage/030-Matchers/030-exist.md +13 -0
- data/rspec-documentation/pages/010-Usage/030-Matchers/040-be_checked.md +13 -0
- data/rspec-documentation/pages/010-Usage/030-Matchers.md +8 -0
- data/rspec-documentation/pages/010-Usage/035-Counters.md +55 -0
- data/rspec-documentation/pages/010-Usage/040-Attributes.md +24 -0
- data/rspec-documentation/pages/010-Usage/050-Enumerating Elements.md +49 -0
- data/rspec-documentation/pages/010-Usage/050-XPath.md +13 -0
- data/rspec-documentation/pages/010-Usage.md +25 -0
- data/rspec-documentation/pages/020-Request Specs.md +21 -0
- data/rspec-documentation/pages/030-Response Inspection.md +23 -0
- data/rspec-documentation/pages/400-Alternatives.md +3 -0
- data/rspec-documentation/pages/500-License.md +11 -0
- data/rspec-documentation/spec_helper.rb +33 -0
- data/rspec-html.gemspec +1 -1
- metadata +22 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c535d0ae9c4cf1a7f73cdae79bf0b09a6ad24e78fb7fe787ea098c9640456940
|
4
|
+
data.tar.gz: 335afe827f7526ed40446930aa6555f06a54c76b0da532c0097b435e0d622ec0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 161327678741ab16f3f010e8c4e3c30d9b098c63387d26e504f45cb54fd7115b2b21e6dd051a683312a489e6d007c3355e25ef3aed4a0f5451ec7fcdbff1d1e0
|
7
|
+
data.tar.gz: b662a85ff8fb34ca580ec8a883bd5241201823cd64decb531929f478f03f24490aaaba123bdad005e2e51d2c52265581063229d19c5cc0c1b9bf35294dd8ce57
|
data/.gitignore
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.7.8
|
data/Gemfile
CHANGED
@@ -6,12 +6,14 @@ source 'https://rubygems.org'
|
|
6
6
|
gemspec
|
7
7
|
|
8
8
|
gem 'activesupport', '~> 6.1'
|
9
|
-
gem '
|
10
|
-
gem '
|
11
|
-
gem '
|
9
|
+
gem 'devpack', '~> 0.4.1'
|
10
|
+
gem 'i18n', '~> 1.14'
|
11
|
+
gem 'mail', '~> 2.8'
|
12
12
|
gem 'rake', '~> 13.0'
|
13
|
+
gem 'rspec-documentation', '~> 0.0.7'
|
14
|
+
gem 'rspec-file_fixtures', '~> 0.1.6'
|
13
15
|
gem 'rspec-its', '~> 1.3'
|
14
|
-
gem 'rubocop', '~> 1.
|
16
|
+
gem 'rubocop', '~> 1.52'
|
15
17
|
gem 'rubocop-rake', '~> 0.6.0'
|
16
|
-
gem 'rubocop-rspec', '~> 2.
|
18
|
+
gem 'rubocop-rspec', '~> 2.22'
|
17
19
|
gem 'strong_versions', '~> 0.4.5'
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rspec-html (0.3.
|
4
|
+
rspec-html (0.3.4)
|
5
5
|
nokogiri (~> 1.10)
|
6
6
|
rspec (~> 3.0)
|
7
7
|
|
@@ -16,34 +16,68 @@ GEM
|
|
16
16
|
zeitwerk (~> 2.3)
|
17
17
|
ast (2.4.2)
|
18
18
|
concurrent-ruby (1.2.2)
|
19
|
+
date (3.3.3)
|
19
20
|
devpack (0.4.1)
|
20
21
|
diff-lcs (1.5.0)
|
21
|
-
|
22
|
+
htmlbeautifier (1.4.2)
|
23
|
+
i18n (1.14.1)
|
22
24
|
concurrent-ruby (~> 1.0)
|
23
25
|
json (2.6.3)
|
24
|
-
|
26
|
+
kramdown (2.4.0)
|
27
|
+
rexml
|
28
|
+
kramdown-parser-gfm (1.1.0)
|
29
|
+
kramdown (~> 2.0)
|
30
|
+
mail (2.8.1)
|
31
|
+
mini_mime (>= 0.1.1)
|
32
|
+
net-imap
|
33
|
+
net-pop
|
34
|
+
net-smtp
|
35
|
+
mini_mime (1.1.2)
|
25
36
|
minitest (5.18.0)
|
26
|
-
|
27
|
-
|
37
|
+
net-imap (0.3.4)
|
38
|
+
date
|
39
|
+
net-protocol
|
40
|
+
net-pop (0.1.2)
|
41
|
+
net-protocol
|
42
|
+
net-protocol (0.2.1)
|
43
|
+
timeout
|
44
|
+
net-smtp (0.3.3)
|
45
|
+
net-protocol
|
46
|
+
nokogiri (1.15.2-x86_64-linux)
|
28
47
|
racc (~> 1.4)
|
29
48
|
paint (2.3.0)
|
49
|
+
paintbrush (0.1.3)
|
30
50
|
parallel (1.23.0)
|
31
|
-
parser (3.2.2.
|
51
|
+
parser (3.2.2.3)
|
32
52
|
ast (~> 2.4.1)
|
33
|
-
|
53
|
+
racc
|
54
|
+
racc (1.7.0)
|
34
55
|
rainbow (3.1.1)
|
35
56
|
rake (13.0.6)
|
36
|
-
|
57
|
+
redcarpet (3.6.0)
|
58
|
+
regexp_parser (2.8.1)
|
37
59
|
rexml (3.2.5)
|
60
|
+
rouge (4.1.2)
|
38
61
|
rspec (3.12.0)
|
39
62
|
rspec-core (~> 3.12.0)
|
40
63
|
rspec-expectations (~> 3.12.0)
|
41
64
|
rspec-mocks (~> 3.12.0)
|
42
65
|
rspec-core (3.12.2)
|
43
66
|
rspec-support (~> 3.12.0)
|
67
|
+
rspec-documentation (0.0.7)
|
68
|
+
htmlbeautifier (~> 1.4)
|
69
|
+
kramdown (~> 2.4)
|
70
|
+
kramdown-parser-gfm (~> 1.1)
|
71
|
+
nokogiri (~> 1.15)
|
72
|
+
paintbrush (~> 0.1.3)
|
73
|
+
redcarpet (~> 3.6)
|
74
|
+
rouge (~> 4.1)
|
75
|
+
rspec (~> 3.12)
|
44
76
|
rspec-expectations (3.12.3)
|
45
77
|
diff-lcs (>= 1.2.0, < 2.0)
|
46
78
|
rspec-support (~> 3.12.0)
|
79
|
+
rspec-file_fixtures (0.1.6)
|
80
|
+
rspec (~> 3.0)
|
47
81
|
rspec-its (1.3.0)
|
48
82
|
rspec-core (>= 3.0.0)
|
49
83
|
rspec-expectations (>= 3.0.0)
|
@@ -51,7 +85,7 @@ GEM
|
|
51
85
|
diff-lcs (>= 1.2.0, < 2.0)
|
52
86
|
rspec-support (~> 3.12.0)
|
53
87
|
rspec-support (3.12.0)
|
54
|
-
rubocop (1.
|
88
|
+
rubocop (1.52.0)
|
55
89
|
json (~> 2.3)
|
56
90
|
parallel (~> 1.10)
|
57
91
|
parser (>= 3.2.0.0)
|
@@ -61,39 +95,45 @@ GEM
|
|
61
95
|
rubocop-ast (>= 1.28.0, < 2.0)
|
62
96
|
ruby-progressbar (~> 1.7)
|
63
97
|
unicode-display_width (>= 2.4.0, < 3.0)
|
64
|
-
rubocop-ast (1.
|
98
|
+
rubocop-ast (1.29.0)
|
65
99
|
parser (>= 3.2.1.0)
|
66
100
|
rubocop-capybara (2.18.0)
|
67
101
|
rubocop (~> 1.41)
|
102
|
+
rubocop-factory_bot (2.23.1)
|
103
|
+
rubocop (~> 1.33)
|
68
104
|
rubocop-rake (0.6.0)
|
69
105
|
rubocop (~> 1.0)
|
70
|
-
rubocop-rspec (2.
|
106
|
+
rubocop-rspec (2.22.0)
|
71
107
|
rubocop (~> 1.33)
|
72
108
|
rubocop-capybara (~> 2.17)
|
109
|
+
rubocop-factory_bot (~> 2.22)
|
73
110
|
ruby-progressbar (1.13.0)
|
74
111
|
strong_versions (0.4.5)
|
75
112
|
i18n (>= 0.5)
|
76
113
|
paint (~> 2.0)
|
114
|
+
timeout (0.3.2)
|
77
115
|
tzinfo (2.0.6)
|
78
116
|
concurrent-ruby (~> 1.0)
|
79
117
|
unicode-display_width (2.4.2)
|
80
118
|
zeitwerk (2.6.8)
|
81
119
|
|
82
120
|
PLATFORMS
|
83
|
-
|
121
|
+
x86_64-linux
|
84
122
|
|
85
123
|
DEPENDENCIES
|
86
124
|
activesupport (~> 6.1)
|
87
|
-
|
88
|
-
|
89
|
-
|
125
|
+
devpack (~> 0.4.1)
|
126
|
+
i18n (~> 1.14)
|
127
|
+
mail (~> 2.8)
|
90
128
|
rake (~> 13.0)
|
129
|
+
rspec-documentation (~> 0.0.7)
|
130
|
+
rspec-file_fixtures (~> 0.1.6)
|
91
131
|
rspec-html!
|
92
132
|
rspec-its (~> 1.3)
|
93
|
-
rubocop (~> 1.
|
133
|
+
rubocop (~> 1.52)
|
94
134
|
rubocop-rake (~> 0.6.0)
|
95
|
-
rubocop-rspec (~> 2.
|
135
|
+
rubocop-rspec (~> 2.22)
|
96
136
|
strong_versions (~> 0.4.5)
|
97
137
|
|
98
138
|
BUNDLED WITH
|
99
|
-
2.
|
139
|
+
2.4.13
|
data/LICENSE.txt
CHANGED
data/Makefile
CHANGED
@@ -1,5 +1,14 @@
|
|
1
|
+
project=rspec-html
|
2
|
+
|
1
3
|
.PHONY:
|
2
4
|
test:
|
3
5
|
bundle exec rspec
|
4
6
|
bundle exec rubocop
|
5
7
|
bundle exec strong_versions
|
8
|
+
bundle exec rspec-documentation
|
9
|
+
|
10
|
+
.PHONY: publish
|
11
|
+
publish:
|
12
|
+
@RSPEC_DOCUMENTATION_URL_ROOT='/$(project)' bundle exec rspec-documentation
|
13
|
+
@rsync --delete -r rspec-documentation/bundle/ docs01.bob.frl:/mnt/docs/$(project)/
|
14
|
+
@echo 'Published.'
|
data/README.md
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
# RSpec::HTML
|
2
2
|
|
3
|
-
_RSpec::HTML_ provides a simple object interface to
|
3
|
+
_RSpec::HTML_ provides a simple object interface to _HTML_ content.
|
4
|
+
|
5
|
+
You can use _RSpec::HTML_ to test any _HTML_ produced by your library or application and it works out of the box with [_RSpec Rails_ request specs](https://relishapp.com/rspec/rspec-rails/docs/request-specs/request-spec).
|
4
6
|
|
5
7
|
## Installation
|
6
8
|
|
7
9
|
Add the gem to your `Gemfile`:
|
8
10
|
|
9
11
|
```ruby
|
10
|
-
gem 'rspec-html', '~> 0.3.
|
12
|
+
gem 'rspec-html', '~> 0.3.4'
|
11
13
|
```
|
12
14
|
|
13
15
|
And rebuild your bundle:
|
@@ -16,205 +18,9 @@ And rebuild your bundle:
|
|
16
18
|
$ bundle install
|
17
19
|
```
|
18
20
|
|
19
|
-
##
|
20
|
-
|
21
|
-
Require the gem in your `spec_helper.rb`:
|
22
|
-
|
23
|
-
```
|
24
|
-
# spec/spec_helper.rb
|
25
|
-
require 'rspec/html'
|
26
|
-
```
|
27
|
-
|
28
|
-
Several [matchers](#matchers) are provided to identify text and _HTML_ elements within the _DOM_. These matchers can only be used with the provided [object interface](#object-interface).
|
29
|
-
|
30
|
-
### Browser Inspection
|
31
|
-
|
32
|
-
To open the current document in your operating system's default browser, call `document.open`. Use this to inspect _HTML_ content while debugging.
|
33
|
-
|
34
|
-
```ruby
|
35
|
-
it 'has complex HTML' do
|
36
|
-
get '/my/path'
|
37
|
-
document.open
|
38
|
-
end
|
39
|
-
```
|
40
|
-
|
41
|
-
Alternatively `document.html_path` writes the current document to a temporary file and returns its path.
|
42
|
-
|
43
|
-
### Object Interface
|
44
|
-
<a name="object-interface"></a>
|
45
|
-
|
46
|
-
The top-level object `document` is available in all tests which reflects the current response body (e.g. in request specs).
|
47
|
-
|
48
|
-
If you need to parse _HTML_ manually you can use the provided `parse_html` helper and then access `document` as normal:
|
49
|
-
|
50
|
-
```ruby
|
51
|
-
let(:document) { parse_html('<html><body>hello</body></html>') }
|
52
|
-
|
53
|
-
it 'says hello' do
|
54
|
-
expect(document.body).to match_text 'hello'
|
55
|
-
end
|
56
|
-
```
|
57
|
-
|
58
|
-
This method can also be used for _ActionMailer_ emails:
|
59
|
-
```ruby
|
60
|
-
let(:document) { parse_html(ActionMailer::Base.deliveries.last.body.decoded) }
|
61
|
-
```
|
62
|
-
|
63
|
-
**Changed in 0.3.0**: `parse_html` no longer assigns `document` automatically, you must use a `let` block to assign it yourself.
|
64
|
-
|
65
|
-
To navigate the _DOM_ by a sequence of tag names use chained method calls on the `document` object:
|
66
|
-
|
67
|
-
#### Tag Traversal
|
68
|
-
```ruby
|
69
|
-
expect(document.body.div.span).to match_text 'some text'
|
70
|
-
```
|
71
|
-
|
72
|
-
#### Attribute Matching
|
73
|
-
To select an element matching certain attributes pass a hash to any of the chained methods:
|
74
|
-
```ruby
|
75
|
-
expect(document.body.div(id: 'my-div').span(align: 'left')).to match_text 'some text'
|
76
|
-
```
|
77
|
-
|
78
|
-
Special attributes like `checked` can be found using the `#attributes` method:
|
79
|
-
```ruby
|
80
|
-
expect(document.input(type: 'checkbox', name: 'my-name')).attributes).to include 'checked'
|
81
|
-
```
|
82
|
-
|
83
|
-
#### Class Matching
|
84
|
-
_CSS_ classes are treated as a special case: to select an element matching a set of classes pass the `class` parameter:
|
85
|
-
```ruby
|
86
|
-
expect(document.body.div(id: 'my-div').span(class: 'my-class')).to match_text 'some text'
|
87
|
-
expect(document.body.div(id: 'my-div').span(class: 'my-class my-other-class')).to match_text 'some text'
|
88
|
-
```
|
89
|
-
|
90
|
-
Classes can be provided in any order, i.e. `'my-class my-other-class'` is equivalent to `'my-other-class my-class'`.
|
91
|
-
|
92
|
-
#### Simple CSS Matching
|
93
|
-
To use a simple CSS selector when no other attributes are needed, pass a string to the tag method:
|
94
|
-
```ruby
|
95
|
-
expect(document.body.div('#my-id.my-class1.my-class2')).to match_text 'some text'
|
96
|
-
```
|
97
|
-
|
98
|
-
This is effectively shorthand for:
|
99
|
-
```ruby
|
100
|
-
expect(document.body.div(id: 'my-id', class: 'my-class1 my-class2')).to match_text 'some text'
|
101
|
-
```
|
102
|
-
|
103
|
-
#### Counting Matchers
|
104
|
-
Use `once`, `twice`, `times`, `at_least`, and `at_most` to match element counts:
|
105
|
-
```ruby
|
106
|
-
expect(document.div('.my-class')).to match_text('some text').once
|
107
|
-
expect(document.div('.my-class')).to match_text('some other text').twice
|
108
|
-
expect(document.div('.my-class')).to match_text('some').times(3)
|
109
|
-
expect(document.div('.my-class')).to match_text('some').at_least(:twice)
|
110
|
-
expect(document.div('.my-class')).to match_text('some').at_least.times(3)
|
111
|
-
expect(document.div('.my-class')).to match_text('some text').at_most.once
|
112
|
-
expect(document.div('.my-class')).to match_text('some other text').at_most.twice
|
113
|
-
expect(document.div('.my-class')).to match_text('text').at_most.times(3)
|
114
|
-
```
|
115
|
-
|
116
|
-
#### Text Matching
|
117
|
-
To select an element that includes a given text string (i.e. excluding mark-up) use the `text` option:
|
118
|
-
```ruby
|
119
|
-
expect(document.body.div(text: 'some text').input[:value]).to eql 'some-value'
|
120
|
-
```
|
121
|
-
|
122
|
-
#### Attribute Retrieval
|
123
|
-
To select an attribute from an element use the hash-style interface:
|
124
|
-
```ruby
|
125
|
-
expect(document.body.div.span[:class]).to match_text 'my-class'
|
126
|
-
expect(document.body.div.span['data-content']).to match_text 'my content'
|
127
|
-
```
|
128
|
-
|
129
|
-
#### Retrieve all matching elements
|
130
|
-
To select all matching elements as an array, use `#all`:
|
131
|
-
```ruby
|
132
|
-
expect(document.span.all.map(&:text)).to eql ['foo', 'bar', 'baz']
|
133
|
-
```
|
134
|
-
|
135
|
-
#### Indexing a Matching Set
|
136
|
-
To select an index from a set of matched elements use the array-style interface (the first matching element is `1`, not `0`):
|
137
|
-
```ruby
|
138
|
-
expect(document.body.div[1].span[1][:class]).to match_text 'my-class'
|
139
|
-
```
|
140
|
-
|
141
|
-
Alternatively, use `#first`, `#last` or, when using _ActiveSupport_, `#second`, `#third`, etc. are also available:
|
142
|
-
|
143
|
-
```ruby
|
144
|
-
expect(document.body.div.first.span.last[:class]).to match_text 'my-class'
|
145
|
-
```
|
146
|
-
|
147
|
-
|
148
|
-
#### Element Existence
|
149
|
-
To test if a matching element was found use the `exist` matcher:
|
150
|
-
```ruby
|
151
|
-
expect(document.body.div[1]).to exist
|
152
|
-
expect(document.body.div[4]).to_not exist
|
153
|
-
```
|
154
|
-
|
155
|
-
#### Length of matched attributes
|
156
|
-
To test the length of matched elements use the `#size` or `#length` method:
|
157
|
-
```ruby
|
158
|
-
expect(document.body.div.size).to eql 3
|
159
|
-
expect(document.body.div.length).to eql 3
|
160
|
-
```
|
161
|
-
|
162
|
-
#### XPath / CSS Selectors
|
163
|
-
If you need something more specific you can always use the _Nokogiri_ `#xpath` and `#css` methods on any element:
|
164
|
-
```ruby
|
165
|
-
expect(document.body.xpath('//span[@class="my-class"]')).to match_text 'some text'
|
166
|
-
expect(document.body.css('span.my-class')).to match_text 'some text'
|
167
|
-
```
|
168
|
-
|
169
|
-
To simply check that an _XPath_ or _CSS_ selector exists use `have_xpath` and `have_css`:
|
170
|
-
```ruby
|
171
|
-
expect(document.body).to have_css 'html body div.myclass'
|
172
|
-
expect(document.body).to have_xpath '//html/body/div[@class="myclass"]'
|
173
|
-
```
|
174
|
-
|
175
|
-
#### Checkboxes
|
176
|
-
|
177
|
-
Use `be_checked` to test if a checkbox is checked:
|
178
|
-
```ruby
|
179
|
-
expect(document.input(type: 'checkbox')).to be_checked
|
180
|
-
```
|
181
|
-
|
182
|
-
### Custom Matchers
|
183
|
-
<a name="matchers"></a>
|
184
|
-
|
185
|
-
**Changed in 0.3.0**: The `contain_text` matcher has been removed. Use `match_text` instead.
|
186
|
-
|
187
|
-
#### match_text
|
188
|
-
|
189
|
-
Use the `match_text` matcher to locate text within a _DOM_ element. All mark-up elements are stripped when using this matcher.
|
190
|
-
|
191
|
-
This matcher receives either a string or a regular expression.
|
192
|
-
|
193
|
-
```ruby
|
194
|
-
expect(document.body.form).to match_text 'Please enter your password'
|
195
|
-
expect(document.body.form).to match_text /Please enter your [a-z]+/
|
196
|
-
```
|
197
|
-
|
198
|
-
#### contain_tag
|
199
|
-
|
200
|
-
Use the `contain_tag` matcher to locate _DOM_ elements within any given element. This matcher accepts two arguments:
|
201
|
-
|
202
|
-
* The tag name of the element you want to match (e.g. `:div`);
|
203
|
-
* _(Optional)_ A hash of options. All options supported by the [object interface](#object-interface) can be used here.
|
204
|
-
|
205
|
-
Without options:
|
206
|
-
```ruby
|
207
|
-
expect(document.div(class: 'my-class')).to contain_tag :span
|
208
|
-
```
|
209
|
-
|
210
|
-
With options:
|
211
|
-
```ruby
|
212
|
-
expect(document.form(class: 'my-form')).to contain_tag :input, name: 'email', class: 'email-input'
|
213
|
-
```
|
214
|
-
|
215
|
-
## Contributing
|
21
|
+
## Documentation
|
216
22
|
|
217
|
-
|
23
|
+
See the [documentation](https://docs.bob.frl/rspec_html) for full usage guide.
|
218
24
|
|
219
25
|
## License
|
220
26
|
|
data/lib/rspec/html/version.rb
CHANGED
data/lib/rspec_html/element.rb
CHANGED
@@ -49,6 +49,7 @@ module RSpecHTML
|
|
49
49
|
|
50
50
|
Tags.each do |tag|
|
51
51
|
define_method tag.downcase do |*args|
|
52
|
+
args[0] = " #{args[0]}" if args.first.is_a?(String) && args.first&.match?(/^[a-zA-Z]/)
|
52
53
|
options = args.first
|
53
54
|
return @search.new_from_find(tag.downcase, options) if options.nil?
|
54
55
|
|
data/lib/rspec_html/search.rb
CHANGED
@@ -56,11 +56,11 @@ module RSpecHTML
|
|
56
56
|
|
57
57
|
# rubocop:disable Naming/PredicateName
|
58
58
|
def has_css?(*args)
|
59
|
-
|
59
|
+
!blank?(@element&.css(*args))
|
60
60
|
end
|
61
61
|
|
62
62
|
def has_xpath?(*args)
|
63
|
-
|
63
|
+
!blank?(@element&.xpath(*args))
|
64
64
|
end
|
65
65
|
# rubocop:enable Naming/PredicateName
|
66
66
|
|
@@ -148,9 +148,9 @@ module RSpecHTML
|
|
148
148
|
end
|
149
149
|
|
150
150
|
def where_xpath(tag, query)
|
151
|
-
conditions = "[#{where_conditions(query)}]" unless query.compact
|
151
|
+
conditions = "[#{where_conditions(query)}]" unless blank?(query.compact)
|
152
152
|
result = @element&.xpath(".//#{tag}#{conditions}")
|
153
|
-
return result unless @siblings.is_a?(Nokogiri::XML::NodeSet) && (result
|
153
|
+
return result unless @siblings.is_a?(Nokogiri::XML::NodeSet) && blank?(result)
|
154
154
|
|
155
155
|
@siblings.xpath(".//#{tag}#{conditions}")
|
156
156
|
end
|
@@ -175,6 +175,12 @@ module RSpecHTML
|
|
175
175
|
|
176
176
|
@element&.css(tag.to_s)
|
177
177
|
end
|
178
|
+
|
179
|
+
def blank?(object)
|
180
|
+
return true unless object
|
181
|
+
|
182
|
+
object.empty?
|
183
|
+
end
|
178
184
|
end
|
179
185
|
# rubocop:enable Metrics/ClassLength
|
180
186
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Introduction
|
2
|
+
|
3
|
+
_RSpec::HTML_ provides a simple object interface to _HTML_ content.
|
4
|
+
|
5
|
+
You can use _RSpec::HTML_ to test any _HTML_ produced by your library or application and it works out of the box with [_RSpec Rails_ request specs](https://relishapp.com/rspec/rspec-rails/docs/request-specs/request-spec).
|
6
|
+
|
7
|
+
## Setup
|
8
|
+
|
9
|
+
Load `rspec-html` in your `spec_helper.rb`:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
# spec/spec_helper.rb
|
13
|
+
|
14
|
+
require 'rspec/html'
|
15
|
+
```
|
16
|
+
|
17
|
+
## Quick Example
|
18
|
+
|
19
|
+
```rspec:html
|
20
|
+
subject(:document) { parse_html(html) }
|
21
|
+
|
22
|
+
let(:html) do
|
23
|
+
<<~HTML
|
24
|
+
<html>
|
25
|
+
<body>
|
26
|
+
<div>Some other content</div>
|
27
|
+
<div class="my-div">
|
28
|
+
My div content
|
29
|
+
</div>
|
30
|
+
</body>
|
31
|
+
</html>
|
32
|
+
HTML
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'matches "My div content"' do
|
36
|
+
expect(document.html.body.div('.my-div')).to match_text 'My div content'
|
37
|
+
end
|
38
|
+
```
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# The `document` Object
|
2
|
+
|
3
|
+
For [_RSpec Rails_ `request` specs](request-specs.html) the `document` object is already defined by _RSpec::HTML_ as the parsed response body.
|
4
|
+
|
5
|
+
If you are testing _HTML_ in any other context, e.g. for parsing _ActionMailer_ emails, simply define `document` with a `let` or `subject` block that calls the provided `parse_html` helper:
|
6
|
+
|
7
|
+
```rspec:html
|
8
|
+
subject(:document) { parse_html(ActionMailer::Base.deliveries.last.body.decoded) }
|
9
|
+
|
10
|
+
it 'contains a welcome message' do
|
11
|
+
expect(document.div('.welcome-message')).to match_text 'Welcome to our website!'
|
12
|
+
end
|
13
|
+
```
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# Selectors
|
2
|
+
|
3
|
+
Each method in the chain can receive arguments to specify selectors on attributes of each element.
|
4
|
+
|
5
|
+
To select an `<input>` element with a `name` attribute whose value is `email`, pass `name: 'email'` to the `input` method:
|
6
|
+
|
7
|
+
## Attribute Selectors
|
8
|
+
|
9
|
+
```rspec:html
|
10
|
+
it 'renders a name field' do
|
11
|
+
get '/users/new'
|
12
|
+
expect(document.form.input(name: 'user[email]')).to exist
|
13
|
+
end
|
14
|
+
```
|
15
|
+
|
16
|
+
## CSS Selectors
|
17
|
+
|
18
|
+
Since `class` is an attribute just like `name` you can specify the exact `class` string to match elements as `document.table(class: 'table users')`:
|
19
|
+
|
20
|
+
However, this test is very fragile - any change to the `class` attribute will cause the test to break, even if the order of the classes changes.
|
21
|
+
|
22
|
+
Instead, you can match using _CSS_ selectors by passing a string directly to each element method:
|
23
|
+
|
24
|
+
```rspec:html
|
25
|
+
it 'renders a users table' do
|
26
|
+
get '/users'
|
27
|
+
expect(document.table('.users')).to exist
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
Any valid _CSS_ selector is permitted:
|
32
|
+
|
33
|
+
```rspec:html
|
34
|
+
it 'renders a users table' do
|
35
|
+
get '/users'
|
36
|
+
expect(document.table('#users-table')).to exist
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
```rspec:html
|
41
|
+
it 'renders a users table' do
|
42
|
+
get '/users'
|
43
|
+
expect(document.table('tr td[class="name"]')).to exist
|
44
|
+
end
|
45
|
+
```
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# `match_text`
|
2
|
+
|
3
|
+
The `match_text` matcher filters out any tags and compacts whitespace to make matching strings within your _HTML_ more straightforward.
|
4
|
+
|
5
|
+
## Strings
|
6
|
+
|
7
|
+
```rspec:html
|
8
|
+
subject(:document) do
|
9
|
+
parse_html '<div>Some <span>text</span> with <span>whitespace</span></div>'
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'matches simple strings' do
|
13
|
+
expect(document.div).to match_text 'Some text with whitespace'
|
14
|
+
end
|
15
|
+
```
|
16
|
+
|
17
|
+
## Regular Expressions
|
18
|
+
|
19
|
+
```rspec:html
|
20
|
+
subject(:document) do
|
21
|
+
parse_html '<div>Some <span>text</span> with <span>whitespace</span></div>'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'matches simple strings' do
|
25
|
+
expect(document.div).to match_text /text.*whitespace/
|
26
|
+
end
|
27
|
+
```
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# `contain_tag`
|
2
|
+
|
3
|
+
The `contain_tag` matcher verifies that an element exists within your document.
|
4
|
+
|
5
|
+
The matcher receives a tag name as a `Symbol` and optionally receives a set of keyword arguments that refine the element definition.
|
6
|
+
|
7
|
+
```rspec:html
|
8
|
+
subject(:document) do
|
9
|
+
parse_html('<html><body><table><tr><td align="center">td tag</td><tr></table></body></html>')
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'matches an element' do
|
13
|
+
expect(document.table).to contain_tag :td, align: 'center'
|
14
|
+
end
|
15
|
+
```
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# `exist`
|
2
|
+
|
3
|
+
The `exist` matcher verifies that a provided element specification exists in the document.
|
4
|
+
|
5
|
+
```rspec:html
|
6
|
+
subject(:document) do
|
7
|
+
parse_html('<html><body><div><span class="my-span">my text</span></div></body></html>')
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'verifies that an element exists' do
|
11
|
+
expect(document.body.div.span('.my-span')).to exist
|
12
|
+
end
|
13
|
+
```
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# `be_checked`
|
2
|
+
|
3
|
+
Use the `be_checked` matcher to verify that a checkbox input is checked.
|
4
|
+
|
5
|
+
```rspec:html
|
6
|
+
subject(:document) do
|
7
|
+
parse_html('<form><input type="checkbox" checked></form>')
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'renders a checked checkbox input' do
|
11
|
+
expect(document.form.input(type: 'checkbox')).to be_checked
|
12
|
+
end
|
13
|
+
```
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Matchers
|
2
|
+
|
3
|
+
_RSpec::HTML_ provides a selection of matchers to help you verify your _HTML_ content.
|
4
|
+
|
5
|
+
* [`match_text`](matchers/match_text.html)
|
6
|
+
* [`contain_tag`](matchers/contain_tag.html)
|
7
|
+
* [`exist`](matchers/exist.html)
|
8
|
+
* [`be_checked`](matchers/be_checked.html)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# Counters
|
2
|
+
|
3
|
+
The [`match_text`](matchers/match_text.html) and [`contain_tag`](matchers/contain_tag.html) matchers support a counting interface to verify the number of occurrences of a given element specification within a document.
|
4
|
+
|
5
|
+
The following methods can be added to a `match_text` or `contain_tag` call:
|
6
|
+
|
7
|
+
* `#once`
|
8
|
+
* `#twice`
|
9
|
+
* `#times(n)`
|
10
|
+
* `#at_least(:once)`, `#at_least(:twice)`, `#at_least.times(n)`
|
11
|
+
* `#at_most(:once)`, `#at_most(:twice)`, `#at_most.times(n)`
|
12
|
+
|
13
|
+
## Exact Counts
|
14
|
+
|
15
|
+
```rspec:html
|
16
|
+
subject(:document) { parse_html('<div>my div</div>') }
|
17
|
+
|
18
|
+
it 'has one div' do
|
19
|
+
expect(document.div).to match_text('my div').once
|
20
|
+
end
|
21
|
+
```
|
22
|
+
|
23
|
+
```rspec:html
|
24
|
+
subject(:document) { parse_html('<div>my div</div><div>my div</div>') }
|
25
|
+
|
26
|
+
it 'has one div' do
|
27
|
+
expect(document.div).to match_text('my div').twice
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
```rspec:html
|
32
|
+
subject(:document) { parse_html('<div>my div</div><div>my div</div><div>my div</div>') }
|
33
|
+
|
34
|
+
it 'has one div' do
|
35
|
+
expect(document.div).to match_text('my div').times(3)
|
36
|
+
end
|
37
|
+
```
|
38
|
+
|
39
|
+
## Minimum/Maximum Counts
|
40
|
+
|
41
|
+
```rspec:html
|
42
|
+
subject(:document) { parse_html('<div>my div</div><div>my div</div><div>my div</div>') }
|
43
|
+
|
44
|
+
it 'has at least two divs' do
|
45
|
+
expect(document.div).to match_text('my div').at_least(:twice)
|
46
|
+
end
|
47
|
+
```
|
48
|
+
|
49
|
+
```rspec:html
|
50
|
+
subject(:document) { parse_html('<div>my div</div><div>my div</div><div>my div</div>') }
|
51
|
+
|
52
|
+
it 'has at most three divs' do
|
53
|
+
expect(document.div).to match_text('my div').at_most.times(3)
|
54
|
+
end
|
55
|
+
```
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Attributes
|
2
|
+
|
3
|
+
If you need to verify the exact value of an attribute, use `Hash` key lookup syntax by calling `#[]`.
|
4
|
+
|
5
|
+
```rspec:html
|
6
|
+
subject(:document) do
|
7
|
+
parse_html('<div><input type="text" value="my-value"></div>')
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'has an input whose value is "my-value"' do
|
11
|
+
expect(document.div.input[:value]).to eql 'my-value'
|
12
|
+
end
|
13
|
+
```
|
14
|
+
|
15
|
+
One particular use case that makes this especially useful is retrieving an anti-CSRF token from a form before submitting a `POST` or `PATCH` request:
|
16
|
+
|
17
|
+
```rspec:html
|
18
|
+
it 'submits a user form' do
|
19
|
+
get '/users/new'
|
20
|
+
token = document.form.input(name: 'authenticity_token')[:value]
|
21
|
+
post '/users', params: { user: { email: 'user@example.com' }, authenticity_token: token }
|
22
|
+
expect(document.div('.flash.notice')).to match_text 'User successfully created'
|
23
|
+
end
|
24
|
+
```
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Enumerating Elements
|
2
|
+
|
3
|
+
Several interfaces exist to assist you if you need to test specifics about the number of elements that match a given element specification.
|
4
|
+
|
5
|
+
## `#all`
|
6
|
+
|
7
|
+
Use `#all` to retrieve all matched elements:
|
8
|
+
|
9
|
+
```rspec:html
|
10
|
+
subject(:document) { parse_html('<div>div #1</div><div>div #2</div><div>div #3</div>') }
|
11
|
+
|
12
|
+
it 'retrieves all matching elements' do
|
13
|
+
expect(document.div.all).to all(match_text /div #[0-9]/)
|
14
|
+
end
|
15
|
+
```
|
16
|
+
|
17
|
+
## `#[]`
|
18
|
+
|
19
|
+
Use `#[]` to index a specific element from a matching set. Note that indexing starts at `1`, not `0`, so the first element in a set is `[1]`.
|
20
|
+
|
21
|
+
```rspec:html
|
22
|
+
subject(:document) { parse_html('<div>div #1</div><div>div #2</div><div>div #3</div>') }
|
23
|
+
|
24
|
+
it 'retrieves all matching elements' do
|
25
|
+
expect(document.div[2]).to match_text 'div #2'
|
26
|
+
end
|
27
|
+
```
|
28
|
+
|
29
|
+
You can also use `#first` or `#last` if you prefer:
|
30
|
+
|
31
|
+
```rspec:html
|
32
|
+
subject(:document) { parse_html('<div>div #1</div><div>div #2</div><div>div #3</div>') }
|
33
|
+
|
34
|
+
it 'retrieves all matching elements' do
|
35
|
+
expect(document.div.last).to match_text 'div #3'
|
36
|
+
end
|
37
|
+
```
|
38
|
+
|
39
|
+
## `#size`
|
40
|
+
|
41
|
+
Use `#size` to verify the length of a set of matched elements:
|
42
|
+
|
43
|
+
```rspec:html
|
44
|
+
subject(:document) { parse_html('<div>div #1</div><div>div #2</div><div>div #3</div>') }
|
45
|
+
|
46
|
+
it 'retrieves all matching elements' do
|
47
|
+
expect(document.div.size).to eql 3
|
48
|
+
end
|
49
|
+
```
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# XPath
|
2
|
+
|
3
|
+
If the provided _DOM_ navigation syntax does not provide a way for you to definitively select the required element, [_XPath_](https://developer.mozilla.org/en-US/docs/Web/XPath) is available via the `#xpath` method which delegates directly to the underlying [`Nokogiri::HTML::Document`](https://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/HTML/Document) object.
|
4
|
+
|
5
|
+
```rspec:html
|
6
|
+
subject(:document) do
|
7
|
+
parse_html('<table><tr><td>My content</td></table>')
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'matches using xpath' do
|
11
|
+
expect(document.xpath('//table/tr/td').text).to eql 'My content'
|
12
|
+
end
|
13
|
+
```
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Usage
|
2
|
+
|
3
|
+
_RSpec::HTML_ uses method chaining to traverse the Document Object Model (_DOM_).
|
4
|
+
|
5
|
+
## Implicit Navigation
|
6
|
+
|
7
|
+
Access a `<td>` tag anywhere in the document:
|
8
|
+
|
9
|
+
```rspec:html
|
10
|
+
it 'renders a user name' do
|
11
|
+
get '/users'
|
12
|
+
expect(document.td('.name')).to match_text 'Example User #1'
|
13
|
+
end
|
14
|
+
```
|
15
|
+
|
16
|
+
## Explicit Navigation
|
17
|
+
|
18
|
+
Or specify the full node tree explicitly to ensure your document's structure:
|
19
|
+
|
20
|
+
```rspec:html
|
21
|
+
it 'renders a user name' do
|
22
|
+
get '/users'
|
23
|
+
expect(document.body.table.tbody.tr.td('.name')).to match_text 'Example User #1'
|
24
|
+
end
|
25
|
+
```
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Request Specs
|
2
|
+
|
3
|
+
If you're using _RSpec_ `request` specs with _Rails_, a `document` object is available in all specs, wrapping the `response.body` of each request.
|
4
|
+
|
5
|
+
```rspec:html
|
6
|
+
it 'generates a users table' do
|
7
|
+
get '/users'
|
8
|
+
expect(document.table('.users').td('.email')).to match_text 'user@example.com'
|
9
|
+
end
|
10
|
+
```
|
11
|
+
|
12
|
+
This is equivalent to:
|
13
|
+
|
14
|
+
```rspec:html
|
15
|
+
let(:document) { parse_html(response.body) }
|
16
|
+
|
17
|
+
it 'generates a users table' do
|
18
|
+
get '/users'
|
19
|
+
expect(document.table('.users').td('.email')).to match_text 'user@example.com'
|
20
|
+
end
|
21
|
+
```
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Response Inspection
|
2
|
+
|
3
|
+
## Browser Inspection
|
4
|
+
|
5
|
+
To make debugging a little easier, the output of the parsed document can be loaded into your operating system's default web browser by calling `document.open`.
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
it 'has complex HTML' do
|
9
|
+
get '/my/path'
|
10
|
+
document.open
|
11
|
+
end
|
12
|
+
```
|
13
|
+
|
14
|
+
## String Inspection
|
15
|
+
|
16
|
+
Alternatively, the document can be printed to `stdout` by calling `puts document`.
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
it 'has complex HTML' do
|
20
|
+
get '/my/path'
|
21
|
+
puts document
|
22
|
+
end
|
23
|
+
```
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# License
|
2
|
+
|
3
|
+
## MIT
|
4
|
+
|
5
|
+
Copyright 2019-2023 Robert Farrell
|
6
|
+
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
8
|
+
|
9
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
10
|
+
|
11
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rspec/html'
|
4
|
+
require 'rspec/file_fixtures'
|
5
|
+
|
6
|
+
require 'mail'
|
7
|
+
|
8
|
+
module ActionMailer
|
9
|
+
# Stub for ActionMailer::Base to return an example delivered email.
|
10
|
+
class Base
|
11
|
+
def self.deliveries
|
12
|
+
[Mail.new { body '<div class="welcome-message">Welcome to our website!</div>' }]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
RSpec::Documentation.configure do |config|
|
18
|
+
config.context do
|
19
|
+
def get(path)
|
20
|
+
@response_body = fixture("html#{path}.html").read
|
21
|
+
end
|
22
|
+
|
23
|
+
def post(path, params:) # rubocop:disable Lint/UnusedMethodArgument
|
24
|
+
@response_body = fixture("html#{path}/create.html").read
|
25
|
+
end
|
26
|
+
|
27
|
+
def response
|
28
|
+
double(body: @response_body)
|
29
|
+
end
|
30
|
+
|
31
|
+
subject { @response_body }
|
32
|
+
end
|
33
|
+
end
|
data/rspec-html.gemspec
CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.executables = []
|
29
29
|
spec.require_paths = ['lib']
|
30
30
|
|
31
|
-
spec.required_ruby_version = '>= 2.
|
31
|
+
spec.required_ruby_version = '>= 2.7'
|
32
32
|
spec.add_dependency 'nokogiri', '~> 1.10'
|
33
33
|
spec.add_dependency 'rspec', '~> 3.0'
|
34
34
|
spec.metadata['rubygems_mfa_required'] = 'true'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-html
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bob Farrell
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -71,6 +71,24 @@ files:
|
|
71
71
|
- lib/rspec_html/reconstituted_element.rb
|
72
72
|
- lib/rspec_html/search.rb
|
73
73
|
- lib/rspec_html/tags.rb
|
74
|
+
- rspec-documentation/pages/000-Introduction.md
|
75
|
+
- rspec-documentation/pages/010-Usage.md
|
76
|
+
- rspec-documentation/pages/010-Usage/010-The document Object.md
|
77
|
+
- rspec-documentation/pages/010-Usage/020-Selectors.md
|
78
|
+
- rspec-documentation/pages/010-Usage/030-Matchers.md
|
79
|
+
- rspec-documentation/pages/010-Usage/030-Matchers/010-match_text.md
|
80
|
+
- rspec-documentation/pages/010-Usage/030-Matchers/020-contain_tag.md
|
81
|
+
- rspec-documentation/pages/010-Usage/030-Matchers/030-exist.md
|
82
|
+
- rspec-documentation/pages/010-Usage/030-Matchers/040-be_checked.md
|
83
|
+
- rspec-documentation/pages/010-Usage/035-Counters.md
|
84
|
+
- rspec-documentation/pages/010-Usage/040-Attributes.md
|
85
|
+
- rspec-documentation/pages/010-Usage/050-Enumerating Elements.md
|
86
|
+
- rspec-documentation/pages/010-Usage/050-XPath.md
|
87
|
+
- rspec-documentation/pages/020-Request Specs.md
|
88
|
+
- rspec-documentation/pages/030-Response Inspection.md
|
89
|
+
- rspec-documentation/pages/400-Alternatives.md
|
90
|
+
- rspec-documentation/pages/500-License.md
|
91
|
+
- rspec-documentation/spec_helper.rb
|
74
92
|
- rspec-html.gemspec
|
75
93
|
- templates/description/contain_tag.erb
|
76
94
|
- templates/description/match_text.erb
|
@@ -92,14 +110,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
92
110
|
requirements:
|
93
111
|
- - ">="
|
94
112
|
- !ruby/object:Gem::Version
|
95
|
-
version: '2.
|
113
|
+
version: '2.7'
|
96
114
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
115
|
requirements:
|
98
116
|
- - ">="
|
99
117
|
- !ruby/object:Gem::Version
|
100
118
|
version: '0'
|
101
119
|
requirements: []
|
102
|
-
rubygems_version: 3.
|
120
|
+
rubygems_version: 3.1.6
|
103
121
|
signing_key:
|
104
122
|
specification_version: 4
|
105
123
|
summary: RSpec HTML
|