xpath 0.1.0 → 0.1.1

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.
@@ -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