glinda 0.1.0

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,466 @@
1
+ require 'spec_helper'
2
+ require 'date'
3
+
4
+ URL = "http://toto.oz"
5
+ AUTHOR = "Glinda"
6
+
7
+ include Capybara::DSL
8
+ include Capybara::RSpecMatchers
9
+
10
+ describe Glinda do
11
+ before(:each) do
12
+ @config = Glinda::Config.new(:markdown => true, :author => AUTHOR, :url => URL)
13
+ @glinda = Rack::MockRequest.new(Glinda::Server.new(@config))
14
+ Glinda::Paths[:articles] = "spec/articles"
15
+ Glinda::Paths[:pages] = "spec/templates"
16
+ Glinda::Paths[:templates] = "spec/templates"
17
+ end
18
+
19
+ describe "GET /" do
20
+ let(:response) { @glinda.get('/') }
21
+
22
+ it "should return status code 200" do
23
+ response.status.should == 200
24
+ end
25
+
26
+ it "should not have an empty body" do
27
+ response.body.should_not be_empty
28
+ end
29
+
30
+ it "should set the content-type" do
31
+ response.content_type.should == "text/html"
32
+ end
33
+
34
+ it "should include 2 articles" do
35
+ visit '/'
36
+ page.all('#articles li').count.should == 3
37
+ end
38
+
39
+ it "should include an archive" do
40
+ visit '/'
41
+ page.all('#archives li').count.should == 2
42
+ end
43
+
44
+ context "with no articles" do
45
+ let(:response) { Rack::MockRequest.new(Glinda::Server.new(@config.merge(:ext => 'oxo'))).get('/') }
46
+
47
+ it "should return status code 200" do
48
+ response.status.should == 200
49
+ end
50
+
51
+ it "should not have an empty body" do
52
+ response.body.should_not be_empty
53
+ end
54
+ end
55
+
56
+ context "with a user-defined to_html" do
57
+ let(:response) do
58
+ @config[:to_html] = lambda do |path, page, binding|
59
+ ERB.new(File.read("#{path}/#{page}.rhtml")).result(binding)
60
+ end
61
+ @glinda.get('/')
62
+ end
63
+
64
+ it "should return status code 200" do
65
+ response.status.should == 200
66
+ end
67
+
68
+ it "should not have an empty body" do
69
+ response.body.should_not be_empty
70
+ end
71
+
72
+ it "should set the content-type" do
73
+ response.content_type.should == "text/html"
74
+ end
75
+
76
+ it "should include 2 articles" do
77
+ visit '/'
78
+ page.all('#articles li').count.should == 3
79
+ end
80
+
81
+ it "should include an archive" do
82
+ visit '/'
83
+ page.all('#archives li').count.should == 2
84
+ end
85
+
86
+ it "should set Etag header" do
87
+ response.headers.should include "ETag"
88
+ end
89
+
90
+ it "should set the ETag value" do
91
+ response.headers["ETag"].should_not be_empty
92
+ end
93
+ end
94
+ end
95
+
96
+ context "GET /about" do
97
+ let(:response) { @glinda.get('/about') }
98
+ it "should return status code 200" do
99
+ response.status.should == 200
100
+ end
101
+
102
+ it "should not have an empty body" do
103
+ response.body.should_not be_empty
104
+ end
105
+
106
+ it "should set the content-type" do
107
+ response.content_type.should == "text/html"
108
+ end
109
+
110
+ it "should have access to @articles" do
111
+ visit '/about'
112
+ page.find('#count').should have_content '5'
113
+ end
114
+ end
115
+
116
+ context "GET a single article" do
117
+ let(:response) { @glinda.get("/1900/05/17/the-wonderful-wizard-of-oz") }
118
+
119
+ it "should return status code 200" do
120
+ response.status.should == 200
121
+ end
122
+
123
+ it "should include the article" do
124
+ visit '/1900/05/17/the-wonderful-wizard-of-oz'
125
+ page.should have_content "Once upon a time"
126
+ end
127
+
128
+
129
+ it "should set the content-type" do
130
+ response.content_type.should == "text/html"
131
+ end
132
+ end
133
+
134
+ context "GET to the archive" do
135
+ context "through a year" do
136
+ before(:each) { visit '/2009' }
137
+
138
+ it "should return a 200" do
139
+ page.status_code.should == 200
140
+ end
141
+
142
+ it "should return the articles for that year" do
143
+ page.all('li.entry').count.should == 3
144
+ end
145
+ end
146
+
147
+ context "through a year & month" do
148
+ before(:each) { visit '/2009/12' }
149
+
150
+ it "should return a 200" do
151
+ page.status_code.should == 200
152
+ end
153
+
154
+ it "should return the articles for that year" do
155
+ page.all('li.entry').count.should == 2
156
+ end
157
+
158
+ it "should include the year and month" do
159
+ page.find("h1").should have_content("2009/12")
160
+ end
161
+ end
162
+ end
163
+
164
+ context "GET to an unknown route with a custom error" do
165
+ before(:each) do
166
+ @config[:error] = lambda {|code| "error: #{code}" }
167
+ Capybara.app = Glinda::Server.new(@config)
168
+ visit('/unknown')
169
+ end
170
+
171
+ it "should return a 404" do
172
+ page.status_code.should == 404
173
+ end
174
+
175
+ it "should display the custom error" do
176
+ page.should have_content "error: 404"
177
+ end
178
+ end
179
+
180
+ context "Request is invalid" do
181
+ let(:response) { @glinda.delete('/invalid') }
182
+ it "should return status code 400" do
183
+ response.status.should == 400
184
+ end
185
+ end
186
+
187
+ context "GET /index.xml (atom feed)" do
188
+ before(:each) do
189
+ visit '/index.xml'
190
+ end
191
+
192
+ it "should set content-type" do
193
+ page.response_headers['content-type'].should == 'application/xml'
194
+ end
195
+
196
+ it "be valid xml" do
197
+ page.all('feed entry').count.should > 0
198
+ end
199
+
200
+ it "should show a summary" do
201
+ page.should have_css 'feed entry summary'
202
+ end
203
+ end
204
+
205
+ context "GET /index?param=testparam (get parameter)" do
206
+ before :each do
207
+ visit 'index?param=testparam'
208
+ end
209
+
210
+ it "should return status code 200" do
211
+ page.status_code.should == 200
212
+ end
213
+
214
+ it "set content-type properly" do
215
+ page.response_headers['content-type'].should == 'text/html'
216
+ end
217
+
218
+ it "contain the env variable" do
219
+ page.should have_content 'env passed: true'
220
+ end
221
+
222
+ it "be able to access the HTTP GET Param" do
223
+ page.should have_content 'request method type: GET'
224
+ end
225
+
226
+ it "should access the http paramiter name value pair" do
227
+ page.should have_content 'request name value pair: param=testparam'
228
+ end
229
+ end
230
+
231
+
232
+
233
+ context "GET to a repo name" do
234
+ before(:all) do
235
+ class Glinda::Repo
236
+ def readme() "#{self[:name]}'s README" end
237
+ end
238
+ end
239
+
240
+ context "when the repo is in the :repos array" do
241
+ before(:each) do
242
+ @config[:github] = {:user => "cloudhead", :repos => ['the-repo']}
243
+ Capybara.app = Glinda::Server.new(@config)
244
+ visit '/the-repo'
245
+ end
246
+ it "should return the repo README" do
247
+ page.should have_content "the-repo's README"
248
+ end
249
+ end
250
+
251
+ context "when the repo is not in the :repos array" do
252
+ before :each do
253
+ @config[:github] = {:user => "cloudhead", :repos => []}
254
+ Capybara.app = Glinda::Server.new(@config)
255
+ visit '/the-repo'
256
+ end
257
+
258
+ it "should return a 404" do
259
+ page.status_code.should == 404
260
+ end
261
+ end
262
+ end
263
+
264
+ context "creating an article" do
265
+ before(:each) do
266
+ @config[:markdown] = true
267
+ @config[:date] = lambda {|t| "the time is #{t.strftime("%Y/%m/%d %H:%M")}" }
268
+ @config[:summary] = {:length => 50}
269
+ Capybara.app = Glinda::Server.new(@config)
270
+ end
271
+
272
+ context "with the bare essentials" do
273
+
274
+ let(:article) { Glinda::Article.new({ title: "Glinda & The Wizard of Oz.", body: "#Chapter I\nHello, *stranger*." }, @config) }
275
+
276
+ it { article.title.should == "Glinda & The Wizard of Oz." }
277
+ it "should parse the body as markdown" do
278
+ article.body.should == "<h1>Chapter I</h1>\n\n<p>Hello, <em>stranger</em>.</p>\n"
279
+ end
280
+
281
+ it "should create the appropriate slug" do
282
+ article.slug.should == "glinda-and-the-wizard-of-oz"
283
+ end
284
+
285
+ it "should set the date" do
286
+ article.date.should == "the time is #{Date.today.strftime("%Y/%m/%d %H:%M")}"
287
+ end
288
+
289
+ it "should create a summary" do
290
+ article.summary.should == article.body
291
+ end
292
+
293
+ it "should have an author" do
294
+ article.author.should == AUTHOR
295
+ end
296
+
297
+ it "should have a path" do
298
+ article.path.should == Date.today.strftime("/%Y/%m/%d/glinda-and-the-wizard-of-oz/")
299
+ end
300
+
301
+ it "should have a URL" do
302
+ article.url.should == Date.today.strftime("#{URL}/%Y/%m/%d/glinda-and-the-wizard-of-oz/")
303
+ end
304
+ end
305
+
306
+ context "with a user-defined summary" do
307
+ let(:article) do
308
+ Glinda::Article.new({
309
+ :title => "Glinda & The Wizard of Oz.",
310
+ :body => "Well,\nhello ~\n, *stranger*."
311
+ }, @config.merge(:markdown => false, :summary => {:max => 150, :delim => /~\n/}))
312
+ end
313
+
314
+ it "should split the article at the delmiter" do
315
+ article.summary.should == "Well,\nhello"
316
+ end
317
+
318
+ it "should not have the delimiter in the body" do
319
+ article.body. !~ /~/
320
+ end
321
+ end
322
+
323
+ context "with everything specified" do
324
+ let(:article) do
325
+ Glinda::Article.new({
326
+ :title => "The Wizard of Oz",
327
+ :body => ("a little bit of text." * 5) + "\n" + "filler" * 10,
328
+ :date => "19/10/1976",
329
+ :slug => "wizard-of-oz",
330
+ :author => "toetoe"
331
+ }, @config)
332
+ end
333
+
334
+ it "should parse the date" do
335
+ article[:date].month.should == 10
336
+ article[:date].year.should == 1976
337
+ end
338
+
339
+ it "should use the slug" do
340
+ article.slug.should == "wizard-of-oz"
341
+ end
342
+
343
+ it "should use the author" do
344
+ article.author.should == "toetoe"
345
+ end
346
+
347
+
348
+ context "and long first paragraph" do
349
+ it "should create a valid summary" do
350
+ article.summary.should == "<p>" + ("a little bit of text." * 5).chop + "&hellip;</p>\n"
351
+ end
352
+ end
353
+
354
+ context "and a short first paragraph" do
355
+ let(:article) do
356
+ @config[:markdown] = false
357
+ Glinda::Article.new({:body => "there ain't such thing as a free lunch\n" * 10}, @config)
358
+ end
359
+
360
+ it "should create a valid summary" do
361
+ article.summary.size.should <= 80
362
+ article.summary.size.should >= 75
363
+ end
364
+ end
365
+ end
366
+
367
+ context "in a subdirectory" do
368
+ context "with implicit leading forward slash" do
369
+ let(:article) do
370
+ conf = Glinda::Config.new({})
371
+ conf.set(:prefix, "blog")
372
+ Glinda::Article.new({
373
+ :title => "Glinda & The Wizard of Oz.",
374
+ :body => "#Chapter I\nhello, *stranger*."
375
+ }, conf)
376
+ end
377
+
378
+ it "should be in the directory" do
379
+ article.path.should == Date.today.strftime("/blog/%Y/%m/%d/glinda-and-the-wizard-of-oz/")
380
+ end
381
+
382
+ end
383
+
384
+ context "with explicit leading forward slash" do
385
+ let(:article) do
386
+ conf = Glinda::Config.new({})
387
+ conf.set(:prefix, "/blog")
388
+ Glinda::Article.new({
389
+ :title => "Glinda & The Wizard of Oz.",
390
+ :body => "#Chapter I\nhello, *stranger*."
391
+ }, conf)
392
+ end
393
+
394
+ it "should be in the directory do" do
395
+ article.path.should == Date.today.strftime("/blog/%Y/%m/%d/glinda-and-the-wizard-of-oz/")
396
+ end
397
+ end
398
+
399
+ context "with explicit trailing forward slash" do
400
+ let(:article) do
401
+ conf = Glinda::Config.new({})
402
+ conf.set(:prefix, "blog/")
403
+ Glinda::Article.new({
404
+ :title => "Glinda & The Wizard of Oz.",
405
+ :body => "#Chapter I\nhello, *stranger*."
406
+ }, conf)
407
+ end
408
+
409
+ it "should be in the directory do" do
410
+ article.path.should == Date.today.strftime("/blog/%Y/%m/%d/glinda-and-the-wizard-of-oz/")
411
+ end
412
+ end
413
+ end
414
+ end
415
+
416
+ context "using Config#set with a hash" do
417
+ let(:conf) do
418
+ conf = Glinda::Config.new({})
419
+ conf.set(:summary, {:delim => /%/})
420
+ conf
421
+ end
422
+
423
+ it "should set summary delim to /%/" do
424
+ conf[:summary][:delim].source.should == "%"
425
+ end
426
+
427
+ it "should leave :max intact" do
428
+ conf[:summary][:max].should == 150
429
+ end
430
+ end
431
+
432
+ context "using Config#set with a block" do
433
+ let(:conf) do
434
+ conf = Glinda::Config.new({})
435
+ conf.set(:to_html) {|path, p, _| path + p }
436
+ conf
437
+ end
438
+
439
+ subject { conf[:to_html] }
440
+
441
+ it { should respond_to :call }
442
+ end
443
+
444
+ context "testing individual configuration parameters" do
445
+ context "generate error pages" do
446
+ let(:conf) do
447
+ conf = Glinda::Config.new({})
448
+ conf.set(:error) {|code| "error code #{code}" }
449
+ conf
450
+ end
451
+
452
+ it "should create an error" do
453
+ conf[:error].call(400).should == "error code 400"
454
+ end
455
+
456
+ end
457
+ end
458
+
459
+ context "extensions to the core Ruby library" do
460
+ it "should respond to iso8601" do
461
+ Date.today.should respond_to :iso8601
462
+ end
463
+ end
464
+ end
465
+
466
+
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'rspec'
3
+ require 'capybara'
4
+ require 'capybara/rspec'
5
+
6
+ $:.unshift File.dirname(__FILE__)
7
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
8
+
9
+ require 'glinda'
10
+
11
+ Capybara.app = Glinda::Server.new
12
+
@@ -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 %>