toto-bongo 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,14 @@
1
+ <!doctype html>
2
+ %html
3
+ %head
4
+ %link{:href => "/stylesheets/blog.css", :rel => "stylesheet", :type => "text/css"}
5
+ %link{:href => "/index.xml", :rel => "alternate", :title => "#{title} - feed", :type => "application/atom+xml"}/
6
+ %meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
7
+ %title= title
8
+ %body
9
+ %section
10
+ = yield
11
+ %footer
12
+ powered by
13
+ %a{:href => "http://github.com/danpal/toto-bongo"} toto
14
+
@@ -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
+
@@ -0,0 +1,75 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{toto-bongo}
8
+ s.version = "1.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Daniel Palacio"]
12
+ s.date = %q{2011-05-10}
13
+ s.description = %q{Minimal blog to use with your existing app}
14
+ s.extra_rdoc_files = [
15
+ "LICENSE",
16
+ "README.md"
17
+ ]
18
+ s.files = [
19
+ ".document",
20
+ "LICENSE",
21
+ "README.md",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "lib/ext/ext.rb",
25
+ "lib/toto-bongo.rb",
26
+ "test/articles/1900-05-17-the-wonderful-wizard-of-oz.txt",
27
+ "test/articles/2001-01-01-two-thousand-and-one.txt",
28
+ "test/articles/2009-04-01-tilt-factor.txt",
29
+ "test/articles/2009-12-04-some-random-article.txt",
30
+ "test/articles/2009-12-11-the-dichotomy-of-design.txt",
31
+ "test/autotest.rb",
32
+ "test/templates/about.html.haml",
33
+ "test/templates/archives.html.haml",
34
+ "test/templates/article.html.haml",
35
+ "test/templates/feed.builder",
36
+ "test/templates/index.builder",
37
+ "test/templates/index.html.haml",
38
+ "test/templates/layout.html.haml",
39
+ "test/test_helper.rb",
40
+ "test/toto_test.rb",
41
+ "toto-bongo.gemspec"
42
+ ]
43
+ s.homepage = %q{https://github.com/danpal/toto-bongo}
44
+ s.require_paths = ["lib"]
45
+ s.rubygems_version = %q{1.3.7}
46
+ s.summary = %q{Tiny blog for your existing app}
47
+ s.test_files = [
48
+ "test/autotest.rb",
49
+ "test/test_helper.rb",
50
+ "test/toto_test.rb"
51
+ ]
52
+
53
+ if s.respond_to? :specification_version then
54
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
55
+ s.specification_version = 3
56
+
57
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
58
+ s.add_development_dependency(%q<riot>, [">= 0"])
59
+ s.add_runtime_dependency(%q<builder>, [">= 0"])
60
+ s.add_runtime_dependency(%q<rack>, [">= 0"])
61
+ s.add_runtime_dependency(%q<RedCloth>, [">= 0"])
62
+ else
63
+ s.add_dependency(%q<riot>, [">= 0"])
64
+ s.add_dependency(%q<builder>, [">= 0"])
65
+ s.add_dependency(%q<rack>, [">= 0"])
66
+ s.add_dependency(%q<RedCloth>, [">= 0"])
67
+ end
68
+ else
69
+ s.add_dependency(%q<riot>, [">= 0"])
70
+ s.add_dependency(%q<builder>, [">= 0"])
71
+ s.add_dependency(%q<rack>, [">= 0"])
72
+ s.add_dependency(%q<RedCloth>, [">= 0"])
73
+ end
74
+ end
75
+
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: toto-bongo
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 1
9
+ version: 1.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Daniel Palacio
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-05-10 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: riot
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :development
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: builder
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :runtime
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: rack
48
+ prerelease: false
49
+ requirement: &id003 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ segments:
55
+ - 0
56
+ version: "0"
57
+ type: :runtime
58
+ version_requirements: *id003
59
+ - !ruby/object:Gem::Dependency
60
+ name: RedCloth
61
+ prerelease: false
62
+ requirement: &id004 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ segments:
68
+ - 0
69
+ version: "0"
70
+ type: :runtime
71
+ version_requirements: *id004
72
+ description: Minimal blog to use with your existing app
73
+ email:
74
+ executables: []
75
+
76
+ extensions: []
77
+
78
+ extra_rdoc_files:
79
+ - LICENSE
80
+ - README.md
81
+ files:
82
+ - .document
83
+ - LICENSE
84
+ - README.md
85
+ - Rakefile
86
+ - VERSION
87
+ - lib/ext/ext.rb
88
+ - lib/toto-bongo.rb
89
+ - test/articles/1900-05-17-the-wonderful-wizard-of-oz.txt
90
+ - test/articles/2001-01-01-two-thousand-and-one.txt
91
+ - test/articles/2009-04-01-tilt-factor.txt
92
+ - test/articles/2009-12-04-some-random-article.txt
93
+ - test/articles/2009-12-11-the-dichotomy-of-design.txt
94
+ - test/autotest.rb
95
+ - test/templates/about.html.haml
96
+ - test/templates/archives.html.haml
97
+ - test/templates/article.html.haml
98
+ - test/templates/feed.builder
99
+ - test/templates/index.builder
100
+ - test/templates/index.html.haml
101
+ - test/templates/layout.html.haml
102
+ - test/test_helper.rb
103
+ - test/toto_test.rb
104
+ - toto-bongo.gemspec
105
+ has_rdoc: true
106
+ homepage: https://github.com/danpal/toto-bongo
107
+ licenses: []
108
+
109
+ post_install_message:
110
+ rdoc_options: []
111
+
112
+ require_paths:
113
+ - lib
114
+ required_ruby_version: !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ segments:
120
+ - 0
121
+ version: "0"
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ segments:
128
+ - 0
129
+ version: "0"
130
+ requirements: []
131
+
132
+ rubyforge_project:
133
+ rubygems_version: 1.3.7
134
+ signing_key:
135
+ specification_version: 3
136
+ summary: Tiny blog for your existing app
137
+ test_files:
138
+ - test/autotest.rb
139
+ - test/test_helper.rb
140
+ - test/toto_test.rb