prezjordan-toto 0.4.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ title: The Wonderful Wizard of Oz
2
+ date: 17/05/1900
3
+
4
+ _Once upon a time_...
5
+
@@ -0,0 +1,5 @@
1
+ title: the wizard of oz
2
+ date: 12/10/1932
3
+
4
+ Once upon a time...
5
+
@@ -0,0 +1,5 @@
1
+ title: the wizard of oz
2
+ date: 12/10/1932
3
+
4
+ Once upon a time...
5
+
@@ -0,0 +1,5 @@
1
+ title: the wizard of oz
2
+ date: 12/10/1932
3
+
4
+ Once upon a time...
5
+
@@ -0,0 +1,5 @@
1
+ title: the wizard of oz
2
+ date: 12/10/1932
3
+
4
+ Once upon a time...
5
+
data/test/autotest.rb ADDED
@@ -0,0 +1,34 @@
1
+ #
2
+ # Convenience Methods
3
+ #
4
+ def run(cmd)
5
+ print "\n\n"
6
+ puts(cmd)
7
+ system(cmd)
8
+ print "\n\n"
9
+ end
10
+
11
+ def run_all_tests
12
+ # see Rakefile for the definition of the test:all task
13
+ system("rake -s test:all VERBOSE=true")
14
+ end
15
+
16
+ #
17
+ # Watchr Rules
18
+ #
19
+ watch('^test/.*?_test\.rb' ) {|m| run("ruby -rubygems %s" % m[0]) }
20
+ watch('^lib/(.*)\.rb' ) {|m| run("ruby -rubygems test/%s_test.rb" % m[1]) }
21
+ watch('^lib/toto/(.*)\.rb' ) {|m| run("ruby -rubygems test/%s_test.rb" % m[1]) }
22
+ watch('^test/test_helper\.rb') { run_all_tests }
23
+
24
+ #
25
+ # Signal Handling
26
+ #
27
+ # Ctrl-\
28
+ Signal.trap('QUIT') do
29
+ puts " --- Running all tests ---\n\n"
30
+ run_all_tests
31
+ end
32
+
33
+ # Ctrl-C
34
+ Signal.trap('INT') { abort("\n") }
@@ -0,0 +1 @@
1
+ <span id="count"><%= @articles.length %></span>
@@ -0,0 +1,5 @@
1
+ <h1><%= @path %></h1>
2
+ <% for entry in archives %>
3
+ <li class="entry"><%= entry.title %></li>
4
+ <% end %>
5
+
@@ -0,0 +1,4 @@
1
+ <h2><%= title %></h2>
2
+ <span><%= date %></h2>
3
+ <p><%= body %></p>
4
+
@@ -0,0 +1,21 @@
1
+ xml.instruct!
2
+ xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
3
+ xml.title @config[:title]
4
+ xml.id @config[:url]
5
+ xml.updated articles.first[:date].iso8601 unless articles.empty?
6
+ xml.author { xml.name @config[:author] }
7
+
8
+ articles.each do |article|
9
+ xml.entry do
10
+ xml.title article.title
11
+ xml.link "rel" => "alternate", "href" => article.url
12
+ xml.id article.url
13
+ xml.published article[:date].iso8601
14
+ xml.updated article[:date].iso8601
15
+ xml.author { xml.name @config[:author] }
16
+ xml.summary article.summary, "type" => "html"
17
+ xml.content article.body, "type" => "html"
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,21 @@
1
+ xml.instruct!
2
+ xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
3
+ xml.title @config[:title]
4
+ xml.id @config[:url]
5
+ xml.updated articles.first[:date].iso8601 unless articles.empty?
6
+ xml.author { xml.name @config[:author] }
7
+
8
+ articles.each do |article|
9
+ xml.entry do
10
+ xml.title article.title
11
+ xml.link "rel" => "alternate", "href" => article.url
12
+ xml.id article.url
13
+ xml.published article[:date].iso8601
14
+ xml.updated article[:date].iso8601
15
+ xml.author { xml.name @config[:author] }
16
+ xml.summary article.summary, "type" => "html"
17
+ xml.content article.body, "type" => "html"
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,13 @@
1
+ <ul id="articles">
2
+ <% for article in articles[0...3] %>
3
+ <li><%= article %></li>
4
+ <% end %>
5
+ </ul>
6
+ <div id="archives">
7
+ <%= archives[3...5] %>
8
+ </div>
9
+ <!-- testing env variable passing -->
10
+ <p>env passed: <%= env != nil %><br/></p>
11
+ <!-- testing get/post parameter passing -->
12
+ <p>request method type: <%= env['REQUEST_METHOD'] %><br/></p>
13
+ <p>request name value pair: <%= env['QUERY_STRING'] %><br/></p>
@@ -0,0 +1,4 @@
1
+ <html>
2
+ <%= yield %>
3
+ </html>
4
+
@@ -0,0 +1 @@
1
+ <%= readme %>
@@ -0,0 +1,44 @@
1
+ require 'rubygems'
2
+ require 'hpricot'
3
+ require 'riot'
4
+
5
+ $:.unshift File.dirname(__FILE__)
6
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
7
+
8
+ require 'toto'
9
+
10
+ module Toto
11
+ class IncludesHTMLMacro < Riot::AssertionMacro
12
+ register :includes_html
13
+
14
+ def evaluate(actual, expected)
15
+ doc = Hpricot.parse(actual)
16
+ expected = expected.to_a.flatten
17
+
18
+ if (doc/expected.first).empty?
19
+ fail("expected #{actual} to contain a <#{expected.first}>")
20
+ elsif !(doc/expected.first).inner_html.match(expected.last)
21
+ fail("expected <#{expected.first}> to contain #{expected.last}")
22
+ else
23
+ pass
24
+ end
25
+ end
26
+ end
27
+
28
+ class IncludesElementsMacro < Riot::AssertionMacro
29
+ register :includes_elements
30
+
31
+ def evaluate(actual, selector, count)
32
+ doc = Hpricot.parse(actual)
33
+ (doc/selector).size == count ? pass : fail("expected #{actual} to contain #{count} #{selector}(s)")
34
+ end
35
+ end
36
+
37
+ class WithinMacro < Riot::AssertionMacro
38
+ register :within
39
+
40
+ def evaluate(actual, expected)
41
+ expected.include?(actual) ? pass : fail("expected #{actual} to be within #{expected}")
42
+ end
43
+ end
44
+ end
data/test/toto_test.rb ADDED
@@ -0,0 +1,285 @@
1
+ require 'test/test_helper'
2
+ require 'date'
3
+
4
+ URL = "http://toto.oz"
5
+ AUTHOR = "toto"
6
+
7
+ context Toto do
8
+ setup do
9
+ @config = Toto::Config.new(:markdown => true, :author => AUTHOR, :url => URL)
10
+ @toto = Rack::MockRequest.new(Toto::Server.new(@config))
11
+ Toto::Paths[:articles] = "test/articles"
12
+ Toto::Paths[:pages] = "test/templates"
13
+ Toto::Paths[:templates] = "test/templates"
14
+ end
15
+
16
+ context "GET /" do
17
+ setup { @toto.get('/') }
18
+
19
+ asserts("returns a 200") { topic.status }.equals 200
20
+ asserts("body is not empty") { not topic.body.empty? }
21
+ asserts("content type is set properly") { topic.content_type }.equals "text/html"
22
+ should("include a couple of article") { topic.body }.includes_elements("#articles li", 3)
23
+ should("include an archive") { topic.body }.includes_elements("#archives li", 2)
24
+
25
+ context "with no articles" do
26
+ setup { Rack::MockRequest.new(Toto::Server.new(@config.merge(:ext => 'oxo'))).get('/') }
27
+
28
+ asserts("body is not empty") { not topic.body.empty? }
29
+ asserts("returns a 200") { topic.status }.equals 200
30
+ end
31
+
32
+ context "with a user-defined to_html" do
33
+ setup do
34
+ @config[:to_html] = lambda do |path, page, binding|
35
+ ERB.new(File.read("#{path}/#{page}.rhtml")).result(binding)
36
+ end
37
+ @toto.get('/')
38
+ end
39
+
40
+ asserts("returns a 200") { topic.status }.equals 200
41
+ asserts("body is not empty") { not topic.body.empty? }
42
+ asserts("content type is set properly") { topic.content_type }.equals "text/html"
43
+ should("include a couple of article") { topic.body }.includes_elements("#articles li", 3)
44
+ should("include an archive") { topic.body }.includes_elements("#archives li", 2)
45
+ asserts("Etag header present") { topic.headers.include? "ETag" }
46
+ asserts("Etag header has a value") { not topic.headers["ETag"].empty? }
47
+ end
48
+ end
49
+
50
+ context "GET /about" do
51
+ setup { @toto.get('/about') }
52
+ asserts("returns a 200") { topic.status }.equals 200
53
+ asserts("body is not empty") { not topic.body.empty? }
54
+ should("have access to @articles") { topic.body }.includes_html("#count" => /5/)
55
+ end
56
+
57
+ context "GET a single article" do
58
+ setup { @toto.get("/1900/05/17/the-wonderful-wizard-of-oz") }
59
+ asserts("returns a 200") { topic.status }.equals 200
60
+ asserts("content type is set properly") { topic.content_type }.equals "text/html"
61
+ should("contain the article") { topic.body }.includes_html("p" => /<em>Once upon a time<\/em>/)
62
+ end
63
+
64
+ context "GET to the archive" do
65
+ context "through a year" do
66
+ setup { @toto.get('/2009') }
67
+ asserts("returns a 200") { topic.status }.equals 200
68
+ should("includes the entries for that year") { topic.body }.includes_elements("li.entry", 3)
69
+ end
70
+
71
+ context "through a year & month" do
72
+ setup { @toto.get('/2009/12') }
73
+ asserts("returns a 200") { topic.status }.equals 200
74
+ should("includes the entries for that month") { topic.body }.includes_elements("li.entry", 2)
75
+ should("includes the year & month") { topic.body }.includes_html("h1" => /2009\/12/)
76
+ end
77
+
78
+ context "through /archive" do
79
+ setup { @toto.get('/archive') }
80
+ end
81
+ end
82
+
83
+ context "GET to an unknown route with a custom error" do
84
+ setup do
85
+ @config[:error] = lambda {|code| "error: #{code}" }
86
+ @toto.get('/unknown')
87
+ end
88
+
89
+ should("returns a 404") { topic.status }.equals 404
90
+ should("return the custom error") { topic.body }.equals "error: 404"
91
+ end
92
+
93
+ context "Request is invalid" do
94
+ setup { @toto.delete('/invalid') }
95
+ should("returns a 400") { topic.status }.equals 400
96
+ end
97
+
98
+ context "GET /index.xml (atom feed)" do
99
+ setup { @toto.get('/index.xml') }
100
+ asserts("content type is set properly") { topic.content_type }.equals "application/xml"
101
+ asserts("body should be valid xml") { topic.body }.includes_html("feed > entry" => /.+/)
102
+ asserts("summary shouldn't be empty") { topic.body }.includes_html("summary" => /.{10,}/)
103
+ end
104
+ context "GET /index?param=testparam (get parameter)" do
105
+ setup { @toto.get('/index?param=testparam') }
106
+ asserts("returns a 200") { topic.status }.equals 200
107
+ asserts("content type is set properly") { topic.content_type }.equals "text/html"
108
+ asserts("contain the env variable") { topic.body }.includes_html("p" => /env passed: true/)
109
+ asserts("access the http get parameter") { topic.body }.includes_html("p" => /request method type: GET/)
110
+ asserts("access the http parameter name value pair") { topic.body }.includes_html("p" => /request name value pair: param=testparam/)
111
+ end
112
+
113
+
114
+
115
+ context "GET to a repo name" do
116
+ setup do
117
+ class Toto::Repo
118
+ def readme() "#{self[:name]}'s README" end
119
+ end
120
+ end
121
+
122
+ context "when the repo is in the :repos array" do
123
+ setup do
124
+ @config[:github] = {:user => "cloudhead", :repos => ['the-repo']}
125
+ @toto.get('/the-repo')
126
+ end
127
+ should("return the-repo's README") { topic.body }.includes("the-repo's README")
128
+ end
129
+
130
+ context "when the repo is not in the :repos array" do
131
+ setup do
132
+ @config[:github] = {:user => "cloudhead", :repos => []}
133
+ @toto.get('/the-repo')
134
+ end
135
+ should("return a 404") { topic.status }.equals 404
136
+ end
137
+ end
138
+
139
+ context "creating an article" do
140
+ setup do
141
+ @config[:markdown] = true
142
+ @config[:date] = lambda {|t| "the time is #{t.strftime("%Y/%m/%d %H:%M")}" }
143
+ @config[:summary] = {:length => 50}
144
+ end
145
+
146
+ context "with the bare essentials" do
147
+ setup do
148
+ Toto::Article.new({
149
+ :title => "Toto & The Wizard of Oz.",
150
+ :body => "#Chapter I\nhello, *stranger*."
151
+ }, @config)
152
+ end
153
+
154
+ should("have a title") { topic.title }.equals "Toto & The Wizard of Oz."
155
+ should("parse the body as markdown") { topic.body }.equals "<h1>Chapter I</h1>\n\n<p>hello, <em>stranger</em>.</p>\n"
156
+ should("create an appropriate slug") { topic.slug }.equals "toto-and-the-wizard-of-oz"
157
+ should("set the date") { topic.date }.equals "the time is #{Date.today.strftime("%Y/%m/%d %H:%M")}"
158
+ should("create a summary") { topic.summary == topic.body }
159
+ should("have an author") { topic.author }.equals AUTHOR
160
+ should("have a path") { topic.path }.equals Date.today.strftime("/%Y/%m/%d/toto-and-the-wizard-of-oz/")
161
+ should("have a url") { topic.url }.equals Date.today.strftime("#{URL}/%Y/%m/%d/toto-and-the-wizard-of-oz/")
162
+ end
163
+
164
+ context "with a user-defined summary" do
165
+ setup do
166
+ Toto::Article.new({
167
+ :title => "Toto & The Wizard of Oz.",
168
+ :body => "Well,\nhello ~\n, *stranger*."
169
+ }, @config.merge(:markdown => false, :summary => {:max => 150, :delim => /~\n/}))
170
+ end
171
+
172
+ should("split the article at the delimiter") { topic.summary }.equals "Well,\nhello"
173
+ should("not have the delimiter in the body") { topic.body !~ /~/ }
174
+ end
175
+
176
+ context "with everything specified" do
177
+ setup do
178
+ Toto::Article.new({
179
+ :title => "The Wizard of Oz",
180
+ :body => ("a little bit of text." * 5) + "\n" + "filler" * 10,
181
+ :date => "19/10/1976",
182
+ :slug => "wizard-of-oz",
183
+ :author => "toetoe"
184
+ }, @config)
185
+ end
186
+
187
+ should("parse the date") { [topic[:date].month, topic[:date].year] }.equals [10, 1976]
188
+ should("use the slug") { topic.slug }.equals "wizard-of-oz"
189
+ should("use the author") { topic.author }.equals "toetoe"
190
+
191
+ context "and long first paragraph" do
192
+ should("create a valid summary") { topic.summary }.equals "<p>" + ("a little bit of text." * 5).chop + "&hellip;</p>\n"
193
+ end
194
+
195
+ context "and a short first paragraph" do
196
+ setup do
197
+ @config[:markdown] = false
198
+ Toto::Article.new({:body => "there ain't such thing as a free lunch\n" * 10}, @config)
199
+ end
200
+
201
+ should("create a valid summary") { topic.summary.size }.within 75..80
202
+ end
203
+ end
204
+
205
+ context "in a subdirectory" do
206
+ context "with implicit leading forward slash" do
207
+ setup do
208
+ conf = Toto::Config.new({})
209
+ conf.set(:prefix, "blog")
210
+ Toto::Article.new({
211
+ :title => "Toto & The Wizard of Oz.",
212
+ :body => "#Chapter I\nhello, *stranger*."
213
+ }, conf)
214
+ end
215
+
216
+ should("be in the directory") { topic.path }.equals Date.today.strftime("/blog/%Y/%m/%d/toto-and-the-wizard-of-oz/")
217
+ end
218
+
219
+ context "with explicit leading forward slash" do
220
+ setup do
221
+ conf = Toto::Config.new({})
222
+ conf.set(:prefix, "/blog")
223
+ Toto::Article.new({
224
+ :title => "Toto & The Wizard of Oz.",
225
+ :body => "#Chapter I\nhello, *stranger*."
226
+ }, conf)
227
+ end
228
+
229
+ should("be in the directory") { topic.path }.equals Date.today.strftime("/blog/%Y/%m/%d/toto-and-the-wizard-of-oz/")
230
+ end
231
+
232
+ context "with explicit trailing forward slash" do
233
+ setup do
234
+ conf = Toto::Config.new({})
235
+ conf.set(:prefix, "blog/")
236
+ Toto::Article.new({
237
+ :title => "Toto & The Wizard of Oz.",
238
+ :body => "#Chapter I\nhello, *stranger*."
239
+ }, conf)
240
+ end
241
+
242
+ should("be in the directory") { topic.path }.equals Date.today.strftime("/blog/%Y/%m/%d/toto-and-the-wizard-of-oz/")
243
+ end
244
+ end
245
+ end
246
+
247
+ context "using Config#set with a hash" do
248
+ setup do
249
+ conf = Toto::Config.new({})
250
+ conf.set(:summary, {:delim => /%/})
251
+ conf
252
+ end
253
+
254
+ should("set summary[:delim] to /%/") { topic[:summary][:delim].source }.equals "%"
255
+ should("leave the :max intact") { topic[:summary][:max] }.equals 150
256
+ end
257
+
258
+ context "using Config#set with a block" do
259
+ setup do
260
+ conf = Toto::Config.new({})
261
+ conf.set(:to_html) {|path, p, _| path + p }
262
+ conf
263
+ end
264
+
265
+ should("set the value to a proc") { topic[:to_html] }.respond_to :call
266
+ end
267
+
268
+ context "testing individual configuration parameters" do
269
+ context "generate error pages" do
270
+ setup do
271
+ conf = Toto::Config.new({})
272
+ conf.set(:error) {|code| "error code #{code}" }
273
+ conf
274
+ end
275
+
276
+ should("create an error page") { topic[:error].call(400) }.equals "error code 400"
277
+ end
278
+ end
279
+
280
+ context "extensions to the core Ruby library" do
281
+ should("respond to iso8601") { Date.today }.respond_to?(:iso8601)
282
+ end
283
+ end
284
+
285
+