Wednesday, July 1, 2009

RSS Feeds by Coincidence

‹prev | My Chain | next›

To finish off my meals RSS feed, I need to implement meal links and published dates in the items. First up is "Then I should see a meal link" which I ought to be able to define with:
Then /^I should see a meal link$/ do
response.
should have_selector("link", :content => "http://www.eeecooks.com/meals/2009/06/11")
end
Running this with Cucumber, I get:
   When I access the meal RSS feed            # features/step_definitions/rss.rb:1
Then I should see the 10 most recent meals # features/step_definitions/rss.rb:6
And I should see the summary of each meal # features/step_definitions/rss.rb:20
And I should see a meal link # features/step_definitions/rss.rb:26
expected following output to contain a <link>http://www.eeecooks.com/meals/2009/06/11</link> tag:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<?xml version="1.0" encoding="UTF-8"?><html><body><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"><channel><title>EEE Cooks: Meals</title>
<link>http://www.eeecooks.com
<description>Meals from a Family Cookbook</description><item><title>Meal 0</title>
<link>http://www.eeecooks.com/meals/2009/06/11
<description>meal summary</description></item><item><title>Meal 1</title>
<link>http://www.eeecooks.com/meals/2009/06/01
<description>meal summary</description></item><item><title>Meal 2</title>
<link>http://www.eeecooks.com/meals/2009/05/22
<description>meal summary</description></item><item><title>Meal 3</title>
<link>http://www.eeecooks.com/meals/2009/05/12
<description>meal summary</description></item><item><title>Meal 4</title>
<link>http://www.eeecooks.com/meals/2009/05/02
<description>meal summary</description></item><item><title>Meal 5</title>
<link>http://www.eeecooks.com/meals/2009/04/22
<description>meal summary</description></item><item><title>Meal 6</title>
<link>http://www.eeecooks.com/meals/2009/04/12
<description>meal summary</description></item><item><title>Meal 7</title>
<link>http://www.eeecooks.com/meals/2009/04/02
<description>meal summary</description></item><item><title>Meal 8</title>
<link>http://www.eeecooks.com/meals/2009/03/23
<description>meal summary</description></item><item><title>Meal 9</title>
<link>http://www.eeecooks.com/meals/2009/03/13
<description>meal summary</description></item></channel></rss></body></html>
(Spec::Expectations::ExpectationNotMetError)
features/rss.feature:13:in `And I should see a meal link'
And I should see a meal published date # features/rss.feature:14

1 scenario
1 failed step
1 undefined step
4 passed steps
Uh... what? I see that URL in the output. Why no match?

The output does not quite match what I expect, so let me puts the output in the Sinatra application:
...
puts rss.to_s

rss.to_s
end
The output is exactly what I expect:
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<channel>
<title>EEE Cooks: Meals</title>
<link>http://www.eeecooks.com</link>
<description>Meals from a Family Cookbook</description>
<item>
<title>Meal 0</title>
<link>http://www.eeecooks.com/meals/2009/06/11</link>
<description>meal summary</description>
</item>
<item>
<title>Meal 1</title>
<link>http://www.eeecooks.com/meals/2009/06/01</link>
<description>meal summary</description>
</item>
<item>
<title>Meal 2</title>
...
After mucking with the link content a bit and even trying have_xpath, I have to concede defeat. Rather than checking for a <link> tag with content "http://www.eeecooks.com/meals/2009/06/11", I check only for the content "http://www.eeecooks.com/meals/2009/06/11":
Then /^I should see a meal link$/ do
response.
should contain("http://www.eeecooks.com/meals/2009/06/11")
end
That works. I will leave it for now, but it will gnaw at me for a couple of days unless I can figure out what went wrong there.

With that sort of working, I move on to the publication date. The <pubDate> tag in the legacy application looks like "Thu, 10 Jul 2008 00:00:00 +0000":
Then /^I should see a meal published date$/ do
response.
should contain("Thu, 11 Jun 2009 00:00:00 +0000")
end
I hard-code this in the RSS::Maker code block in the Sinatra application:
  rss = RSS::Maker.make("2.0") do |maker|
maker.channel.title = "EEE Cooks: Meals"
maker.channel.link = ROOT_URL
maker.channel.description = "Meals from a Family Cookbook"
@meal_view.each do |couch_rec|
data = RestClient.get "#{@@db}/#{couch_rec['key']}"
meal = JSON.parse(data)
date = Date.parse(meal['date'])
maker.items.new_item do |item|
item.link = ROOT_URL + date.strftime("/meals/%Y/%m/%d")
item.title = meal['title']
item.pubDate = "Thu, 11 Jul 2009 00:00:00 +0000"
item.description = meal['summary']
end
end
end
When I run the Cucumber scenario now, things fail immediately:
  Scenario: Meal RSS                           # features/rss.feature:7
Given 20 yummy meals # features/step_definitions/site.rb:1
When I access the meal RSS feed # features/step_definitions/rss.rb:1
value <Thu, 11 Jul 2009 00:00:00 +0000> of tag <dc:date> is not available. (RSS::NotAvailableValueError)
/usr/lib/ruby/1.8/rss/dublincore.rb:143:in `content='
...
Geez, it it really not my day.

Google is not my ally on this particular error, but, eventually, I determine that pubDate needs a Time object:
        item.pubDate = Time.parse(meal['date'])
And finally, I have this scenario complete:
cstrom@jaynestown:~/repos/eee-code$ cucumber features -n -s "Meal RSS"
Sinatra::Test is deprecated; use Rack::Test instead.
Feature: RSS

So that I tell my user when there are updates to this great cooking site
As an RSS bot
I want to be able to consume your RSS

Scenario: Meal RSS
Given 20 yummy meals
When I access the meal RSS feed
Then I should see the 10 most recent meals
And I should see the summary of each meal
And I should see a meal link
And I should see a meal published date

1 scenario
6 passed steps
Tomorrow: the recipe RSS feed. Hopefully, lessons learned from the meal RSS feed will make it go significantly smoother.

No comments:

Post a Comment