uformats 1.2.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.
@@ -0,0 +1,500 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+ require 'uformats/hreview'
3
+ require 'uformats/hcalendar'
4
+
5
+ class HReviewTest < Test::Unit::TestCase
6
+
7
+ def test_should_find_all_reviews
8
+ html = '<html>' << SOURCES[:cafe_borrone] << SOURCES[:crepes_on_cole] << '</html>'
9
+ doc = REXML::Document.new(html)
10
+ hreviews = []
11
+ Microformats::HReview.each(doc) do |hr|
12
+ hreviews << hr
13
+ end
14
+ assert_equal(2, hreviews.length)
15
+ end
16
+
17
+ def test_should_have_lookup_to_allow_deep_lookups_without_errors
18
+ r = review(:cafe_borrone)
19
+ assert_equal('1010 El Camino Real', r.lookup(:item, :vcard, :adr, :street_address))
20
+ assert_equal('1010 El Camino Real', r.lookup(:item, :vcard, :adrs, 0, :street_address))
21
+ assert_nil(r.lookup(:item, :vcard, :adrs, 0, :post_office_box))
22
+ assert_equal(18, r.lookup(:ratings, 'Food', :score))
23
+ end
24
+
25
+ def test_should_expose_vcard_fn_and_url_at_top_level
26
+ r = review(:cafe_borrone)
27
+ assert_equal(r.item.vcard.fn, r.item.fn)
28
+ assert_equal(r.item.vcard.url, r.item.url)
29
+ assert_equal(r.item.vcard.urls, r.item.urls)
30
+ end
31
+
32
+ def test_should_parse_sample_crepes_on_cole
33
+ r = review(:crepes_on_cole)
34
+ assert_equal(5, r.rating.score)
35
+ assert_equal(5, r.rating.best)
36
+ assert_equal(1, r.rating.worst)
37
+ assert_equal('Crepes on Cole', r.item.fn)
38
+ assert_equal('Crepes on Cole is awesome', r.summary)
39
+ assert_equal('Tantek', r.reviewer.fn)
40
+ assert_equal('2005-04-19T06:00:00Z', r.dtreviewed.utc.xmlschema)
41
+ assert_not_nil(r.description =~ /<p>\s*Crepes on Cole is one of the best/um)
42
+ end
43
+
44
+ def test_should_parse_sample_cafe_borrone
45
+ r = review(:cafe_borrone)
46
+ assert_equal('Cafe Borrone', r.item.fn)
47
+ assert_equal('1010 El Camino Real', r.item.vcard.adr.street_address)
48
+ assert_equal('San Francisco', r.item.vcard.adr.locality)
49
+ assert_equal('CA', r.item.vcard.adr.region)
50
+ assert_equal('94025', r.item.vcard.adr.postal_code)
51
+ assert_equal('+1-650-327-0830', r.item.vcard.tel.value)
52
+ assert_equal('http://cafeborrone.com', r.item.url)
53
+ assert_equal(18, r.ratings['Food'].score)
54
+ assert_equal(30, r.ratings['Food'].best)
55
+ assert_equal(1, r.ratings['Food'].worst)
56
+ assert_equal(19, r.ratings['Ambience'].score)
57
+ assert_equal(30, r.ratings['Ambience'].best)
58
+ assert_equal(15, r.ratings['Service'].score)
59
+ assert_equal(30, r.ratings['Service'].best)
60
+ assert_equal(2, r.ratings['Price'].score)
61
+ assert_equal(5, r.ratings['Price'].best)
62
+ assert_nil(r.rating)
63
+ assert_not_nil(r.description =~ %r!<p>\s+This <abbr class='type' title='business'>!um)
64
+ assert_equal('business', r.type)
65
+ assert_equal('0.2', r.version)
66
+ assert_equal('anonymous', r.reviewer.fn)
67
+ assert_equal(Time.parse('20050428T2130-0700'), r.dtreviewed)
68
+ end
69
+
70
+ def test_should_parse_sample_postal_service
71
+ r = review(:postal_service)
72
+ assert_equal('http://www.amazon.com/exec/obidos/ASIN/B000089CJI/', r.item.url)
73
+ assert_equal('http://images.amazon.com/images/P/B000089CJI.01._SCTHUMBZZZ_.jpg', r.item.photo)
74
+ assert_equal('The Postal Service: Give Up', r.item.fn)
75
+ assert_not_nil(r.description =~ /<p>\s*"The people thought they were just being rewarded/um)
76
+ assert_equal(5, r.rating.score)
77
+ assert_equal(1, r.rating.worst)
78
+ assert_equal(5, r.rating.best)
79
+ assert_equal('Adam Rifkin', r.reviewer.fn)
80
+ assert_equal('http://ifindkarma.com/blog/', r.reviewer.url)
81
+ assert_equal(2005, r.dtreviewed.year)
82
+ assert_equal(2, r.dtreviewed.month)
83
+ end
84
+
85
+ def test_should_parse_sample_hero
86
+ r = review(:hero)
87
+ assert_equal('anonymous', r.reviewer.fn)
88
+ assert_equal('2005-04-18', r.dtreviewed.strftime('%Y-%m-%d'))
89
+ assert_equal('Ying Xiong (HERO)', r.item.fn)
90
+ assert_equal('http://www.imdb.com/title/tt0299977/', r.item.url)
91
+ assert_equal(4, r.rating.score)
92
+ assert_equal(1, r.rating.worst)
93
+ assert_equal(5, r.rating.best)
94
+ assert_not_nil(r.description =~ /This movie has great music and visuals./um)
95
+ end
96
+
97
+ def test_should_parse_multiple_urls_and_photos
98
+ r = review(:multi)
99
+ assert_equal('http://example.com/front.jpg', r.item.photo)
100
+ assert_equal('http://example.com/front.jpg', r.item.photos[0])
101
+ assert_equal('http://example.com/back.jpg', r.item.photos[1])
102
+ assert_equal('http://example.com/one', r.item.url)
103
+ assert_equal('http://example.com/one', r.item.urls[0])
104
+ assert_equal('http://example.com/two', r.item.urls[1])
105
+ end
106
+
107
+ def test_should_detect_invalid_reviews
108
+ assert(!review(:invalid_item).valid?)
109
+ assert(review(:cafe_borrone).valid?)
110
+ assert(review(:event_review_without_vevent).valid?)
111
+ assert(!review(:invalid_type_review).valid?)
112
+ end
113
+
114
+ def test_should_find_identifiers
115
+ r = review(:with_identifiers)
116
+ assert_equal(2, r.item.urls.length)
117
+ assert_equal('urn:ean.ucc:123', r.item.urls[0])
118
+ assert_equal('urn:product/nikon/d70', r.item.urls[1])
119
+ end
120
+
121
+ def test_should_raise_exception_on_unknown_key_as_method
122
+ r = review(:cafe_borrone)
123
+ assert_raises(NoMethodError){ r.frobnitz }
124
+ assert_nothing_raised{ r.item }
125
+ end
126
+
127
+ def test_should_parse_worst_score
128
+ r = review(:with_worst)
129
+ assert_equal(1, r.rating.worst)
130
+ end
131
+
132
+ def test_should_convert_score_to_float
133
+ r = review(:with_worst)
134
+ assert_in_delta(0.75, r.rating.to_f, 0.01)
135
+ end
136
+
137
+ # Version 0.3 changes
138
+
139
+ def test_should_see_version_0_3_review_as_valid
140
+ r = review(:version_0_3)
141
+ assert(r.valid?)
142
+ end
143
+
144
+ def test_should_find_licenses_in_0_3_review
145
+ r = review(:version_0_3)
146
+ assert_equal(1, r.licenses.length)
147
+ assert_in_delta(4.5, r.rating.score, 0.01)
148
+ assert_equal("http://example.com/licenses/only-on-tuesdays-2.1", r.licenses.first)
149
+ assert_equal("http://example.com/licenses/only-on-tuesdays-2.1", r.license)
150
+ end
151
+
152
+ def test_should_require_hcard_for_business_or_person_post_0_3
153
+ assert(!review(:invalid_person_review).valid?)
154
+ assert(review(:valid_person_review_0_2).valid?)
155
+ assert(!review(:invalid_business_review).valid?)
156
+ end
157
+
158
+ def test_should_parse_embedded_hcalendar_event
159
+ r = review(:event_review)
160
+ assert_equal('The Event', r.item.vevent.summary)
161
+ assert_equal('The Location', r.item.vevent.location)
162
+ end
163
+
164
+ def test_should_parse_sample_cafe_borrone_0_3
165
+ r = review(:cafe_borrone_0_3)
166
+ assert_equal('Cafe Borrone', r.item.fn)
167
+ assert_equal('1010 El Camino Real', r.item.vcard.adr.street_address)
168
+ assert_equal('Menlo Park', r.item.vcard.adr.locality)
169
+ assert_equal('CA', r.item.vcard.adr.region)
170
+ assert_equal('94025', r.item.vcard.adr.postal_code)
171
+ assert_equal('+1-650-327-0830', r.item.vcard.tel.value)
172
+ assert_equal('http://cafeborrone.com', r.item.url)
173
+ assert_equal(18, r.ratings['Food'].score)
174
+ assert_equal(30, r.ratings['Food'].best)
175
+ assert_equal(1, r.ratings['Food'].worst)
176
+ assert_equal(19, r.ratings['Ambience'].score)
177
+ assert_equal(30, r.ratings['Ambience'].best)
178
+ assert_equal(15, r.ratings['Service'].score)
179
+ assert_equal(30, r.ratings['Service'].best)
180
+ assert_equal(2, r.ratings['Price'].score)
181
+ assert_equal(5, r.ratings['Price'].best)
182
+ assert_nil(r.rating)
183
+ assert_not_nil(r.description =~ %r!<p>\s+This <abbr class='type' title='business'>!um)
184
+ assert_equal('business', r.type)
185
+ assert_equal('0.3', r.version)
186
+ assert_equal('anonymous', r.reviewer.fn)
187
+ assert_equal(Time.parse('20050428T2130-0700'), r.dtreviewed)
188
+ end
189
+
190
+ def test_should_return_best_and_worst_attributes_of_score_as_integers
191
+ r = Microformats::HReview::Rating.new
192
+ r.best = 10.0
193
+ r.worst = 1.0
194
+ r.score = 9.5
195
+ assert_equal('10', r.best.to_s)
196
+ assert_equal('1', r.worst.to_s)
197
+ assert_equal('9.5', r.score.to_s)
198
+ end
199
+
200
+ def review(name)
201
+ return Microformats::HReview.first(REXML::Document.new(SOURCES[name]))
202
+ end
203
+
204
+ SOURCES = {
205
+ :crepes_on_cole => %{
206
+ <div class="hreview">
207
+ <span><span class="rating">5</span> out of 5 stars</span>
208
+ <h4 class="summary"><span class="item fn">Crepes on Cole</span> is awesome</h4>
209
+ <span>Reviewer: <span class="reviewer fn">Tantek</span> -
210
+ <abbr class="dtreviewed" title="20050418T2300-0700">April 18, 2005</abbr></span>
211
+ <blockquote class="description"><p>
212
+ Crepes on Cole is one of the best little creperies in San Francisco.
213
+ Excellent food and service. Plenty of tables in a variety of sizes
214
+ for parties large and small. Window seating makes for excellent
215
+ people watching to/from the N-Judah which stops right outside.
216
+ I've had many fun social gatherings here, as well as gotten
217
+ plenty of work done thanks to neighborhood WiFi.
218
+ </p></blockquote>
219
+ <p>Visit date: <span>April 2005</span></p>
220
+ <p>Food eaten: <span>Florentine crepe</span></p>
221
+ </div>},
222
+ :cafe_borrone => %{
223
+ <div class="hreview">
224
+ <div class="item vcard">
225
+ <div class="fn org summary">Cafe Borrone</div>
226
+ <span class="adr">
227
+ <span class="street-address">1010 El Camino Real</span>,
228
+ <span class="locality">San Francisco</span>,
229
+ <span class="region">CA</span>
230
+ <span class="postal-code">94025</span>,
231
+ </span>
232
+ <span class="tel"><span class="voice work">+1-650-327-0830</span></span>;
233
+ <a class="url" href="http://cafeborrone.com">cafeborrone.com</a>
234
+ </div>
235
+ <ul class="categories">
236
+ <li><a href="http://en.wikipedia.org/wiki/Food" rel="tag">
237
+ Food: <span class="rating">18</span>/<span class="best">30</span></a>;</li>
238
+ <li><a href="http://flickr.com/photos/tags/Ambience" rel="tag">
239
+ Ambience: <span class="rating">19</span>/<span class="best">30</span></a>;</li>
240
+ <li><a href="http://en.wikipedia.org/wiki/Service" rel="tag">
241
+ Service: <span class="rating">15</span>/<span class="best">30</span></a>;</li>
242
+ <li><a href="http://en.wikipedia.org/wiki/Price" rel="tag">
243
+ Price: <abbr class="rating" title="2">$$</abbr>...</a></li>
244
+ </ul>
245
+ <blockquote class="description"><p>
246
+ This <abbr class="type" title="business">
247
+ <a href="http://en.wikipedia.org/wiki/cafe" rel="tag">cafe</a></abbr>
248
+ is a welcoming oasis on the Peninsula.
249
+ It even has a fountain outside which nearly eliminates
250
+ the sounds of El Camino traffic. Next door to a superb indy bookstore,
251
+ Cafe Borrone is an ideal spot to grab a
252
+ <a href="http://en.wikipedia.org/wiki/coffee" rel="tag">coffee</a>
253
+ or a meal to accompany a newly purchased book or imported periodical.
254
+ <a href="http://technorati.com/tag/soup" rel="tag">Soups</a> and
255
+ <a href="http://technorati.com/tag/sandwich" rel="tag">sandwich</a>
256
+ specials rotate daily. The corn chowder with croutons and big chunks of cheese
257
+ goes especially well with a freshly toasted mini-baguette. Evenings are
258
+ often crowded and may require sharing a table with a perfect stranger.
259
+ <a href="http://flickr.com/photos/tags/espresso" rel="tag">Espresso</a>
260
+ afficionados will appreciate the
261
+ <a href="http://en.wikipedia.org/wiki/Illy" rel="tag">Illy</a> coffee.
262
+ Noise levels can vary from peaceful in the late mornings to nearly overwhelming on
263
+ <a href="http://en.wikipedia.org/wiki/jazz" rel="tag">jazz</a> band nights.
264
+ </p></blockquote>
265
+ Review (<a href="http://microformats.org/wiki/hreview">
266
+ hReview v<span class="version">0.2</span></a>)
267
+ by <span class="reviewer">anonymous</span>,
268
+ <abbr class="dtreviewed" title="20050428T2130-0700">April 28th, 2005</abbr>.
269
+ </div>},
270
+ :cafe_borrone_0_3 => %{
271
+ <div class="hreview">
272
+ <div class="item vcard">
273
+ <div class="fn org summary">Cafe Borrone</div>
274
+ <span class="adr">
275
+ <span class="street-address">1010 El Camino Real</span>,
276
+ <span class="locality">Menlo Park</span>,
277
+ <span class="region">CA</span>
278
+ <span class="postal-code">94025</span>,
279
+ </span>
280
+ <span class="tel">+1-650-327-0830</span>;
281
+ <a class="url" href="http://cafeborrone.com">cafeborrone.com</a>
282
+ </div>
283
+ <ul class="categories">
284
+ <li class="rating"><a href="http://en.wikipedia.org/wiki/Food" rel="tag">
285
+ Food: <span class="value">18</span>/<span class="best">30</span></a>;</li>
286
+ <li class="rating"><a href="http://flickr.com/photos/tags/Ambience" rel="tag">
287
+ Ambience: <span class="value">19</span>/<span class="best">30</span></a>;</li>
288
+ <li class="rating"><a href="http://en.wikipedia.org/wiki/Service" rel="tag">
289
+ Service: <span class="value">15</span>/<span class="best">30</span></a>;</li>
290
+ <li class="rating"><a href="http://en.wikipedia.org/wiki/Price" rel="tag">
291
+ Price: <abbr class="value" title="2">$$</abbr>...</a></li>
292
+ </ul>
293
+ <div class="description"><p>
294
+ This <abbr class="type" title="business">
295
+ <a href="http://en.wikipedia.org/wiki/cafe" rel="tag">cafe</a></abbr>
296
+ is a welcoming oasis on the Peninsula.
297
+ It even has a fountain outside which nearly eliminates
298
+ the sounds of El Camino traffic. Next door to a superb indy bookstore,
299
+ Cafe Borrone is an ideal spot to grab a
300
+ <a href="http://en.wikipedia.org/wiki/coffee" rel="tag">coffee</a>
301
+ or a meal to accompany a newly purchased book or imported periodical.
302
+ <a href="http://technorati.com/tag/soup" rel="tag">Soups</a> and
303
+ <a href="http://technorati.com/tag/sandwich" rel="tag">sandwich</a>
304
+ specials rotate daily. The corn chowder with croutons and big chunks of cheese
305
+ goes especially well with a freshly toasted mini-baguette. Evenings are
306
+ often crowded and may require sharing a table with a perfect stranger.
307
+ <a href="http://flickr.com/photos/tags/espresso" rel="tag">Espresso</a>
308
+ afficionados will appreciate the
309
+ <a href="http://en.wikipedia.org/wiki/Illy" rel="tag">Illy</a> coffee.
310
+ Noise levels can vary from peaceful in the late mornings to nearly overwhelming on
311
+ <a href="http://en.wikipedia.org/wiki/jazz" rel="tag">jazz</a> band nights.
312
+ </p></div>
313
+ Review (<a href="http://microformats.org/wiki/hreview">
314
+ hReview v<span class="version">0.3</span></a>)
315
+ by <span class="reviewer vcard"><span class="fn">anonymous</span></span>,
316
+ <abbr class="dtreviewed" title="20050428T2130-0700">April 28th, 2005</abbr>.
317
+ </div>},
318
+ :postal_service => %{
319
+ <div class="hreview">
320
+ <a class="item url" href="http://www.amazon.com/exec/obidos/ASIN/B000089CJI/">
321
+ <img src="http://images.amazon.com/images/P/B000089CJI.01._SCTHUMBZZZ_.jpg"
322
+ alt="Album cover photo: The Postal Service: Give Up. "
323
+ class="photo" />
324
+ <span class="fn">The Postal Service: Give Up</span></a>
325
+ <blockquote class="description"><p>
326
+ "The people thought they were just being rewarded for treating others
327
+ as they like to be treated, for obeying stop signs and curing diseases,
328
+ for mailing letters with the address of the sender... Don't wake me,
329
+ I plan on sleeping in..."
330
+ </p><p>
331
+ "Nothing Better" is a great track on this album, too...
332
+ </p></blockquote>
333
+ (<abbr class="rating" title="5">*****</abbr>)
334
+ <p class="reviewer vcard">Review by
335
+ <a class="url fn" href="http://ifindkarma.com/blog/">Adam Rifkin</a>,
336
+ <abbr class="dtreviewed" title="200502">February 2005</abbr>
337
+ </p>
338
+ </div>},
339
+ :hero => %{
340
+ <div class="hreview">
341
+ <span class="reviewer">
342
+ <span class="fn">anonymous</span>,
343
+ <abbr class="dtreviewed" title="20050418">April 18th, 2005</abbr>
344
+ </span>
345
+ <div class="item">
346
+ <a lang="zh" class="url fn" href="http://www.imdb.com/title/tt0299977/">
347
+ Ying Xiong (<span lang="en">HERO</span>)
348
+ </a>
349
+ </div>
350
+ <div>Rating: <span class="rating">4</span> out of 5</div>
351
+ <blockquote class="description"><p>
352
+ This movie has great music and visuals.
353
+ </p></blockquote>
354
+ </div>},
355
+ :multi => %{
356
+ <div class='hreview'>
357
+ <span class='version'>0.2</span>
358
+ <p class="reviewer fn">Reviewer</p>
359
+ <abbr class="dtreviewed" title="20010101">2001-01-01</abbr>
360
+ <span class='type'>product</span>
361
+ <div class='item'>
362
+ <img class="photo" src="http://example.com/front.jpg" alt="front view" />
363
+ <img class="photo" src="http://example.com/back.jpg" alt="back view" />
364
+ <span class='fn'>item_fn</span>
365
+ <ul class='identifiers'>
366
+ <li><a class='url' href='http://example.com/one'>item_url1</a></li>
367
+ <li><a class='url' href='http://example.com/two'>item_url2</a></li>
368
+ </ul>
369
+ </div>},
370
+ :invalid_item => %{
371
+ <div class="hreview">
372
+ <span class="reviewer">
373
+ <span class="fn">anonymous</span>,
374
+ <abbr class="dtreviewed" title="20050418">April 18th, 2005</abbr>
375
+ </span>
376
+ <div>Rating: <span class="rating">4</span> out of 5</div>
377
+ <blockquote class="description"><p>
378
+ This movie has great music and visuals.
379
+ </p></blockquote>
380
+ </div>},
381
+ :with_identifiers => %{
382
+ <div class='hreview'>
383
+ <span class='version' style='display:none'>0.2</span>
384
+ <span class='type' style='display:none'>product</span>
385
+ <div class='item'>
386
+ <span class='fn'>asd</span>
387
+ <ul class='identifiers'>
388
+ <li><a class='url' href='urn:ean.ucc:123'>urn:ean.ucc:123</a></li>
389
+ <li><a class='url' href='urn:product/nikon/d70'>urn:product/nikon/d70</a></li>
390
+ </ul>
391
+ </div>
392
+ <div class='description'>dsa</div>
393
+ Rated <span class='rating'>1</span>
394
+ by <span class='reviewer fn'>chris</span>
395
+ on <abbr class='dtreviewed' title='2006-01-12T16:09:00+00:00'>Jan 12, 2006</abbr>
396
+ </div>},
397
+ :version_0_3 => %{
398
+ <div>
399
+ <a href="http://example.com/licenses/dont-find-me" rel="license">No!</a>
400
+ <div class="hreview">
401
+ <a href="http://example.com/licenses/only-on-tuesdays-2.1" rel="license">Only on Tuesdays 2.1</a>
402
+ <div class="item">
403
+ <a class="url fn" href="http://example.com/item">
404
+ Item Name
405
+ </a>
406
+ </div>
407
+ <div>Rating: <span class="rating">4.5</span> out of 5</div>
408
+ <blockquote class="description"><p>
409
+ Description.
410
+ </p></blockquote>
411
+ </div>
412
+ </div>
413
+ },
414
+ :with_worst => %{
415
+ <div class="hreview">
416
+ <div class="item fn">Foo</div>
417
+ <div>Rating: <span class="rating">4</span> (<span class="worst">1</span>-<span class="best">5</span>)</div>
418
+ <blockquote class="description"><p>
419
+ Description.
420
+ </p></blockquote>
421
+ </div>
422
+ },
423
+ :event_review => %{
424
+ <div class="hreview">
425
+ <span class='type' style='display:none'>event</span>
426
+ <span class="reviewer vcard">
427
+ <span class="fn">John Doe</span>,
428
+ <abbr class="dtreviewed" title="20050418">April 18th, 2005</abbr>
429
+ </span>
430
+ <span class="item vevent">
431
+ <a class="url" href="http://www.example.com/event">
432
+ <span class="summary">The Event</span>:
433
+ at <span class="location">The Location</span>
434
+ </a>
435
+ </span>
436
+ <div>Rating: <span class="rating">4</span> out of 5</div>
437
+ <blockquote class="description"><p>
438
+ Description.
439
+ </p></blockquote>
440
+ </div>
441
+ },
442
+ :event_review_without_vevent => %{
443
+ <div class="hreview">
444
+ <span class='type' style='display:none'>event</span>
445
+ <span class="reviewer vcard">
446
+ <span class="fn">John Doe</span>,
447
+ <abbr class="dtreviewed" title="20050418">April 18th, 2005</abbr>
448
+ </span>
449
+ <span class="item fn">The Event</span>
450
+ <div>Rating: <span class="rating">4</span> out of 5</div>
451
+ <blockquote class="description"><p>
452
+ Description.
453
+ </p></blockquote>
454
+ </div>
455
+ },
456
+ :invalid_person_review => %{
457
+ <div class="hreview">
458
+ <span class="version">0.3</span>
459
+ <span class='type'>person</span>
460
+ <span class="item fn">John Doe</span>
461
+ <div>Rating: <span class="rating">4</span> out of 5</div>
462
+ <blockquote class="description"><p>
463
+ Description.
464
+ </p></blockquote>
465
+ </div>
466
+ },
467
+ :valid_person_review_0_2 => %{
468
+ <div class="hreview">
469
+ <span class="version">0.2</span>
470
+ <span class='type'>person</span>
471
+ <span class="item fn">John Doe</span>
472
+ <div>Rating: <span class="rating">4</span> out of 5</div>
473
+ <blockquote class="description"><p>
474
+ Description.
475
+ </p></blockquote>
476
+ </div>
477
+ },
478
+ :invalid_business_review => %{
479
+ <div class="hreview">
480
+ <span class='type'>business</span>
481
+ <span class="item fn">John Doe, Inc.</span>
482
+ <div>Rating: <span class="rating">4</span> out of 5</div>
483
+ <blockquote class="description"><p>
484
+ Description.
485
+ </p></blockquote>
486
+ </div>
487
+ },
488
+ :invalid_type_review => %{
489
+ <div class="hreview">
490
+ <span class='type'>foo</span>
491
+ <span class="item fn">Item Name</span>
492
+ <div>Rating: <span class="rating">4</span> out of 5</div>
493
+ <blockquote class="description"><p>
494
+ Description.
495
+ </p></blockquote>
496
+ </div>
497
+ },
498
+ }
499
+
500
+ end