hmachine 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/.gitignore +2 -2
  2. data/Gemfile +6 -4
  3. data/Gemfile.lock +51 -0
  4. data/README.md +123 -9
  5. data/Rakefile +12 -3
  6. data/bin/hmachine +99 -0
  7. data/hmachine.gemspec +132 -0
  8. data/lib/hmachine.rb +121 -12
  9. data/lib/hmachine/microformat.rb +39 -20
  10. data/lib/hmachine/microformat/adr.rb +22 -0
  11. data/lib/hmachine/microformat/geo.rb +48 -0
  12. data/lib/hmachine/microformat/hcard.rb +169 -11
  13. data/lib/hmachine/microformat/rellicense.rb +20 -0
  14. data/lib/hmachine/microformat/reltag.rb +38 -0
  15. data/lib/hmachine/microformat/votelinks.rb +42 -0
  16. data/lib/hmachine/microformat/xfn.rb +54 -0
  17. data/lib/hmachine/microformat/xmdp.rb +14 -0
  18. data/lib/hmachine/microformat/xoxo.rb +69 -0
  19. data/lib/hmachine/pattern.rb +26 -0
  20. data/lib/hmachine/pattern/abbr.rb +21 -0
  21. data/lib/hmachine/pattern/datetime.rb +75 -0
  22. data/lib/hmachine/pattern/typevalue.rb +32 -0
  23. data/lib/hmachine/pattern/url.rb +32 -0
  24. data/lib/hmachine/pattern/valueclass.rb +51 -0
  25. data/lib/hmachine/posh.rb +3 -0
  26. data/lib/hmachine/posh/anchor.rb +40 -0
  27. data/lib/hmachine/posh/base.rb +204 -0
  28. data/lib/hmachine/posh/definition_list.rb +41 -0
  29. data/test/fixtures/huffduffer.html +466 -0
  30. data/test/fixtures/likeorhate.html +48 -0
  31. data/test/fixtures/rel_license.html +4 -0
  32. data/test/fixtures/test-fixture/hcard/hcard1.html +147 -0
  33. data/test/fixtures/test-fixture/hcard/hcard11.html +123 -0
  34. data/test/fixtures/test-fixture/hcard/hcard12.html +178 -0
  35. data/test/fixtures/test-fixture/hcard/hcard17.html +165 -0
  36. data/test/fixtures/test-fixture/hcard/hcard2.html +264 -0
  37. data/test/fixtures/test-fixture/hcard/hcard3.html +144 -0
  38. data/test/fixtures/test-fixture/hcard/hcard4.html +117 -0
  39. data/test/fixtures/test-fixture/hcard/hcard5.html +119 -0
  40. data/test/fixtures/test-fixture/hcard/hcard6.html +188 -0
  41. data/test/fixtures/test-fixture/hcard/hcard7.html +188 -0
  42. data/test/fixtures/test-fixture/hcard/hcard8.html +130 -0
  43. data/test/fixtures/test-fixture/hcard/hcard9.html +111 -0
  44. data/test/fixtures/test-fixture/hcard/hcard99.html +215 -0
  45. data/test/fixtures/test-fixture/value-class-date-time/value-dt-test-YYYY-MM-DD--HH-MM.html +9 -0
  46. data/test/fixtures/test-fixture/value-class-date-time/value-dt-test-abbr-YYYY-MM-DD--HH-MM.html +4 -0
  47. data/test/fixtures/xfn.html +198 -0
  48. data/test/fixtures/xmdp.html +32 -0
  49. data/test/fixtures/xoxo.html +51 -0
  50. data/test/hmachine_test.rb +122 -6
  51. data/test/microformat/adr_test.rb +47 -0
  52. data/test/microformat/geo_test.rb +66 -0
  53. data/test/microformat/hcard_test.rb +487 -20
  54. data/test/microformat/rellicense_test.rb +36 -0
  55. data/test/microformat/reltag_test.rb +61 -0
  56. data/test/microformat/votelinks_test.rb +44 -0
  57. data/test/microformat/xfn_test.rb +28 -0
  58. data/test/microformat/xmdp_test.rb +16 -0
  59. data/test/microformat/xoxo_test.rb +51 -0
  60. data/test/microformat_test.rb +12 -34
  61. data/test/pattern/date_time_test.rb +55 -0
  62. data/test/pattern/value_class_test.rb +33 -0
  63. data/test/pattern_test.rb +132 -0
  64. data/test/posh/anchor_test.rb +41 -0
  65. data/test/posh/base_test.rb +150 -0
  66. data/test/posh/definition_list_test.rb +38 -0
  67. data/test/test_helper.rb +24 -6
  68. metadata +93 -15
  69. data/lib/hmachine/microformat/base.rb +0 -17
@@ -0,0 +1,9 @@
1
+ <div id="uf">
2
+ <span class="dtstart">
3
+ <span class="value">2009-06-26</span> at <span class="value">19:00</span>
4
+ </span>
5
+ to
6
+ <span class="dtend">
7
+ <span class="value">2009-06-26</span> at <span class="value">22:00</span>
8
+ </span>
9
+ </div>
@@ -0,0 +1,4 @@
1
+ <span class="dtstart">
2
+ <abbr class="value" title="2008-06-24">this Tuesday</abbr>
3
+ at <span class="value">18:30</span>
4
+ </span>
@@ -0,0 +1,198 @@
1
+ <!DOCTYPE html PUBdtC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
5
+ <title>XFN Test Data</title>
6
+ <style type="text/css">
7
+ body {
8
+ font-family: Helvetica, Arial, sans-serif;
9
+ color: #161616;
10
+ }
11
+ h1, h2, h3, h4 {
12
+ color: #333;
13
+ }
14
+
15
+ h1 {
16
+ font-weight: normal;
17
+ font-size: 240%;
18
+ }
19
+
20
+ dt {
21
+ font-weight: bold;
22
+ padding-left:20px;
23
+ }
24
+
25
+ .valid dt {
26
+ color: #45C445;
27
+ }
28
+ .invalid dt {
29
+ color: #D22828;
30
+ }
31
+ a { color: #666666; }
32
+ </style>
33
+ </head>
34
+
35
+ <body>
36
+ <h1>XFN Test Data</h1>
37
+ <h4>Steve Ivy, 02-05-2007</h4>
38
+ <p>This test data is based on the <a href="http://gmpg.org/xfn/11">XFN 1.1 profile</a>. Comments or suggestions on this data can be sent to <a href="mailto:steveivy@gmail.com">steveivy@gmail.com</a>.</p>
39
+ <h3>Valid Relationships - singletons</h3>
40
+ <p>These represent a single relationship on each link and are all valid.</p>
41
+
42
+ <dl class="valid">
43
+ <dt>Friendship - pick at most one</dt>
44
+ <dd><a href="#contact" rel="contact">friend - contact</a></dd>
45
+ <dd><a href="#acquaintance" rel="acquaintance">friend - acquaintance</a></dd>
46
+ <dd><a href="#friend" rel="friend">friend - friend</a></dd>
47
+ </dl>
48
+
49
+ <dl class="valid">
50
+ <dt>Physical</dt>
51
+ <dd><a href="#met" rel="met">physical - met</a></dd>
52
+ </dl>
53
+
54
+ <dl class="valid">
55
+ <dt>Professional</dt>
56
+ <dd><a href="#co-worker" rel="co-worker">professional - co-worker</a></dd>
57
+ <dd><a href="#colleague" rel="colleague">professional - colleague</a></dd>
58
+ </dl>
59
+
60
+ <dl class="valid">
61
+ <dt>Geographical - pick at most one</dt>
62
+ <dd><a href="#co-resident" rel="co-resident">geographical - co-resident</a></dd>
63
+ <dd><a href="#neighbor" rel="neighbor">geographical - neighbor</a></dd>
64
+ </dl>
65
+
66
+ <dl class="valid">
67
+ <dt>Family - pick at most one</dt>
68
+ <dd><a href="#child" rel="child">family - child</a></dd>
69
+ <dd><a href="#parent" rel="parent">family - parent</a></dd>
70
+ <dd><a href="#sibling" rel="sibling">family - sibling</a></dd>
71
+ <dd><a href="#spouse" rel="spouse">family - spouse</a></dd>
72
+ <dd><a href="#kin" rel="kin">family - kin</a></dd>
73
+ </dl>
74
+
75
+ <dl class="valid">
76
+ <dt>Romantic</dt>
77
+ <dd><a href="#muse" rel="muse">romantic - muse</a></dt>
78
+ <dd><a href="#crush" rel="crush">romantic - crush</a></dd>
79
+ <dd><a href="#date" rel="colleague">romantic - date</a></dd>
80
+ <dd><a href="#sweetheart" rel="sweetheart">romantic - sweetheart</a></dd>
81
+ </dl>
82
+
83
+ <dl class="valid">
84
+ <dt>Identity</dt>
85
+ <dd><a href="#me" rel="me">me</a> (exclusive of all other values)</dd>
86
+ </dl>
87
+
88
+ <h3>Valid Relationships - compound</h3>
89
+ <p>These represent compound relationship on each link and should all be valid.</p>
90
+
91
+ <dl class="valid">
92
+ <dt>Friendship + Physical</dt>
93
+ <dd><a href="#contact" rel="contact met">contact + met</a></dd>
94
+ <dd><a href="#acquaintance" rel="acquaintance met">acquaintance + met</a></dd>
95
+ <dd><a href="#friend" rel="friend met">friend + met</a></dd>
96
+ </dl>
97
+
98
+ <dl class="valid">
99
+ <dt>Friendship + Professional</dt>
100
+ <dd><a href="#contact" rel="contact co-worker">contact + co-worker</a></dd>
101
+ <dd><a href="#acquaintance" rel="acquaintance co-worker">acquaintance + co-worker</a></dd>
102
+ <dd><a href="#friend" rel="friend co-worker">friend + co-worker</a></dd>
103
+ </dl>
104
+
105
+ <dl class="valid">
106
+ <dt>Friendship + Geographic</dt>
107
+ <dd><a href="#contact" rel="contact co-resident">contact + co-resident</a></dd>
108
+ <dd><a href="#acquaintance" rel="acquaintance co-resident">acquaintance + co-resident</a></dd>
109
+ <dd><a href="#friend" rel="friend co-resident">friend - co-resident</a></dd>
110
+ <dd><a href="#contact2" rel="contact co-resident">contact + neighbor</a></dd>
111
+ <dd><a href="#acquaintance2" rel="acquaintance neighbor">acquaintance + neighbor</a></dd>
112
+ <dd><a href="#friend2" rel="friend neighbor">friend - neighbor</a></dd>
113
+ </dl>
114
+
115
+ <dl class="valid">
116
+ <dt>Professional + Physical</dt>
117
+ <dd><a href="#co-worker" rel="co-worker met">co-worker + met</a></dd>
118
+ <dd><a href="#colleague" rel="colleague met">colleague + met</a></dd>
119
+ </dl>
120
+
121
+ <dl class="valid">
122
+ <dt>Professional + Romantic</dt>
123
+ <dd><a href="#co-worker" rel="co-worker muse">co-worker + muse</a></dd>
124
+ <dd><a href="#colleague" rel="colleague muse">colleague + muse</a></dd>
125
+ <dd><a href="#co-worker" rel="co-worker crush">co-worker + crush</a></dd>
126
+ <dd><a href="#colleague" rel="colleague crush">colleague + crush</a></dd>
127
+ <dd><a href="#co-worker" rel="co-worker date">co-worker + date</a></dd>
128
+ <dd><a href="#colleague" rel="colleague date">colleague + date</a></dd>
129
+ <dd><a href="#co-worker" rel="co-worker sweetheart">co-worker + sweetheart</a></dd>
130
+ <dd><a href="#colleague" rel="colleague sweetheart">colleague + sweetheart</a></dd>
131
+ </dl>
132
+
133
+ <dl class="valid">
134
+ <dt>Family + Professional</dt>
135
+ <dd><a href="#child" rel="child co-worker">child + co-worker</a></dd>
136
+ <dd><a href="#child" rel="child colleague">child + colleague</a></dd>
137
+ <dd><a href="#parent" rel="parent co-worker">parent + co-worker</a></dd>
138
+ <dd><a href="#parent" rel="parent colleague">parent + colleague</a></dd>
139
+ <dd><a href="#sibling" rel="sibling co-worker">sibling + co-worker</a></dd>
140
+ <dd><a href="#sibling" rel="sibling colleague">sibling + colleague</a></dd>
141
+ <dd><a href="#spouse" rel="spouse co-worker">spouse + co-worker</a></dd>
142
+ <dd><a href="#spouse" rel="spouse colleague">spouse + colleague</a></dd>
143
+ <dd><a href="#kin" rel="kin co-worker">kin + co-worker</a></dd>
144
+ <dd><a href="#kin" rel="kin colleague">kin + colleague</a></dd>
145
+ </dl>
146
+
147
+ <h3>Invalid relationships</h3>
148
+ <p>These relationships violate rules of exclusivity, mostly.</p>
149
+
150
+ <dl class="invalid">
151
+ <dt>Friendship - multiple values</dt>
152
+ <dd><a href="#contact" rel="contact acquaintance">contact + acquaintance</a></dd>
153
+ <dd><a href="#acquaintance" rel="acquaintance friend">acquaintance + friend</a></dd>
154
+ <dd><a href="#friend" rel="friend contact">friend + contact</a></dd>
155
+ </dl>
156
+
157
+ <dl class="invalid">
158
+ <dt>Geographical - multiple values</dt>
159
+ <dd><a href="#co-resident" rel="co-resident neighbor">co-resident + neighbor</a></dd>
160
+ </dl>
161
+
162
+ <dl class="invalid">
163
+ <dt>Family - multiple values</dt>
164
+ <dd><a href="#child" rel="child parent">child + parent</a></dd>
165
+ <dd><a href="#child" rel="child sibling">child + sibling</a></dd>
166
+ <dd><a href="#child" rel="child spouse">child + spouse</a></dd>
167
+ <dd><a href="#child" rel="child kin">child + kin</a></dd>
168
+ <dd><a href="#parent" rel="parent sibling">parent + sibling</a></dd>
169
+ <dd><a href="#parent" rel="parent spouse">parent + spouse</a></dd>
170
+ <dd><a href="#parent" rel="parent kin">parent + kin</a></dd>
171
+ <dd><a href="#sibling" rel="sibling spouse">sibling + spouse</a></dd>
172
+ <dd><a href="#sibling" rel="sibling kin">sibling + kin</a></dd>
173
+ <dd><a href="#spouse" rel="spouse kin">spouse + kin</a></dd>
174
+ </dl>
175
+
176
+ <dl class="invalid">
177
+ <dt>Identity - me + anything</dt>
178
+ <dd><a href="#contact" rel="me contact">me + contact</a></dd>
179
+ <dd><a href="#acquaintance" rel="me acquaintance">me + acquaintance</a></dd>
180
+ <dd><a href="#friend" rel="me friend">me + friend</a></dd>
181
+ <dd><a href="#met" rel="me met">me + met</a></dd>
182
+ <dd><a href="#co-worker" rel="me co-worker">me + co-worker</a></dd>
183
+ <dd><a href="#colleague" rel="me colleague">me + colleague</a></dd>
184
+ <dd><a href="#co-resident" rel="me co-resident">me + co-resident</a></dd>
185
+ <dd><a href="#neighbor" rel="me neighbor">me + neighbor</a></dd>
186
+ <dd><a href="#child" rel="me child">me + child</a></dd>
187
+ <dd><a href="#parent" rel="me parent">me + parent</a></dd>
188
+ <dd><a href="#sibling" rel="me sibling">me + sibling</a></dd>
189
+ <dd><a href="#spouse" rel="me spouse">me + spouse</a></dd>
190
+ <dd><a href="#kin" rel="me kin">me + kin</a></dd>
191
+ <dd><a href="#muse" rel="me muse">me + muse</a></dt>
192
+ <dd><a href="#crush" rel="me crush">me + crush</a></dd>
193
+ <dd><a href="#date" rel="me colleague">me + date</a></dd>
194
+ <dd><a href="#sweetheart" rel="me sweetheart">me + sweetheart</a></dd>
195
+ </dl>
196
+
197
+ </body>
198
+ </html>
@@ -0,0 +1,32 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head><title>sample HTML profile</title>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
6
+ </head>
7
+ <body>
8
+ <dl class="profile">
9
+ <dt id='author'>author</dt>
10
+ <dd>A person who wrote (at least part of) the document.</dd>
11
+ <dt id='keywords'>keywords</dt>
12
+ <dd>A comma and/or space separated list of the
13
+ keywords or keyphrases of the document.</dd>
14
+ <dt id='copyright'>copyright</dt>
15
+ <dd>The name (or names) of the copyright holder(s)
16
+ for this document, and/or a complete statement of copyright.</dd>
17
+ <dt id='date'>date</dt>
18
+ <dd>The last updated date of the document, in ISO8601 date format.</dd>
19
+ <dt id='identifier'>identifier</dt>
20
+ <dd>The normative URI for the document.</dd>
21
+ <dt id='rel'>rel</dt>
22
+ <dd>
23
+ <dl>
24
+ <dt id='script'>script</dt>
25
+ <dd>A reference to a client-side script. When used with the
26
+ LINK element, the script is evaluated as the document loads and
27
+ may modify the contents of the document dynamically.</dd>
28
+ </dl>
29
+ </dd>
30
+ </dl>
31
+ </body>
32
+ </html>
@@ -0,0 +1,51 @@
1
+ <ol class='xoxo'>
2
+ <li>Subject 1
3
+ <ol>
4
+ <li>subpoint a</li>
5
+ <li>subpoint b</li>
6
+ </ol>
7
+ </li>
8
+ <li>Subject 2
9
+ <ol compact="compact">
10
+ <li>subpoint c</li>
11
+ <li>subpoint d</li>
12
+ </ol>
13
+ </li>
14
+ <li>Subject 3
15
+ <ol>
16
+ <li>subpoint e</li>
17
+ <li>subpoint f
18
+ <ol>
19
+ <li>subsubpoint i</li>
20
+ <li>subsubpoint ii</li>
21
+ </ol>
22
+ </li>
23
+ </ol>
24
+ </li>
25
+ <li>
26
+ <dl>
27
+ <dt>text</dt>
28
+ <dd>item 1</dd>
29
+ <dt>description</dt>
30
+ <dd>This item represents the main point we're trying to make.</dd>
31
+ <dt>url</dt>
32
+ <dd>http://example.com/more.xoxo</dd>
33
+ <dt>title</dt>
34
+ <dd>title of item 1</dd>
35
+ <dt>type</dt>
36
+ <dd>text/xml</dd>
37
+ <dt>rel</dt>
38
+ <dd>help</dd>
39
+ </dl>
40
+ </li>
41
+ <li>
42
+ <a href="http://example.com/more.xoxo"
43
+ title="title of item 1"
44
+ type="text/xml"
45
+ rel="help">item 1</a>
46
+ <dl>
47
+ <dt>description</dt>
48
+ <dd>This item represents the main point we're trying to make.</dd>
49
+ </dl>
50
+ </li>
51
+ </ol>
@@ -2,16 +2,132 @@ require File.join(File.dirname(__FILE__), 'test_helper')
2
2
 
3
3
  class HMachineTest < Test::Unit::TestCase
4
4
  setup do
5
+ FakeWeb.register_uri(:get, "http://markwunsch.com/", :body => "Nothing to be found 'round here")
5
6
  @html = get_fixture('hcard/commercenet.html')
7
+ @doc = Nokogiri.parse(@html)
6
8
  end
7
9
 
8
- test 'gets a Nokogiri doc for a string of HTML' do
9
- doc = HMachine.get_document(@html)
10
- assert doc.is_a?(Nokogiri::HTML::Document), "Document is a #{doc.class}"
10
+ teardown do
11
+ FakeWeb.clean_registry
11
12
  end
12
13
 
13
- test 'finds the microformats in a document' do
14
- microformats = HMachine.find(@html)
15
- assert microformats.respond_to? :length
14
+ describe 'Class Level Methods' do
15
+ should 'normalize names' do
16
+ assert_equal :hcard, HMachine.normalize("hCard")
17
+ end
18
+
19
+ should 'map symbol names to Extraction methods' do
20
+ assert_equal HMachine::Pattern::ValueClass, HMachine.map(:value_class)
21
+ end
22
+
23
+ should 'parse an html document into a Nokogiri doc' do
24
+ assert HMachine.get_document('<div id="hello">World</div').is_a?(Nokogiri::XML::Node)
25
+ end
26
+
27
+ should 'open a url and get the document' do
28
+ doc = HMachine.get_url('http://markwunsch.com')
29
+ assert doc.is_a?(Nokogiri::XML::Document)
30
+ end
31
+
32
+ should 'get a document with a url or a string of html' do
33
+ doc = HMachine.get('http://markwunsch.com')
34
+ assert doc.is_a?(Nokogiri::XML::Document)
35
+ assert_equal 'http://markwunsch.com/', doc.url
36
+ assert HMachine.get('<p>Hello world</p>').is_a?(Nokogiri::XML::Document)
37
+ end
38
+
39
+ should 'find all microformats in a document' do
40
+ huffduff = HMachine.find get_fixture('huffduffer.html')
41
+ assert_equal 45, huffduff.count
42
+ end
43
+
44
+ should 'find a specific format in a document' do
45
+ huffduff = get_fixture('huffduffer.html')
46
+ hcards = HMachine.find huffduff, :hcard
47
+ assert_equal 10, hcards.count
48
+ end
49
+ end
50
+
51
+ describe 'Module' do
52
+ setup do
53
+ @klass = Class.new.send(:include, HMachine)
54
+ end
55
+
56
+ should 'define a function to search nodes' do
57
+ test = @klass.new
58
+ test.search {|node| node.css('div') }
59
+ assert_respond_to test.search, :call
60
+ end
61
+
62
+ should 'find an element in a node' do
63
+ test = @klass.new
64
+ test.search {|node| node.css('div') }
65
+ assert test.find_in(@doc).is_a?(Nokogiri::XML::NodeSet), "Search resulted in #{test.find_in(@doc).class}"
66
+ end
67
+
68
+ should 'test if an element can be found in a node' do
69
+ test = @klass.new
70
+ test.search {|node| node.css('foobar') }
71
+ assert !test.found_in?(@doc)
72
+ end
73
+
74
+ should 'define a function to validate nodes' do
75
+ test = @klass.new
76
+ test.validate {|node| true if node }
77
+ assert_respond_to test.validate, :call
78
+ end
79
+
80
+ should 'have a smart default validation method' do
81
+ test = @klass.new
82
+ node = @doc.css('.vcard').first
83
+ assert test.validate.call(node)
84
+ end
85
+
86
+ should 'test if a node is valid' do
87
+ test = @klass.new
88
+ node = @doc.css('.vcard').first
89
+ test.validate { |node| node['class'] == 'vcard' }
90
+ assert test.valid?(node)
91
+ end
92
+
93
+ should 'define an extraction method' do
94
+ test = @klass.new
95
+ test.extract {|node| node.content }
96
+ assert_respond_to test.extract, :call
97
+ end
98
+
99
+ should 'extract node content if no parsers are defined' do
100
+ test = @klass.new
101
+ assert_equal @doc.content.strip, test.extract_from(@doc)
102
+ end
103
+
104
+ should 'attempt to use a parser to extract content from node' do
105
+ test = @klass.new
106
+ test.extract {|node| node.css('a.fn').first['href'] }
107
+ assert_equal @doc.css('a.fn').first['href'], test.extract_from(@doc)
108
+ end
109
+
110
+ should "parse a node, extracting its contents" do
111
+ test = @klass.new
112
+ test.search {|node| node.css('.fn') }
113
+ assert_equal @doc.css('.fn').first.content, test.parse(@doc)
114
+ end
115
+
116
+ should 'parse a document, and return an array of contents' do
117
+ test = @klass.new
118
+ tel_type = @doc.css('.tel > .type').collect {|node| node.content }
119
+ test.search {|node| node.css('.tel') }
120
+ test.extract {|node| node.css('.type').first.content }
121
+ assert_equal tel_type, test.parse(@doc)
122
+ end
123
+
124
+ should 'parse the first instance of an element in a node' do
125
+ test = @klass.new
126
+ tel_type = @doc.css('.tel > .type').collect {|node| node.content }
127
+ test.search {|node| node.css('.tel') }
128
+ test.extract {|node| node.css('.type').first.content }
129
+ assert_equal tel_type.first, test.parse_first(@doc)
130
+ end
131
+
16
132
  end
17
133
  end
@@ -0,0 +1,47 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper')
2
+
3
+ class AdrTest < Test::Unit::TestCase
4
+ setup do
5
+ @klass = HMachine::Microformat::Adr
6
+ @html = %Q{<div class="adr">
7
+ <div class="street-address">665 3rd St.</div>
8
+ <div class="extended-address">Suite 207</div>
9
+ <span class="locality">San Francisco</span>,
10
+ <span class="region">CA</span>
11
+ <span class="postal-code">94107</span>
12
+ <div class="country-name">U.S.A.</div>
13
+ </div>}
14
+ @doc = Nokogiri.parse(@html)
15
+ @adr = @klass.parse_first(@doc)
16
+ end
17
+
18
+ should 'have a street address' do
19
+ assert @adr.has_property?(:street_address)
20
+ assert_equal '665 3rd St.', @adr.street_address
21
+ end
22
+
23
+ should 'have an extended address' do
24
+ assert @adr.has_property?(:extended_address)
25
+ assert_equal 'Suite 207', @adr.extended_address
26
+ end
27
+
28
+ should 'have a locality' do
29
+ assert @adr.has_property?(:locality)
30
+ assert_equal 'San Francisco', @adr.locality
31
+ end
32
+
33
+ should 'have a region' do
34
+ assert @adr.has_property?(:region)
35
+ assert_equal 'CA', @adr.region
36
+ end
37
+
38
+ should 'have a postal code' do
39
+ assert @adr.has_property?(:postal_code)
40
+ assert_equal '94107', @adr.postal_code
41
+ end
42
+
43
+ should 'have a country name' do
44
+ assert @adr.has_property?(:country_name)
45
+ assert_equal 'U.S.A.', @adr.country_name
46
+ end
47
+ end