With half a brain, I was able to drive by example a start on the homepage mini-calendar. I left off with the mini-calendar showing a numeric date and little else. This was all done in the Sinatra action:
get %r{/mini/.*} doAlthough not an MVC framework, I have done my view code separately in Haml templates. So first up today is to write some examples for the mini-calendar view. As can be seen from the
url = "#{@@db}/_design/meals/_view/count_by_month?group=true\&limit=1\&descending=true"
data = RestClient.get url
@last_month = JSON.parse(data)['rows'].first['key']
"<h1>#{@last_month}</h1>"
end
mini
action, there will be a @last_month
(with a meal) instance variable, so my examples will all expect that to be set. In RSpec:require File.expand_path(File.dirname(__FILE__) + '/../spec_helper' )The first example will describe the date heading:
describe "mini_calendar.haml" do
before(:each) do
assigns[:last_month] = "2009-08"
end
end
it "should show a human readable month and year" doRunning this example, of course, I find failure due to the lack of the template:
render("views/mini_calendar.haml")
response.should have_selector("h1", :content => "August 2009")
end
cstrom@jaynestown:~/repos/eee-code$ spec ./spec/views/mini_calendar.haml_spec.rbOnce again I find myself in the familiar, comfortable confines of the change-the-message or make-it-pass cycle. I can change the above message by creating the template. The new failure message becomes:
F
1)
Errno::ENOENT in 'mini_calendar.haml should show a human readable month and year'
No such file or directory - ./views/mini_calendar.haml
/home/cstrom/repos/eee-code/spec/spec_helper.rb:25:in `read'
/home/cstrom/repos/eee-code/spec/spec_helper.rb:25:in `render'
./spec/views/mini_calendar.haml_spec.rb:9:
Finished in 0.00705 seconds
1 example, 1 failure
cstrom@jaynestown:~/repos/eee-code$ spec ./spec/views/mini_calendar.haml_spec.rbFinally, I can make the example pass by displaying the current month inside an
F
1)
'mini_calendar.haml should show a human readable month and year' FAILED
expected following output to contain a <h1>August 2009</h1> tag:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
./spec/views/mini_calendar.haml_spec.rb:10:
Finished in 0.007892 seconds
1 example, 1 failure
<h1>
tag:%h1The reason for the change-the-message or make-it-pass cycle is to ensure that every step is built on validated assumptions from the previous step. There is nothing worse than spending 10 minutes trying to solve a problem only to realize that you are solving the wrong problem (like creating the template with the wrong name).
= month_text @last_month
I do notice a problem with my naming convention. The Haml template will always show the month requested, not the "latest month". The current step in the current Cucumber scenario drove a default date—the last month with a meal. But as mentioned, this template is displaying the requested month. So I change the expected instance variable in the examples from
@last_month
to @month
:describe "mini_calendar.haml" doOddly enough, that example still passes:
before(:each) do
assigns[:month] = "2009-08"
end
it "should show a human readable month and year" do
render("views/mini_calendar.haml")
response.should have_selector("h1", :content => "August 2009")
end
end
cstrom@jaynestown:~/repos/eee-code$ spec ./spec/views/mini_calendar.haml_spec.rbThe reason for the non-failure has to do with the
.
Finished in 0.008105 seconds
1 example, 0 failures
month_text
helper method:def month_text(date_frag)Since the
Date.parse("#{date_frag}-01").strftime("%B %Y")
end
@last_month
variable is not being set in the example, date_frag
argument is now nil
. This means that Date.parse
is now trying to parse the string "-01". How can that return an actual date? Somehow it does:>> Date.parse("-01").to_sThis example will fail in two days (once the example month is different than the current month). For the time being, I will create another example to fail as expected:
=> "2009-08-01"
it "should show a human readable month and year for other months" doThat example does fail:
assigns[:month] = "2009-01"
render("views/mini_calendar.haml")
response.should have_selector("h1", :content => "January 2009")
end
cstrom@jaynestown:~/repos/eee-code$ spec ./spec/views/mini_calendar.haml_spec.rbMaking that example pass is a simple matter of using the new
.F
1)
'mini_calendar.haml should show a human readable month and year for other months' FAILED
expected following output to contain a <h1>January 2009</h1> tag:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><h1>
August 2009
</h1></body></html>
./spec/views/mini_calendar.haml_spec.rb:16:
Finished in 0.010549 seconds
2 examples, 1 failure
@month
instance variable:%h1This was a nice demonstration of the value in taking small steps in the change-the-message or make-it-pass cycle. I could have easily made the changes without the small steps. I might even have made the change without introducing a subtle defect. By taking small steps, I know that I have not introduced a subtle defect.
= month_text @month
With that, I can work my way back out to the Cucumber scenario to mark the current step as complete:
Then /^I should see the calendar for (.+)$/ do |date|Cucumber had not suggested the RegExp for the date—rather I saw an opportunity for re-use coming very soon. And, indeed, in addition to one newly passing step, I have some blue ones as well:
response.should have_selector("h1", :content => date)
end
I spend a little more time driving days in the mini-calendar. Tomorrow I ought to be able to link to meals from the calendar and mark off another step or two in my scenario.
No comments:
Post a Comment