nesta 0.9.13 → 0.10.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. checksums.yaml +7 -0
  2. data/{spec/spec.opts → .rspec} +0 -0
  3. data/.travis.yml +3 -2
  4. data/CHANGES +130 -1
  5. data/Gemfile +1 -8
  6. data/Gemfile.lock +68 -51
  7. data/LICENSE +1 -1
  8. data/README.md +38 -6
  9. data/Rakefile +2 -5
  10. data/bin/nesta +59 -3
  11. data/config.ru +3 -0
  12. data/lib/nesta.rb +1 -1
  13. data/lib/nesta/app.rb +20 -17
  14. data/lib/nesta/commands.rb +6 -3
  15. data/lib/nesta/config.rb +52 -15
  16. data/lib/nesta/helpers.rb +30 -3
  17. data/lib/nesta/models.rb +48 -30
  18. data/lib/nesta/navigation.rb +32 -12
  19. data/lib/nesta/overrides.rb +5 -5
  20. data/lib/nesta/version.rb +1 -1
  21. data/nesta.gemspec +9 -10
  22. data/smoke-test.sh +102 -0
  23. data/spec/atom_spec.rb +52 -49
  24. data/spec/commands_spec.rb +22 -16
  25. data/spec/config_spec.rb +66 -6
  26. data/spec/fixtures/nesta-plugin-test/lib/nesta-plugin-test/init.rb +1 -3
  27. data/spec/model_factory.rb +16 -16
  28. data/spec/models_spec.rb +197 -144
  29. data/spec/overrides_spec.rb +21 -21
  30. data/spec/page_spec.rb +182 -136
  31. data/spec/sitemap_spec.rb +48 -43
  32. data/spec/spec_helper.rb +32 -17
  33. data/templates/Gemfile +5 -2
  34. data/templates/config/config.yml +13 -13
  35. data/templates/config/deploy.rb +2 -2
  36. data/templates/index.haml +2 -0
  37. data/templates/themes/app.rb +1 -1
  38. data/templates/themes/views/layout.haml +7 -0
  39. data/templates/themes/views/master.sass +3 -0
  40. data/templates/themes/views/page.haml +1 -0
  41. data/views/atom.haml +3 -3
  42. data/views/comments.haml +1 -1
  43. data/views/error.haml +1 -1
  44. data/views/feed.haml +1 -1
  45. data/views/layout.haml +6 -3
  46. data/views/master.sass +143 -133
  47. data/views/mixins.sass +53 -28
  48. data/views/normalize.scss +396 -0
  49. data/views/page_meta.haml +2 -2
  50. data/views/sitemap.haml +2 -2
  51. data/views/summaries.haml +2 -2
  52. metadata +155 -202
  53. data/lib/nesta/cache.rb +0 -138
@@ -4,6 +4,14 @@ describe "Config" do
4
4
  after(:each) do
5
5
  ENV.keys.each { |variable| ENV.delete(variable) if variable =~ /NESTA_/ }
6
6
  end
7
+
8
+ it 'should return default value for "Read more"' do
9
+ Nesta::Config.read_more.should == 'Continue reading'
10
+ end
11
+
12
+ it 'should return nil for author when not defined' do
13
+ Nesta::Config.author.should == nil
14
+ end
7
15
 
8
16
  describe "when settings defined in ENV" do
9
17
  before(:each) do
@@ -22,10 +30,25 @@ describe "Config" do
22
30
  end
23
31
 
24
32
  it "should know how to cope with boolean values" do
25
- ENV["NESTA_CACHE"] = "true"
26
- Nesta::Config.cache.should be_true
27
- ENV["NESTA_CACHE"] = "false"
28
- Nesta::Config.cache.should be_false
33
+ Nesta::Config.settings << 'a_boolean'
34
+ begin
35
+ ENV["NESTA_A_BOOLEAN"] = "true"
36
+ Nesta::Config.a_boolean.should be_true
37
+ ENV["NESTA_A_BOOLEAN"] = "false"
38
+ Nesta::Config.a_boolean.should be_false
39
+ ensure
40
+ Nesta::Config.settings.pop
41
+ ENV.delete('NESTA_A_BOOLEAN')
42
+ end
43
+ end
44
+
45
+ it 'should return configured value for "Read more"' do
46
+ ENV['NESTA_READ_MORE'] = 'Read on'
47
+ begin
48
+ Nesta::Config.read_more.should == 'Read on'
49
+ ensure
50
+ ENV.delete('NESTA_READ_MORE')
51
+ end
29
52
  end
30
53
 
31
54
  it "should set author hash from ENV" do
@@ -58,10 +81,47 @@ describe "Config" do
58
81
  Nesta::Config.author["email"].should be_nil
59
82
  end
60
83
 
61
- it "should override top level settings with RACK_ENV specific settings" do
84
+ it "should override top level settings with environment specific settings" do
62
85
  stub_config_key('content', 'general/path')
63
- stub_config_key('content', 'rack_env/path', :rack_env => true)
86
+ stub_config_key('content', 'rack_env/path', for_environment: true)
64
87
  Nesta::Config.content.should == 'rack_env/path'
65
88
  end
66
89
  end
90
+
91
+ describe 'Nesta::Config.fetch' do
92
+ it 'should be retrieve settings from environment' do
93
+ ENV['NESTA_MY_SETTING'] = 'value in ENV'
94
+ begin
95
+ Nesta::Config.fetch('my_setting').should == 'value in ENV'
96
+ Nesta::Config.fetch(:my_setting).should == 'value in ENV'
97
+ ensure
98
+ ENV.delete('NESTA_MY_SETTING')
99
+ end
100
+ end
101
+
102
+ it 'should retrieved settings from YAML' do
103
+ stub_config_key('my_setting', 'value in YAML')
104
+ Nesta::Config.fetch('my_setting').should == 'value in YAML'
105
+ Nesta::Config.fetch(:my_setting).should == 'value in YAML'
106
+ end
107
+
108
+ it "should throw NotDefined if a setting isn't defined" do
109
+ lambda {
110
+ Nesta::Config.fetch('no such setting')
111
+ }.should raise_error(Nesta::Config::NotDefined)
112
+ end
113
+
114
+ it 'should allow default values to be set' do
115
+ Nesta::Config.fetch('no such setting', 'default').should == 'default'
116
+ end
117
+
118
+ it 'should cope with non-truthy boolean values' do
119
+ ENV['NESTA_SETTING'] = 'false'
120
+ begin
121
+ Nesta::Config.fetch('setting').should == false
122
+ ensure
123
+ ENV.delete('NESTA_SETTING')
124
+ end
125
+ end
126
+ end
67
127
  end
@@ -2,9 +2,7 @@ module Nesta
2
2
  module Plugin
3
3
  module Test
4
4
  module Helpers
5
- helpers do
6
- # If your plugin needs any helper methods, add them here...
7
- end
5
+ # If your plugin needs any helper methods, add them here...
8
6
  end
9
7
  end
10
8
  end
@@ -6,28 +6,28 @@ module ModelFactory
6
6
  yield(path) if block_given?
7
7
  Nesta::Page.new(path)
8
8
  end
9
-
9
+
10
10
  def create_article(options = {}, &block)
11
11
  o = {
12
- :path => 'article-prefix/my-article',
13
- :heading => 'My article',
14
- :content => 'Content goes here',
15
- :metadata => {
12
+ path: 'article-prefix/my-article',
13
+ heading: 'My article',
14
+ content: 'Content goes here',
15
+ metadata: {
16
16
  'date' => '29 December 2008'
17
17
  }.merge(options.delete(:metadata) || {})
18
18
  }.merge(options)
19
19
  create_page(o, &block)
20
20
  end
21
-
21
+
22
22
  def create_category(options = {}, &block)
23
23
  o = {
24
- :path => 'category-prefix/my-category',
25
- :heading => 'My category',
26
- :content => 'Content goes here'
24
+ path: 'category-prefix/my-category',
25
+ heading: 'My category',
26
+ content: 'Content goes here'
27
27
  }.merge(options)
28
28
  create_page(o, &block)
29
29
  end
30
-
30
+
31
31
  def write_menu_item(indent, file, menu_item)
32
32
  if menu_item.is_a?(Array)
33
33
  indent.sub!(/^/, ' ')
@@ -42,20 +42,20 @@ module ModelFactory
42
42
  file = filename(Nesta::Config.content_path, 'menu', :txt)
43
43
  File.open(file, 'w') { |file| file.write(menu_text) }
44
44
  end
45
-
45
+
46
46
  def delete_page(type, permalink, extension)
47
47
  file = filename(Nesta::Config.page_path, permalink, extension)
48
48
  FileUtils.rm(file)
49
49
  end
50
-
50
+
51
51
  def create_content_directories
52
52
  FileUtils.mkdir_p(Nesta::Config.page_path)
53
53
  FileUtils.mkdir_p(Nesta::Config.attachment_path)
54
54
  end
55
-
55
+
56
56
  def mock_file_stat(method, filename, time)
57
- stat = mock(:stat)
58
- stat.stub!(:mtime).and_return(Time.parse(time))
57
+ stat = double(:stat)
58
+ stat.stub(:mtime).and_return(Time.parse(time))
59
59
  File.send(method, :stat).with(filename).and_return(stat)
60
60
  end
61
61
 
@@ -63,7 +63,7 @@ module ModelFactory
63
63
  def filename(directory, basename, extension = :mdown)
64
64
  File.join(directory, "#{basename}.#{extension}")
65
65
  end
66
-
66
+
67
67
  def heading(options)
68
68
  prefix = case options[:ext]
69
69
  when :haml
@@ -26,47 +26,60 @@ module ModelMatchers
26
26
  end
27
27
  end
28
28
 
29
- describe "Page", :shared => true do
30
- include ModelFactory
31
- include ModelMatchers
29
+ shared_context "Page testing" do
30
+ include Webrat::Matchers
32
31
 
33
32
  def create_page(options)
34
- super(options.merge(:ext => @extension))
33
+ super(options.merge(ext: @extension))
35
34
  end
36
35
 
37
36
  before(:each) do
38
37
  stub_configuration
39
38
  end
40
-
39
+
41
40
  after(:each) do
42
41
  remove_temp_directory
43
42
  Nesta::FileModel.purge_cache
44
43
  end
45
-
44
+ end
45
+
46
+ shared_examples_for "Page" do
47
+ include ModelFactory
48
+ include ModelMatchers
49
+
46
50
  it "should be findable" do
47
- create_page(:heading => 'Apple', :path => 'the-apple')
51
+ create_page(heading: 'Apple', path: 'the-apple')
48
52
  Nesta::Page.find_all.should have(1).item
49
53
  end
50
54
 
55
+ it "should return the filename for a path" do
56
+ create_page(heading: 'Banana', path: 'banana')
57
+ Nesta::Page.find_file_for_path('banana').should =~ /banana.#{@extension}$/
58
+ end
59
+
60
+ it "should return nil for files that don't exist" do
61
+ Nesta::Page.find_file_for_path('foobar').should be_nil
62
+ end
63
+
51
64
  it "should find by path" do
52
- create_page(:heading => 'Banana', :path => 'banana')
65
+ create_page(heading: 'Banana', path: 'banana')
53
66
  Nesta::Page.find_by_path('banana').heading.should == 'Banana'
54
67
  end
55
-
68
+
56
69
  it "should find index page by path" do
57
- create_page(:heading => 'Banana', :path => 'banana/index')
70
+ create_page(heading: 'Banana', path: 'banana/index')
58
71
  Nesta::Page.find_by_path('banana').heading.should == 'Banana'
59
72
  end
60
73
 
61
74
  it "should respond to #parse_metadata, returning hash of key/value" do
62
- page = create_page(:heading => 'Banana', :path => 'banana')
75
+ page = create_page(heading: 'Banana', path: 'banana')
63
76
  metadata = page.parse_metadata('My key: some value')
64
77
  metadata['my key'].should == 'some value'
65
78
  end
66
79
 
67
80
  it "should be parseable if metadata is invalid" do
68
81
  dodgy_metadata = "Key: value\nKey without value\nAnother key: value"
69
- create_page(:heading => 'Banana', :path => 'banana') do |path|
82
+ create_page(heading: 'Banana', path: 'banana') do |path|
70
83
  text = File.read(path)
71
84
  File.open(path, 'w') do |file|
72
85
  file.puts(dodgy_metadata)
@@ -77,59 +90,60 @@ describe "Page", :shared => true do
77
90
  end
78
91
 
79
92
  describe "for home page" do
80
- it "should set title to heading and site title" do
81
- create_page(:heading => 'Home', :path => 'index')
82
- Nesta::Page.find_by_path('/').title.should == 'Home - My blog'
93
+ it "should set title to heading" do
94
+ create_page(heading: 'Home', path: 'index')
95
+ Nesta::Page.find_by_path('/').title.should == 'Home'
83
96
  end
84
97
 
85
98
  it "should respect title metadata" do
86
- create_page(:path => 'index', :metadata => { 'title' => 'Specific title' })
99
+ create_page(path: 'index', metadata: { 'title' => 'Specific title' })
87
100
  Nesta::Page.find_by_path('/').title.should == 'Specific title'
88
101
  end
89
102
 
90
103
  it "should set title to site title by default" do
91
- create_page(:path => 'index')
104
+ create_page(path: 'index')
92
105
  Nesta::Page.find_by_path('/').title.should == 'My blog'
93
106
  end
94
107
 
95
108
  it "should set permalink to empty string" do
96
- create_page(:path => 'index')
109
+ create_page(path: 'index')
97
110
  Nesta::Page.find_by_path('/').permalink.should == ''
98
111
  end
99
112
 
100
113
  it "should set abspath to /" do
101
- create_page(:path => 'index')
114
+ create_page(path: 'index')
102
115
  Nesta::Page.find_by_path('/').abspath.should == '/'
103
116
  end
104
117
  end
105
-
118
+
106
119
  it "should not find nonexistent page" do
107
120
  Nesta::Page.find_by_path("no-such-page").should be_nil
108
121
  end
109
-
122
+
110
123
  it "should ensure file exists on instantiation" do
111
124
  lambda {
112
125
  Nesta::Page.new("no-such-file")
113
126
  }.should raise_error(Sinatra::NotFound)
114
127
  end
115
-
128
+
116
129
  it "should reload cached files when modified" do
117
- create_page(:path => "a-page", :heading => "Version 1")
118
- File.stub!(:mtime).and_return(Time.new - 1)
130
+ create_page(path: "a-page", heading: "Version 1")
131
+ now = Time.now
132
+ File.stub(:mtime).and_return(now - 1)
119
133
  Nesta::Page.find_by_path("a-page")
120
- create_page(:path => "a-page", :heading => "Version 2")
121
- File.stub!(:mtime).and_return(Time.new)
134
+ create_page(path: "a-page", heading: "Version 2")
135
+ File.stub(:mtime).and_return(now)
122
136
  Nesta::Page.find_by_path("a-page").heading.should == "Version 2"
123
137
  end
124
138
 
125
139
  it "should have default priority of 0 in category" do
126
- page = create_page(:metadata => { 'categories' => 'some-page' })
140
+ page = create_page(metadata: { 'categories' => 'some-page' })
127
141
  page.priority('some-page').should == 0
128
142
  page.priority('another-page').should be_nil
129
143
  end
130
144
 
131
145
  it "should read priority from category metadata" do
132
- page = create_page(:metadata => {
146
+ page = create_page(metadata: {
133
147
  'categories' => ' some-page:1, another-page , and-another :-1 '
134
148
  })
135
149
  page.priority('some-page').should == 1
@@ -140,48 +154,48 @@ describe "Page", :shared => true do
140
154
  describe "with assigned pages" do
141
155
  before(:each) do
142
156
  @category = create_category
143
- create_article(:heading => 'Article 1', :path => 'article-1')
157
+ create_article(heading: 'Article 1', path: 'article-1')
144
158
  create_article(
145
- :heading => 'Article 2',
146
- :path => 'article-2',
147
- :metadata => {
159
+ heading: 'Article 2',
160
+ path: 'article-2',
161
+ metadata: {
148
162
  'date' => '30 December 2008',
149
163
  'categories' => @category.path
150
164
  }
151
165
  )
152
166
  @article = create_article(
153
- :heading => 'Article 3',
154
- :path => 'article-3',
155
- :metadata => {
167
+ heading: 'Article 3',
168
+ path: 'article-3',
169
+ metadata: {
156
170
  'date' => '31 December 2008',
157
171
  'categories' => @category.path
158
172
  }
159
173
  )
160
174
  @category1 = create_category(
161
- :path => 'category-1',
162
- :heading => 'Category 1',
163
- :metadata => { 'categories' => @category.path }
175
+ path: 'category-1',
176
+ heading: 'Category 1',
177
+ metadata: { 'categories' => @category.path }
164
178
  )
165
179
  @category2 = create_category(
166
- :path => 'category-2',
167
- :heading => 'Category 2',
168
- :metadata => { 'categories' => @category.path }
180
+ path: 'category-2',
181
+ heading: 'Category 2',
182
+ metadata: { 'categories' => @category.path }
169
183
  )
170
184
  @category3 = create_category(
171
- :path => 'category-3',
172
- :heading => 'Category 3',
173
- :metadata => { 'categories' => "#{@category.path}:1" }
185
+ path: 'category-3',
186
+ heading: 'Category 3',
187
+ metadata: { 'categories' => "#{@category.path}:1" }
174
188
  )
175
189
  end
176
190
 
177
191
  it "should find articles" do
178
192
  @category.articles.should have(2).items
179
193
  end
180
-
194
+
181
195
  it "should order articles by reverse chronological order" do
182
196
  @category.articles.first.path.should == @article.path
183
197
  end
184
-
198
+
185
199
  it "should find pages" do
186
200
  @category.pages.should have(3).items
187
201
  end
@@ -189,17 +203,17 @@ describe "Page", :shared => true do
189
203
  it "should sort pages by priority" do
190
204
  @category.pages.index(@category3).should == 0
191
205
  end
192
-
206
+
193
207
  it "should order pages by heading if priority not set" do
194
208
  pages = @category.pages
195
209
  pages.index(@category1).should < pages.index(@category2)
196
210
  end
197
211
 
198
212
  it "should not find pages scheduled in the future" do
199
- future_date = (Time.now + 86400).strftime("%d %B %Y")
200
- article = create_article(:heading => "Article 4",
201
- :path => "foo/article-4",
202
- :metadata => { "date" => future_date })
213
+ future_date = (Time.now + 172800).strftime("%d %B %Y")
214
+ article = create_article(heading: "Article 4",
215
+ path: "foo/article-4",
216
+ metadata: { "date" => future_date })
203
217
  Nesta::Page.find_articles.detect{|a| a == article}.should be_nil
204
218
  end
205
219
  end
@@ -207,13 +221,13 @@ describe "Page", :shared => true do
207
221
  describe "with pages in draft" do
208
222
  before(:each) do
209
223
  @category = create_category
210
- @draft = create_page(:heading => 'Forthcoming content',
211
- :path => 'foo/in-draft',
212
- :metadata => {
224
+ @draft = create_page(heading: 'Forthcoming content',
225
+ path: 'foo/in-draft',
226
+ metadata: {
213
227
  'categories' => @category.path,
214
228
  'flags' => 'draft'
215
229
  })
216
- Nesta::App.stub!(:production?).and_return(true)
230
+ Nesta::App.stub(:production?).and_return(true)
217
231
  end
218
232
 
219
233
  it "should not find assigned drafts" do
@@ -224,105 +238,111 @@ describe "Page", :shared => true do
224
238
  Nesta::Page.find_by_path('foo/in-draft').should be_nil
225
239
  end
226
240
  end
227
-
241
+
228
242
  describe "when finding articles" do
229
243
  before(:each) do
230
- create_article(:heading => "Article 1", :path => "article-1")
231
- create_article(:heading => "Article 2",
232
- :path => "article-2",
233
- :metadata => { "date" => "31 December 2008" })
234
- create_article(:heading => "Article 3",
235
- :path => "foo/article-3",
236
- :metadata => { "date" => "30 December 2008" })
237
- end
238
-
244
+ create_article(heading: "Article 1", path: "article-1")
245
+ create_article(heading: "Article 2",
246
+ path: "article-2",
247
+ metadata: { "date" => "31 December 2008" })
248
+ create_article(heading: "Article 3",
249
+ path: "foo/article-3",
250
+ metadata: { "date" => "30 December 2008" })
251
+ end
252
+
239
253
  it "should only find pages with dates" do
240
254
  articles = Nesta::Page.find_articles
241
255
  articles.size.should > 0
242
256
  Nesta::Page.find_articles.each { |page| page.date.should_not be_nil }
243
257
  end
244
-
258
+
245
259
  it "should return articles in reverse chronological order" do
246
260
  article1, article2 = Nesta::Page.find_articles[0..1]
247
261
  article1.date.should > article2.date
248
262
  end
249
263
  end
250
-
264
+
251
265
  it "should be able to find parent page" do
252
- category = create_category(:path => 'parent')
253
- article = create_article(:path => 'parent/child')
266
+ category = create_category(path: 'parent')
267
+ article = create_article(path: 'parent/child')
254
268
  article.parent.should == category
255
269
  end
256
-
270
+
257
271
  describe "(with deep index page)" do
258
272
  it "should be able to find index parent" do
259
- home = create_category(:path => 'index', :heading => 'Home')
260
- category = create_category(:path => 'parent')
273
+ home = create_category(path: 'index', heading: 'Home')
274
+ category = create_category(path: 'parent')
261
275
  category.parent.should == home
262
276
  home.parent.should be_nil
263
277
  end
264
278
 
265
279
  it "should be able to find parent of index" do
266
- category = create_category(:path => "parent")
267
- index = create_category(:path => "parent/child/index")
280
+ category = create_category(path: "parent")
281
+ index = create_category(path: "parent/child/index")
268
282
  index.parent.should == category
269
283
  end
270
284
 
271
285
  it "should be able to find permalink of index" do
272
- index = create_category(:path => "parent/child/index")
286
+ index = create_category(path: "parent/child/index")
273
287
  index.permalink.should == 'child'
274
288
  end
275
289
  end
276
290
 
277
291
  describe "(with missing nested page)" do
278
292
  it "should consider grandparent to be parent" do
279
- grandparent = create_category(:path => 'grandparent')
280
- child = create_category(:path => 'grandparent/parent/child')
293
+ grandparent = create_category(path: 'grandparent')
294
+ child = create_category(path: 'grandparent/parent/child')
281
295
  child.parent.should == grandparent
282
296
  end
283
297
 
284
298
  it "should consider grandparent home page to be parent" do
285
- home = create_category(:path => 'index')
286
- child = create_category(:path => 'parent/child')
299
+ home = create_category(path: 'index')
300
+ child = create_category(path: 'parent/child')
287
301
  child.parent.should == home
288
302
  end
289
303
  end
290
304
 
291
305
  describe "when assigned to categories" do
292
306
  before(:each) do
293
- create_category(:heading => "Apple", :path => "the-apple")
294
- create_category(:heading => "Banana", :path => "banana")
307
+ create_category(heading: "Apple", path: "the-apple")
308
+ create_category(heading: "Banana", path: "banana")
295
309
  @article = create_article(
296
- :metadata => { "categories" => "banana, the-apple" })
310
+ metadata: { "categories" => "banana, the-apple" })
297
311
  end
298
-
312
+
299
313
  it "should be possible to list the categories" do
300
314
  @article.categories.should have(2).items
301
315
  @article.should be_in_category("the-apple")
302
316
  @article.should be_in_category("banana")
317
+ @article.should_not be_in_category("orange")
303
318
  end
304
319
 
305
- it "should sort categories by heading" do
306
- @article.categories.first.heading.should == "Apple"
320
+ it "should sort categories by link text" do
321
+ create_category(heading: "Orange",
322
+ metadata: { "link text" => "A citrus fruit" },
323
+ path: "orange")
324
+ article = create_article(metadata: { "categories" => "apple, orange" })
325
+ @article.categories.first.link_text.should == "Apple"
326
+ article.categories.first.link_text.should == "A citrus fruit"
307
327
  end
308
-
328
+
309
329
  it "should not be assigned to non-existant category" do
310
330
  delete_page(:category, "banana", @extension)
311
331
  @article.should_not be_in_category("banana")
312
332
  end
313
333
  end
314
-
334
+
315
335
  it "should set parent to nil when at root" do
316
- create_category(:path => "top-level").parent.should be_nil
336
+ create_category(path: "top-level").parent.should be_nil
317
337
  end
318
-
338
+
319
339
  describe "when not assigned to category" do
320
340
  it "should have empty category list" do
321
341
  article = create_article
322
342
  Nesta::Page.find_by_path(article.path).categories.should be_empty
323
343
  end
324
344
  end
325
-
345
+
326
346
  describe "with no content" do
327
347
  it "should produce no HTML output" do
328
348
  create_article do |path|
@@ -338,7 +358,7 @@ describe "Page", :shared => true do
338
358
  create_article
339
359
  @article = Nesta::Page.find_all.first
340
360
  end
341
-
361
+
342
362
  it "should use default layout" do
343
363
  @article.layout.should == :layout
344
364
  end
@@ -346,24 +366,28 @@ describe "Page", :shared => true do
346
366
  it "should use default template" do
347
367
  @article.template.should == :page
348
368
  end
349
-
369
+
350
370
  it "should parse heading correctly" do
351
- @article.to_html.should have_tag("h1", "My article")
371
+ @article.to_html.should have_selector("h1", content: "My article")
352
372
  end
353
-
373
+
374
+ it "should use heading as link text" do
375
+ @article.link_text.should == "My article"
376
+ end
377
+
354
378
  it "should have default read more link text" do
355
379
  @article.read_more.should == "Continue reading"
356
380
  end
357
-
381
+
358
382
  it "should not have description" do
359
383
  @article.description.should be_nil
360
384
  end
361
-
385
+
362
386
  it "should not have keywords" do
363
387
  @article.keywords.should be_nil
364
388
  end
365
389
  end
366
-
390
+
367
391
  describe "with metadata" do
368
392
  before(:each) do
369
393
  @layout = 'my_layout'
@@ -374,7 +398,8 @@ describe "Page", :shared => true do
374
398
  @summary = 'Multiline\n\nsummary'
375
399
  @read_more = 'Continue at your leisure'
376
400
  @skillz = 'ruby, guitar, bowstaff'
377
- @article = create_article(:metadata => {
401
+ @link_text = 'Link to stuff page'
402
+ @article = create_article(metadata: {
378
403
  'date' => @date.gsub('September', 'Sep'),
379
404
  'description' => @description,
380
405
  'flags' => 'draft, orange',
@@ -383,70 +408,71 @@ describe "Page", :shared => true do
383
408
  'read more' => @read_more,
384
409
  'skillz' => @skillz,
385
410
  'summary' => @summary,
386
- 'template' => @template
411
+ 'template' => @template,
412
+ 'link text' => @link_text,
387
413
  })
388
414
  end
389
415
 
390
416
  it "should override default layout" do
391
417
  @article.layout.should == @layout.to_sym
392
418
  end
393
-
419
+
394
420
  it "should override default template" do
395
421
  @article.template.should == @template.to_sym
396
422
  end
397
-
423
+
398
424
  it "should set permalink to basename of filename" do
399
425
  @article.permalink.should == 'my-article'
400
426
  end
401
-
427
+
402
428
  it "should set path from filename" do
403
429
  @article.path.should == 'article-prefix/my-article'
404
430
  end
405
-
431
+
406
432
  it "should retrieve heading" do
407
433
  @article.heading.should == 'My article'
408
434
  end
409
-
435
+
410
436
  it "should be possible to convert an article to HTML" do
411
- @article.to_html.should have_tag("h1", "My article")
437
+ @article.to_html.should have_selector("h1", content: "My article")
412
438
  end
413
-
439
+
414
440
  it "should not include metadata in the HTML" do
415
- @article.to_html.should_not have_tag("p", /^Date/)
441
+ @article.to_html.should_not have_selector("p:contains('Date')")
416
442
  end
417
443
 
418
444
  it "should not include heading in body markup" do
419
445
  @article.body_markup.should_not include("My article")
420
446
  end
421
-
447
+
422
448
  it "should not include heading in body" do
423
- @article.body.should_not have_tag("h1", "My article")
449
+ @article.body.should_not have_selector("h1", content: "My article")
424
450
  end
425
451
 
426
452
  it "should retrieve description from metadata" do
427
453
  @article.description.should == @description
428
454
  end
429
-
455
+
430
456
  it "should retrieve keywords from metadata" do
431
457
  @article.keywords.should == @keywords
432
458
  end
433
-
459
+
434
460
  it "should retrieve date published from metadata" do
435
461
  @article.date.strftime("%d %B %Y").should == @date
436
462
  end
437
-
463
+
438
464
  it "should retrieve read more link from metadata" do
439
465
  @article.read_more.should == @read_more
440
466
  end
441
-
467
+
442
468
  it "should retrieve summary text from metadata" do
443
469
  @article.summary.should match(/#{@summary.split('\n\n').first}/)
444
470
  end
445
-
471
+
446
472
  it "should treat double newline chars as paragraph break in summary" do
447
473
  @article.summary.should match(/#{@summary.split('\n\n').last}/)
448
474
  end
449
-
475
+
450
476
  it "should allow access to metadata" do
451
477
  @article.metadata('skillz').should == @skillz
452
478
  end
@@ -459,92 +485,116 @@ describe "Page", :shared => true do
459
485
  it "should know whether or not it's a draft" do
460
486
  @article.should be_draft
461
487
  end
488
+
489
+ it "should allow link text to be specified explicitly" do
490
+ @article.link_text.should == @link_text
491
+ end
462
492
  end
463
-
493
+
464
494
  describe "when checking last modification time" do
465
495
  before(:each) do
466
496
  create_article
467
497
  @article = Nesta::Page.find_all.first
468
498
  end
469
-
499
+
470
500
  it "should check filesystem" do
471
501
  mock_file_stat(:should_receive, @article.filename, "3 January 2009")
472
502
  @article.last_modified.should == Time.parse("3 January 2009")
473
503
  end
474
504
  end
505
+
506
+ describe "with no heading" do
507
+ before(:each) do
508
+ @no_heading_page = create_page(path: 'page-with-no-heading')
509
+ end
510
+
511
+ it "should raise a HeadingNotSet exception if you call heading" do
512
+ lambda do
513
+ @no_heading_page.heading
514
+ end.should raise_error(Nesta::HeadingNotSet, /page-with-no-heading/);
515
+ end
516
+
517
+ it "should raise a LinkTextNotSet exception if you call link_text" do
518
+ lambda do
519
+ @no_heading_page.link_text
520
+ end.should raise_error(Nesta::LinkTextNotSet, /page-with-no-heading/);
521
+ end
522
+ end
475
523
  end
476
524
 
477
525
  describe "All types of page" do
478
526
  include ModelFactory
479
527
 
480
- before(:each) do
481
- stub_configuration
482
- end
483
-
484
- after(:each) do
485
- remove_temp_directory
486
- Nesta::FileModel.purge_cache
487
- end
488
-
528
+ include_context "Page testing"
529
+
489
530
  it "should still return top level menu items" do
490
531
  # Page.menu_items is deprecated; we're keeping it for the moment so
491
532
  # that we don't break themes or code in a local app.rb (just yet).
492
- page1 = create_category(:path => "page-1")
493
- page2 = create_category(:path => "page-2")
533
+ page1 = create_category(path: "page-1")
534
+ page2 = create_category(path: "page-2")
494
535
  create_menu([page1.path, page2.path].join("\n"))
495
536
  Nesta::Page.menu_items.should == [page1, page2]
496
537
  end
497
538
  end
498
539
 
499
540
  describe "Markdown page" do
541
+ include ModelFactory
542
+
500
543
  before(:each) do
501
544
  @extension = :mdown
502
545
  end
503
546
 
547
+ include_context "Page testing"
504
548
  it_should_behave_like "Page"
505
549
 
506
550
  it "should set heading from first h1 tag" do
507
551
  page = create_page(
508
- :heading => "First heading", :content => "# Second heading")
552
+ path: "a-page",
553
+ heading: "First heading",
554
+ content: "# Second heading"
555
+ )
509
556
  page.heading.should == "First heading"
510
557
  end
511
558
 
512
559
  it "should ignore trailing # characters in headings" do
513
- article = create_article(:heading => 'With trailing #')
560
+ article = create_article(heading: 'With trailing #')
514
561
  article.heading.should == 'With trailing'
515
562
  end
516
563
  end
517
564
 
518
565
  describe "Haml page" do
566
+ include ModelFactory
567
+
519
568
  before(:each) do
520
569
  @extension = :haml
521
570
  end
522
571
 
572
+ include_context "Page testing"
523
573
  it_should_behave_like "Page"
524
574
 
525
575
  it "should set heading from first h1 tag" do
526
576
  page = create_page(
527
- :path => "a-page",
528
- :heading => "First heading",
529
- :content => "%h1 Second heading"
577
+ path: "a-page",
578
+ heading: "First heading",
579
+ content: "%h1 Second heading"
530
580
  )
531
581
  page.heading.should == "First heading"
532
582
  end
533
583
 
534
584
  it "should wrap <p> tags around one line summary text" do
535
585
  page = create_page(
536
- :path => "a-page",
537
- :heading => "First para",
538
- :metadata => { "Summary" => "Wrap me" }
586
+ path: "a-page",
587
+ heading: "First para",
588
+ metadata: { "Summary" => "Wrap me" }
539
589
  )
540
590
  page.summary.should include("<p>Wrap me</p>")
541
591
  end
542
592
 
543
593
  it "should wrap <p> tags around multiple lines of summary text" do
544
594
  page = create_page(
545
- :path => "a-page",
546
- :heading => "First para",
547
- :metadata => { "Summary" => 'Wrap me\nIn paragraph tags' }
595
+ path: "a-page",
596
+ heading: "First para",
597
+ metadata: { "Summary" => 'Wrap me\nIn paragraph tags' }
548
598
  )
549
599
  page.summary.should include("<p>Wrap me</p>")
550
600
  page.summary.should include("<p>In paragraph tags</p>")
@@ -552,17 +602,20 @@ describe "Haml page" do
552
602
  end
553
603
 
554
604
  describe "Textile page" do
605
+ include ModelFactory
606
+
555
607
  before(:each) do
556
608
  @extension = :textile
557
609
  end
558
610
 
611
+ include_context "Page testing"
559
612
  it_should_behave_like "Page"
560
613
 
561
614
  it "should set heading from first h1 tag" do
562
615
  page = create_page(
563
- :path => "a-page",
564
- :heading => "First heading",
565
- :content => "h1. Second heading"
616
+ path: "a-page",
617
+ heading: "First heading",
618
+ content: "h1. Second heading"
566
619
  )
567
620
  page.heading.should == "First heading"
568
621
  end
@@ -573,7 +626,7 @@ describe "Menu" do
573
626
 
574
627
  before(:each) do
575
628
  stub_configuration
576
- @page = create_page(:path => "page-1")
629
+ @page = create_page(path: "page-1")
577
630
  end
578
631
 
579
632
  after(:each) do
@@ -596,7 +649,7 @@ describe "Menu" do
596
649
  describe "with nested sub menus" do
597
650
  before(:each) do
598
651
  (2..6).each do |i|
599
- instance_variable_set("@page#{i}", create_page(:path => "page-#{i}"))
652
+ instance_variable_set("@page#{i}", create_page(path: "page-#{i}"))
600
653
  end
601
654
  text = <<-EOF
602
655
  #{@page.path}