rspec-html 0.1.2 → 0.2.3
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 +4 -4
- data/.rubocop.yml +81 -0
- data/Gemfile.lock +36 -32
- data/README.md +114 -16
- data/lib/rspec/html.rb +11 -1
- data/lib/rspec/html/version.rb +1 -1
- data/lib/rspec_html.rb +11 -6
- data/lib/rspec_html/element.rb +47 -0
- data/lib/rspec_html/matchers.rb +33 -0
- data/lib/rspec_html/matchers/base.rb +61 -0
- data/lib/rspec_html/matchers/contain_tag.rb +15 -0
- data/lib/rspec_html/matchers/contain_text.rb +17 -0
- data/lib/rspec_html/reconstituted_element.rb +36 -0
- data/lib/rspec_html/search.rb +127 -0
- data/lib/rspec_html/tags.rb +31 -0
- data/rspec-html.gemspec +4 -4
- data/templates/description/contain_tag.erb +1 -0
- data/templates/description/contain_text.erb +1 -0
- data/templates/failure/contain_tag.erb +5 -0
- data/templates/failure/contain_text.erb +5 -0
- metadata +29 -23
- data/lib/rspec_html/body.rb +0 -14
- data/lib/rspec_html/document.rb +0 -34
- data/lib/rspec_html/head.rb +0 -22
- data/lib/rspec_html/nameable.rb +0 -8
- data/lib/rspec_html/searchable.rb +0 -18
- data/lib/rspec_html/title.rb +0 -14
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cf565ab0af76a2408b1185d8516aa6a18ac94bdf3521bd76235ffeab2cf85c84
|
|
4
|
+
data.tar.gz: cceb245c801bb10e3a84d942a8101014a585ac5b00e958bd682b6b0a3599143a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 07ea3aedf2366de58c8c39af7ff8fcf17ff273ea1df71799215a0f19fdd029a0e32a8517b154e140175b6211d258d6376ef4faa40fdcb645ca4183196a4cec96
|
|
7
|
+
data.tar.gz: ca57887c542a4817181d1da196fc05f9739be992aa7a10b2cdb7aae293d066ddfc6c2009aeb204cfc315ac2745ef36ac1792fa29b22f11a09cb02cb441a7d14b
|
data/.rubocop.yml
CHANGED
|
@@ -2,3 +2,84 @@ Metrics/BlockLength:
|
|
|
2
2
|
Exclude:
|
|
3
3
|
- 'spec/**/*'
|
|
4
4
|
- 'rspec-html.gemspec'
|
|
5
|
+
|
|
6
|
+
Gemspec/RequiredRubyVersion:
|
|
7
|
+
Enabled: false
|
|
8
|
+
|
|
9
|
+
Layout/LineLength:
|
|
10
|
+
Max: 100
|
|
11
|
+
|
|
12
|
+
Layout/EmptyLinesAroundAttributeAccessor:
|
|
13
|
+
Enabled: true
|
|
14
|
+
Layout/SpaceAroundMethodCallOperator:
|
|
15
|
+
Enabled: true
|
|
16
|
+
Lint/DeprecatedOpenSSLConstant:
|
|
17
|
+
Enabled: true
|
|
18
|
+
Lint/DuplicateElsifCondition:
|
|
19
|
+
Enabled: true
|
|
20
|
+
Lint/MixedRegexpCaptureTypes:
|
|
21
|
+
Enabled: true
|
|
22
|
+
Lint/RaiseException:
|
|
23
|
+
Enabled: true
|
|
24
|
+
Lint/StructNewOverride:
|
|
25
|
+
Enabled: true
|
|
26
|
+
Style/AccessorGrouping:
|
|
27
|
+
Enabled: true
|
|
28
|
+
Style/ArrayCoercion:
|
|
29
|
+
Enabled: true
|
|
30
|
+
Style/BisectedAttrAccessor:
|
|
31
|
+
Enabled: true
|
|
32
|
+
Style/CaseLikeIf:
|
|
33
|
+
Enabled: true
|
|
34
|
+
Style/ExponentialNotation:
|
|
35
|
+
Enabled: true
|
|
36
|
+
Style/HashAsLastArrayItem:
|
|
37
|
+
Enabled: true
|
|
38
|
+
Style/HashEachMethods:
|
|
39
|
+
Enabled: true
|
|
40
|
+
Style/HashLikeCase:
|
|
41
|
+
Enabled: true
|
|
42
|
+
Style/HashTransformKeys:
|
|
43
|
+
Enabled: true
|
|
44
|
+
Style/HashTransformValues:
|
|
45
|
+
Enabled: true
|
|
46
|
+
Style/RedundantAssignment:
|
|
47
|
+
Enabled: true
|
|
48
|
+
Style/RedundantFetchBlock:
|
|
49
|
+
Enabled: true
|
|
50
|
+
Style/RedundantFileExtensionInRequire:
|
|
51
|
+
Enabled: true
|
|
52
|
+
Style/RedundantRegexpCharacterClass:
|
|
53
|
+
Enabled: true
|
|
54
|
+
Style/RedundantRegexpEscape:
|
|
55
|
+
Enabled: true
|
|
56
|
+
Style/SlicingWithRange:
|
|
57
|
+
Enabled: true
|
|
58
|
+
Lint/BinaryOperatorWithIdenticalOperands:
|
|
59
|
+
Enabled: true
|
|
60
|
+
Lint/DuplicateRescueException:
|
|
61
|
+
Enabled: true
|
|
62
|
+
Lint/EmptyConditionalBody:
|
|
63
|
+
Enabled: true
|
|
64
|
+
Lint/FloatComparison:
|
|
65
|
+
Enabled: true
|
|
66
|
+
Lint/MissingSuper:
|
|
67
|
+
Enabled: true
|
|
68
|
+
Lint/OutOfRangeRegexpRef:
|
|
69
|
+
Enabled: true
|
|
70
|
+
Lint/SelfAssignment:
|
|
71
|
+
Enabled: true
|
|
72
|
+
Lint/TopLevelReturnWithArgument:
|
|
73
|
+
Enabled: true
|
|
74
|
+
Lint/UnreachableLoop:
|
|
75
|
+
Enabled: true
|
|
76
|
+
Style/ExplicitBlockArgument:
|
|
77
|
+
Enabled: true
|
|
78
|
+
Style/GlobalStdStream:
|
|
79
|
+
Enabled: true
|
|
80
|
+
Style/OptionalBooleanParameter:
|
|
81
|
+
Enabled: true
|
|
82
|
+
Style/SingleArgumentDig:
|
|
83
|
+
Enabled: true
|
|
84
|
+
Style/StringConcatenation:
|
|
85
|
+
Enabled: true
|
data/Gemfile.lock
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
rspec-html (0.
|
|
4
|
+
rspec-html (0.2.3)
|
|
5
5
|
nokogiri (~> 1.10)
|
|
6
6
|
rspec (~> 3.0)
|
|
7
7
|
|
|
8
8
|
GEM
|
|
9
9
|
remote: https://rubygems.org/
|
|
10
10
|
specs:
|
|
11
|
-
ast (2.4.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
i18n (1.7.0)
|
|
11
|
+
ast (2.4.1)
|
|
12
|
+
byebug (11.1.3)
|
|
13
|
+
concurrent-ruby (1.1.6)
|
|
14
|
+
devpack (0.1.2)
|
|
15
|
+
diff-lcs (1.4.4)
|
|
16
|
+
i18n (1.8.5)
|
|
18
17
|
concurrent-ruby (~> 1.0)
|
|
19
|
-
jaro_winkler (1.5.4)
|
|
20
18
|
mini_portile2 (2.4.0)
|
|
21
|
-
nokogiri (1.10.
|
|
19
|
+
nokogiri (1.10.10)
|
|
22
20
|
mini_portile2 (~> 2.4.0)
|
|
23
|
-
paint (2.
|
|
24
|
-
parallel (1.19.
|
|
25
|
-
parser (2.
|
|
26
|
-
ast (~> 2.4.
|
|
21
|
+
paint (2.2.0)
|
|
22
|
+
parallel (1.19.2)
|
|
23
|
+
parser (2.7.1.4)
|
|
24
|
+
ast (~> 2.4.1)
|
|
27
25
|
rainbow (3.0.0)
|
|
28
|
-
rake (
|
|
26
|
+
rake (13.0.1)
|
|
27
|
+
regexp_parser (1.7.1)
|
|
28
|
+
rexml (3.2.4)
|
|
29
29
|
rspec (3.9.0)
|
|
30
30
|
rspec-core (~> 3.9.0)
|
|
31
31
|
rspec-expectations (~> 3.9.0)
|
|
32
32
|
rspec-mocks (~> 3.9.0)
|
|
33
|
-
rspec-core (3.9.
|
|
34
|
-
rspec-support (~> 3.9.
|
|
35
|
-
rspec-expectations (3.9.
|
|
33
|
+
rspec-core (3.9.2)
|
|
34
|
+
rspec-support (~> 3.9.3)
|
|
35
|
+
rspec-expectations (3.9.2)
|
|
36
36
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
37
37
|
rspec-support (~> 3.9.0)
|
|
38
38
|
rspec-its (1.3.0)
|
|
@@ -41,36 +41,40 @@ GEM
|
|
|
41
41
|
rspec-mocks (3.9.1)
|
|
42
42
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
43
43
|
rspec-support (~> 3.9.0)
|
|
44
|
-
rspec-support (3.9.
|
|
45
|
-
rubocop (0.
|
|
46
|
-
jaro_winkler (~> 1.5.1)
|
|
44
|
+
rspec-support (3.9.3)
|
|
45
|
+
rubocop (0.89.1)
|
|
47
46
|
parallel (~> 1.10)
|
|
48
|
-
parser (>= 2.
|
|
47
|
+
parser (>= 2.7.1.1)
|
|
49
48
|
rainbow (>= 2.2.2, < 4.0)
|
|
49
|
+
regexp_parser (>= 1.7)
|
|
50
|
+
rexml
|
|
51
|
+
rubocop-ast (>= 0.3.0, < 1.0)
|
|
50
52
|
ruby-progressbar (~> 1.7)
|
|
51
|
-
unicode-display_width (>= 1.4.0, <
|
|
52
|
-
rubocop-
|
|
53
|
-
|
|
53
|
+
unicode-display_width (>= 1.4.0, < 2.0)
|
|
54
|
+
rubocop-ast (0.3.0)
|
|
55
|
+
parser (>= 2.7.1.4)
|
|
56
|
+
rubocop-rspec (1.42.0)
|
|
57
|
+
rubocop (>= 0.87.0)
|
|
54
58
|
ruby-progressbar (1.10.1)
|
|
55
|
-
strong_versions (0.
|
|
56
|
-
i18n (>= 0.5
|
|
59
|
+
strong_versions (0.4.5)
|
|
60
|
+
i18n (>= 0.5)
|
|
57
61
|
paint (~> 2.0)
|
|
58
|
-
unicode-display_width (1.
|
|
62
|
+
unicode-display_width (1.7.0)
|
|
59
63
|
|
|
60
64
|
PLATFORMS
|
|
61
65
|
ruby
|
|
62
66
|
|
|
63
67
|
DEPENDENCIES
|
|
64
|
-
betterp (~> 0.1.3)
|
|
65
68
|
bundler (~> 2.0)
|
|
66
69
|
byebug (~> 11.0)
|
|
70
|
+
devpack (~> 0.1.2)
|
|
67
71
|
i18n (~> 1.7)
|
|
68
|
-
rake (~>
|
|
72
|
+
rake (~> 13.0)
|
|
69
73
|
rspec-html!
|
|
70
74
|
rspec-its (~> 1.3)
|
|
71
|
-
rubocop (~> 0.
|
|
75
|
+
rubocop (~> 0.89.1)
|
|
72
76
|
rubocop-rspec (~> 1.36)
|
|
73
|
-
strong_versions (~> 0.
|
|
77
|
+
strong_versions (~> 0.4.5)
|
|
74
78
|
|
|
75
79
|
BUNDLED WITH
|
|
76
80
|
2.0.2
|
data/README.md
CHANGED
|
@@ -4,18 +4,17 @@ _RSpec::HTML_ provides a simple object interface to HTML responses from [_RSpec
|
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
+
Add the gem to your `Gemfile`:
|
|
8
|
+
|
|
7
9
|
```ruby
|
|
8
|
-
gem 'rspec-html', '~> 0.
|
|
10
|
+
gem 'rspec-html', '~> 0.2.3'
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
And then execute:
|
|
13
|
-
|
|
14
|
-
$ bundle
|
|
13
|
+
And rebuild your bundle:
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
```bash
|
|
16
|
+
$ bundle install
|
|
17
|
+
```
|
|
19
18
|
|
|
20
19
|
## Usage
|
|
21
20
|
|
|
@@ -26,19 +25,118 @@ Require the gem in your `spec_helper.rb`:
|
|
|
26
25
|
require 'rspec/html'
|
|
27
26
|
```
|
|
28
27
|
|
|
29
|
-
|
|
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
|
+
### Object Interface
|
|
31
|
+
<a name="object-interface"></a>
|
|
32
|
+
|
|
33
|
+
The top-level object `document` is available in all tests which reflects the current response body (e.g. in request specs).
|
|
34
|
+
|
|
35
|
+
If you need to parse _HTML_ manually you can use the provided `parse_html` helper and then access `document` as normal:
|
|
30
36
|
|
|
31
37
|
```ruby
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
expect(document.body).to include 'something'
|
|
36
|
-
expect(document.body).to have_css 'html body div.myclass'
|
|
37
|
-
expect(document.body).to have_xpath '//html/body/div[@class="myclass"]'
|
|
38
|
-
end
|
|
38
|
+
before { parse_html('<html><body>hello</body></html>') }
|
|
39
|
+
it 'says hello' do
|
|
40
|
+
expect(document.body).to contain_text 'hello'
|
|
39
41
|
end
|
|
40
42
|
```
|
|
41
43
|
|
|
44
|
+
To navigate the _DOM_ by a sequence of tag names use chained method calls on the `document` object:
|
|
45
|
+
|
|
46
|
+
#### Tag Traversal
|
|
47
|
+
```ruby
|
|
48
|
+
expect(document.body.div.span).to contain_text 'some text'
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
#### Attribute Matching
|
|
52
|
+
To select an element matching certain attributes pass a hash to any of the chained methods:
|
|
53
|
+
```ruby
|
|
54
|
+
expect(document.body.div(id: 'my-div').span(align: 'left')).to contain_text 'some text'
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
#### Class Matching
|
|
58
|
+
_CSS_ classes are treated as a special case: to select an element matching a set of classes pass the `class` parameter:
|
|
59
|
+
```ruby
|
|
60
|
+
expect(document.body.div(id: 'my-div').span(class: 'my-class')).to contain_text 'some text'
|
|
61
|
+
expect(document.body.div(id: 'my-div').span(class: 'my-class my-other-class')).to contain_text 'some text'
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Classes can be provided in any order, i.e. `'my-class my-other-class'` is equivalent to `'my-other-class my-class'`.
|
|
65
|
+
|
|
66
|
+
#### Text Matching
|
|
67
|
+
To select an element that includes a given text string (i.e. excluding mark-up) use the `text` option:
|
|
68
|
+
```ruby
|
|
69
|
+
expect(document.body.div(text: 'some text').input[:value]).to eql 'some-value'
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
#### Attribute Retrieval
|
|
73
|
+
To select an attribute from an element use the hash-style interface:
|
|
74
|
+
```ruby
|
|
75
|
+
expect(document.body.div.span[:class]).to contain_text 'my-class'
|
|
76
|
+
expect(document.body.div.span['data-content']).to contain_text 'my content'
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
#### Indexing a Matching Set
|
|
80
|
+
To select an index from a set of matched elements use the array-style interface (the first matching element is `1`, not `0`):
|
|
81
|
+
```ruby
|
|
82
|
+
expect(document.body.div[1].span[1][:class]).to contain_text 'my-class'
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
#### Element Existence
|
|
86
|
+
To test if a matching element was found use the `exist` matcher:
|
|
87
|
+
```ruby
|
|
88
|
+
expect(document.body.div[1]).to exist
|
|
89
|
+
expect(document.body.div[4]).to_not exist
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### Length of matched attributes
|
|
93
|
+
To test the length of matched elements use the `#size` or `#length` method:
|
|
94
|
+
```ruby
|
|
95
|
+
expect(document.body.div.size).to eql 3
|
|
96
|
+
expect(document.body.div.length).to eql 3
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
#### XPath / CSS Selectors
|
|
100
|
+
If you need something more specific you can always use the _Nokogiri_ `#xpath` and `#css` methods on any element:
|
|
101
|
+
```ruby
|
|
102
|
+
expect(document.body.xpath('//span[@class="my-class"]')).to contain_text 'some text'
|
|
103
|
+
expect(document.body.css('span.my-class')).to contain_text 'some text'
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
To simply check that an _XPath_ or _CSS_ selector exists use `have_xpath` and `have_css`:
|
|
107
|
+
```ruby
|
|
108
|
+
expect(document.body).to have_css 'html body div.myclass'
|
|
109
|
+
expect(document.body).to have_xpath '//html/body/div[@class="myclass"]'
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Custom Matchers
|
|
113
|
+
<a name="matchers"></a>
|
|
114
|
+
|
|
115
|
+
#### contain_text
|
|
116
|
+
|
|
117
|
+
Use the `contain_text` matcher to locate text within a _DOM_ element. All mark-up elements are stripped when using this matcher.
|
|
118
|
+
|
|
119
|
+
```ruby
|
|
120
|
+
expect(document.body.form).to contain_text 'Please enter your password'
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
#### contain_tag
|
|
124
|
+
|
|
125
|
+
Use the `contain_tag` matcher to locate _DOM_ elements within any given element. This matcher accepts two arguments:
|
|
126
|
+
|
|
127
|
+
* The tag name of the element you want to match (e.g. `:div`);
|
|
128
|
+
* _(Optional)_ A hash of options. All options supported by the [object interface](#object-interface) can be used here.
|
|
129
|
+
|
|
130
|
+
Without options:
|
|
131
|
+
```ruby
|
|
132
|
+
expect(document.div(class: 'my-class')).to contain_tag :span
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
With options:
|
|
136
|
+
```ruby
|
|
137
|
+
expect(document.form(class: 'my-form')).to contain_tag :input, name: 'email', class: 'email-input'
|
|
138
|
+
```
|
|
139
|
+
|
|
42
140
|
## Contributing
|
|
43
141
|
|
|
44
142
|
Feel free to make a pull request.
|
data/lib/rspec/html.rb
CHANGED
|
@@ -9,7 +9,17 @@ module RSpec
|
|
|
9
9
|
# Module extension for RSpec::SharedContext
|
|
10
10
|
module HTML
|
|
11
11
|
def document
|
|
12
|
-
|
|
12
|
+
return @document if @document
|
|
13
|
+
|
|
14
|
+
if !defined?(response) || response.nil?
|
|
15
|
+
raise RSpecHTML::NoResponseError, 'No `response` object found. Make a request first.'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
RSpecHTML::Element.new(Nokogiri::HTML.parse(response.body), :document)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def parse_html(content)
|
|
22
|
+
@document = RSpecHTML::Element.new(Nokogiri::HTML.parse(content), :document)
|
|
13
23
|
end
|
|
14
24
|
end
|
|
15
25
|
end
|
data/lib/rspec/html/version.rb
CHANGED
data/lib/rspec_html.rb
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'nokogiri'
|
|
4
|
+
|
|
4
5
|
require 'pathname'
|
|
6
|
+
require 'forwardable'
|
|
5
7
|
|
|
6
|
-
require 'rspec_html/
|
|
7
|
-
require 'rspec_html/
|
|
8
|
-
require 'rspec_html/
|
|
9
|
-
require 'rspec_html/
|
|
10
|
-
require 'rspec_html/
|
|
11
|
-
require 'rspec_html/title'
|
|
8
|
+
require 'rspec_html/tags'
|
|
9
|
+
require 'rspec_html/element'
|
|
10
|
+
require 'rspec_html/search'
|
|
11
|
+
require 'rspec_html/reconstituted_element'
|
|
12
|
+
require 'rspec_html/matchers'
|
|
12
13
|
|
|
13
14
|
# Support module for rspec/html
|
|
14
15
|
module RSpecHTML
|
|
16
|
+
class Error < StandardError; end
|
|
17
|
+
class NoResponseError < Error; end
|
|
15
18
|
def self.root
|
|
16
19
|
Pathname.new(__dir__).parent
|
|
17
20
|
end
|
|
18
21
|
end
|
|
22
|
+
|
|
23
|
+
RSpec.configure { |config| config.include RSpecHTML::Matchers }
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RSpecHTML
|
|
4
|
+
# HTML DOM element abstraction
|
|
5
|
+
class Element
|
|
6
|
+
attr_reader :name, :element
|
|
7
|
+
|
|
8
|
+
extend Forwardable
|
|
9
|
+
|
|
10
|
+
def_delegators :@search,
|
|
11
|
+
:has_css?, :has_xpath?, :include?, :present?, :exist?,
|
|
12
|
+
:text, :size, :length, :[]
|
|
13
|
+
|
|
14
|
+
def initialize(element, name, options: {}, siblings: [])
|
|
15
|
+
@name = name
|
|
16
|
+
@element = element
|
|
17
|
+
@options = options
|
|
18
|
+
@siblings = siblings
|
|
19
|
+
@search = Search.new(@element, @siblings)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def inspect
|
|
23
|
+
"<#{self.class}::#{name.to_s.capitalize}>"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_s
|
|
27
|
+
@element.to_s
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
Tags.each do |tag|
|
|
31
|
+
define_method tag.downcase do |*args|
|
|
32
|
+
options = args.first
|
|
33
|
+
return @search.new_from_find(tag.downcase, options) if options.nil?
|
|
34
|
+
|
|
35
|
+
@search.new_from_where(tag.downcase, options)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def reconstituted
|
|
40
|
+
self.class.reconstituted(name, @options)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.reconstituted(tag, options = {})
|
|
44
|
+
ReconstitutedElement.new(tag, options).to_s
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rspec_html/matchers/base'
|
|
4
|
+
require 'rspec_html/matchers/contain_text'
|
|
5
|
+
require 'rspec_html/matchers/contain_tag'
|
|
6
|
+
|
|
7
|
+
module RSpecHTML
|
|
8
|
+
# Provides matchers for identifying elements and text within a DOM element.
|
|
9
|
+
module Matchers
|
|
10
|
+
extend RSpec::Matchers::DSL
|
|
11
|
+
extend RSpec::Matchers::DSL::Macros
|
|
12
|
+
|
|
13
|
+
# rubocop:disable Metrics/MethodLength
|
|
14
|
+
def self.define_matcher(name, class_)
|
|
15
|
+
matcher name do |expected, options|
|
|
16
|
+
rspec_html_matcher = class_.new(expected, options || {})
|
|
17
|
+
match do |actual|
|
|
18
|
+
rspec_html_matcher
|
|
19
|
+
.save_actual(actual)
|
|
20
|
+
.match(actual)
|
|
21
|
+
.tap { @actual = rspec_html_matcher.rspec_actual }
|
|
22
|
+
end
|
|
23
|
+
description { rspec_html_matcher.description }
|
|
24
|
+
failure_message { rspec_html_matcher.failure_message }
|
|
25
|
+
diffable if class_.diffable?
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
# rubocop:enable Metrics/MethodLength
|
|
29
|
+
|
|
30
|
+
define_matcher(:contain_text, ContainText)
|
|
31
|
+
define_matcher(:contain_tag, ContainTag)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RSpecHTML
|
|
4
|
+
module Matchers
|
|
5
|
+
# Mix-in class to provide a uniform interface and message templating for all matchers.
|
|
6
|
+
module Base
|
|
7
|
+
def self.included(base)
|
|
8
|
+
base.class_eval do
|
|
9
|
+
class << self
|
|
10
|
+
def diffable
|
|
11
|
+
@diffable = true
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def diffable?
|
|
15
|
+
@diffable
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
attr_reader :rspec_actual
|
|
22
|
+
|
|
23
|
+
def initialize(expected, options)
|
|
24
|
+
@expected = expected
|
|
25
|
+
@options = options
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def description
|
|
29
|
+
template(:description, @options, @expected)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def failure_message
|
|
33
|
+
template(:failure, @options, @expected, @actual)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def save_actual(actual)
|
|
37
|
+
@actual = actual
|
|
38
|
+
self
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def reconstituted(element, options)
|
|
42
|
+
RSpecHTML::Element.reconstituted(element, options)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def template(type, options, expected, actual = nil)
|
|
48
|
+
ERB.new(template_path(type).read).result(binding)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def template_path(type)
|
|
52
|
+
RSpecHTML.root.join('templates', type.to_s, "#{filename}.erb")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def filename
|
|
56
|
+
_, _, name = self.class.name.rpartition('::')
|
|
57
|
+
(name[0] + name[1..].gsub(/(.)([A-Z])/, '\1_\2')).downcase
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RSpecHTML
|
|
4
|
+
module Matchers
|
|
5
|
+
# Matches elements within a given DOM element.
|
|
6
|
+
class ContainTag
|
|
7
|
+
include Base
|
|
8
|
+
|
|
9
|
+
def match(actual)
|
|
10
|
+
@actual = actual.to_s
|
|
11
|
+
actual.public_send(@expected, @options).present?
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RSpecHTML
|
|
4
|
+
module Matchers
|
|
5
|
+
# Matches text within a given DOM element.
|
|
6
|
+
class ContainText
|
|
7
|
+
include Base
|
|
8
|
+
|
|
9
|
+
diffable
|
|
10
|
+
|
|
11
|
+
def match(actual)
|
|
12
|
+
@rspec_actual = actual&.text
|
|
13
|
+
(actual&.text || '').include?(@expected.to_s)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RSpecHTML
|
|
4
|
+
# Reconstructs an HTML representation of an element from provided parameters.
|
|
5
|
+
class ReconstitutedElement
|
|
6
|
+
def initialize(tag, options)
|
|
7
|
+
@tag = tag
|
|
8
|
+
@options = options
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def to_s
|
|
12
|
+
name = @tag.to_s.downcase
|
|
13
|
+
return '#document' if name == 'document'
|
|
14
|
+
return name if name == 'document'
|
|
15
|
+
return "<#{name}#{formatted_attributes} />" unless @options&.key?(:text)
|
|
16
|
+
|
|
17
|
+
"<#{name}#{formatted_attributes}>#{@options[:text]}</#{name}>"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def mapped_attributes
|
|
23
|
+
return [] if @options.nil?
|
|
24
|
+
|
|
25
|
+
@options.reject { |key| key.to_sym == :text }.map do |key, value|
|
|
26
|
+
next %(#{key}="#{value}") unless key.to_sym == :class && value.is_a?(Array)
|
|
27
|
+
|
|
28
|
+
%(#{key}="#{value.join(' ')}")
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def formatted_attributes
|
|
33
|
+
mapped_attributes.empty? ? nil : " #{mapped_attributes.join(' ')}"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RSpecHTML
|
|
4
|
+
# Provides element/attribute/text searching for HTML entities
|
|
5
|
+
class Search
|
|
6
|
+
def initialize(element, siblings)
|
|
7
|
+
@element = element
|
|
8
|
+
@siblings = siblings
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def include?(val)
|
|
12
|
+
text.include?(val)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def css(*args)
|
|
16
|
+
self.class.new(@element&.css(*args), :css)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def xpath(*args)
|
|
20
|
+
self.class.new(@element&.xpath(*args), :xpath)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def present?
|
|
24
|
+
!@element.nil?
|
|
25
|
+
end
|
|
26
|
+
alias exist? present?
|
|
27
|
+
|
|
28
|
+
# rubocop:disable Naming/PredicateName
|
|
29
|
+
def has_css?(*args)
|
|
30
|
+
!@element&.css(*args)&.empty?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def has_xpath?(*args)
|
|
34
|
+
!@element&.xpath(*args)&.empty?
|
|
35
|
+
end
|
|
36
|
+
# rubocop:enable Naming/PredicateName
|
|
37
|
+
|
|
38
|
+
def [](val)
|
|
39
|
+
return index(val) if val.is_a?(Integer)
|
|
40
|
+
return range(val) if val.is_a?(Range)
|
|
41
|
+
|
|
42
|
+
@element&.attr(val.to_s)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def text
|
|
46
|
+
@element&.text&.gsub(/\s+/, ' ')&.strip || ''
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def size
|
|
50
|
+
return @element.size if @element.respond_to?(:size)
|
|
51
|
+
|
|
52
|
+
@siblings.size
|
|
53
|
+
end
|
|
54
|
+
alias length size
|
|
55
|
+
|
|
56
|
+
def new_from_find(tag, options)
|
|
57
|
+
Element.new(
|
|
58
|
+
find(tag),
|
|
59
|
+
tag,
|
|
60
|
+
options: options,
|
|
61
|
+
siblings: find(tag, all: true)
|
|
62
|
+
)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def new_from_where(tag, options)
|
|
66
|
+
Element.new(
|
|
67
|
+
where(tag, options),
|
|
68
|
+
tag,
|
|
69
|
+
options: options,
|
|
70
|
+
siblings: where(tag, options, all: true)
|
|
71
|
+
)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def index(val)
|
|
77
|
+
zero_index_error if val.zero?
|
|
78
|
+
self.class.new(@siblings[val - 1], @element.name)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def range(val)
|
|
82
|
+
zero_index_error if val.first.zero?
|
|
83
|
+
self.class.new(@siblings[(val.first - 1)..(val.last - 1)], :range)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def zero_index_error
|
|
87
|
+
raise ArgumentError, 'Index for matched sets starts at 1, not 0.'
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def where(tag, query, all: false)
|
|
91
|
+
matched = if query[:class]
|
|
92
|
+
where_class(tag, query[:class]) & where_xpath(tag, query.merge(class: nil))
|
|
93
|
+
else
|
|
94
|
+
where_xpath(tag, query)
|
|
95
|
+
end
|
|
96
|
+
return matched&.first unless all
|
|
97
|
+
|
|
98
|
+
matched
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def where_xpath(tag, query)
|
|
102
|
+
conditions = "[#{where_conditions(query)}]" unless query.compact.empty?
|
|
103
|
+
@element&.xpath("//#{tag}#{conditions}")
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def where_conditions(query)
|
|
107
|
+
query.compact.map do |key, value|
|
|
108
|
+
next if value.nil?
|
|
109
|
+
next %(@#{key}="#{value}") unless key == :text
|
|
110
|
+
|
|
111
|
+
%[contains(text(),"#{value}")]
|
|
112
|
+
end.join ' and '
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def where_class(tag, class_or_classes)
|
|
116
|
+
classes = class_or_classes.is_a?(Array) ? class_or_classes : class_or_classes.to_s.split
|
|
117
|
+
selector = classes.map(&:to_s).join('.')
|
|
118
|
+
@element&.css("#{tag}.#{selector}")
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def find(tag, all: false)
|
|
122
|
+
return @element&.css(tag.to_s)&.first unless all
|
|
123
|
+
|
|
124
|
+
@element&.css(tag.to_s)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RSpecHTML
|
|
4
|
+
# HTML tag identification, used to determine viability for DOM traversal via chained methods.
|
|
5
|
+
class Tags
|
|
6
|
+
def self.include?(val)
|
|
7
|
+
tags.include?(val.to_s.upcase)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.each(&block)
|
|
11
|
+
tags.each { |tag| block.call(tag) }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# rubocop:disable Metrics/MethodLength
|
|
15
|
+
def self.tags
|
|
16
|
+
%w[
|
|
17
|
+
A ABBR ACRONYM ADDRESS APPLET AREA ARTICLE ASIDE AUDIO B BASE BASEFONT BDI BDO BGSOUND
|
|
18
|
+
BIG BLINK BLOCKQUOTE BODY BR BUTTON CANVAS CAPTION CENTER CITE CODE COL COLGROUP COMMAND
|
|
19
|
+
CONTENT DATA DATALIST DD DEL DETAILS DFN DIALOG DIR DIV DL DT ELEMENT EM EMBED FIELDSET
|
|
20
|
+
FIGCAPTION FIGURE FONT FOOTER FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HEADER HGROUP HR
|
|
21
|
+
HTML I IFRAME IMAGE IMG INPUT INS ISINDEX KBD KEYGEN LABEL LEGEND LI LINK LISTING MAIN
|
|
22
|
+
MAIN MAP MARK MARQUEE MENU MENUITEM META METER MULTICOL NAV NEXTID NOBR NOEMBED NOFRAMES
|
|
23
|
+
NOSCRIPT OBJECT OL OPTGROUP OPTION OUTPUT P PARAM PICTURE PLAINTEXT PRE PROGRESS Q RB RP
|
|
24
|
+
RT RTC RUBY S SAMP SCRIPT SECTION SELECT SHADOW SLOT SMALL SOURCE SPACER SPAN STRIKE
|
|
25
|
+
STRONG STYLE SUB SUMMARY SUP TABLE TBODY TD TEMPLATE TEXTAREA TFOOT TH THEAD TIME TITLE
|
|
26
|
+
TR TRACK TT U UL VAR VIDEO WBR XMP
|
|
27
|
+
]
|
|
28
|
+
end
|
|
29
|
+
# rubocop:enable Metrics/MethodLength
|
|
30
|
+
end
|
|
31
|
+
end
|
data/rspec-html.gemspec
CHANGED
|
@@ -31,13 +31,13 @@ Gem::Specification.new do |spec|
|
|
|
31
31
|
spec.add_dependency 'nokogiri', '~> 1.10'
|
|
32
32
|
spec.add_dependency 'rspec', '~> 3.0'
|
|
33
33
|
|
|
34
|
-
spec.add_development_dependency 'betterp', '~> 0.1.3'
|
|
35
34
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
|
36
35
|
spec.add_development_dependency 'byebug', '~> 11.0'
|
|
36
|
+
spec.add_development_dependency 'devpack', '~> 0.1.2'
|
|
37
37
|
spec.add_development_dependency 'i18n', '~> 1.7'
|
|
38
|
-
spec.add_development_dependency 'rake', '~>
|
|
38
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
|
39
39
|
spec.add_development_dependency 'rspec-its', '~> 1.3'
|
|
40
|
-
spec.add_development_dependency 'rubocop', '~> 0.
|
|
40
|
+
spec.add_development_dependency 'rubocop', '~> 0.89.1'
|
|
41
41
|
spec.add_development_dependency 'rubocop-rspec', '~> 1.36'
|
|
42
|
-
spec.add_development_dependency 'strong_versions', '~> 0.
|
|
42
|
+
spec.add_development_dependency 'strong_versions', '~> 0.4.5'
|
|
43
43
|
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
contain tag <%= RSpecHTML::Element.reconstituted(expected, @options) %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
contain text <%= expected.inspect %>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<% if actual.element.nil? %>
|
|
2
|
+
Expected <%= reconstituted(actual, @options) %> to contain <%= reconstituted(expected, @options) %> but the element did not exist.
|
|
3
|
+
<% else %>
|
|
4
|
+
Expected <%= reconstituted(actual, @options) %> to contain <%= reconstituted(expected, @options) %> but it did not.
|
|
5
|
+
<% end %>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<% if actual.element.nil? %>
|
|
2
|
+
Expected <%= actual.reconstituted %> to contain <%= expected.inspect %> but the element did not exist.
|
|
3
|
+
<% else %>
|
|
4
|
+
Expected text in <%= actual.reconstituted %> <%= (actual.text&.strip || '').inspect %> to contain <%= expected.inspect %> but it did not.
|
|
5
|
+
<% end %>
|
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.
|
|
4
|
+
version: 0.2.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bob Farrell
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-
|
|
11
|
+
date: 2020-08-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: nokogiri
|
|
@@ -39,47 +39,47 @@ dependencies:
|
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '3.0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
42
|
+
name: bundler
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: 0
|
|
47
|
+
version: '2.0'
|
|
48
48
|
type: :development
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: 0
|
|
54
|
+
version: '2.0'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name:
|
|
56
|
+
name: byebug
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
59
|
- - "~>"
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: '
|
|
61
|
+
version: '11.0'
|
|
62
62
|
type: :development
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: '
|
|
68
|
+
version: '11.0'
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
|
-
name:
|
|
70
|
+
name: devpack
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
72
72
|
requirements:
|
|
73
73
|
- - "~>"
|
|
74
74
|
- !ruby/object:Gem::Version
|
|
75
|
-
version:
|
|
75
|
+
version: 0.1.2
|
|
76
76
|
type: :development
|
|
77
77
|
prerelease: false
|
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
79
|
requirements:
|
|
80
80
|
- - "~>"
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
|
-
version:
|
|
82
|
+
version: 0.1.2
|
|
83
83
|
- !ruby/object:Gem::Dependency
|
|
84
84
|
name: i18n
|
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -100,14 +100,14 @@ dependencies:
|
|
|
100
100
|
requirements:
|
|
101
101
|
- - "~>"
|
|
102
102
|
- !ruby/object:Gem::Version
|
|
103
|
-
version: '
|
|
103
|
+
version: '13.0'
|
|
104
104
|
type: :development
|
|
105
105
|
prerelease: false
|
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
|
107
107
|
requirements:
|
|
108
108
|
- - "~>"
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
|
-
version: '
|
|
110
|
+
version: '13.0'
|
|
111
111
|
- !ruby/object:Gem::Dependency
|
|
112
112
|
name: rspec-its
|
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -128,14 +128,14 @@ dependencies:
|
|
|
128
128
|
requirements:
|
|
129
129
|
- - "~>"
|
|
130
130
|
- !ruby/object:Gem::Version
|
|
131
|
-
version: 0.
|
|
131
|
+
version: 0.89.1
|
|
132
132
|
type: :development
|
|
133
133
|
prerelease: false
|
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
|
135
135
|
requirements:
|
|
136
136
|
- - "~>"
|
|
137
137
|
- !ruby/object:Gem::Version
|
|
138
|
-
version: 0.
|
|
138
|
+
version: 0.89.1
|
|
139
139
|
- !ruby/object:Gem::Dependency
|
|
140
140
|
name: rubocop-rspec
|
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -156,14 +156,14 @@ dependencies:
|
|
|
156
156
|
requirements:
|
|
157
157
|
- - "~>"
|
|
158
158
|
- !ruby/object:Gem::Version
|
|
159
|
-
version: 0.
|
|
159
|
+
version: 0.4.5
|
|
160
160
|
type: :development
|
|
161
161
|
prerelease: false
|
|
162
162
|
version_requirements: !ruby/object:Gem::Requirement
|
|
163
163
|
requirements:
|
|
164
164
|
- - "~>"
|
|
165
165
|
- !ruby/object:Gem::Version
|
|
166
|
-
version: 0.
|
|
166
|
+
version: 0.4.5
|
|
167
167
|
description: HTML document abstraction and matchers for RSpec
|
|
168
168
|
email:
|
|
169
169
|
- git@bob.frl
|
|
@@ -187,13 +187,19 @@ files:
|
|
|
187
187
|
- lib/rspec/html.rb
|
|
188
188
|
- lib/rspec/html/version.rb
|
|
189
189
|
- lib/rspec_html.rb
|
|
190
|
-
- lib/rspec_html/
|
|
191
|
-
- lib/rspec_html/
|
|
192
|
-
- lib/rspec_html/
|
|
193
|
-
- lib/rspec_html/
|
|
194
|
-
- lib/rspec_html/
|
|
195
|
-
- lib/rspec_html/
|
|
190
|
+
- lib/rspec_html/element.rb
|
|
191
|
+
- lib/rspec_html/matchers.rb
|
|
192
|
+
- lib/rspec_html/matchers/base.rb
|
|
193
|
+
- lib/rspec_html/matchers/contain_tag.rb
|
|
194
|
+
- lib/rspec_html/matchers/contain_text.rb
|
|
195
|
+
- lib/rspec_html/reconstituted_element.rb
|
|
196
|
+
- lib/rspec_html/search.rb
|
|
197
|
+
- lib/rspec_html/tags.rb
|
|
196
198
|
- rspec-html.gemspec
|
|
199
|
+
- templates/description/contain_tag.erb
|
|
200
|
+
- templates/description/contain_text.erb
|
|
201
|
+
- templates/failure/contain_tag.erb
|
|
202
|
+
- templates/failure/contain_text.erb
|
|
197
203
|
homepage: https://github.com/bobf/rspec-html
|
|
198
204
|
licenses:
|
|
199
205
|
- MIT
|
data/lib/rspec_html/body.rb
DELETED
data/lib/rspec_html/document.rb
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module RSpecHTML
|
|
4
|
-
# HTML Document representation
|
|
5
|
-
class Document
|
|
6
|
-
def initialize(html)
|
|
7
|
-
@html = html
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
# rubocop:disable Naming/PredicateName
|
|
11
|
-
def has_xpath?(*args)
|
|
12
|
-
!parsed_html.xpath(*args).empty?
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def has_css?(*args)
|
|
16
|
-
!parsed_html.css(*args).empty?
|
|
17
|
-
end
|
|
18
|
-
# rubocop:enable Naming/PredicateName
|
|
19
|
-
|
|
20
|
-
def body
|
|
21
|
-
Body.new(parsed_html)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def head
|
|
25
|
-
Head.new(parsed_html)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
private
|
|
29
|
-
|
|
30
|
-
def parsed_html
|
|
31
|
-
@parsed_html ||= Nokogiri::HTML(@html)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
data/lib/rspec_html/head.rb
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module RSpecHTML
|
|
4
|
-
# HTML/BODY abstraction
|
|
5
|
-
class Head
|
|
6
|
-
include Nameable
|
|
7
|
-
|
|
8
|
-
def initialize(parsed_html)
|
|
9
|
-
@parsed_html = parsed_html
|
|
10
|
-
@entity = parsed_html.css('head')
|
|
11
|
-
@name = :head
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def title
|
|
15
|
-
Title.new(@parsed_html)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def include?(val)
|
|
19
|
-
title.include?(val)
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
data/lib/rspec_html/nameable.rb
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module RSpecHTML
|
|
4
|
-
# Mixin module providing methods for searching text content of HTML entities
|
|
5
|
-
module Searchable
|
|
6
|
-
def include?(val)
|
|
7
|
-
@entity.text.include?(val)
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def to_s
|
|
11
|
-
@entity.text.strip
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def inspect
|
|
15
|
-
%("#{self}")
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
data/lib/rspec_html/title.rb
DELETED