nesta 0.9.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.
Files changed (53) hide show
  1. data/.gitignore +13 -0
  2. data/Gemfile +6 -0
  3. data/Gemfile.lock +58 -0
  4. data/LICENSE +19 -0
  5. data/README.md +45 -0
  6. data/Rakefile +12 -0
  7. data/bin/nesta +67 -0
  8. data/config.ru +9 -0
  9. data/config/config.yml.sample +73 -0
  10. data/config/deploy.rb.sample +62 -0
  11. data/lib/nesta/app.rb +199 -0
  12. data/lib/nesta/cache.rb +139 -0
  13. data/lib/nesta/commands.rb +135 -0
  14. data/lib/nesta/config.rb +87 -0
  15. data/lib/nesta/models.rb +313 -0
  16. data/lib/nesta/nesta.rb +0 -0
  17. data/lib/nesta/overrides.rb +59 -0
  18. data/lib/nesta/path.rb +11 -0
  19. data/lib/nesta/plugins.rb +15 -0
  20. data/lib/nesta/version.rb +3 -0
  21. data/nesta.gemspec +49 -0
  22. data/scripts/import-from-mephisto +207 -0
  23. data/spec/atom_spec.rb +138 -0
  24. data/spec/commands_spec.rb +220 -0
  25. data/spec/config_spec.rb +69 -0
  26. data/spec/model_factory.rb +94 -0
  27. data/spec/models_spec.rb +445 -0
  28. data/spec/overrides_spec.rb +113 -0
  29. data/spec/page_spec.rb +428 -0
  30. data/spec/path_spec.rb +28 -0
  31. data/spec/sitemap_spec.rb +102 -0
  32. data/spec/spec.opts +1 -0
  33. data/spec/spec_helper.rb +72 -0
  34. data/templates/Gemfile +8 -0
  35. data/templates/Rakefile +35 -0
  36. data/templates/config.ru +9 -0
  37. data/templates/config/config.yml +73 -0
  38. data/templates/config/deploy.rb +47 -0
  39. data/views/analytics.haml +12 -0
  40. data/views/atom.builder +28 -0
  41. data/views/categories.haml +3 -0
  42. data/views/comments.haml +8 -0
  43. data/views/error.haml +13 -0
  44. data/views/feed.haml +3 -0
  45. data/views/index.haml +5 -0
  46. data/views/layout.haml +27 -0
  47. data/views/master.sass +246 -0
  48. data/views/not_found.haml +13 -0
  49. data/views/page.haml +29 -0
  50. data/views/sidebar.haml +3 -0
  51. data/views/sitemap.builder +15 -0
  52. data/views/summaries.haml +14 -0
  53. metadata +302 -0
@@ -0,0 +1,113 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
2
+ require File.expand_path('model_factory', File.dirname(__FILE__))
3
+
4
+ describe "Rendering" do
5
+ include ConfigSpecHelper
6
+ include ModelFactory
7
+ include RequestSpecHelper
8
+
9
+ def create_fixture(type, name, content)
10
+ base_path = {
11
+ :local => Nesta::Path.local,
12
+ :theme => Nesta::Path.themes(@theme)
13
+ }[type]
14
+ path = File.join(base_path, name)
15
+ @fixtures << path
16
+ FileUtils.mkdir_p(File.dirname(path))
17
+ open(path, 'w') { |file| file.write(content) }
18
+ end
19
+
20
+ def create_template(type, name, content)
21
+ create_fixture(type, File.join('views', name), content)
22
+ end
23
+
24
+ def create_app_file(type)
25
+ create_fixture(type, 'app.rb', "DEFINED_IN_#{type.to_s.upcase}_FILE = true")
26
+ end
27
+
28
+ before(:each) do
29
+ @app_root = Nesta::App.root
30
+ Nesta::App.root = File.expand_path('fixtures/tmp', File.dirname(__FILE__))
31
+ @theme = 'my-theme'
32
+ @fixtures = []
33
+ stub_configuration
34
+ end
35
+
36
+ after(:each) do
37
+ @fixtures.each { |path| FileUtils.rm(path) if File.exist?(path) }
38
+ Nesta::App.root = @app_root
39
+ end
40
+
41
+ describe "when local files exist" do
42
+ before(:each) do
43
+ create_template(:local, 'page.haml', '%p Local template')
44
+ end
45
+
46
+ it "should use local application files" do
47
+ create_app_file(:local)
48
+ Nesta::Overrides.load_local_app
49
+ Object.const_get(:DEFINED_IN_LOCAL_FILE).should be_true
50
+ end
51
+
52
+ it "should use local template in place of default" do
53
+ get create_category.abspath
54
+ body.should have_tag("p", "Local template")
55
+ end
56
+ end
57
+
58
+ describe "when theme installed" do
59
+ before(:each) do
60
+ create_template(:theme, 'page.haml', '%p Theme template')
61
+ end
62
+
63
+ it "should not require theme application file automatically" do
64
+ create_app_file(:theme)
65
+ lambda {
66
+ Object.const_get(:DEFINED_IN_THEME_FILE)
67
+ }.should raise_error(NameError)
68
+ end
69
+
70
+ it "should not use theme templates automatically" do
71
+ get create_category.abspath
72
+ body.should_not have_tag("p", "Theme template")
73
+ end
74
+
75
+ describe "and configured" do
76
+ before(:each) do
77
+ stub_config_key("theme", @theme)
78
+ end
79
+
80
+ it "should require theme application file" do
81
+ create_app_file(:theme)
82
+ Nesta::Overrides.load_theme_app
83
+ Object.const_get(:DEFINED_IN_THEME_FILE).should be_true
84
+ end
85
+
86
+ it "should use theme's template in place of default" do
87
+ get create_category.abspath
88
+ body.should have_tag("p", "Theme template")
89
+ end
90
+
91
+ context "and local files exist" do
92
+ before(:each) do
93
+ create_template(:local, "page.haml", "%p Local template")
94
+ end
95
+
96
+ it "should require local and theme application files" do
97
+ create_app_file(:local)
98
+ create_app_file(:theme)
99
+ Nesta::Overrides.load_theme_app
100
+ Nesta::Overrides.load_local_app
101
+ Object.const_get(:DEFINED_IN_LOCAL_FILE).should be_true
102
+ Object.const_get(:DEFINED_IN_THEME_FILE).should be_true
103
+ end
104
+
105
+ it "should use local template" do
106
+ get create_category.abspath
107
+ body.should_not have_tag("p", "Theme template")
108
+ body.should have_tag("p", "Local template")
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
data/spec/page_spec.rb ADDED
@@ -0,0 +1,428 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
2
+ require File.expand_path('model_factory', File.dirname(__FILE__))
3
+
4
+ describe "page with keyword and description", :shared => true do
5
+ it "should set the keywords meta tag" do
6
+ do_get
7
+ body.should have_tag("meta[@name=keywords][@content='#{@keywords}']")
8
+ end
9
+
10
+ it "should set description meta tag" do
11
+ do_get
12
+ body.should have_tag("meta[@name=description][@content='#{@description}']")
13
+ end
14
+ end
15
+
16
+ describe "page that can display menus", :shared => true do
17
+ it "should not display menu by default" do
18
+ do_get
19
+ body.should_not have_tag("#sidebar ul.menu")
20
+ end
21
+
22
+ describe "and simple menu configured" do
23
+ before(:each) do
24
+ create_menu(@category.path)
25
+ end
26
+
27
+ it "should link to top level menu items" do
28
+ do_get
29
+ body.should have_tag(
30
+ "ul.menu a[@href=#{@category.abspath}]", Regexp.new(@category.heading))
31
+ end
32
+ end
33
+
34
+ describe "and nested menu configured" do
35
+ before(:each) do
36
+ @level2 = create_category(:path => "level-2", :heading => "Level 2")
37
+ @level3 = create_category(:path => "level-3", :heading => "Level 3")
38
+ text = <<-EOF
39
+ #{@category.abspath}
40
+ #{@level2.abspath}
41
+ #{@level3.abspath}
42
+ EOF
43
+ create_menu(text)
44
+ end
45
+
46
+ it "should display first level of nested sub menus" do
47
+ do_get
48
+ body.should have_tag("ul.menu li ul li a", Regexp.new(@level2.heading))
49
+ end
50
+
51
+ it "should not display nested menus to arbitrary depth" do
52
+ do_get
53
+ body.should_not have_tag("ul.menu li ul li ul")
54
+ end
55
+ end
56
+ end
57
+
58
+ describe "The layout" do
59
+ include ConfigSpecHelper
60
+ include ModelFactory
61
+ include RequestSpecHelper
62
+
63
+ it "should not include GA JavaScript by default" do
64
+ stub_configuration
65
+ get "/"
66
+ body.should_not have_tag("script", /'_setAccount', 'UA-1234'/)
67
+ end
68
+
69
+ it "should include GA JavaScript if configured" do
70
+ stub_config_key('google_analytics_code', 'UA-1234', :rack_env => true)
71
+ stub_configuration
72
+ get '/'
73
+ body.should have_tag('script', /'_setAccount', 'UA-1234'/)
74
+ end
75
+ end
76
+
77
+ describe "The home page" do
78
+ include ConfigSpecHelper
79
+ include ModelFactory
80
+ include RequestSpecHelper
81
+
82
+ before(:each) do
83
+ stub_configuration
84
+ create_category
85
+ end
86
+
87
+ after(:each) do
88
+ remove_fixtures
89
+ Nesta::FileModel.purge_cache
90
+ end
91
+
92
+ def do_get
93
+ get "/"
94
+ end
95
+
96
+ describe "when categories exist" do
97
+ before(:each) do
98
+ @category = create_category
99
+ end
100
+
101
+ it_should_behave_like "page that can display menus"
102
+ end
103
+
104
+ it "should render successfully" do
105
+ do_get
106
+ last_response.should be_ok
107
+ end
108
+
109
+ it "should display title and subtitle in title tag" do
110
+ do_get
111
+ body.should have_tag("title", "My blog - about stuff")
112
+ end
113
+
114
+ it "should display site title in h1 tag" do
115
+ do_get
116
+ body.should have_tag('#header p.title', /My blog/)
117
+ end
118
+
119
+ it "should display site subtitle in h1 tag" do
120
+ do_get
121
+ body.should have_tag('#header p.subtitle', /about stuff/)
122
+ end
123
+
124
+ it "should set description meta tag" do
125
+ do_get
126
+ body.should have_tag("meta[@name=description][@content='great web site']")
127
+ end
128
+
129
+ it "should set keywords meta tag" do
130
+ do_get
131
+ body.should have_tag("meta[@name=keywords][@content='home, page']")
132
+ end
133
+
134
+ describe "when articles have no summary" do
135
+ before(:each) do
136
+ create_article
137
+ do_get
138
+ end
139
+
140
+ it "should display full content of article" do
141
+ body.should have_tag("p", "Content goes here")
142
+ end
143
+
144
+ it "should not display read more link" do
145
+ body.should_not have_tag("a", /continue/i)
146
+ end
147
+ end
148
+
149
+ describe "when articles have metadata" do
150
+ before(:each) do
151
+ @summary = 'Multiline\n\nsummary'
152
+ @read_more = "Continue at your leisure"
153
+ @article = create_article(:metadata => {
154
+ "summary" => @summary,
155
+ "read more" => @read_more
156
+ })
157
+ do_get
158
+ end
159
+
160
+ it "should display link to article in h2 tag" do
161
+ body.should have_tag(
162
+ "h2 a[@href=#{@article.abspath}]", /^\s*#{@article.heading}$/)
163
+ end
164
+
165
+ it "should display article summary if available" do
166
+ body.should have_tag("p", @summary.split('\n\n').first)
167
+ end
168
+
169
+ it "should display read more link" do
170
+ body.should have_tag("a[@href=#{@article.abspath}]", @read_more)
171
+ end
172
+ end
173
+ end
174
+
175
+ describe "An article" do
176
+ include ConfigSpecHelper
177
+ include ModelFactory
178
+ include RequestSpecHelper
179
+
180
+ before(:each) do
181
+ stub_configuration
182
+ @date = "07 September 2009"
183
+ @keywords = "things, stuff"
184
+ @description = "Page about stuff"
185
+ @summary = 'Multiline\n\nsummary'
186
+ @article = create_article(:metadata => {
187
+ "date" => @date.gsub("September", "Sep"),
188
+ "description" => @description,
189
+ "keywords" => @keywords,
190
+ "summary" => @summary,
191
+ })
192
+ end
193
+
194
+ after(:each) do
195
+ remove_fixtures
196
+ Nesta::FileModel.purge_cache
197
+ end
198
+
199
+ def do_get
200
+ get @article.abspath
201
+ end
202
+
203
+ it_should_behave_like "page with keyword and description"
204
+
205
+ describe "when categories exist" do
206
+ before(:each) do
207
+ @category = create_category
208
+ end
209
+
210
+ it_should_behave_like "page that can display menus"
211
+ end
212
+
213
+ it "should render successfully" do
214
+ do_get
215
+ last_response.should be_ok
216
+ end
217
+
218
+ it "should display the heading" do
219
+ do_get
220
+ body.should have_tag("h1", "My article")
221
+ end
222
+
223
+ it "should not display category links" do
224
+ do_get
225
+ body.should_not have_tag("div.breadcrumb div.categories", /filed in/)
226
+ end
227
+
228
+ it "should display the date" do
229
+ do_get
230
+ body.should have_tag("div.date", @date)
231
+ end
232
+
233
+ it "should display the content" do
234
+ do_get
235
+ body.should have_tag("p", "Content goes here")
236
+ end
237
+
238
+ describe "that is assigned to categories" do
239
+ before(:each) do
240
+ create_category(:heading => "Apple", :path => "the-apple")
241
+ @category = create_category(:heading => "Banana", :path => "banana")
242
+ @article = create_article(
243
+ :path => "#{@category.path}/article",
244
+ :metadata => { "categories" => "banana, the-apple" }
245
+ )
246
+ end
247
+
248
+ it "should render successfully" do
249
+ do_get
250
+ last_response.should be_ok
251
+ end
252
+
253
+ it "should link to each category" do
254
+ do_get
255
+ body.should have_tag("div.categories", /Categories/)
256
+ body.should have_tag("div.categories") do |categories|
257
+ categories.should have_tag("a[@href=/banana]", "Banana")
258
+ categories.should have_tag("a[@href=/the-apple]", "Apple")
259
+ end
260
+ end
261
+
262
+ it "should link to a category in breadcrumb" do
263
+ do_get
264
+ body.should have_tag(
265
+ "div.breadcrumb/a[@href=#{@category.abspath}]", @category.heading)
266
+ end
267
+
268
+ it "should contain category name in page title" do
269
+ do_get
270
+ body.should_not have_tag("title", /My blog/)
271
+ body.should have_tag("title", /- #{@category.heading}$/)
272
+ end
273
+ end
274
+ end
275
+
276
+ describe "A page" do
277
+ include ConfigSpecHelper
278
+ include ModelFactory
279
+ include RequestSpecHelper
280
+
281
+ before(:each) do
282
+ stub_configuration
283
+ end
284
+
285
+ after(:each) do
286
+ remove_fixtures
287
+ Nesta::FileModel.purge_cache
288
+ end
289
+
290
+ def do_get
291
+ get @category.abspath
292
+ end
293
+
294
+ describe "that doesn't exist" do
295
+ it "should render the 404 page" do
296
+ get "/no-such-page"
297
+ last_response.should_not be_ok
298
+ end
299
+ end
300
+
301
+ describe "that has meta data" do
302
+ before(:each) do
303
+ @content = "Page content"
304
+ @description = "Page about stuff"
305
+ @keywords = "things, stuff"
306
+ @category = create_category(
307
+ :content => "# My category\n\n#{@content}",
308
+ :metadata => { "description" => @description, "keywords" => @keywords }
309
+ )
310
+ end
311
+
312
+ it_should_behave_like "page with keyword and description"
313
+ it_should_behave_like "page that can display menus"
314
+
315
+ it "should render successfully" do
316
+ do_get
317
+ last_response.should be_ok
318
+ end
319
+
320
+ it "should display the heading" do
321
+ do_get
322
+ body.should have_tag("h1", @category.heading)
323
+ end
324
+
325
+ it "should display the content" do
326
+ do_get
327
+ body.should have_tag("p", @content)
328
+ end
329
+
330
+ describe "with associated articles" do
331
+ before(:each) do
332
+ @article = create_article(
333
+ :path => "another-page",
334
+ :heading => "Categorised",
335
+ :metadata => { :categories => @category.path },
336
+ :content => "Article content"
337
+ )
338
+ @article2 = create_article(
339
+ :path => "second-article", :heading => "Second article")
340
+ end
341
+
342
+ it "should display links to articles" do
343
+ do_get
344
+ body.should have_tag(
345
+ "h3 a[@href='#{@article.abspath}']", /^\s*#{@article.heading}$/)
346
+ body.should_not have_tag("h3", @article2.heading)
347
+ end
348
+ end
349
+
350
+ it "should not include Disqus comments by default" do
351
+ do_get
352
+ body.should_not have_tag('#disqus_thread')
353
+ end
354
+ end
355
+
356
+ describe "that is configured to show Disqus comments" do
357
+ before(:each) do
358
+ stub_config_key("disqus_short_name", "mysite")
359
+ @category = create_category
360
+ end
361
+
362
+ it "should display Disqus comments" do
363
+ do_get
364
+ body.should have_tag('#disqus_thread')
365
+ body.should have_tag('script[@src*="mysite/embed.js"]')
366
+ end
367
+ end
368
+ end
369
+
370
+ describe "A Haml page" do
371
+ include ConfigSpecHelper
372
+ include ModelFactory
373
+ include RequestSpecHelper
374
+
375
+ before(:each) do
376
+ stub_configuration
377
+ end
378
+
379
+ after(:each) do
380
+ remove_fixtures
381
+ Nesta::FileModel.purge_cache
382
+ end
383
+
384
+ it "should be able to access helper methods" do
385
+ create_page(
386
+ :path => "a-page",
387
+ :ext => :haml,
388
+ :content => "%div= format_date(Date.new(2010, 11, 23))"
389
+ )
390
+ get "/a-page"
391
+ body.should have_tag("div", "23 November 2010")
392
+ end
393
+ end
394
+
395
+ describe "attachments" do
396
+ include ConfigSpecHelper
397
+ include ModelFactory
398
+ include RequestSpecHelper
399
+
400
+ def create_attachment
401
+ stub_configuration
402
+ create_content_directories
403
+ path = File.join(Nesta::Config.attachment_path, "test.txt")
404
+ File.open(path, "w") { |file| file.write("I'm a test attachment") }
405
+ end
406
+
407
+ before(:each) do
408
+ create_attachment
409
+ get "/attachments/test.txt"
410
+ end
411
+
412
+ after(:each) do
413
+ remove_fixtures
414
+ Nesta::FileModel.purge_cache
415
+ end
416
+
417
+ it "should be served successfully" do
418
+ last_response.should be_ok
419
+ end
420
+
421
+ it "should be sent to the client" do
422
+ body.should include("I'm a test attachment")
423
+ end
424
+
425
+ it "should set the appropriate MIME type" do
426
+ last_response.headers["Content-Type"].should =~ Regexp.new("^text/plain")
427
+ end
428
+ end