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.
- checksums.yaml +7 -0
- data/{spec/spec.opts → .rspec} +0 -0
- data/.travis.yml +3 -2
- data/CHANGES +130 -1
- data/Gemfile +1 -8
- data/Gemfile.lock +68 -51
- data/LICENSE +1 -1
- data/README.md +38 -6
- data/Rakefile +2 -5
- data/bin/nesta +59 -3
- data/config.ru +3 -0
- data/lib/nesta.rb +1 -1
- data/lib/nesta/app.rb +20 -17
- data/lib/nesta/commands.rb +6 -3
- data/lib/nesta/config.rb +52 -15
- data/lib/nesta/helpers.rb +30 -3
- data/lib/nesta/models.rb +48 -30
- data/lib/nesta/navigation.rb +32 -12
- data/lib/nesta/overrides.rb +5 -5
- data/lib/nesta/version.rb +1 -1
- data/nesta.gemspec +9 -10
- data/smoke-test.sh +102 -0
- data/spec/atom_spec.rb +52 -49
- data/spec/commands_spec.rb +22 -16
- data/spec/config_spec.rb +66 -6
- data/spec/fixtures/nesta-plugin-test/lib/nesta-plugin-test/init.rb +1 -3
- data/spec/model_factory.rb +16 -16
- data/spec/models_spec.rb +197 -144
- data/spec/overrides_spec.rb +21 -21
- data/spec/page_spec.rb +182 -136
- data/spec/sitemap_spec.rb +48 -43
- data/spec/spec_helper.rb +32 -17
- data/templates/Gemfile +5 -2
- data/templates/config/config.yml +13 -13
- data/templates/config/deploy.rb +2 -2
- data/templates/index.haml +2 -0
- data/templates/themes/app.rb +1 -1
- data/templates/themes/views/layout.haml +7 -0
- data/templates/themes/views/master.sass +3 -0
- data/templates/themes/views/page.haml +1 -0
- data/views/atom.haml +3 -3
- data/views/comments.haml +1 -1
- data/views/error.haml +1 -1
- data/views/feed.haml +1 -1
- data/views/layout.haml +6 -3
- data/views/master.sass +143 -133
- data/views/mixins.sass +53 -28
- data/views/normalize.scss +396 -0
- data/views/page_meta.haml +2 -2
- data/views/sitemap.haml +2 -2
- data/views/summaries.haml +2 -2
- metadata +155 -202
- data/lib/nesta/cache.rb +0 -138
data/spec/config_spec.rb
CHANGED
@@ -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
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
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', :
|
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
|
data/spec/model_factory.rb
CHANGED
@@ -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
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
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
|
-
:
|
25
|
-
:
|
26
|
-
:
|
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 =
|
58
|
-
stat.stub
|
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
|
data/spec/models_spec.rb
CHANGED
@@ -26,47 +26,60 @@ module ModelMatchers
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
|
30
|
-
include
|
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(:
|
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(:
|
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(:
|
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(:
|
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(:
|
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(:
|
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
|
81
|
-
create_page(:
|
82
|
-
Nesta::Page.find_by_path('/').title.should == 'Home
|
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(:
|
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(:
|
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(:
|
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(:
|
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(:
|
118
|
-
|
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(:
|
121
|
-
File.stub
|
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(:
|
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(:
|
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(:
|
157
|
+
create_article(heading: 'Article 1', path: 'article-1')
|
144
158
|
create_article(
|
145
|
-
:
|
146
|
-
:
|
147
|
-
:
|
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
|
-
:
|
154
|
-
:
|
155
|
-
:
|
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
|
-
:
|
162
|
-
:
|
163
|
-
:
|
175
|
+
path: 'category-1',
|
176
|
+
heading: 'Category 1',
|
177
|
+
metadata: { 'categories' => @category.path }
|
164
178
|
)
|
165
179
|
@category2 = create_category(
|
166
|
-
:
|
167
|
-
:
|
168
|
-
:
|
180
|
+
path: 'category-2',
|
181
|
+
heading: 'Category 2',
|
182
|
+
metadata: { 'categories' => @category.path }
|
169
183
|
)
|
170
184
|
@category3 = create_category(
|
171
|
-
:
|
172
|
-
:
|
173
|
-
:
|
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 +
|
200
|
-
article = create_article(:
|
201
|
-
:
|
202
|
-
:
|
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(:
|
211
|
-
:
|
212
|
-
:
|
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
|
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(:
|
231
|
-
create_article(:
|
232
|
-
:
|
233
|
-
:
|
234
|
-
create_article(:
|
235
|
-
:
|
236
|
-
:
|
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(:
|
253
|
-
article = create_article(:
|
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(:
|
260
|
-
category = create_category(:
|
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(:
|
267
|
-
index = create_category(:
|
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(:
|
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(:
|
280
|
-
child = create_category(:
|
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(:
|
286
|
-
child = create_category(:
|
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(:
|
294
|
-
create_category(:
|
307
|
+
create_category(heading: "Apple", path: "the-apple")
|
308
|
+
create_category(heading: "Banana", path: "banana")
|
295
309
|
@article = create_article(
|
296
|
-
:
|
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
|
306
|
-
|
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(:
|
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
|
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
|
-
@
|
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
|
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
|
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
|
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
|
-
|
481
|
-
|
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(:
|
493
|
-
page2 = create_category(:
|
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
|
-
:
|
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(:
|
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
|
-
:
|
528
|
-
:
|
529
|
-
:
|
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
|
-
:
|
537
|
-
:
|
538
|
-
:
|
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
|
-
:
|
546
|
-
:
|
547
|
-
:
|
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
|
-
:
|
564
|
-
:
|
565
|
-
:
|
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(:
|
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(:
|
652
|
+
instance_variable_set("@page#{i}", create_page(path: "page-#{i}"))
|
600
653
|
end
|
601
654
|
text = <<-EOF
|
602
655
|
#{@page.path}
|