xpath 2.1.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ce787a09ca48f5c96580cbced2533d00b741a0e3
4
- data.tar.gz: c4310006453b0029c593077b225d36e79dfd35af
3
+ metadata.gz: ae41f677ac864edf9c7689365012dc5f73731f61
4
+ data.tar.gz: 63f10b70109aa842ac464b8491071a286b583f4c
5
5
  SHA512:
6
- metadata.gz: 83b64861c13aecd52661c7cbc598f90c4a17aeb71c86936f0bec36d97ffe4248fc8302cad434742b95074b6aded1de563c33a3f82df12e4baf42d10c42d132ac
7
- data.tar.gz: bc2e7c29f1240475904601bc7f8ad2ecda2978536b97e1ab407bc855ec16b7f64b48cc49400a501833bb8ac643bcc8b1e2052d4a05974c3df7ca0355ac26fe4e
6
+ metadata.gz: 7683342805b10e97fcb6593148c0beedb6ad43b7087915697b4a87b4127d88d1669e9e3d6a630a019a500c2203eff4a8b6c702e8bedb313ee41ca1ad726be446
7
+ data.tar.gz: 4d9146f6cd818e364b94b95f219d40a70571c33a01faa58af9feccb7d3f40d7f0e1b0d9093ef1aec4aae2429859001fa15e341a032a4248575804886e0fd8344
@@ -5,7 +5,6 @@ require 'xpath/expression'
5
5
  require 'xpath/literal'
6
6
  require 'xpath/union'
7
7
  require 'xpath/renderer'
8
- require 'xpath/html'
9
8
 
10
9
  module XPath
11
10
  extend XPath::DSL
@@ -68,7 +68,7 @@ module XPath
68
68
 
69
69
  METHODS = [
70
70
  # node set
71
- :count, :id, :local_name, :namespace_uri, :name,
71
+ :count, :id, :local_name, :namespace_uri,
72
72
  # string
73
73
  :string, :concat, :starts_with, :contains, :substring_before,
74
74
  :substring_after, :substring, :string_length, :normalize_space,
@@ -86,8 +86,13 @@ module XPath
86
86
  end
87
87
  end
88
88
 
89
+ def qname
90
+ method(:name)
91
+ end
92
+
89
93
  alias_method :inverse, :not
90
94
  alias_method :~, :not
95
+ alias_method :!, :not
91
96
  alias_method :normalize, :normalize_space
92
97
  alias_method :n, :normalize_space
93
98
 
@@ -95,6 +100,7 @@ module XPath
95
100
  [:equals, :"=", :==],
96
101
  [:or, :or, :|],
97
102
  [:and, :and, :&],
103
+ [:not_equals, :!=, :!=],
98
104
  [:lte, :<=, :<=],
99
105
  [:lt, :<, :<],
100
106
  [:gte, :>=, :>=],
@@ -128,6 +134,10 @@ module XPath
128
134
 
129
135
  alias_method :self_axis, :self
130
136
 
137
+ def contains_word(word)
138
+ function(:concat, " ", current.normalize_space, " ").contains(" #{word} ")
139
+ end
140
+
131
141
  def one_of(*expressions)
132
142
  expressions.map do |e|
133
143
  current.equals(e)
@@ -1,3 +1,3 @@
1
1
  module XPath
2
- VERSION = '2.1.0'
2
+ VERSION = '3.0.0'
3
3
  end
@@ -17,7 +17,7 @@
17
17
 
18
18
  <div id="woo" title="wooDiv" data="id">
19
19
  <ul><li>A list</li></ul>
20
- <p title="gorilla">Bax</p>
20
+ <p class="cat fish dog" title="gorilla">Bax</p>
21
21
  <p>Bax</p>
22
22
  <p id="wooDiv">Blah</p>
23
23
  </div>
@@ -26,7 +26,7 @@
26
26
 
27
27
  <div id="preference">
28
28
  <p id="is-fuzzy">allamas</p>
29
- <p id="is-exact">llama</p>
29
+ <p class="fish" id="is-exact">llama</p>
30
30
  </div>
31
31
 
32
32
  <p id="whitespace">
@@ -37,7 +37,7 @@
37
37
  </p>
38
38
 
39
39
  <div id="moar">
40
- <p id="impchay">chimp</p>
40
+ <p class="catfish" id="impchay">chimp</p>
41
41
  <div id="elephantay">elephant</div>
42
42
  <p id="amingoflay">flamingo</p>
43
43
  </div>
@@ -9,7 +9,7 @@ describe XPath::Union do
9
9
  @expr1 = XPath.generate { |x| x.descendant(:p) }
10
10
  @expr2 = XPath.generate { |x| x.descendant(:div) }
11
11
  @collection = XPath::Union.new(@expr1, @expr2)
12
- @collection.expressions.should == [@expr1, @expr2]
12
+ @collection.expressions.should eq [@expr1, @expr2]
13
13
  end
14
14
  end
15
15
 
@@ -20,7 +20,7 @@ describe XPath::Union do
20
20
  @collection = XPath::Union.new(@expr1, @expr2)
21
21
  exprs = []
22
22
  @collection.each { |expr| exprs << expr }
23
- exprs.should == [@expr1, @expr2]
23
+ exprs.should eq [@expr1, @expr2]
24
24
  end
25
25
  end
26
26
 
@@ -29,7 +29,7 @@ describe XPath::Union do
29
29
  @expr1 = XPath.generate { |x| x.descendant(:p) }
30
30
  @expr2 = XPath.generate { |x| x.descendant(:div) }
31
31
  @collection = XPath::Union.new(@expr1, @expr2)
32
- @collection.map { |expr| expr.expression }.should == [:descendant, :descendant]
32
+ @collection.map { |expr| expr.expression }.should eq [:descendant, :descendant]
33
33
  end
34
34
  end
35
35
 
@@ -39,9 +39,9 @@ describe XPath::Union do
39
39
  @expr2 = XPath.generate { |x| x.descendant(:div).where(x.attr(:id) == 'foo') }
40
40
  @collection = XPath::Union.new(@expr1, @expr2)
41
41
  @results = doc.xpath(@collection.to_xpath)
42
- @results[0][:title].should == 'fooDiv'
43
- @results[1].text.should == 'Blah'
44
- @results[2].text.should == 'Bax'
42
+ @results[0][:title].should eq 'fooDiv'
43
+ @results[1].text.should eq 'Blah'
44
+ @results[2].text.should eq 'Bax'
45
45
  end
46
46
  end
47
47
 
@@ -54,9 +54,9 @@ describe XPath::Union do
54
54
  @xpath1 = @collection.where(XPath.attr(:id) == 'foo').to_xpath
55
55
  @xpath2 = @collection.where(XPath.attr(:id) == 'fooDiv').to_xpath
56
56
  @results = doc.xpath(@xpath1)
57
- @results[0][:title].should == 'fooDiv'
57
+ @results[0][:title].should eq 'fooDiv'
58
58
  @results = doc.xpath(@xpath2)
59
- @results[0][:id].should == 'fooDiv'
59
+ @results[0][:id].should eq 'fooDiv'
60
60
  end
61
61
  end
62
62
 
@@ -20,14 +20,14 @@ describe XPath do
20
20
 
21
21
  it "should work as a mixin" do
22
22
  xpath = Thingy.new.foo_div.to_xpath
23
- doc.xpath(xpath).first[:title].should == 'fooDiv'
23
+ doc.xpath(xpath).first[:title].should eq 'fooDiv'
24
24
  end
25
25
 
26
26
  describe '#descendant' do
27
27
  it "should find nodes that are nested below the current node" do
28
28
  @results = xpath { |x| x.descendant(:p) }
29
- @results[0].text.should == "Blah"
30
- @results[1].text.should == "Bax"
29
+ @results[0].text.should eq "Blah"
30
+ @results[1].text.should eq "Bax"
31
31
  end
32
32
 
33
33
  it "should not find nodes outside the context" do
@@ -40,22 +40,22 @@ describe XPath do
40
40
 
41
41
  it "should find multiple kinds of nodes" do
42
42
  @results = xpath { |x| x.descendant(:p, :ul) }
43
- @results[0].text.should == 'Blah'
44
- @results[3].text.should == 'A list'
43
+ @results[0].text.should eq 'Blah'
44
+ @results[3].text.should eq 'A list'
45
45
  end
46
46
 
47
47
  it "should find all nodes when no arguments given" do
48
48
  @results = xpath { |x| x.descendant[x.attr(:id) == 'foo'].descendant }
49
- @results[0].text.should == 'Blah'
50
- @results[4].text.should == 'A list'
49
+ @results[0].text.should eq 'Blah'
50
+ @results[4].text.should eq 'A list'
51
51
  end
52
52
  end
53
53
 
54
54
  describe '#child' do
55
55
  it "should find nodes that are nested directly below the current node" do
56
56
  @results = xpath { |x| x.descendant(:div).child(:p) }
57
- @results[0].text.should == "Blah"
58
- @results[1].text.should == "Bax"
57
+ @results[0].text.should eq "Blah"
58
+ @results[1].text.should eq "Bax"
59
59
  end
60
60
 
61
61
  it "should not find nodes that are nested further down below the current node" do
@@ -65,46 +65,46 @@ describe XPath do
65
65
 
66
66
  it "should find multiple kinds of nodes" do
67
67
  @results = xpath { |x| x.descendant(:div).child(:p, :ul) }
68
- @results[0].text.should == 'Blah'
69
- @results[3].text.should == 'A list'
68
+ @results[0].text.should eq 'Blah'
69
+ @results[3].text.should eq 'A list'
70
70
  end
71
71
 
72
72
  it "should find all nodes when no arguments given" do
73
73
  @results = xpath { |x| x.descendant[x.attr(:id) == 'foo'].child }
74
- @results[0].text.should == 'Blah'
75
- @results[3].text.should == 'A list'
74
+ @results[0].text.should eq 'Blah'
75
+ @results[3].text.should eq 'A list'
76
76
  end
77
77
  end
78
78
 
79
79
  describe '#axis' do
80
80
  it "should find nodes given the xpath axis" do
81
81
  @results = xpath { |x| x.axis(:descendant, :p) }
82
- @results[0].text.should == "Blah"
82
+ @results[0].text.should eq "Blah"
83
83
  end
84
84
 
85
85
  it "should find nodes given the xpath axis without a specific tag" do
86
86
  @results = xpath { |x| x.descendant(:div)[x.attr(:id) == 'foo'].axis(:descendant) }
87
- @results[0][:id].should == "fooDiv"
87
+ @results[0][:id].should eq "fooDiv"
88
88
  end
89
89
  end
90
90
 
91
91
  describe '#next_sibling' do
92
92
  it "should find nodes which are immediate siblings of the current node" do
93
- xpath { |x| x.descendant(:p)[x.attr(:id) == 'fooDiv'].next_sibling(:p) }.first.text.should == 'Bax'
94
- xpath { |x| x.descendant(:p)[x.attr(:id) == 'fooDiv'].next_sibling(:ul, :p) }.first.text.should == 'Bax'
95
- xpath { |x| x.descendant(:p)[x.attr(:title) == 'monkey'].next_sibling(:ul, :p) }.first.text.should == 'A list'
93
+ xpath { |x| x.descendant(:p)[x.attr(:id) == 'fooDiv'].next_sibling(:p) }.first.text.should eq 'Bax'
94
+ xpath { |x| x.descendant(:p)[x.attr(:id) == 'fooDiv'].next_sibling(:ul, :p) }.first.text.should eq 'Bax'
95
+ xpath { |x| x.descendant(:p)[x.attr(:title) == 'monkey'].next_sibling(:ul, :p) }.first.text.should eq 'A list'
96
96
  xpath { |x| x.descendant(:p)[x.attr(:id) == 'fooDiv'].next_sibling(:ul, :li) }.first.should be_nil
97
- xpath { |x| x.descendant(:p)[x.attr(:id) == 'fooDiv'].next_sibling }.first.text.should == 'Bax'
97
+ xpath { |x| x.descendant(:p)[x.attr(:id) == 'fooDiv'].next_sibling }.first.text.should eq 'Bax'
98
98
  end
99
99
  end
100
100
 
101
101
  describe '#previous_sibling' do
102
102
  it "should find nodes which are exactly preceding the current node" do
103
- xpath { |x| x.descendant(:p)[x.attr(:id) == 'wooDiv'].previous_sibling(:p) }.first.text.should == 'Bax'
104
- xpath { |x| x.descendant(:p)[x.attr(:id) == 'wooDiv'].previous_sibling(:ul, :p) }.first.text.should == 'Bax'
105
- xpath { |x| x.descendant(:p)[x.attr(:title) == 'gorilla'].previous_sibling(:ul, :p) }.first.text.should == 'A list'
103
+ xpath { |x| x.descendant(:p)[x.attr(:id) == 'wooDiv'].previous_sibling(:p) }.first.text.should eq 'Bax'
104
+ xpath { |x| x.descendant(:p)[x.attr(:id) == 'wooDiv'].previous_sibling(:ul, :p) }.first.text.should eq 'Bax'
105
+ xpath { |x| x.descendant(:p)[x.attr(:title) == 'gorilla'].previous_sibling(:ul, :p) }.first.text.should eq 'A list'
106
106
  xpath { |x| x.descendant(:p)[x.attr(:id) == 'wooDiv'].previous_sibling(:ul, :li) }.first.should be_nil
107
- xpath { |x| x.descendant(:p)[x.attr(:id) == 'wooDiv'].previous_sibling }.first.text.should == 'Bax'
107
+ xpath { |x| x.descendant(:p)[x.attr(:id) == 'wooDiv'].previous_sibling }.first.text.should eq 'Bax'
108
108
  end
109
109
  end
110
110
 
@@ -114,7 +114,7 @@ describe XPath do
114
114
  foo_div = x.anywhere(:div).where(x.attr(:id) == 'foo')
115
115
  x.descendant(:p).where(x.attr(:id) == foo_div.attr(:title))
116
116
  end
117
- @results[0].text.should == "Blah"
117
+ @results[0].text.should eq "Blah"
118
118
  end
119
119
 
120
120
  it "should find multiple kinds of nodes regardless of the context" do
@@ -123,10 +123,10 @@ describe XPath do
123
123
  context.anywhere(:p, :ul)
124
124
  end
125
125
 
126
- @results[0].text.should == 'Blah'
127
- @results[3].text.should == 'A list'
128
- @results[4].text.should == 'A list'
129
- @results[6].text.should == 'Bax'
126
+ @results[0].text.should eq 'Blah'
127
+ @results[3].text.should eq 'A list'
128
+ @results[4].text.should eq 'A list'
129
+ @results[6].text.should eq 'Bax'
130
130
  end
131
131
 
132
132
  it "should find all nodes when no arguments given regardless of the context" do
@@ -134,13 +134,13 @@ describe XPath do
134
134
  context=x.descendant(:div).where(x.attr(:id)=='woo')
135
135
  context.anywhere
136
136
  end
137
- @results[0].name.should == 'html'
138
- @results[1].name.should == 'head'
139
- @results[2].name.should == 'body'
140
- @results[6].text.should == 'Blah'
141
- @results[10].text.should == 'A list'
142
- @results[13].text.should == 'A list'
143
- @results[15].text.should == 'Bax'
137
+ @results[0].name.should eq 'html'
138
+ @results[1].name.should eq 'head'
139
+ @results[2].name.should eq 'body'
140
+ @results[6].text.should eq 'Blah'
141
+ @results[10].text.should eq 'A list'
142
+ @results[13].text.should eq 'A list'
143
+ @results[15].text.should eq 'Bax'
144
144
  end
145
145
 
146
146
  end
@@ -150,7 +150,7 @@ describe XPath do
150
150
  @results = xpath do |x|
151
151
  x.descendant(:div).where(x.attr(:title).contains('ooD'))
152
152
  end
153
- @results[0][:id].should == "foo"
153
+ @results[0][:id].should eq "foo"
154
154
  end
155
155
 
156
156
  it "should find nodes that contain the given expression" do
@@ -158,7 +158,18 @@ describe XPath do
158
158
  expression = x.anywhere(:div).where(x.attr(:title) == 'fooDiv').attr(:id)
159
159
  x.descendant(:div).where(x.attr(:title).contains(expression))
160
160
  end
161
- @results[0][:id].should == "foo"
161
+ @results[0][:id].should eq "foo"
162
+ end
163
+ end
164
+
165
+ describe "#contains_word" do
166
+ it "should find nodes that contain the given word in its entirety" do
167
+ @results = xpath do |x|
168
+ x.descendant.where(x.attr(:class).contains_word('fish'))
169
+ end
170
+ @results[0].text.should eq "Bax"
171
+ @results[1].text.should eq "llama"
172
+ @results.length.should eq 2
162
173
  end
163
174
  end
164
175
 
@@ -167,9 +178,9 @@ describe XPath do
167
178
  @results = xpath do |x|
168
179
  x.descendant(:*).where(x.attr(:id).starts_with('foo'))
169
180
  end
170
- @results.size.should == 2
171
- @results[0][:id].should == "foo"
172
- @results[1][:id].should == "fooDiv"
181
+ @results.size.should eq 2
182
+ @results[0][:id].should eq "foo"
183
+ @results[1][:id].should eq "fooDiv"
173
184
  end
174
185
 
175
186
  it "should find nodes that contain the given expression" do
@@ -177,17 +188,17 @@ describe XPath do
177
188
  expression = x.anywhere(:div).where(x.attr(:title) == 'fooDiv').attr(:id)
178
189
  x.descendant(:div).where(x.attr(:title).starts_with(expression))
179
190
  end
180
- @results[0][:id].should == "foo"
191
+ @results[0][:id].should eq "foo"
181
192
  end
182
193
  end
183
194
 
184
195
  describe '#text' do
185
196
  it "should select a node's text" do
186
197
  @results = xpath { |x| x.descendant(:p).where(x.text == 'Bax') }
187
- @results[0].text.should == 'Bax'
188
- @results[1][:title].should == 'monkey'
198
+ @results[0].text.should eq 'Bax'
199
+ @results[1][:title].should eq 'monkey'
189
200
  @results = xpath { |x| x.descendant(:div).where(x.descendant(:p).text == 'Bax') }
190
- @results[0][:title].should == 'fooDiv'
201
+ @results[0][:title].should eq 'fooDiv'
191
202
  end
192
203
  end
193
204
 
@@ -195,14 +206,14 @@ describe XPath do
195
206
  context "when called with one argument" do
196
207
  it "should select the part of a string after the specified character" do
197
208
  @results = xpath { |x| x.descendant(:span).where(x.attr(:id) == "substring").text.substring(7) }
198
- @results.should == "there"
209
+ @results.should eq "there"
199
210
  end
200
211
  end
201
212
 
202
213
  context "when called with two arguments" do
203
214
  it "should select the part of a string after the specified character, up to the given length" do
204
215
  @results = xpath { |x| x.descendant(:span).where(x.attr(:id) == "substring").text.substring(2, 4) }
205
- @results.should == "ello"
216
+ @results.should eq "ello"
206
217
  end
207
218
  end
208
219
  end
@@ -210,63 +221,78 @@ describe XPath do
210
221
  describe '#function' do
211
222
  it "should call the given xpath function" do
212
223
  @results = xpath { |x| x.function(:boolean, x.function(:true) == x.function(:false)) }
213
- @results.should == false
224
+ @results.should eq false
214
225
  end
215
226
  end
216
227
 
217
228
  describe '#method' do
218
229
  it "should call the given xpath function with the current node as the first argument" do
219
230
  @results = xpath { |x| x.descendant(:span).where(x.attr(:id) == "string-length").text.method(:"string-length") }
220
- @results.should == 11
231
+ @results.should eq 11
221
232
  end
222
233
  end
223
234
 
224
235
  describe '#string_length' do
225
236
  it "should return the length of a string" do
226
237
  @results = xpath { |x| x.descendant(:span).where(x.attr(:id) == "string-length").text.string_length }
227
- @results.should == 11
238
+ @results.should eq 11
228
239
  end
229
240
  end
230
241
 
231
242
  describe '#where' do
232
243
  it "should limit the expression to find only certain nodes" do
233
- xpath { |x| x.descendant(:div).where(:"@id = 'foo'") }.first[:title].should == "fooDiv"
244
+ xpath { |x| x.descendant(:div).where(:"@id = 'foo'") }.first[:title].should eq "fooDiv"
234
245
  end
235
246
 
236
247
  it "should be aliased as []" do
237
- xpath { |x| x.descendant(:div)[:"@id = 'foo'"] }.first[:title].should == "fooDiv"
248
+ xpath { |x| x.descendant(:div)[:"@id = 'foo'"] }.first[:title].should eq "fooDiv"
238
249
  end
239
250
  end
240
251
 
241
252
  describe '#inverse' do
242
253
  it "should invert the expression" do
243
- xpath { |x| x.descendant(:p).where(x.attr(:id).equals('fooDiv').inverse) }.first.text.should == 'Bax'
254
+ xpath { |x| x.descendant(:p).where(x.attr(:id).equals('fooDiv').inverse) }.first.text.should eq 'Bax'
244
255
  end
245
256
 
246
257
  it "should be aliased as the unary tilde" do
247
- xpath { |x| x.descendant(:p).where(~x.attr(:id).equals('fooDiv')) }.first.text.should == 'Bax'
258
+ xpath { |x| x.descendant(:p).where(~x.attr(:id).equals('fooDiv')) }.first.text.should eq 'Bax'
259
+ end
260
+
261
+ it "should be aliased as the unary bang" do
262
+ xpath { |x| x.descendant(:p).where(!x.attr(:id).equals('fooDiv')) }.first.text.should eq 'Bax'
248
263
  end
249
264
  end
250
265
 
251
266
  describe '#equals' do
252
267
  it "should limit the expression to find only certain nodes" do
253
- xpath { |x| x.descendant(:div).where(x.attr(:id).equals('foo')) }.first[:title].should == "fooDiv"
268
+ xpath { |x| x.descendant(:div).where(x.attr(:id).equals('foo')) }.first[:title].should eq "fooDiv"
254
269
  end
255
270
 
256
271
  it "should be aliased as ==" do
257
- xpath { |x| x.descendant(:div).where(x.attr(:id) == 'foo') }.first[:title].should == "fooDiv"
272
+ xpath { |x| x.descendant(:div).where(x.attr(:id) == 'foo') }.first[:title].should eq "fooDiv"
258
273
  end
259
274
  end
260
275
 
276
+ describe '#not_equals' do
277
+ it "should match only when not equal" do
278
+ xpath { |x| x.descendant(:div).where(x.attr(:id).not_equals('bar')) }.first[:title].should eq "fooDiv"
279
+ end
280
+
281
+ it "should be aliased as !=" do
282
+ xpath { |x| x.descendant(:div).where(x.attr(:id) != 'bar') }.first[:title].should eq "fooDiv"
283
+ end
284
+ end
285
+
286
+
261
287
  describe '#is' do
262
288
  it "uses equality when :exact given" do
263
- xpath(:exact) { |x| x.descendant(:div).where(x.attr(:id).is('foo')) }.first[:title].should == "fooDiv"
289
+ xpath(:exact) { |x| x.descendant(:div).where(x.attr(:id).is('foo')) }.first[:title].should eq "fooDiv"
264
290
  xpath(:exact) { |x| x.descendant(:div).where(x.attr(:id).is('oo')) }.first.should be_nil
265
291
  end
266
292
 
267
293
  it "uses substring matching otherwise" do
268
- xpath { |x| x.descendant(:div).where(x.attr(:id).is('foo')) }.first[:title].should == "fooDiv"
269
- xpath { |x| x.descendant(:div).where(x.attr(:id).is('oo')) }.first[:title].should == "fooDiv"
294
+ xpath { |x| x.descendant(:div).where(x.attr(:id).is('foo')) }.first[:title].should eq "fooDiv"
295
+ xpath { |x| x.descendant(:div).where(x.attr(:id).is('oo')) }.first[:title].should eq "fooDiv"
270
296
  end
271
297
  end
272
298
 
@@ -276,9 +302,9 @@ describe XPath do
276
302
  p = x.anywhere(:div).where(x.attr(:id) == 'foo').attr(:title)
277
303
  x.descendant(:*).where(x.attr(:id).one_of('foo', p, 'baz'))
278
304
  end
279
- @results[0][:title].should == "fooDiv"
280
- @results[1].text.should == "Blah"
281
- @results[2][:title].should == "bazDiv"
305
+ @results[0][:title].should eq "fooDiv"
306
+ @results[1].text.should eq "Blah"
307
+ @results[2][:title].should eq "bazDiv"
282
308
  end
283
309
  end
284
310
 
@@ -287,14 +313,14 @@ describe XPath do
287
313
  @results = xpath do |x|
288
314
  x.descendant(:*).where(x.contains('Bax').and(x.attr(:title).equals('monkey')))
289
315
  end
290
- @results[0][:title].should == "monkey"
316
+ @results[0][:title].should eq "monkey"
291
317
  end
292
318
 
293
319
  it "should be aliased as ampersand (&)" do
294
320
  @results = xpath do |x|
295
321
  x.descendant(:*).where(x.contains('Bax') & x.attr(:title).equals('monkey'))
296
322
  end
297
- @results[0][:title].should == "monkey"
323
+ @results[0][:title].should eq "monkey"
298
324
  end
299
325
  end
300
326
 
@@ -303,57 +329,57 @@ describe XPath do
303
329
  @results = xpath do |x|
304
330
  x.descendant(:*).where(x.attr(:id).equals('foo').or(x.attr(:id).equals('fooDiv')))
305
331
  end
306
- @results[0][:title].should == "fooDiv"
307
- @results[1].text.should == "Blah"
332
+ @results[0][:title].should eq "fooDiv"
333
+ @results[1].text.should eq "Blah"
308
334
  end
309
335
 
310
336
  it "should be aliased as pipe (|)" do
311
337
  @results = xpath do |x|
312
338
  x.descendant(:*).where(x.attr(:id).equals('foo') | x.attr(:id).equals('fooDiv'))
313
339
  end
314
- @results[0][:title].should == "fooDiv"
315
- @results[1].text.should == "Blah"
340
+ @results[0][:title].should eq "fooDiv"
341
+ @results[1].text.should eq "Blah"
316
342
  end
317
343
  end
318
344
 
319
345
  describe '#attr' do
320
346
  it "should be an attribute" do
321
347
  @results = xpath { |x| x.descendant(:div).where(x.attr(:id)) }
322
- @results[0][:title].should == "barDiv"
323
- @results[1][:title].should == "fooDiv"
348
+ @results[0][:title].should eq "barDiv"
349
+ @results[1][:title].should eq "fooDiv"
324
350
  end
325
351
  end
326
352
 
327
353
  describe '#css' do
328
354
  it "should find nodes by the given CSS selector" do
329
355
  @results = xpath { |x| x.css('#preference p') }
330
- @results[0].text.should == 'allamas'
331
- @results[1].text.should == 'llama'
356
+ @results[0].text.should eq 'allamas'
357
+ @results[1].text.should eq 'llama'
332
358
  end
333
359
 
334
360
  it "should respect previous expression" do
335
361
  @results = xpath { |x| x.descendant[x.attr(:id) == 'moar'].css('p') }
336
- @results[0].text.should == 'chimp'
337
- @results[1].text.should == 'flamingo'
362
+ @results[0].text.should eq 'chimp'
363
+ @results[1].text.should eq 'flamingo'
338
364
  end
339
365
 
340
366
  it "should be composable" do
341
367
  @results = xpath { |x| x.css('#moar').descendant(:p) }
342
- @results[0].text.should == 'chimp'
343
- @results[1].text.should == 'flamingo'
368
+ @results[0].text.should eq 'chimp'
369
+ @results[1].text.should eq 'flamingo'
344
370
  end
345
371
 
346
372
  it "should allow comma separated selectors" do
347
373
  @results = xpath { |x| x.descendant[x.attr(:id) == 'moar'].css('div, p') }
348
- @results[0].text.should == 'chimp'
349
- @results[1].text.should == 'elephant'
350
- @results[2].text.should == 'flamingo'
374
+ @results[0].text.should eq 'chimp'
375
+ @results[1].text.should eq 'elephant'
376
+ @results[2].text.should eq 'flamingo'
351
377
  end
352
378
  end
353
379
 
354
- describe '#name' do
380
+ describe '#qname' do
355
381
  it "should match the node's name" do
356
- xpath { |x| x.descendant(:*).where(x.name == 'ul') }.first.text.should == "A list"
382
+ xpath { |x| x.descendant(:*).where(x.qname == 'ul') }.first.text.should eq "A list"
357
383
  end
358
384
  end
359
385
 
@@ -365,9 +391,9 @@ describe XPath do
365
391
  @xpath1 = @collection.where(XPath.attr(:id) == 'foo').to_xpath
366
392
  @xpath2 = @collection.where(XPath.attr(:id) == 'fooDiv').to_xpath
367
393
  @results = doc.xpath(@xpath1)
368
- @results[0][:title].should == 'fooDiv'
394
+ @results[0][:title].should eq 'fooDiv'
369
395
  @results = doc.xpath(@xpath2)
370
- @results[0][:id].should == 'fooDiv'
396
+ @results[0][:id].should eq 'fooDiv'
371
397
  end
372
398
 
373
399
  it "should be aliased as +" do
@@ -377,119 +403,119 @@ describe XPath do
377
403
  @xpath1 = @collection.where(XPath.attr(:id) == 'foo').to_xpath
378
404
  @xpath2 = @collection.where(XPath.attr(:id) == 'fooDiv').to_xpath
379
405
  @results = doc.xpath(@xpath1)
380
- @results[0][:title].should == 'fooDiv'
406
+ @results[0][:title].should eq 'fooDiv'
381
407
  @results = doc.xpath(@xpath2)
382
- @results[0][:id].should == 'fooDiv'
408
+ @results[0][:id].should eq 'fooDiv'
383
409
  end
384
410
  end
385
411
 
386
412
  describe "#last" do
387
413
  it "returns the number of elements in the context" do
388
414
  @results = xpath { |x| x.descendant(:p)[XPath.position() == XPath.last()] }
389
- @results[0].text.should == "Bax"
390
- @results[1].text.should == "Blah"
391
- @results[2].text.should == "llama"
415
+ @results[0].text.should eq "Bax"
416
+ @results[1].text.should eq "Blah"
417
+ @results[2].text.should eq "llama"
392
418
  end
393
419
  end
394
420
 
395
421
  describe "#position" do
396
422
  it "returns the position of elements in the context" do
397
423
  @results = xpath { |x| x.descendant(:p)[XPath.position() == 2] }
398
- @results[0].text.should == "Bax"
399
- @results[1].text.should == "Bax"
424
+ @results[0].text.should eq "Bax"
425
+ @results[1].text.should eq "Bax"
400
426
  end
401
427
  end
402
428
 
403
429
  describe "#count" do
404
430
  it "counts the number of occurrences" do
405
431
  @results = xpath { |x| x.descendant(:div)[x.descendant(:p).count == 2] }
406
- @results[0][:id].should == "preference"
432
+ @results[0][:id].should eq "preference"
407
433
  end
408
434
  end
409
435
 
410
436
  describe "#lte" do
411
437
  it "checks lesser than or equal" do
412
438
  @results = xpath { |x| x.descendant(:p)[XPath.position() <= 2] }
413
- @results[0].text.should == "Blah"
414
- @results[1].text.should == "Bax"
415
- @results[2][:title].should == "gorilla"
416
- @results[3].text.should == "Bax"
439
+ @results[0].text.should eq "Blah"
440
+ @results[1].text.should eq "Bax"
441
+ @results[2][:title].should eq "gorilla"
442
+ @results[3].text.should eq "Bax"
417
443
  end
418
444
  end
419
445
 
420
446
  describe "#lt" do
421
447
  it "checks lesser than" do
422
448
  @results = xpath { |x| x.descendant(:p)[XPath.position() < 2] }
423
- @results[0].text.should == "Blah"
424
- @results[1][:title].should == "gorilla"
449
+ @results[0].text.should eq "Blah"
450
+ @results[1][:title].should eq "gorilla"
425
451
  end
426
452
  end
427
453
 
428
454
  describe "#gte" do
429
455
  it "checks greater than or equal" do
430
456
  @results = xpath { |x| x.descendant(:p)[XPath.position() >= 2] }
431
- @results[0].text.should == "Bax"
432
- @results[1][:title].should == "monkey"
433
- @results[2].text.should == "Bax"
434
- @results[3].text.should == "Blah"
457
+ @results[0].text.should eq "Bax"
458
+ @results[1][:title].should eq "monkey"
459
+ @results[2].text.should eq "Bax"
460
+ @results[3].text.should eq "Blah"
435
461
  end
436
462
  end
437
463
 
438
464
  describe "#gt" do
439
465
  it "checks greater than" do
440
466
  @results = xpath { |x| x.descendant(:p)[XPath.position() > 2] }
441
- @results[0][:title].should == "monkey"
442
- @results[1].text.should == "Blah"
467
+ @results[0][:title].should eq "monkey"
468
+ @results[1].text.should eq "Blah"
443
469
  end
444
470
  end
445
471
 
446
472
  describe "#plus" do
447
473
  it "adds stuff" do
448
474
  @results = xpath { |x| x.descendant(:p)[XPath.position().plus(1) == 2] }
449
- @results[0][:id].should == "fooDiv"
450
- @results[1][:title].should == "gorilla"
475
+ @results[0][:id].should eq "fooDiv"
476
+ @results[1][:title].should eq "gorilla"
451
477
  end
452
478
  end
453
479
 
454
480
  describe "#minus" do
455
481
  it "subtracts stuff" do
456
482
  @results = xpath { |x| x.descendant(:p)[XPath.position().minus(1) == 0] }
457
- @results[0][:id].should == "fooDiv"
458
- @results[1][:title].should == "gorilla"
483
+ @results[0][:id].should eq "fooDiv"
484
+ @results[1][:title].should eq "gorilla"
459
485
  end
460
486
  end
461
487
 
462
488
  describe "#multiply" do
463
489
  it "multiplies stuff" do
464
490
  @results = xpath { |x| x.descendant(:p)[XPath.position() * 3 == 3] }
465
- @results[0][:id].should == "fooDiv"
466
- @results[1][:title].should == "gorilla"
491
+ @results[0][:id].should eq "fooDiv"
492
+ @results[1][:title].should eq "gorilla"
467
493
  end
468
494
  end
469
495
 
470
496
  describe "#divide" do
471
497
  it "divides stuff" do
472
498
  @results = xpath { |x| x.descendant(:p)[XPath.position() / 2 == 1] }
473
- @results[0].text.should == "Bax"
474
- @results[1].text.should == "Bax"
499
+ @results[0].text.should eq "Bax"
500
+ @results[1].text.should eq "Bax"
475
501
  end
476
502
  end
477
503
 
478
504
  describe "#mod" do
479
505
  it "take modulo" do
480
506
  @results = xpath { |x| x.descendant(:p)[XPath.position() % 2 == 1] }
481
- @results[0].text.should == "Blah"
482
- @results[1][:title].should == "monkey"
483
- @results[2][:title].should == "gorilla"
507
+ @results[0].text.should eq "Blah"
508
+ @results[1][:title].should eq "monkey"
509
+ @results[2][:title].should eq "gorilla"
484
510
  end
485
511
  end
486
512
 
487
513
  describe "#ancestor" do
488
514
  it "finds ancestor nodes" do
489
515
  @results = xpath { |x| x.descendant(:p)[1].ancestor }
490
- @results[0].node_name.should == "html"
491
- @results[1].node_name.should == "body"
492
- @results[2][:id].should == "foo"
516
+ @results[0].node_name.should eq "html"
517
+ @results[1].node_name.should eq "body"
518
+ @results[2][:id].should eq "foo"
493
519
  end
494
520
  end
495
521
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xpath
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonas Nicklas
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain:
11
11
  - gem-public_cert.pem
12
- date: 2017-05-25 00:00:00.000000000 Z
12
+ date: 2017-12-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
@@ -17,14 +17,14 @@ dependencies:
17
17
  requirements:
18
18
  - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: '1.3'
20
+ version: '1.8'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
- version: '1.3'
27
+ version: '1.8'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: rspec
30
30
  requirement: !ruby/object:Gem::Requirement
@@ -92,7 +92,6 @@ files:
92
92
  - lib/xpath.rb
93
93
  - lib/xpath/dsl.rb
94
94
  - lib/xpath/expression.rb
95
- - lib/xpath/html.rb
96
95
  - lib/xpath/literal.rb
97
96
  - lib/xpath/renderer.rb
98
97
  - lib/xpath/union.rb
@@ -100,7 +99,6 @@ files:
100
99
  - spec/fixtures/form.html
101
100
  - spec/fixtures/simple.html
102
101
  - spec/fixtures/stuff.html
103
- - spec/html_spec.rb
104
102
  - spec/spec_helper.rb
105
103
  - spec/union_spec.rb
106
104
  - spec/xpath_spec.rb
@@ -116,7 +114,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
116
114
  requirements:
117
115
  - - ">="
118
116
  - !ruby/object:Gem::Version
119
- version: 1.9.3
117
+ version: '2.2'
120
118
  required_rubygems_version: !ruby/object:Gem::Requirement
121
119
  requirements:
122
120
  - - ">="
@@ -124,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
122
  version: '0'
125
123
  requirements: []
126
124
  rubyforge_project:
127
- rubygems_version: 2.5.2
125
+ rubygems_version: 2.6.13
128
126
  signing_key:
129
127
  specification_version: 4
130
128
  summary: Generate XPath expressions from Ruby
@@ -1,175 +0,0 @@
1
- module XPath
2
- module HTML
3
- include XPath::DSL
4
- extend self
5
-
6
- # Match an `a` link element.
7
- #
8
- # @param [String] locator
9
- # Text, id, title, or image alt attribute of the link
10
- #
11
- def link(locator)
12
- locator = locator.to_s
13
- link = descendant(:a)[attr(:href)]
14
- link[attr(:id).equals(locator) | string.n.is(locator) | attr(:title).is(locator) | descendant(:img)[attr(:alt).is(locator)]]
15
- end
16
-
17
- # Match a `submit`, `image`, or `button` element.
18
- #
19
- # @param [String] locator
20
- # Value, title, id, or image alt attribute of the button
21
- #
22
- def button(locator)
23
- locator = locator.to_s
24
- button = descendant(:input)[attr(:type).one_of('submit', 'reset', 'image', 'button')][attr(:id).equals(locator) | attr(:value).is(locator) | attr(:title).is(locator)]
25
- button += descendant(:button)[attr(:id).equals(locator) | attr(:value).is(locator) | string.n.is(locator) | attr(:title).is(locator)]
26
- button += descendant(:input)[attr(:type).equals('image')][attr(:alt).is(locator)]
27
- end
28
-
29
-
30
- # Match anything returned by either {#link} or {#button}.
31
- #
32
- # @param [String] locator
33
- # Text, id, title, or image alt attribute of the link or button
34
- #
35
- def link_or_button(locator)
36
- link(locator) + button(locator)
37
- end
38
-
39
-
40
- # Match any `fieldset` element.
41
- #
42
- # @param [String] locator
43
- # Legend or id of the fieldset
44
- #
45
- def fieldset(locator)
46
- locator = locator.to_s
47
- descendant(:fieldset)[attr(:id).equals(locator) | child(:legend)[string.n.is(locator)]]
48
- end
49
-
50
-
51
- # Match any `input`, `textarea`, or `select` element that doesn't have a
52
- # type of `submit`, `image`, or `hidden`.
53
- #
54
- # @param [String] locator
55
- # Label, id, or name of field to match
56
- #
57
- def field(locator)
58
- locator = locator.to_s
59
- xpath = descendant(:input, :textarea, :select)[~attr(:type).one_of('submit', 'image', 'hidden')]
60
- xpath = locate_field(xpath, locator)
61
- xpath
62
- end
63
-
64
-
65
- # Match any `input` or `textarea` element that can be filled with text.
66
- # This excludes any inputs with a type of `submit`, `image`, `radio`,
67
- # `checkbox`, `hidden`, or `file`.
68
- #
69
- # @param [String] locator
70
- # Label, id, or name of field to match
71
- #
72
- def fillable_field(locator)
73
- locator = locator.to_s
74
- xpath = descendant(:input, :textarea)[~attr(:type).one_of('submit', 'image', 'radio', 'checkbox', 'hidden', 'file')]
75
- xpath = locate_field(xpath, locator)
76
- xpath
77
- end
78
-
79
-
80
- # Match any `select` element.
81
- #
82
- # @param [String] locator
83
- # Label, id, or name of the field to match
84
- #
85
- def select(locator)
86
- locator = locator.to_s
87
- locate_field(descendant(:select), locator)
88
- end
89
-
90
-
91
- # Match any `input` element of type `checkbox`.
92
- #
93
- # @param [String] locator
94
- # Label, id, or name of the checkbox to match
95
- #
96
- def checkbox(locator)
97
- locator = locator.to_s
98
- locate_field(descendant(:input)[attr(:type).equals('checkbox')], locator)
99
- end
100
-
101
-
102
- # Match any `input` element of type `radio`.
103
- #
104
- # @param [String] locator
105
- # Label, id, or name of the radio button to match
106
- #
107
- def radio_button(locator)
108
- locator = locator.to_s
109
- locate_field(descendant(:input)[attr(:type).equals('radio')], locator)
110
- end
111
-
112
-
113
- # Match any `input` element of type `file`.
114
- #
115
- # @param [String] locator
116
- # Label, id, or name of the file field to match
117
- #
118
- def file_field(locator)
119
- locator = locator.to_s
120
- locate_field(descendant(:input)[attr(:type).equals('file')], locator)
121
- end
122
-
123
-
124
- # Match an `optgroup` element.
125
- #
126
- # @param [String] name
127
- # Label for the option group
128
- #
129
- def optgroup(locator)
130
- locator = locator.to_s
131
- descendant(:optgroup)[attr(:label).is(locator)]
132
- end
133
-
134
-
135
- # Match an `option` element.
136
- #
137
- # @param [String] name
138
- # Visible text of the option
139
- #
140
- def option(locator)
141
- locator = locator.to_s
142
- descendant(:option)[string.n.is(locator)]
143
- end
144
-
145
-
146
- # Match any `table` element.
147
- #
148
- # @param [String] locator
149
- # Caption or id of the table to match
150
- # @option options [Array] :rows
151
- # Content of each cell in each row to match
152
- #
153
- def table(locator)
154
- locator = locator.to_s
155
- descendant(:table)[attr(:id).equals(locator) | descendant(:caption).is(locator)]
156
- end
157
-
158
- # Match any 'dd' element.
159
- #
160
- # @param [String] locator
161
- # Id of the 'dd' element or text from preciding 'dt' element content
162
- def definition_description(locator)
163
- locator = locator.to_s
164
- descendant(:dd)[attr(:id).equals(locator) | previous_sibling(:dt)[string.n.equals(locator)] ]
165
- end
166
-
167
- protected
168
-
169
- def locate_field(xpath, locator)
170
- locate_field = xpath[attr(:id).equals(locator) | attr(:name).equals(locator) | attr(:placeholder).equals(locator) | attr(:id).equals(anywhere(:label)[string.n.is(locator)].attr(:for))]
171
- locate_field += descendant(:label)[string.n.is(locator)].descendant(xpath)
172
- locate_field
173
- end
174
- end
175
- end
@@ -1,308 +0,0 @@
1
- require 'spec_helper'
2
- require 'nokogiri'
3
-
4
- describe XPath::HTML do
5
- let(:template) { 'form' }
6
- let(:template_path) { File.read(File.expand_path("fixtures/#{template}.html", File.dirname(__FILE__))) }
7
- let(:doc) { Nokogiri::HTML(template_path) }
8
- let(:type) { |example| example.metadata[:type] }
9
-
10
- def get(*args)
11
- all(*args).first
12
- end
13
-
14
- def all(*args)
15
- doc.xpath(XPath::HTML.send(subject, *args).to_xpath(type)).map { |node| node[:data] }
16
- end
17
-
18
- describe '#link' do
19
- subject { :link }
20
-
21
- it("finds links by id") { get('some-id').should == 'link-id' }
22
- it("finds links by content") { get('An awesome link').should == 'link-text' }
23
- it("finds links by content regardless of whitespace") { get('My whitespaced link').should == 'link-whitespace' }
24
- it("finds links with child tags by content") { get('An emphatic link').should == 'link-children' }
25
- it("finds links by the content of their child tags") { get('emphatic').should == 'link-children' }
26
- it("finds links by approximate content") { get('awesome').should == 'link-text' }
27
- it("finds links by title") { get('My title').should == 'link-title' }
28
- it("finds links by approximate title") { get('title').should == 'link-title' }
29
- it("finds links by image's alt attribute") { get('Alt link').should == 'link-img' }
30
- it("finds links by image's approximate alt attribute") { get('Alt').should == 'link-img' }
31
- it("does not find links without href attriutes") { get('Wrong Link').should be_nil }
32
- it("casts to string") { get(:'some-id').should == 'link-id' }
33
-
34
- context "with exact match", :type => :exact do
35
- it("finds links by content") { get('An awesome link').should == 'link-text' }
36
- it("does not find links by approximate content") { get('awesome').should be_nil }
37
- it("finds links by title") { get('My title').should == 'link-title' }
38
- it("does not find links by approximate title") { get('title').should be_nil }
39
- it("finds links by image's alt attribute") { get('Alt link').should == 'link-img' }
40
- it("does not find links by image's approximate alt attribute") { get('Alt').should be_nil }
41
- end
42
- end
43
-
44
- describe '#button' do
45
- subject { :button }
46
-
47
- context "with submit type" do
48
- it("finds buttons by id") { get('submit-with-id').should == 'id-submit' }
49
- it("finds buttons by value") { get('submit-with-value').should == 'value-submit' }
50
- it("finds buttons by approximate value") { get('mit-with-val').should == 'value-submit' }
51
- it("finds buttons by title") { get('My submit title').should == 'title-submit' }
52
- it("finds buttons by approximate title") { get('submit title').should == 'title-submit' }
53
-
54
- context "with exact match", :type => :exact do
55
- it("finds buttons by value") { get('submit-with-value').should == 'value-submit' }
56
- it("does not find buttons by approximate value") { get('mit-with-val').should be_nil }
57
- it("finds buttons by title") { get('My submit title').should == 'title-submit' }
58
- it("does not find buttons by approximate title") { get('submit title').should be_nil }
59
- end
60
- end
61
-
62
- context "with reset type" do
63
- it("finds buttons by id") { get('reset-with-id').should == 'id-reset' }
64
- it("finds buttons by value") { get('reset-with-value').should == 'value-reset' }
65
- it("finds buttons by approximate value") { get('set-with-val').should == 'value-reset' }
66
- it("finds buttons by title") { get('My reset title').should == 'title-reset' }
67
- it("finds buttons by approximate title") { get('reset title').should == 'title-reset' }
68
-
69
- context "with exact match", :type => :exact do
70
- it("finds buttons by value") { get('reset-with-value').should == 'value-reset' }
71
- it("does not find buttons by approximate value") { get('set-with-val').should be_nil }
72
- it("finds buttons by title") { get('My reset title').should == 'title-reset' }
73
- it("does not find buttons by approximate title") { get('reset title').should be_nil }
74
- end
75
- end
76
-
77
- context "with button type" do
78
- it("finds buttons by id") { get('button-with-id').should == 'id-button' }
79
- it("finds buttons by value") { get('button-with-value').should == 'value-button' }
80
- it("finds buttons by approximate value") { get('ton-with-val').should == 'value-button' }
81
- it("finds buttons by title") { get('My button title').should == 'title-button' }
82
- it("finds buttons by approximate title") { get('button title').should == 'title-button' }
83
-
84
- context "with exact match", :type => :exact do
85
- it("finds buttons by value") { get('button-with-value').should == 'value-button' }
86
- it("does not find buttons by approximate value") { get('ton-with-val').should be_nil }
87
- it("finds buttons by title") { get('My button title').should == 'title-button' }
88
- it("does not find buttons by approximate title") { get('button title').should be_nil }
89
- end
90
- end
91
-
92
- context "with image type" do
93
- it("finds buttons by id") { get('imgbut-with-id').should == 'id-imgbut' }
94
- it("finds buttons by value") { get('imgbut-with-value').should == 'value-imgbut' }
95
- it("finds buttons by approximate value") { get('gbut-with-val').should == 'value-imgbut' }
96
- it("finds buttons by alt attribute") { get('imgbut-with-alt').should == 'alt-imgbut' }
97
- it("finds buttons by approximate alt attribute") { get('mgbut-with-al').should == 'alt-imgbut' }
98
- it("finds buttons by title") { get('My imgbut title').should == 'title-imgbut' }
99
- it("finds buttons by approximate title") { get('imgbut title').should == 'title-imgbut' }
100
-
101
- context "with exact match", :type => :exact do
102
- it("finds buttons by value") { get('imgbut-with-value').should == 'value-imgbut' }
103
- it("does not find buttons by approximate value") { get('gbut-with-val').should be_nil }
104
- it("finds buttons by alt attribute") { get('imgbut-with-alt').should == 'alt-imgbut' }
105
- it("does not find buttons by approximate alt attribute") { get('mgbut-with-al').should be_nil }
106
- it("finds buttons by title") { get('My imgbut title').should == 'title-imgbut' }
107
- it("does not find buttons by approximate title") { get('imgbut title').should be_nil }
108
- end
109
- end
110
-
111
- context "with button tag" do
112
- it("finds buttons by id") { get('btag-with-id').should == 'id-btag' }
113
- it("finds buttons by value") { get('btag-with-value').should == 'value-btag' }
114
- it("finds buttons by approximate value") { get('tag-with-val').should == 'value-btag' }
115
- it("finds buttons by text") { get('btag-with-text').should == 'text-btag' }
116
- it("finds buttons by text ignoring whitespace") { get('My whitespaced button').should == 'btag-with-whitespace' }
117
- it("finds buttons by approximate text ") { get('tag-with-tex').should == 'text-btag' }
118
- it("finds buttons with child tags by text") { get('An emphatic button').should == 'btag-with-children' }
119
- it("finds buttons by text of their children") { get('emphatic').should == 'btag-with-children' }
120
- it("finds buttons by title") { get('My btag title').should == 'title-btag' }
121
- it("finds buttons by approximate title") { get('btag title').should == 'title-btag' }
122
-
123
- context "with exact match", :type => :exact do
124
- it("finds buttons by value") { get('btag-with-value').should == 'value-btag' }
125
- it("does not find buttons by approximate value") { get('tag-with-val').should be_nil }
126
- it("finds buttons by text") { get('btag-with-text').should == 'text-btag' }
127
- it("does not find buttons by approximate text ") { get('tag-with-tex').should be_nil }
128
- it("finds buttons by title") { get('My btag title').should == 'title-btag' }
129
- it("does not find buttons by approximate title") { get('btag title').should be_nil }
130
- end
131
- end
132
-
133
- context "with unkown type" do
134
- it("does not find the button") { get('schmoo button').should be_nil }
135
- end
136
-
137
- it("casts to string") { get(:'tag-with-tex').should == 'text-btag' }
138
- end
139
-
140
- describe '#fieldset' do
141
- subject { :fieldset }
142
-
143
- it("finds fieldsets by id") { get('some-fieldset-id').should == 'fieldset-id' }
144
- it("finds fieldsets by legend") { get('Some Legend').should == 'fieldset-legend' }
145
- it("finds fieldsets by legend child tags") { get('Span Legend').should == 'fieldset-legend-span' }
146
- it("accepts approximate legends") { get('Legend').should == 'fieldset-legend' }
147
- it("finds nested fieldsets by legend") { get('Inner legend').should == 'fieldset-inner' }
148
- it("casts to string") { get(:'Inner legend').should == 'fieldset-inner' }
149
-
150
- context "with exact match", :type => :exact do
151
- it("finds fieldsets by legend") { get('Some Legend').should == 'fieldset-legend' }
152
- it("does not find by approximate legends") { get('Legend').should be_nil }
153
- end
154
- end
155
-
156
- describe '#field' do
157
- subject { :field }
158
-
159
- context "by id" do
160
- it("finds inputs with no type") { get('input-with-id').should == 'input-with-id-data' }
161
- it("finds inputs with text type") { get('input-text-with-id').should == 'input-text-with-id-data' }
162
- it("finds inputs with password type") { get('input-password-with-id').should == 'input-password-with-id-data' }
163
- it("finds inputs with custom type") { get('input-custom-with-id').should == 'input-custom-with-id-data' }
164
- it("finds textareas") { get('textarea-with-id').should == 'textarea-with-id-data' }
165
- it("finds select boxes") { get('select-with-id').should == 'select-with-id-data' }
166
- it("does not find submit buttons") { get('input-submit-with-id').should be_nil }
167
- it("does not find image buttons") { get('input-image-with-id').should be_nil }
168
- it("does not find hidden fields") { get('input-hidden-with-id').should be_nil }
169
- end
170
-
171
- context "by name" do
172
- it("finds inputs with no type") { get('input-with-name').should == 'input-with-name-data' }
173
- it("finds inputs with text type") { get('input-text-with-name').should == 'input-text-with-name-data' }
174
- it("finds inputs with password type") { get('input-password-with-name').should == 'input-password-with-name-data' }
175
- it("finds inputs with custom type") { get('input-custom-with-name').should == 'input-custom-with-name-data' }
176
- it("finds textareas") { get('textarea-with-name').should == 'textarea-with-name-data' }
177
- it("finds select boxes") { get('select-with-name').should == 'select-with-name-data' }
178
- it("does not find submit buttons") { get('input-submit-with-name').should be_nil }
179
- it("does not find image buttons") { get('input-image-with-name').should be_nil }
180
- it("does not find hidden fields") { get('input-hidden-with-name').should be_nil }
181
- end
182
-
183
- context "by placeholder" do
184
- it("finds inputs with no type") { get('input-with-placeholder').should == 'input-with-placeholder-data' }
185
- it("finds inputs with text type") { get('input-text-with-placeholder').should == 'input-text-with-placeholder-data' }
186
- it("finds inputs with password type") { get('input-password-with-placeholder').should == 'input-password-with-placeholder-data' }
187
- it("finds inputs with custom type") { get('input-custom-with-placeholder').should == 'input-custom-with-placeholder-data' }
188
- it("finds textareas") { get('textarea-with-placeholder').should == 'textarea-with-placeholder-data' }
189
- it("does not find hidden fields") { get('input-hidden-with-placeholder').should be_nil }
190
- end
191
-
192
- context "by referenced label" do
193
- it("finds inputs with no type") { get('Input with label').should == 'input-with-label-data' }
194
- it("finds inputs with text type") { get('Input text with label').should == 'input-text-with-label-data' }
195
- it("finds inputs with password type") { get('Input password with label').should == 'input-password-with-label-data' }
196
- it("finds inputs with custom type") { get('Input custom with label').should == 'input-custom-with-label-data' }
197
- it("finds textareas") { get('Textarea with label').should == 'textarea-with-label-data' }
198
- it("finds select boxes") { get('Select with label').should == 'select-with-label-data' }
199
- it("does not find submit buttons") { get('Input submit with label').should be_nil }
200
- it("does not find image buttons") { get('Input image with label').should be_nil }
201
- it("does not find hidden fields") { get('Input hidden with label').should be_nil }
202
- end
203
-
204
- context "by parent label" do
205
- it("finds inputs with no type") { get('Input with parent label').should == 'input-with-parent-label-data' }
206
- it("finds inputs with text type") { get('Input text with parent label').should == 'input-text-with-parent-label-data' }
207
- it("finds inputs with password type") { get('Input password with parent label').should == 'input-password-with-parent-label-data' }
208
- it("finds inputs with custom type") { get('Input custom with parent label').should == 'input-custom-with-parent-label-data' }
209
- it("finds textareas") { get('Textarea with parent label').should == 'textarea-with-parent-label-data' }
210
- it("finds select boxes") { get('Select with parent label').should == 'select-with-parent-label-data' }
211
- it("does not find submit buttons") { get('Input submit with parent label').should be_nil }
212
- it("does not find image buttons") { get('Input image with parent label').should be_nil }
213
- it("does not find hidden fields") { get('Input hidden with parent label').should be_nil }
214
- end
215
-
216
- it("casts to string") { get(:'select-with-id').should == 'select-with-id-data' }
217
- end
218
-
219
- describe '#fillable_field' do
220
- subject{ :fillable_field }
221
- context "by parent label" do
222
- it("finds inputs with text type") { get('Label text').should == 'id-text' }
223
- it("finds inputs where label has problem chars") { get("Label text's got an apostrophe").should == 'id-problem-text' }
224
- end
225
-
226
- end
227
-
228
- describe '#select' do
229
- subject{ :select }
230
- it("finds selects by id") { get('select-with-id').should == 'select-with-id-data' }
231
- it("finds selects by name") { get('select-with-name').should == 'select-with-name-data' }
232
- it("finds selects by label") { get('Select with label').should == 'select-with-label-data' }
233
- it("finds selects by parent label") { get('Select with parent label').should == 'select-with-parent-label-data' }
234
- it("casts to string") { get(:'Select with parent label').should == 'select-with-parent-label-data' }
235
- end
236
-
237
- describe '#checkbox' do
238
- subject{ :checkbox }
239
- it("finds checkboxes by id") { get('input-checkbox-with-id').should == 'input-checkbox-with-id-data' }
240
- it("finds checkboxes by name") { get('input-checkbox-with-name').should == 'input-checkbox-with-name-data' }
241
- it("finds checkboxes by label") { get('Input checkbox with label').should == 'input-checkbox-with-label-data' }
242
- it("finds checkboxes by parent label") { get('Input checkbox with parent label').should == 'input-checkbox-with-parent-label-data' }
243
- it("casts to string") { get(:'Input checkbox with parent label').should == 'input-checkbox-with-parent-label-data' }
244
- end
245
-
246
- describe '#radio_button' do
247
- subject{ :radio_button }
248
- it("finds radio buttons by id") { get('input-radio-with-id').should == 'input-radio-with-id-data' }
249
- it("finds radio buttons by name") { get('input-radio-with-name').should == 'input-radio-with-name-data' }
250
- it("finds radio buttons by label") { get('Input radio with label').should == 'input-radio-with-label-data' }
251
- it("finds radio buttons by parent label") { get('Input radio with parent label').should == 'input-radio-with-parent-label-data' }
252
- it("casts to string") { get(:'Input radio with parent label').should == 'input-radio-with-parent-label-data' }
253
- end
254
-
255
- describe '#file_field' do
256
- subject{ :file_field }
257
- it("finds file fields by id") { get('input-file-with-id').should == 'input-file-with-id-data' }
258
- it("finds file fields by name") { get('input-file-with-name').should == 'input-file-with-name-data' }
259
- it("finds file fields by label") { get('Input file with label').should == 'input-file-with-label-data' }
260
- it("finds file fields by parent label") { get('Input file with parent label').should == 'input-file-with-parent-label-data' }
261
- it("casts to string") { get(:'Input file with parent label').should == 'input-file-with-parent-label-data' }
262
- end
263
-
264
- describe "#optgroup" do
265
- subject { :optgroup }
266
- it("finds optgroups by label") { get('Group A').should == 'optgroup-a' }
267
- it("finds optgroups by approximate label") { get('oup A').should == 'optgroup-a' }
268
- it("casts to string") { get(:'Group A').should == 'optgroup-a' }
269
-
270
- context "with exact match", :type => :exact do
271
- it("finds by label") { get('Group A').should == 'optgroup-a' }
272
- it("does not find by approximate label") { get('oup A').should be_nil }
273
- end
274
- end
275
-
276
- describe '#option' do
277
- subject{ :option }
278
- it("finds by text") { get('Option with text').should == 'option-with-text-data' }
279
- it("finds by approximate text") { get('Option with').should == 'option-with-text-data' }
280
- it("casts to string") { get(:'Option with text').should == 'option-with-text-data' }
281
-
282
- context "with exact match", :type => :exact do
283
- it("finds by text") { get('Option with text').should == 'option-with-text-data' }
284
- it("does not find by approximate text") { get('Option with').should be_nil }
285
- end
286
- end
287
-
288
- describe "#table" do
289
- subject {:table}
290
- it("finds by id") { get('table-with-id').should == 'table-with-id-data' }
291
- it("finds by caption") { get('Table with caption').should == 'table-with-caption-data' }
292
- it("finds by approximate caption") { get('Table with').should == 'table-with-caption-data' }
293
- it("casts to string") { get(:'Table with caption').should == 'table-with-caption-data' }
294
-
295
- context "with exact match", :type => :exact do
296
- it("finds by caption") { get('Table with caption').should == 'table-with-caption-data' }
297
- it("does not find by approximate caption") { get('Table with').should be_nil }
298
- end
299
- end
300
-
301
- describe "#definition_description" do
302
- subject {:definition_description}
303
- let(:template) {'stuff'}
304
- it("find definition description by id") { get('latte').should == "with-id" }
305
- it("find definition description by term") { get("Milk").should == "with-dt" }
306
- it("casts to string") { get(:"Milk").should == "with-dt" }
307
- end
308
- end