xpath 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,5 @@
1
+ require 'nokogiri'
2
+
1
3
  module XPath
2
4
  autoload :Expression, 'xpath/expression'
3
5
  autoload :Union, 'xpath/union'
@@ -45,6 +47,17 @@ module XPath
45
47
  Expression::Variable.new(name)
46
48
  end
47
49
 
50
+ def string
51
+ Expression::StringFunction.new(current)
52
+ end
53
+
54
+ def css(selector)
55
+ paths = Nokogiri::CSS.xpath_for(selector).map do |selector|
56
+ Expression::CSS.new(current, Expression::Literal.new(selector))
57
+ end
58
+ Union.new(*paths)
59
+ end
60
+
48
61
  def varstring(name)
49
62
  var(name).string_literal
50
63
  end
@@ -25,9 +25,6 @@ module XPath
25
25
  def initialize(left, expressions)
26
26
  @left = wrap_xpath(left)
27
27
  @expressions = expressions.map { |e| wrap_xpath(e) }
28
- if @expressions.empty?
29
- raise ArgumentError, "must specify at least one expression"
30
- end
31
28
  end
32
29
  end
33
30
 
@@ -45,8 +42,10 @@ module XPath
45
42
  def to_xpath(predicate=nil)
46
43
  if @expressions.length == 1
47
44
  "#{@left.to_xpath(predicate)}/#{@expressions.first.to_xpath(predicate)}"
48
- else
45
+ elsif @expressions.length > 1
49
46
  "#{@left.to_xpath(predicate)}/*[#{@expressions.map { |e| "self::#{e.to_xpath(predicate)}" }.join(" | ")}]"
47
+ else
48
+ "#{@left.to_xpath(predicate)}/*"
50
49
  end
51
50
  end
52
51
  end
@@ -55,8 +54,10 @@ module XPath
55
54
  def to_xpath(predicate=nil)
56
55
  if @expressions.length == 1
57
56
  "#{@left.to_xpath(predicate)}//#{@expressions.first.to_xpath(predicate)}"
58
- else
57
+ elsif @expressions.length > 1
59
58
  "#{@left.to_xpath(predicate)}//*[#{@expressions.map { |e| "self::#{e.to_xpath(predicate)}" }.join(" | ")}]"
59
+ else
60
+ "#{@left.to_xpath(predicate)}//*"
60
61
  end
61
62
  end
62
63
  end
@@ -65,8 +66,10 @@ module XPath
65
66
  def to_xpath(predicate=nil)
66
67
  if @expressions.length == 1
67
68
  "#{@left.to_xpath(predicate)}/following-sibling::*[1]/self::#{@expressions.first.to_xpath(predicate)}"
68
- else
69
+ elsif @expressions.length > 1
69
70
  "#{@left.to_xpath(predicate)}/following-sibling::*[1]/self::*[#{@expressions.map { |e| "self::#{e.to_xpath(predicate)}" }.join(" | ")}]"
71
+ else
72
+ "#{@left.to_xpath(predicate)}/following-sibling::*[1]/self::*"
70
73
  end
71
74
  end
72
75
  end
@@ -211,6 +214,12 @@ module XPath
211
214
  end
212
215
  end
213
216
 
217
+ class CSS < Binary
218
+ def to_xpath(predicate=nil)
219
+ "#{@left.to_xpath}#{@right.to_xpath}"
220
+ end
221
+ end
222
+
214
223
  def current
215
224
  self
216
225
  end
@@ -237,10 +246,6 @@ module XPath
237
246
  Expression::Is.new(current, expression)
238
247
  end
239
248
 
240
- def string
241
- Expression::StringFunction.new(current)
242
- end
243
-
244
249
  def or(expression)
245
250
  Expression::Or.new(current, expression)
246
251
  end
@@ -3,13 +3,9 @@ module XPath
3
3
  include XPath
4
4
  extend self
5
5
 
6
- def from_css(css)
7
- XPath::Union.new(*Nokogiri::CSS.xpath_for(css).map { |selector| ::XPath::Expression::Literal.new(:".#{selector}") }.flatten)
8
- end
9
-
10
6
  def link(locator)
11
7
  link = descendant(:a)[attr(:href)]
12
- link[attr(:id).equals(locator) | text.is(locator) | attr(:title).is(locator) | descendant(:img)[attr(:alt).is(locator)]]
8
+ link[attr(:id).equals(locator) | string.n.is(locator) | attr(:title).is(locator) | descendant(:img)[attr(:alt).is(locator)]]
13
9
  end
14
10
 
15
11
  def content(locator)
@@ -18,7 +14,7 @@ module XPath
18
14
 
19
15
  def button(locator)
20
16
  button = descendant(:input)[attr(:type).one_of('submit', 'image', 'button')][attr(:id).equals(locator) | attr(:value).is(locator)]
21
- button += descendant(:button)[attr(:id).equals(locator) | attr(:value).is(locator) | text.is(locator)]
17
+ button += descendant(:button)[attr(:id).equals(locator) | attr(:value).is(locator) | string.n.is(locator)]
22
18
  button += descendant(:input)[attr(:type).equals('image')][attr(:alt).is(locator)]
23
19
  end
24
20
 
@@ -86,7 +82,7 @@ module XPath
86
82
  end
87
83
 
88
84
  def table_rows(rows)
89
- row_conditions = descendant(:tr)[table_row(rows.first)]
85
+ row_conditions = descendant(:tr)[table_row(rows.first)]
90
86
  rows.drop(1).each do |row|
91
87
  row_conditions = row_conditions.next_sibling(:tr)[table_row(row)]
92
88
  end
@@ -94,21 +90,13 @@ module XPath
94
90
  end
95
91
 
96
92
  def table_row(cells)
97
- cell_conditions = child(:td, :th)[text.equals(cells.first)]
93
+ cell_conditions = child(:td, :th)[text.equals(cells.first)]
98
94
  cells.drop(1).each do |cell|
99
95
  cell_conditions = cell_conditions.next_sibling(:td, :th)[text.equals(cell)]
100
96
  end
101
97
  cell_conditions
102
98
  end
103
99
 
104
- def wrap(path)
105
- if path.respond_to?(:to_xpaths)
106
- path.to_xpaths
107
- else
108
- [path.to_s].flatten
109
- end
110
- end
111
-
112
100
  protected
113
101
 
114
102
  def locate_field(xpath, locator)
@@ -1,3 +1,3 @@
1
1
  module XPath
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
@@ -1,5 +1,62 @@
1
1
  <h1>Form</h1>
2
2
 
3
+ <p>
4
+ <a id="awesome-link" href="#link">An awesome link</a>
5
+ <a id="some-id" href="#id">With id</a>
6
+ <a title="My title" href="#title">A cool title</a>
7
+ <a href="#image"><img src="foo.png" alt="Alt link"/></a>
8
+ <a title="This title is too long" href="#bar">A link at a time</a>
9
+ <a title="This title" href="#foo">A link</a>
10
+ <a href="#bar"><img src="foo.png" alt="An image that is beautiful"/></a>
11
+ <a href="#foo"><img src="foo.ong" alt="An image"/></a>
12
+ <a>Wrong Link</a>
13
+ <a href="#spacey"> My
14
+
15
+ whitespaced
16
+ link</a>
17
+ <a href="#has-children">
18
+ An <em>emphatic</em> link with some children
19
+ </a>
20
+ </p>
21
+
22
+ <p>
23
+ <input type="submit" id="submit-with-id" data="id-submit" value="Has ID"/>
24
+ <input type="submit" value="submit-with-value" data="value-submit"/>
25
+ <input type="submit" value="not exact value submit" data="not-exact-value-submit"/>
26
+ <input type="submit" value="exact value submit" data="exact-value-submit"/>
27
+
28
+ <input type="button" id="button-with-id" data="id-button" value="Has ID"/>
29
+ <input type="button" value="button-with-value" data="value-button"/>
30
+ <input type="button" value="not exact value button" data="not-exact-value-button"/>
31
+ <input type="button" value="exact value button" data="exact-value-button"/>
32
+
33
+ <input type="image" id="imgbut-with-id" data="id-imgbut" value="Has ID"/>
34
+ <input type="image" value="imgbut-with-value" data="value-imgbut"/>
35
+ <input type="image" alt="imgbut-with-alt" data="alt-imgbut"/>
36
+ <input type="image" value="not exact value imgbut" data="not-exact-value-imgbut"/>
37
+ <input type="image" value="exact value imgbut" data="exact-value-imgbut"/>
38
+
39
+ <button id="btag-with-id" data="id-btag" value="Has ID"/>
40
+ <button value="btag-with-value" data="value-btag"/>
41
+ <button value="not exact value btag" data="not-exact-value-btag"/>
42
+ <button value="exact value btag" data="exact-value-btag"/>
43
+
44
+ <button data="text-btag">btag-with-text</button>
45
+ <button data="not-exact-text-btag">not exact text btag</button>
46
+ <button data="exact-text-btag">exact text btag</button>
47
+
48
+ <button data="btag-with-whitespace"> My
49
+
50
+ whitespaced
51
+ button</button>
52
+ <button href="btag-with-children">
53
+ An <em>emphatic</em> button with some children
54
+ </button>
55
+
56
+ <input type="schmoo" value="schmoo button" data="schmoo"/>
57
+ </p>
58
+
59
+
3
60
  <form action="/form" method="post">
4
61
 
5
62
  <p>
@@ -32,7 +89,7 @@
32
89
  <label for="form_last_name">Last Name</label>
33
90
  <input type="text" name="form[last_name]" value="Smith" id="form_last_name"/>
34
91
  </p>
35
-
92
+
36
93
  <p>
37
94
  <label for="form_name_explanation">Explanation of Name</label>
38
95
  <textarea name="form[name_explanation]" id="form_name_explanation"></textarea>
@@ -47,7 +104,7 @@
47
104
  <label for="form_schmooo">Schmooo</label>
48
105
  <input type="schmooo" name="form[schmooo]" value="This is Schmooo!" id="form_schmooo"/>
49
106
  </p>
50
-
107
+
51
108
  <p>
52
109
  <label>Street<br/>
53
110
  <input type="text" name="form[street]" value="Sesame street 66"/>
@@ -74,7 +131,7 @@
74
131
  <label for="form_image">Image</label>
75
132
  <input type="file" name="form[image]" id="form_image"/>
76
133
  </p>
77
-
134
+
78
135
  <p>
79
136
  <input type="hidden" name="form[token]" value="12345" id="form_token"/>
80
137
  </p>
@@ -196,7 +253,7 @@
196
253
  <label for="form_document">Document</label>
197
254
  <input type="file" name="form[document]" id="form_document"/>
198
255
  </p>
199
-
256
+
200
257
  <p>
201
258
  <input type="submit" value="Upload"/>
202
259
  <p>
@@ -229,7 +286,7 @@
229
286
  <label for="html5_color">Html5 Color</label>
230
287
  <input type="color" name="form[html5_color]" value="#FFF" id="html5_color"/>
231
288
  </p>
232
-
289
+
233
290
  <p>
234
291
  <input type="submit" name="form[html5_submit]" value="html5_submit"/>
235
292
  </p>
@@ -24,3 +24,9 @@ A lot
24
24
  of
25
25
  whitespace
26
26
  </p>
27
+
28
+ <div id="moar">
29
+ <p id="impchay">chimp</p>
30
+ <p id="amingoflay">flamingo</p>
31
+ <div id="elephantay">elephant</div>
32
+ </div>
@@ -0,0 +1,195 @@
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
+
9
+ def get(xpath)
10
+ all(xpath).first
11
+ end
12
+
13
+ def all(xpath)
14
+ xpath.to_xpaths.map do |xpath|
15
+ doc.xpath(xpath)
16
+ end.flatten
17
+ end
18
+
19
+ describe '#link' do
20
+ it "finds links by id" do
21
+ get(XPath::HTML.link('some-id'))[:href].should == '#id'
22
+ end
23
+
24
+ it "finds links by content" do
25
+ get(XPath::HTML.link('An awesome link'))[:href].should == '#link'
26
+ end
27
+
28
+ it "finds links by content without caring about whitespace" do
29
+ get(XPath::HTML.link('My whitespaced link'))[:href].should == '#spacey'
30
+ end
31
+
32
+ it "finds links with child tags by content" do
33
+ get(XPath::HTML.link('An emphatic link'))[:href].should == '#has-children'
34
+ get(XPath::HTML.link('emphatic'))[:href].should == '#has-children'
35
+ end
36
+
37
+ it "finds links by approximate content" do
38
+ get(XPath::HTML.link('awesome'))[:href].should == '#link'
39
+ end
40
+
41
+ it "prefers exact matches of content" do
42
+ result = all(XPath::HTML.link('A link'))
43
+ result[0][:href].should == '#foo'
44
+ result[1][:href].should == '#bar'
45
+ end
46
+
47
+ it "finds links by title" do
48
+ get(XPath::HTML.link('My title'))[:href].should == '#title'
49
+ end
50
+
51
+ it "finds links by approximate title" do
52
+ get(XPath::HTML.link('title'))[:href].should == '#title'
53
+ end
54
+
55
+ it "prefers exact matches of title" do
56
+ result = all(XPath::HTML.link('This title'))
57
+ result[0][:href].should == '#foo'
58
+ result[1][:href].should == '#bar'
59
+ end
60
+
61
+ it "finds links by an image's alt attribute" do
62
+ get(XPath::HTML.link('Alt link'))[:href].should == '#image'
63
+ end
64
+
65
+ it "finds links by an image's approximate alt attribute" do
66
+ get(XPath::HTML.link('Alt'))[:href].should == '#image'
67
+ end
68
+
69
+ it "prefers exact matches of image's alt attribute" do
70
+ result = all(XPath::HTML.link('An image'))
71
+ result[0][:href].should == '#foo'
72
+ result[1][:href].should == '#bar'
73
+ end
74
+
75
+ it "does not find links without href attriutes" do
76
+ get(XPath::HTML.link('Wrong Link')).should be_nil
77
+ end
78
+ end
79
+
80
+ describe '#button' do
81
+ context "with submit type" do
82
+ it "finds buttons by id" do
83
+ get(XPath::HTML.button('submit-with-id'))[:data].should == 'id-submit'
84
+ end
85
+
86
+ it "finds buttons by value" do
87
+ get(XPath::HTML.button('submit-with-value'))[:data].should == 'value-submit'
88
+ end
89
+
90
+ it "finds buttons by approximate value " do
91
+ get(XPath::HTML.button('mit-with-val'))[:data].should == 'value-submit'
92
+ end
93
+
94
+ it "finds prefers buttons with exact value " do
95
+ results = all(XPath::HTML.button('exact value submit'))
96
+ results[0][:data].should == 'exact-value-submit'
97
+ results[1][:data].should == 'not-exact-value-submit'
98
+ end
99
+ end
100
+
101
+ context "with button type" do
102
+ it "finds buttons by id" do
103
+ get(XPath::HTML.button('button-with-id'))[:data].should == 'id-button'
104
+ end
105
+
106
+ it "finds buttons by value" do
107
+ get(XPath::HTML.button('button-with-value'))[:data].should == 'value-button'
108
+ end
109
+
110
+ it "finds buttons by approximate value " do
111
+ get(XPath::HTML.button('ton-with-val'))[:data].should == 'value-button'
112
+ end
113
+
114
+ it "finds prefers buttons with exact value " do
115
+ results = all(XPath::HTML.button('exact value button'))
116
+ results[0][:data].should == 'exact-value-button'
117
+ results[1][:data].should == 'not-exact-value-button'
118
+ end
119
+ end
120
+
121
+ context "with image type" do
122
+ it "finds buttons by id" do
123
+ get(XPath::HTML.button('imgbut-with-id'))[:data].should == 'id-imgbut'
124
+ end
125
+
126
+ it "finds buttons by value" do
127
+ get(XPath::HTML.button('imgbut-with-value'))[:data].should == 'value-imgbut'
128
+ end
129
+
130
+ it "finds buttons by approximate value " do
131
+ get(XPath::HTML.button('gbut-with-val'))[:data].should == 'value-imgbut'
132
+ end
133
+
134
+ it "finds buttons by alt attribute" do
135
+ get(XPath::HTML.button('imgbut-with-alt'))[:data].should == 'alt-imgbut'
136
+ end
137
+
138
+ it "prefers buttons with exact value " do
139
+ results = all(XPath::HTML.button('exact value imgbut'))
140
+ results[0][:data].should == 'exact-value-imgbut'
141
+ results[1][:data].should == 'not-exact-value-imgbut'
142
+ end
143
+ end
144
+
145
+ context "with button tag" do
146
+ it "finds buttons by id" do
147
+ get(XPath::HTML.button('btag-with-id'))[:data].should == 'id-btag'
148
+ end
149
+
150
+ it "finds buttons by value" do
151
+ get(XPath::HTML.button('btag-with-value'))[:data].should == 'value-btag'
152
+ end
153
+
154
+ it "finds buttons by approximate value " do
155
+ get(XPath::HTML.button('tag-with-val'))[:data].should == 'value-btag'
156
+ end
157
+
158
+ it "finds prefers buttons with exact value " do
159
+ results = all(XPath::HTML.button('exact value btag'))
160
+ results[0][:data].should == 'exact-value-btag'
161
+ results[1][:data].should == 'not-exact-value-btag'
162
+ end
163
+
164
+ it "finds buttons by text" do
165
+ get(XPath::HTML.button('btag-with-text'))[:data].should == 'text-btag'
166
+ end
167
+
168
+ it "finds buttons by text ignoring whitespace" do
169
+ get(XPath::HTML.button('My whitespaced button'))[:data].should == 'btag-with-whitespace'
170
+ end
171
+
172
+ it "finds buttons by approximate text " do
173
+ get(XPath::HTML.button('tag-with-tex'))[:data].should == 'text-btag'
174
+ end
175
+
176
+ it "finds buttons with child tags by text" do
177
+ get(XPath::HTML.button('An emphatic button'))[:href].should == 'btag-with-children'
178
+ get(XPath::HTML.button('emphatic'))[:href].should == 'btag-with-children'
179
+ end
180
+
181
+ it "prefers buttons with exact text" do
182
+ results = all(XPath::HTML.button('exact text btag'))
183
+ results[0][:data].should == 'exact-text-btag'
184
+ results[1][:data].should == 'not-exact-text-btag'
185
+ end
186
+ end
187
+
188
+ context "with unkown type" do
189
+ it "does not find the button" do
190
+ get(XPath::HTML.button('schmoo button')).should be_nil
191
+ end
192
+ end
193
+
194
+ end
195
+ end
@@ -43,6 +43,12 @@ describe XPath do
43
43
  @results[0].text.should == 'Blah'
44
44
  @results[3].text.should == 'A list'
45
45
  end
46
+
47
+ it "should find all nodes when no arguments given" do
48
+ @results = xpath { |x| x.descendant[x.attr(:id) == 'foo'].descendant }
49
+ @results[0].text.should == 'Blah'
50
+ @results[4].text.should == 'A list'
51
+ end
46
52
  end
47
53
 
48
54
  describe '#child' do
@@ -62,6 +68,12 @@ describe XPath do
62
68
  @results[0].text.should == 'Blah'
63
69
  @results[3].text.should == 'A list'
64
70
  end
71
+
72
+ it "should find all nodes when no arguments given" do
73
+ @results = xpath { |x| x.descendant[x.attr(:id) == 'foo'].child }
74
+ @results[0].text.should == 'Blah'
75
+ @results[3].text.should == 'A list'
76
+ end
65
77
  end
66
78
 
67
79
  describe '#next_sibling' do
@@ -70,6 +82,7 @@ describe XPath do
70
82
  xpath { |x| x.descendant(:p)[x.attr(:id) == 'fooDiv'].next_sibling(:ul, :p) }.first.text.should == 'Bax'
71
83
  xpath { |x| x.descendant(:p)[x.attr(:title) == 'monkey'].next_sibling(:ul, :p) }.first.text.should == 'A list'
72
84
  xpath { |x| x.descendant(:p)[x.attr(:id) == 'fooDiv'].next_sibling(:ul, :li) }.first.should be_nil
85
+ xpath { |x| x.descendant(:p)[x.attr(:id) == 'fooDiv'].next_sibling }.first.text.should == 'Bax'
73
86
  end
74
87
  end
75
88
 
@@ -221,7 +234,7 @@ describe XPath do
221
234
  @results[0][:title].should == "barDiv"
222
235
  @results[1][:title].should == "fooDiv"
223
236
  end
224
-
237
+
225
238
  it "should be closed" do
226
239
  @results = xpath do |x|
227
240
  foo_div = x.anywhere(:div).where(x.attr(:id) == 'foo')
@@ -231,6 +244,27 @@ describe XPath do
231
244
  end
232
245
  end
233
246
 
247
+ describe '#css' do
248
+ it "should find nodes by the given CSS selector" do
249
+ @results = xpath { |x| x.css('#preference p') }
250
+ @results[0].text.should == 'allamas'
251
+ @results[1].text.should == 'llama'
252
+ end
253
+
254
+ it "should respect previous expression" do
255
+ @results = xpath { |x| x.descendant[x.attr(:id) == 'moar'].css('p') }
256
+ @results[0].text.should == 'chimp'
257
+ @results[1].text.should == 'flamingo'
258
+ end
259
+
260
+ it "should allow comma separated selectors" do
261
+ @results = xpath { |x| x.descendant[x.attr(:id) == 'moar'].css('div, p') }
262
+ @results[0].text.should == 'chimp'
263
+ @results[1].text.should == 'flamingo'
264
+ @results[2].text.should == 'elephant'
265
+ end
266
+ end
267
+
234
268
  describe '#name' do
235
269
  it "should match the node's name" do
236
270
  xpath { |x| x.descendant(:*).where(x.name == 'ul') }.first.text.should == "A list"
@@ -250,7 +284,11 @@ describe XPath do
250
284
 
251
285
  it "should raise an argument error if the interpolation key is not given" do
252
286
  @xpath = XPath.generate { |x| x.descendant(:*).where(x.attr(:id) == x.var(:id).string_literal) }
253
- lambda { @xpath.apply.to_xpath }.should raise_error(ArgumentError)
287
+ if defined?(KeyError)
288
+ lambda { @xpath.apply.to_xpath }.should raise_error(KeyError)
289
+ else
290
+ lambda { @xpath.apply.to_xpath }.should raise_error(ArgumentError)
291
+ end
254
292
  end
255
293
  end
256
294
 
@@ -274,8 +312,8 @@ describe XPath do
274
312
 
275
313
  describe '#union' do
276
314
  it "should create a union expression" do
277
- @expr1 = XPath.generate { |x| x.descendant(:p) }
278
- @expr2 = XPath.generate { |x| x.descendant(:div) }
315
+ @expr1 = XPath.generate { |x| x.descendant(:p) }
316
+ @expr2 = XPath.generate { |x| x.descendant(:div) }
279
317
  @collection = @expr1.union(@expr2)
280
318
  @xpath1 = @collection.where(XPath.attr(:id) == 'foo').to_xpath
281
319
  @xpath2 = @collection.where(XPath.attr(:id) == XPath.varstring(:id)).apply(:id => 'fooDiv').to_xpath
@@ -286,8 +324,8 @@ describe XPath do
286
324
  end
287
325
 
288
326
  it "should be aliased as +" do
289
- @expr1 = XPath.generate { |x| x.descendant(:p) }
290
- @expr2 = XPath.generate { |x| x.descendant(:div) }
327
+ @expr1 = XPath.generate { |x| x.descendant(:p) }
328
+ @expr2 = XPath.generate { |x| x.descendant(:div) }
291
329
  @collection = @expr1 + @expr2
292
330
  @xpath1 = @collection.where(XPath.attr(:id) == 'foo').to_xpath
293
331
  @xpath2 = @collection.where(XPath.attr(:id) == XPath.varstring(:id)).apply(:id => 'fooDiv').to_xpath
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xpath
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 0
10
- version: 0.1.0
9
+ - 1
10
+ version: 0.1.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jonas Nicklas
@@ -15,39 +15,38 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-15 00:00:00 +02:00
18
+ date: 2010-10-06 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: rspec
22
+ name: nokogiri
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - ">="
27
+ - - ~>
28
28
  - !ruby/object:Gem::Version
29
- hash: 13
29
+ hash: 9
30
30
  segments:
31
31
  - 1
32
- - 2
33
- - 9
34
- version: 1.2.9
35
- type: :development
32
+ - 3
33
+ version: "1.3"
34
+ type: :runtime
36
35
  version_requirements: *id001
37
36
  - !ruby/object:Gem::Dependency
38
- name: nokogiri
37
+ name: rspec
39
38
  prerelease: false
40
39
  requirement: &id002 !ruby/object:Gem::Requirement
41
40
  none: false
42
41
  requirements:
43
42
  - - ">="
44
43
  - !ruby/object:Gem::Version
45
- hash: 29
44
+ hash: 13
46
45
  segments:
47
46
  - 1
48
- - 3
49
- - 3
50
- version: 1.3.3
47
+ - 2
48
+ - 9
49
+ version: 1.2.9
51
50
  type: :development
52
51
  version_requirements: *id002
53
52
  - !ruby/object:Gem::Dependency
@@ -84,6 +83,7 @@ files:
84
83
  - spec/fixtures/form.html
85
84
  - spec/fixtures/simple.html
86
85
  - spec/fixtures/stuff.html
86
+ - spec/html_spec.rb
87
87
  - spec/spec_helper.rb
88
88
  - spec/union_spec.rb
89
89
  - spec/xpath_spec.rb