robb-toto 0.4.6.1

Sign up to get free protection for your applications and to get access to all the features.
data/test/toto_test.rb ADDED
@@ -0,0 +1,342 @@
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
+
105
+ context "GET to a repo name" do
106
+ setup do
107
+ class Toto::Repo
108
+ def readme() "#{self[:name]}'s README" end
109
+ end
110
+ end
111
+
112
+ context "when the repo is in the :repos array" do
113
+ setup do
114
+ @config[:github] = {:user => "cloudhead", :repos => ['the-repo']}
115
+ @toto.get('/the-repo')
116
+ end
117
+ should("return the-repo's README") { topic.body }.includes("the-repo's README")
118
+ end
119
+
120
+ context "when the repo is not in the :repos array" do
121
+ setup do
122
+ @config[:github] = {:user => "cloudhead", :repos => []}
123
+ @toto.get('/the-repo')
124
+ end
125
+ should("return a 404") { topic.status }.equals 404
126
+ end
127
+ end
128
+
129
+ context "creating an article" do
130
+ setup do
131
+ @config[:markdown] = true
132
+ @config[:date] = lambda {|t| "the time is #{t.strftime("%Y/%m/%d %H:%M")}" }
133
+ @config[:summary] = {:length => 50}
134
+ end
135
+
136
+ context "with the bare essentials" do
137
+ setup do
138
+ Toto::Article.new({
139
+ :title => "Toto & The Wizard of Oz.",
140
+ :body => "#Chapter I\nhello, *stranger*."
141
+ }, @config)
142
+ end
143
+
144
+ should("have a title") { topic.title }.equals "Toto & The Wizard of Oz."
145
+ should("parse the body as markdown") { topic.body }.equals "<h1>Chapter I</h1>\n\n<p>hello, <em>stranger</em>.</p>\n"
146
+ should("create an appropriate slug") { topic.slug }.equals "toto-and-the-wizard-of-oz"
147
+ should("set the date") { topic.date }.equals "the time is #{Date.today.strftime("%Y/%m/%d %H:%M")}"
148
+ should("create a summary") { topic.summary == topic.body }
149
+ should("have an author") { topic.author }.equals AUTHOR
150
+ should("have a path") { topic.path }.equals Date.today.strftime("/%Y/%m/%d/toto-and-the-wizard-of-oz/")
151
+ should("have a url") { topic.url }.equals Date.today.strftime("#{URL}/%Y/%m/%d/toto-and-the-wizard-of-oz/")
152
+ end
153
+
154
+ context "with a user-defined summary" do
155
+ setup do
156
+ Toto::Article.new({
157
+ :title => "Toto & The Wizard of Oz.",
158
+ :body => "Well,\nhello ~\n, *stranger*."
159
+ }, @config.merge(:markdown => false, :summary => {:max => 150, :delim => /~\n/}))
160
+ end
161
+
162
+ should("split the article at the delimiter") { topic.summary }.equals "Well,\nhello"
163
+ should("not have the delimiter in the body") { topic.body !~ /~/ }
164
+ end
165
+
166
+ context "with everything specified" do
167
+ setup do
168
+ @config[:permalink] = ":year/:title"
169
+
170
+ Toto::Article.new({
171
+ :title => "The Wizard of Oz",
172
+ :body => ("a little bit of text." * 5) + "\n" + "filler" * 10,
173
+ :date => "19/10/1976",
174
+ :slug => "wizard-of-oz",
175
+ :author => "toetoe"
176
+ }, @config)
177
+ end
178
+
179
+ should("parse the date") { [topic[:date].month, topic[:date].year] }.equals [10, 1976]
180
+ should("use the slug") { topic.slug }.equals "wizard-of-oz"
181
+ should("use the author") { topic.author }.equals "toetoe"
182
+ should("use the permalink") { topic.path }.equals "/1976/wizard-of-oz/"
183
+
184
+ context "and long first paragraph" do
185
+ should("create a valid summary") { topic.summary }.equals "<p>" + ("a little bit of text." * 5).chop + "&hellip;</p>\n"
186
+ end
187
+
188
+ context "and a short first paragraph" do
189
+ setup do
190
+ @config[:markdown] = false
191
+ Toto::Article.new({:body => "there ain't such thing as a free lunch\n" * 10}, @config)
192
+ end
193
+
194
+ should("create a valid summary") { topic.summary.size }.within 75..80
195
+ end
196
+
197
+ end
198
+
199
+ context "with custom permalink data" do
200
+ context "with extraneous metadata" do
201
+ setup do
202
+ @config[:permalink] = "/:foo/:bar"
203
+
204
+ Toto::Article.new({
205
+ # Bare minimum
206
+ :title => "Toto & The Wizard of Oz.",
207
+ :body => "Well,\nhello ~\n, *stranger*.",
208
+ # Actually testing this
209
+ :foo => "foo",
210
+ :bar => "bar",
211
+ }, @config)
212
+ end
213
+
214
+ should("use the correct data") { topic.path }.equals "/foo/bar/"
215
+ end
216
+
217
+ context "with colliding metadata" do
218
+ setup do
219
+ @config[:permalink] = "/:year/:title"
220
+
221
+ Toto::Article.new({
222
+ # Bare minimum
223
+ :title => "Toto & The Wizard of Oz.",
224
+ :body => "Well,\nhello ~\n, *stranger*.",
225
+ # Actually testing this
226
+ :year => 1007,
227
+ }, @config)
228
+ end
229
+
230
+ should("use the metadata instead of the generated data") { topic.path }.equals "/1007/toto-and-the-wizard-of-oz/"
231
+ end
232
+
233
+ context "with missing metadata" do
234
+ setup do
235
+ @config[:permalink] = "/:foo/:title"
236
+
237
+ Toto::Article.new({
238
+ # Bare minimum
239
+ :title => "Toto & The Wizard of Oz.",
240
+ :body => "Well,\nhello ~\n, *stranger*.",
241
+ }, @config)
242
+ end
243
+
244
+ should("continue without error") { topic.path }.equals "/toto-and-the-wizard-of-oz/"
245
+ should("not contain foward slash twice or more") { not topic.path =~ %r{//} }
246
+ end
247
+ end
248
+
249
+ context "in a subdirectory" do
250
+ context "with implicit leading forward slash" do
251
+ setup do
252
+ conf = Toto::Config.new({})
253
+ conf.set(:prefix, "blog")
254
+ Toto::Article.new({
255
+ :title => "Toto & The Wizard of Oz.",
256
+ :body => "#Chapter I\nhello, *stranger*."
257
+ }, conf)
258
+ end
259
+
260
+ should("be in the directory") { topic.path }.equals Date.today.strftime("/blog/%Y/%m/%d/toto-and-the-wizard-of-oz/")
261
+ end
262
+
263
+ context "with explicit leading forward slash" do
264
+ setup do
265
+ conf = Toto::Config.new({})
266
+ conf.set(:prefix, "/blog")
267
+ Toto::Article.new({
268
+ :title => "Toto & The Wizard of Oz.",
269
+ :body => "#Chapter I\nhello, *stranger*."
270
+ }, conf)
271
+ end
272
+
273
+ should("be in the directory") { topic.path }.equals Date.today.strftime("/blog/%Y/%m/%d/toto-and-the-wizard-of-oz/")
274
+ end
275
+
276
+ context "with explicit trailing forward slash" do
277
+ setup do
278
+ conf = Toto::Config.new({})
279
+ conf.set(:prefix, "blog/")
280
+ Toto::Article.new({
281
+ :title => "Toto & The Wizard of Oz.",
282
+ :body => "#Chapter I\nhello, *stranger*."
283
+ }, conf)
284
+ end
285
+
286
+ should("be in the directory") { topic.path }.equals Date.today.strftime("/blog/%Y/%m/%d/toto-and-the-wizard-of-oz/")
287
+ end
288
+
289
+ context "in a sub-subdirectory" do
290
+ setup do
291
+ conf = Toto::Config.new({})
292
+ conf.set(:prefix, "my/blog")
293
+ Toto::Article.new({
294
+ :title => "Toto & The Wizard of Oz.",
295
+ :body => "#Chapter I\nhello, *stranger*."
296
+ }, conf)
297
+ end
298
+
299
+ should("be in the directory") { topic.path }.equals Date.today.strftime("/my/blog/%Y/%m/%d/toto-and-the-wizard-of-oz/")
300
+ end
301
+ end
302
+ end
303
+
304
+ context "using Config#set with a hash" do
305
+ setup do
306
+ conf = Toto::Config.new({})
307
+ conf.set(:summary, {:delim => /%/})
308
+ conf
309
+ end
310
+
311
+ should("set summary[:delim] to /%/") { topic[:summary][:delim].source }.equals "%"
312
+ should("leave the :max intact") { topic[:summary][:max] }.equals 150
313
+ end
314
+
315
+ context "using Config#set with a block" do
316
+ setup do
317
+ conf = Toto::Config.new({})
318
+ conf.set(:to_html) {|path, p, _| path + p }
319
+ conf
320
+ end
321
+
322
+ should("set the value to a proc") { topic[:to_html] }.respond_to :call
323
+ end
324
+
325
+ context "testing individual configuration parameters" do
326
+ context "generate error pages" do
327
+ setup do
328
+ conf = Toto::Config.new({})
329
+ conf.set(:error) {|code| "error code #{code}" }
330
+ conf
331
+ end
332
+
333
+ should("create an error page") { topic[:error].call(400) }.equals "error code 400"
334
+ end
335
+ end
336
+
337
+ context "extensions to the core Ruby library" do
338
+ should("respond to iso8601") { Date.today }.respond_to?(:iso8601)
339
+ end
340
+ end
341
+
342
+
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: robb-toto
3
+ version: !ruby/object:Gem::Version
4
+ hash: 117
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 4
9
+ - 6
10
+ - 1
11
+ version: 0.4.6.1
12
+ platform: ruby
13
+ authors:
14
+ - cloudhead
15
+ - evaryont
16
+ autorequire:
17
+ bindir: bin
18
+ cert_chain: []
19
+
20
+ date: 2010-09-14 00:00:00 +02:00
21
+ default_executable:
22
+ dependencies:
23
+ - !ruby/object:Gem::Dependency
24
+ name: riot
25
+ prerelease: false
26
+ requirement: &id001 !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ hash: 3
32
+ segments:
33
+ - 0
34
+ version: "0"
35
+ type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: builder
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 3
46
+ segments:
47
+ - 0
48
+ version: "0"
49
+ type: :runtime
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: rack
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ type: :runtime
64
+ version_requirements: *id003
65
+ - !ruby/object:Gem::Dependency
66
+ name: rdiscount
67
+ prerelease: false
68
+ requirement: &id004 !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ type: :runtime
78
+ version_requirements: *id004
79
+ description: the tiniest blog-engine in Oz. Build of evaryont's branch with better permalink choices
80
+ email: self@cloudhead.net
81
+ executables: []
82
+
83
+ extensions: []
84
+
85
+ extra_rdoc_files:
86
+ - LICENSE
87
+ - README.md
88
+ - TODO
89
+ files:
90
+ - .document
91
+ - .gitignore
92
+ - LICENSE
93
+ - README.md
94
+ - Rakefile
95
+ - TODO
96
+ - VERSION
97
+ - lib/ext/ext.rb
98
+ - lib/toto.rb
99
+ - test/articles/1900-05-17-the-wonderful-wizard-of-oz.txt
100
+ - test/articles/2001-01-01-two-thousand-and-one.txt
101
+ - test/articles/2009-04-01-tilt-factor.txt
102
+ - test/articles/2009-12-04-some-random-article.txt
103
+ - test/articles/2009-12-11-the-dichotomy-of-design.txt
104
+ - test/autotest.rb
105
+ - test/templates/about.rhtml
106
+ - test/templates/archives.rhtml
107
+ - test/templates/article.rhtml
108
+ - test/templates/feed.builder
109
+ - test/templates/index.builder
110
+ - test/templates/index.rhtml
111
+ - test/templates/layout.rhtml
112
+ - test/templates/repo.rhtml
113
+ - test/test_helper.rb
114
+ - test/toto_test.rb
115
+ has_rdoc: true
116
+ homepage: http://github.com/cloudhead/toto
117
+ licenses: []
118
+
119
+ post_install_message:
120
+ rdoc_options:
121
+ - --charset=UTF-8
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ hash: 3
130
+ segments:
131
+ - 0
132
+ version: "0"
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ none: false
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ hash: 3
139
+ segments:
140
+ - 0
141
+ version: "0"
142
+ requirements: []
143
+
144
+ rubyforge_project:
145
+ rubygems_version: 1.3.7
146
+ signing_key:
147
+ specification_version: 3
148
+ summary: the tiniest blog-engine in Oz
149
+ test_files:
150
+ - test/autotest.rb
151
+ - test/test_helper.rb
152
+ - test/toto_test.rb