Thursday, May 28, 2009

The Simplest Meal Possible

‹prev | My Chain | next›

The next scenario up is "Browsing a meal on a specific date":
  Scenario: Browsing a meal on a specific date

Given a "Focaccia!" meal enjoyed on March 3, 2009
When I view the meal
Then I should see the "Focaccia!" title
And I should be able to follow a link to the list of meals in March of 2009
That's a pretty weak Cucumber scenario. It describes only very superficially what a user would expect to see on a meal page (a title and a link to the list of meals in that month).

Users should also be able to follow links to:

  • the list of meal in the current year (the year and month serving a breadcrumbs)

  • recipes prepared for the current meal

  • the previous and subsequent meals prepared

That's a lot not described by that scenario. So let's split it into two scenarios—one for browsing on a particular date and one between dates:
  Scenario: Navigating between meals

Given a "Focaccia!" meal enjoyed on March 3, 2009
And a "Star Wars: The Dinner" meal enjoyed on February 28, 2009
And "Pumpkin is a Very Exciting Vegetable" meal enjoyed on December 3, 2008
When I view the "Focaccia!" meal
Then I should see the "Focaccia!" title
When I click "Star Wars: The Dinner"
Then I should see the "Star Wars: The Dinner" title
When I click "Pumpkin is a Very Exciting Vegetable"
Then I should see the "Pumpkin is a Very Exciting Vegetable" title
When I click "Star Wars: The Dinner"
Then I should see the "Star Wars: The Dinner" title
When I click "Focaccia!"
Then I should see the "Focaccia!" title

Scenario: Browsing a meal on a specific date

Given a "Focaccia!" meal enjoyed on March 3, 2009
And a "Focaccia" recipe from March 3, 2009
When I view the "Focaccia!" meal
Then I should see the "Focaccia!" title
And I should see a link to the "Focaccia" recipe in the menu
When I click the "March" link
Then I should see "Focaccia!" in the list of meals
When I click the "Focaccia" link
And I click the "2009" link
Then I should see "Focaccia!" in the list of meals
When I click the "Focaccia!" link
And I click the "Focaccia" link
Then I should see the "Focaccia" recipe
That's more like it! There are many new steps to be implemented, so I may as well get started immediately.

First up in the "Browsing a meal on a specific date" scenario is the Given step, "Given a "Focaccia!" meal enjoyed on March 3, 2009". When I run the entire scenario, it shows up in the output a yellow (not implemented). That's odd, I have yet to implement a "Given a meal" step?

Actually, I have:
Given /^a "([^\"]*)" meal enjoyed in (.+)$/ do |title, date_str|
Why doesn't that match "Given a "Focaccia!" meal enjoyed on March 3, 2009"? Ah, the text is on March 3, but the step implementation would only match in March 3. I can fix that with a simple RegExp character class:
Given /^a "([^\"]*)" meal enjoyed [io]n (.+)$/ do |title, date_str|
With that I have one Given step done. Cucumber tells me that I need to get the next one done:
You can implement step definitions for missing steps with these snippets:

Given /^a "([^\"]*)" recipe from March 3, 2009$/ do |arg1|
pending
end
I take that and implement it in features/recipe_details.rb:
Given /^a "([^\"]*)" recipe from (.+)$/ do |title, date_str|
date = Date.parse(date_str)
@recipe_permalink = date.to_s + "-" + title.downcase.gsub(/\W/, '-')

recipe = {
:title => title,
:date => date,
:summary => "#{title} summary",
:instructions => "#{title} instructions"
}

RestClient.put "#{@@db}/#{@recipe_permalink}",
recipe.to_json,
:content_type => 'application/json'
end
Now I have reached the when-I-visit-the meal step, which I implement as:
When /^I view the "([^\"]*)" meal$/ do |arg1|
visit("/meals/#{@meal_permalink}")
response.status.should == 200
end
That step fails, of course, so it is time to work my way into the actual code. The example that describes the desired behavior (simply that it responds OK):
    describe "GET /meals/YYYY/MM/DD" do
it "should respond OK" do
get "/meals/2009/05/28"
response.should be_ok
end
end
And the simplest thing to make this code pass is:
get %r{/meals/(\d+)/(\d+)/(\d+)} do |year, month, day|
end
Back in the Cucumber scenario, I expect the visit-the-meal step to pass, but am disappointed to find:
cstrom@jaynestown:~/repos/eee-code$ cucumber features \
-s "Browsing a meal on a specific date"
Feature: Browse Meals

So that I can find meals made on special occasions
As a person interested in finding meals
I want to browse meals by date

Scenario: Browsing a meal on a specific date # features/browse_meals.feature:36
Given a "Focaccia!" meal enjoyed on March 3, 2009 # features/step_definitions/meal_details.rb:1
And a "Focaccia" recipe from March 3, 2009 # features/step_definitions/recipe_details.rb:137
When I view the "Focaccia!" meal # features/step_definitions/meal_details.rb:32
expected: 200,
got: 404 (using ==)
Diff:
@@ -1,2 +1,2 @@
-200
+404
(Spec::Expectations::ExpectationNotMetError)
features/browse_meals.feature:40:in `When I view the "Focaccia!" meal'
...
Ah, I am storing meals in CouchDB in ISO 8601 format, but the URLs for the Sinatra app have slashes (e.g. 2009/05/28). A simple gsub in the visit step will resolve my issue:
When /^I view the "([^\"]*)" meal$/ do |arg1|
visit("/meals/#{@meal_permalink.gsub(/-/, '/')}")
response.status.should == 200
end
And now I have three passing steps:



Next up, serious "inside" work, retrieving the meal, displaying it and the necessary links to implement the remaining steps in that scenario. Tomorrow.
(commit)

No comments:

Post a Comment