nesta 0.11.1 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +5 -5
  2. data/.gitmodules +6 -0
  3. data/.travis.yml +9 -4
  4. data/CHANGES +18 -2
  5. data/Gemfile +1 -1
  6. data/Gemfile.lock +70 -54
  7. data/LICENSE +1 -1
  8. data/RELEASING.md +5 -6
  9. data/Rakefile +20 -3
  10. data/lib/nesta/app.rb +4 -8
  11. data/lib/nesta/commands/command.rb +1 -2
  12. data/lib/nesta/commands/demo/content.rb +23 -5
  13. data/lib/nesta/commands/theme/install.rb +9 -7
  14. data/lib/nesta/helpers.rb +14 -0
  15. data/lib/nesta/models.rb +26 -22
  16. data/lib/nesta/navigation.rb +1 -1
  17. data/lib/nesta/version.rb +1 -1
  18. data/nesta.gemspec +10 -11
  19. data/templates/config/config.yml +1 -1
  20. data/{spec → test}/fixtures/nesta-plugin-test/Gemfile +0 -0
  21. data/{spec → test}/fixtures/nesta-plugin-test/Rakefile +0 -0
  22. data/{spec → test}/fixtures/nesta-plugin-test/lib/nesta-plugin-test.rb +0 -0
  23. data/{spec → test}/fixtures/nesta-plugin-test/lib/nesta-plugin-test/init.rb +0 -0
  24. data/{spec → test}/fixtures/nesta-plugin-test/lib/nesta-plugin-test/version.rb +0 -0
  25. data/{spec → test}/fixtures/nesta-plugin-test/nesta-plugin-test.gemspec +0 -0
  26. data/test/integration/atom_feed_test.rb +178 -0
  27. data/test/integration/commands/demo/content_test.rb +31 -0
  28. data/test/integration/commands/edit_test.rb +21 -0
  29. data/test/integration/commands/new_test.rb +120 -0
  30. data/test/integration/commands/plugin/create_test.rb +128 -0
  31. data/test/integration/commands/theme/create_test.rb +35 -0
  32. data/test/integration/commands/theme/enable_test.rb +22 -0
  33. data/test/integration/commands/theme/install_test.rb +62 -0
  34. data/test/integration/default_theme_test.rb +220 -0
  35. data/test/integration/overrides_test.rb +118 -0
  36. data/test/integration/route_handlers_test.rb +96 -0
  37. data/test/integration/sitemap_test.rb +85 -0
  38. data/test/integration_test_helper.rb +61 -0
  39. data/test/support/model_factory.rb +169 -0
  40. data/test/support/silence_commands_during_tests.rb +5 -0
  41. data/test/support/temporary_files.rb +33 -0
  42. data/test/support/test_configuration.rb +19 -0
  43. data/test/test_helper.rb +26 -0
  44. data/test/unit/commands_test.rb +23 -0
  45. data/test/unit/config_test.rb +138 -0
  46. data/test/unit/file_model_test.rb +71 -0
  47. data/test/unit/menu_test.rb +82 -0
  48. data/test/unit/page_test.rb +571 -0
  49. data/test/unit/path_test.rb +41 -0
  50. data/test/unit/plugin_test.rb +47 -0
  51. data/views/master.sass +1 -1
  52. metadata +81 -85
  53. data/smoke-test.sh +0 -107
  54. data/spec/atom_spec.rb +0 -141
  55. data/spec/commands/demo/content_spec.rb +0 -65
  56. data/spec/commands/edit_spec.rb +0 -27
  57. data/spec/commands/new_spec.rb +0 -88
  58. data/spec/commands/plugin/create_spec.rb +0 -97
  59. data/spec/commands/system_spec.rb +0 -25
  60. data/spec/commands/theme/create_spec.rb +0 -41
  61. data/spec/commands/theme/enable_spec.rb +0 -44
  62. data/spec/commands/theme/install_spec.rb +0 -56
  63. data/spec/config_spec.rb +0 -127
  64. data/spec/model_factory.rb +0 -92
  65. data/spec/models_spec.rb +0 -700
  66. data/spec/overrides_spec.rb +0 -132
  67. data/spec/page_spec.rb +0 -560
  68. data/spec/path_spec.rb +0 -28
  69. data/spec/plugin_spec.rb +0 -51
  70. data/spec/sitemap_spec.rb +0 -105
  71. data/spec/spec_helper.rb +0 -114
@@ -1,41 +0,0 @@
1
- require File.expand_path('../../spec_helper', File.dirname(__FILE__))
2
- require File.expand_path('../../../lib/nesta/commands', File.dirname(__FILE__))
3
-
4
- describe "nesta:theme:create" do
5
- include_context "temporary working directory"
6
-
7
- def should_exist(file)
8
- File.exist?(Nesta::Path.themes(@name, file)).should be_true
9
- end
10
-
11
- before(:each) do
12
- Nesta::App.stub(:root).and_return(TempFileHelper::TEMP_DIR)
13
- @name = 'my-new-theme'
14
- Nesta::Commands::Theme::Create.new(@name).execute
15
- end
16
-
17
- it "should create the theme directory" do
18
- File.directory?(Nesta::Path.themes(@name)).should be_true
19
- end
20
-
21
- it "should create a dummy README file" do
22
- should_exist('README.md')
23
- text = File.read(Nesta::Path.themes(@name, 'README.md'))
24
- text.should match(/#{@name} is a theme/)
25
- end
26
-
27
- it "should create a default app.rb file" do
28
- should_exist('app.rb')
29
- end
30
-
31
- it "should create public and views directories" do
32
- should_exist("public/#{@name}")
33
- should_exist('views')
34
- end
35
-
36
- it "should copy the default view templates into views" do
37
- %w(layout.haml page.haml master.sass).each do |file|
38
- should_exist("views/#{file}")
39
- end
40
- end
41
- end
@@ -1,44 +0,0 @@
1
- require File.expand_path('../../spec_helper', File.dirname(__FILE__))
2
- require File.expand_path('../../../lib/nesta/commands', File.dirname(__FILE__))
3
-
4
- describe "nesta:theme:enable" do
5
- include_context "temporary working directory"
6
-
7
- before(:each) do
8
- config = temp_path('config.yml')
9
- Nesta::Config.stub(:yaml_path).and_return(config)
10
- @name = 'mytheme'
11
- @command = Nesta::Commands::Theme::Enable.new(@name)
12
- end
13
-
14
- shared_examples_for "command that configures the theme" do
15
- it "should enable the theme" do
16
- @command.execute
17
- File.read(Nesta::Config.yaml_path).should match(/^theme: #{@name}/)
18
- end
19
- end
20
-
21
- describe "when theme config is commented out" do
22
- before(:each) do
23
- create_config_yaml(' # theme: blah')
24
- end
25
-
26
- it_should_behave_like "command that configures the theme"
27
- end
28
-
29
- describe "when another theme is configured" do
30
- before(:each) do
31
- create_config_yaml('theme: another')
32
- end
33
-
34
- it_should_behave_like "command that configures the theme"
35
- end
36
-
37
- describe "when no theme config exists" do
38
- before(:each) do
39
- create_config_yaml('# I have no theme config')
40
- end
41
-
42
- it_should_behave_like "command that configures the theme"
43
- end
44
- end
@@ -1,56 +0,0 @@
1
- require File.expand_path('../../spec_helper', File.dirname(__FILE__))
2
- require File.expand_path('../../../lib/nesta/commands', File.dirname(__FILE__))
3
-
4
- describe "nesta:theme:install" do
5
- include_context "temporary working directory"
6
-
7
- before(:each) do
8
- @repo_url = 'git://github.com/gma/nesta-theme-mine.git'
9
- @theme_dir = 'themes/mine'
10
- FileUtils.mkdir_p(File.join(@theme_dir, '.git'))
11
- @command = Nesta::Commands::Theme::Install.new(@repo_url)
12
- @command.stub(:enable)
13
- @command.stub(:run_process)
14
- end
15
-
16
- after(:each) do
17
- FileUtils.rm_r(@theme_dir)
18
- end
19
-
20
- it "should clone the repository" do
21
- @command.should_receive(:run_process).with(
22
- 'git', 'clone', @repo_url, @theme_dir)
23
- @command.execute
24
- end
25
-
26
- it "should remove the theme's .git directory" do
27
- @command.execute
28
- File.exist?(@theme_dir).should be_true
29
- File.exist?(File.join(@theme_dir, '.git')).should be_false
30
- end
31
-
32
- it "should enable the freshly installed theme" do
33
- @command.should_receive(:enable)
34
- @command.execute
35
- end
36
-
37
- describe "when theme URL doesn't match recommended pattern" do
38
- before(:each) do
39
- @repo_url = 'git://foobar.com/path/to/mytheme.git'
40
- @other_theme_dir = 'themes/mytheme'
41
- FileUtils.mkdir_p(File.join(@other_theme_dir, '.git'))
42
- @command = Nesta::Commands::Theme::Install.new(@repo_url)
43
- @command.stub(:enable)
44
- end
45
-
46
- after(:each) do
47
- FileUtils.rm_r(@other_theme_dir)
48
- end
49
-
50
- it "should use the basename as theme dir" do
51
- @command.should_receive(:run_process).with(
52
- 'git', 'clone', @repo_url, @other_theme_dir)
53
- @command.execute
54
- end
55
- end
56
- end
@@ -1,127 +0,0 @@
1
- require File.expand_path('spec_helper', File.dirname(__FILE__))
2
-
3
- describe "Config" do
4
- after(:each) do
5
- ENV.keys.each { |variable| ENV.delete(variable) if variable =~ /NESTA_/ }
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
15
-
16
- describe "when settings defined in ENV" do
17
- before(:each) do
18
- @title = "Title from ENV"
19
- ENV["NESTA_TITLE"] = @title
20
- end
21
-
22
- it "should fallback to config.yml" do
23
- stub_config_key("subtitle", "Subtitle in YAML file")
24
- Nesta::Config.subtitle.should == "Subtitle in YAML file"
25
- end
26
-
27
- it "should override config.yml" do
28
- stub_config_key("title", "Title in YAML file")
29
- Nesta::Config.title.should == @title
30
- end
31
-
32
- it "should know how to cope with boolean values" do
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
52
- end
53
-
54
- it "should set author hash from ENV" do
55
- name = "Name from ENV"
56
- uri = "URI from ENV"
57
- ENV["NESTA_AUTHOR__NAME"] = name
58
- ENV["NESTA_AUTHOR__URI"] = uri
59
- Nesta::Config.author["name"].should == name
60
- Nesta::Config.author["uri"].should == uri
61
- Nesta::Config.author["email"].should be_nil
62
- end
63
- end
64
-
65
- describe "when settings only defined in config.yml" do
66
- before(:each) do
67
- @title = "Title in YAML file"
68
- stub_config_key("subtitle", @title)
69
- end
70
-
71
- it "should read configuration from YAML" do
72
- Nesta::Config.subtitle.should == @title
73
- end
74
-
75
- it "should set author hash from YAML" do
76
- name = "Name from YAML"
77
- uri = "URI from YAML"
78
- stub_config_key("author", { "name" => name, "uri" => uri })
79
- Nesta::Config.author["name"].should == name
80
- Nesta::Config.author["uri"].should == uri
81
- Nesta::Config.author["email"].should be_nil
82
- end
83
-
84
- it "should override top level settings with environment specific settings" do
85
- stub_config_key('content', 'general/path')
86
- stub_config_key('content', 'rack_env/path', for_environment: true)
87
- Nesta::Config.content.should == 'rack_env/path'
88
- end
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
127
- end
@@ -1,92 +0,0 @@
1
- module ModelFactory
2
- def create_page(options)
3
- extension = options[:ext] || :mdown
4
- path = filename(Nesta::Config.page_path, options[:path], extension)
5
- create_file(path, options)
6
- yield(path) if block_given?
7
- Nesta::Page.new(path)
8
- end
9
-
10
- def create_article(options = {}, &block)
11
- o = {
12
- path: 'article-prefix/my-article',
13
- heading: 'My article',
14
- content: 'Content goes here',
15
- metadata: {
16
- 'date' => '29 December 2008'
17
- }.merge(options.delete(:metadata) || {})
18
- }.merge(options)
19
- create_page(o, &block)
20
- end
21
-
22
- def create_category(options = {}, &block)
23
- o = {
24
- path: 'category-prefix/my-category',
25
- heading: 'My category',
26
- content: 'Content goes here'
27
- }.merge(options)
28
- create_page(o, &block)
29
- end
30
-
31
- def write_menu_item(indent, file, menu_item)
32
- if menu_item.is_a?(Array)
33
- indent.sub!(/^/, ' ')
34
- menu_item.each { |path| write_menu_item(indent, file, path) }
35
- indent.sub!(/^ /, '')
36
- else
37
- file.write("#{indent}#{menu_item}\n")
38
- end
39
- end
40
-
41
- def create_menu(menu_text)
42
- file = filename(Nesta::Config.content_path, 'menu', :txt)
43
- File.open(file, 'w') { |file| file.write(menu_text) }
44
- end
45
-
46
- def delete_page(type, permalink, extension)
47
- file = filename(Nesta::Config.page_path, permalink, extension)
48
- FileUtils.rm(file)
49
- end
50
-
51
- def create_content_directories
52
- FileUtils.mkdir_p(Nesta::Config.page_path)
53
- FileUtils.mkdir_p(Nesta::Config.attachment_path)
54
- end
55
-
56
- def mock_file_stat(method, filename, time)
57
- stat = double(:stat)
58
- stat.stub(:mtime).and_return(Time.parse(time))
59
- File.send(method, :stat).with(filename).and_return(stat)
60
- end
61
-
62
- private
63
- def filename(directory, basename, extension = :mdown)
64
- File.join(directory, "#{basename}.#{extension}")
65
- end
66
-
67
- def heading(options)
68
- prefix = case options[:ext]
69
- when :haml
70
- "%div\n %h1"
71
- when :textile
72
- "<div>\nh1."
73
- else
74
- '# '
75
- end
76
- "#{prefix} #{options[:heading]}\n\n"
77
- end
78
-
79
- def create_file(path, options = {})
80
- create_content_directories
81
- metadata = options[:metadata] || {}
82
- metatext = metadata.map { |key, value| "#{key}: #{value}" }.join("\n")
83
- heading = options[:heading] ? heading(options) : ''
84
- contents =<<-EOF
85
- #{metatext}
86
-
87
- #{heading}#{options[:content]}
88
- EOF
89
- FileUtils.mkdir_p(File.dirname(path))
90
- File.open(path, 'w') { |file| file.write(contents) }
91
- end
92
- end
@@ -1,700 +0,0 @@
1
- require File.expand_path('spec_helper', File.dirname(__FILE__))
2
- require File.expand_path('model_factory', File.dirname(__FILE__))
3
-
4
- module ModelMatchers
5
- class HavePage
6
- def initialize(path)
7
- @category = path
8
- end
9
-
10
- def matches?(article)
11
- @article = article
12
- article.categories.map { |c| c.path }.include?(@category)
13
- end
14
-
15
- def failure_message
16
- "expected '#{@article.path}' to be assigned to #{@category}"
17
- end
18
-
19
- def negative_failure_message
20
- "'#{@article.path}' should not be assigned to #{@category}"
21
- end
22
- end
23
-
24
- def be_in_category(path)
25
- HavePage.new(path)
26
- end
27
- end
28
-
29
- shared_context "Page testing" do
30
- include Webrat::Matchers
31
-
32
- def create_page(options)
33
- super(options.merge(ext: @extension))
34
- end
35
-
36
- before(:each) do
37
- stub_configuration
38
- end
39
-
40
- after(:each) do
41
- remove_temp_directory
42
- Nesta::FileModel.purge_cache
43
- end
44
- end
45
-
46
- shared_examples_for "Page" do
47
- include ModelFactory
48
- include ModelMatchers
49
-
50
- it "should be findable" do
51
- create_page(heading: 'Apple', path: 'the-apple')
52
- Nesta::Page.find_all.should have(1).item
53
- end
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
-
64
- it "should find by path" do
65
- create_page(heading: 'Banana', path: 'banana')
66
- Nesta::Page.find_by_path('banana').heading.should == 'Banana'
67
- end
68
-
69
- it "should find index page by path" do
70
- create_page(heading: 'Banana', path: 'banana/index')
71
- Nesta::Page.find_by_path('banana').heading.should == 'Banana'
72
- end
73
-
74
- it "should respond to #parse_metadata, returning hash of key/value" do
75
- page = create_page(heading: 'Banana', path: 'banana')
76
- metadata = page.parse_metadata('My key: some value')
77
- metadata['my key'].should == 'some value'
78
- end
79
-
80
- it "should be parseable if metadata is invalid" do
81
- dodgy_metadata = "Key: value\nKey without value\nAnother key: value"
82
- create_page(heading: 'Banana', path: 'banana') do |path|
83
- text = File.read(path)
84
- File.open(path, 'w') do |file|
85
- file.puts(dodgy_metadata)
86
- file.write(text)
87
- end
88
- end
89
- Nesta::Page.find_by_path('banana')
90
- end
91
-
92
- describe "for home page" do
93
- it "should set title to heading" do
94
- create_page(heading: 'Home', path: 'index')
95
- Nesta::Page.find_by_path('/').title.should == 'Home'
96
- end
97
-
98
- it "should respect title metadata" do
99
- create_page(path: 'index', metadata: { 'title' => 'Specific title' })
100
- Nesta::Page.find_by_path('/').title.should == 'Specific title'
101
- end
102
-
103
- it "should set title to site title by default" do
104
- create_page(path: 'index')
105
- Nesta::Page.find_by_path('/').title.should == 'My blog'
106
- end
107
-
108
- it "should set permalink to empty string" do
109
- create_page(path: 'index')
110
- Nesta::Page.find_by_path('/').permalink.should == ''
111
- end
112
-
113
- it "should set abspath to /" do
114
- create_page(path: 'index')
115
- Nesta::Page.find_by_path('/').abspath.should == '/'
116
- end
117
- end
118
-
119
- it "should not find nonexistent page" do
120
- Nesta::Page.find_by_path("no-such-page").should be_nil
121
- end
122
-
123
- it "should ensure file exists on instantiation" do
124
- lambda {
125
- Nesta::Page.new("no-such-file")
126
- }.should raise_error(Sinatra::NotFound)
127
- end
128
-
129
- it "should reload cached files when modified" do
130
- create_page(path: "a-page", heading: "Version 1")
131
- now = Time.now
132
- File.stub(:mtime).and_return(now - 1)
133
- Nesta::Page.find_by_path("a-page")
134
- create_page(path: "a-page", heading: "Version 2")
135
- File.stub(:mtime).and_return(now)
136
- Nesta::Page.find_by_path("a-page").heading.should == "Version 2"
137
- end
138
-
139
- it "should have default priority of 0 in category" do
140
- page = create_page(metadata: { 'categories' => 'some-page' })
141
- page.priority('some-page').should == 0
142
- page.priority('another-page').should be_nil
143
- end
144
-
145
- it "should read priority from category metadata" do
146
- page = create_page(metadata: {
147
- 'categories' => ' some-page:1, another-page , and-another :-1 '
148
- })
149
- page.priority('some-page').should == 1
150
- page.priority('another-page').should == 0
151
- page.priority('and-another').should == -1
152
- end
153
-
154
- describe "with assigned pages" do
155
- before(:each) do
156
- @category = create_category
157
- create_article(heading: 'Article 1', path: 'article-1')
158
- create_article(
159
- heading: 'Article 2',
160
- path: 'article-2',
161
- metadata: {
162
- 'date' => '30 December 2008',
163
- 'categories' => @category.path
164
- }
165
- )
166
- @article = create_article(
167
- heading: 'Article 3',
168
- path: 'article-3',
169
- metadata: {
170
- 'date' => '31 December 2008',
171
- 'categories' => @category.path
172
- }
173
- )
174
- @category1 = create_category(
175
- path: 'category-1',
176
- heading: 'Category 1',
177
- metadata: { 'categories' => @category.path }
178
- )
179
- @category2 = create_category(
180
- path: 'category-2',
181
- heading: 'Category 2',
182
- metadata: { 'categories' => @category.path }
183
- )
184
- @category3 = create_category(
185
- path: 'category-3',
186
- heading: 'Category 3',
187
- metadata: { 'categories' => "#{@category.path}:1" }
188
- )
189
- end
190
-
191
- it "should find articles" do
192
- @category.articles.should have(2).items
193
- end
194
-
195
- it "should order articles by reverse chronological order" do
196
- @category.articles.first.path.should == @article.path
197
- end
198
-
199
- it "should find pages" do
200
- @category.pages.should have(3).items
201
- end
202
-
203
- it "should sort pages by priority" do
204
- @category.pages.index(@category3).should == 0
205
- end
206
-
207
- it "should order pages by heading if priority not set" do
208
- pages = @category.pages
209
- pages.index(@category1).should < pages.index(@category2)
210
- end
211
-
212
- it "should not find pages scheduled in the future" do
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 })
217
- Nesta::Page.find_articles.detect{|a| a == article}.should be_nil
218
- end
219
- end
220
-
221
- describe "with pages in draft" do
222
- before(:each) do
223
- @category = create_category
224
- @draft = create_page(heading: 'Forthcoming content',
225
- path: 'foo/in-draft',
226
- metadata: {
227
- 'categories' => @category.path,
228
- 'flags' => 'draft'
229
- })
230
- Nesta::App.stub(:production?).and_return(true)
231
- end
232
-
233
- it "should not find assigned drafts" do
234
- @category.pages.should_not include(@draft)
235
- end
236
-
237
- it "should not find drafts by path" do
238
- Nesta::Page.find_by_path('foo/in-draft').should be_nil
239
- end
240
- end
241
-
242
- describe "when finding articles" do
243
- before(:each) do
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
-
253
- it "should only find pages with dates" do
254
- articles = Nesta::Page.find_articles
255
- articles.size.should > 0
256
- Nesta::Page.find_articles.each { |page| page.date.should_not be_nil }
257
- end
258
-
259
- it "should return articles in reverse chronological order" do
260
- article1, article2 = Nesta::Page.find_articles[0..1]
261
- article1.date.should > article2.date
262
- end
263
- end
264
-
265
- it "should be able to find parent page" do
266
- category = create_category(path: 'parent')
267
- article = create_article(path: 'parent/child')
268
- article.parent.should == category
269
- end
270
-
271
- describe "(with deep index page)" do
272
- it "should be able to find index parent" do
273
- home = create_category(path: 'index', heading: 'Home')
274
- category = create_category(path: 'parent')
275
- category.parent.should == home
276
- home.parent.should be_nil
277
- end
278
-
279
- it "should be able to find parent of index" do
280
- category = create_category(path: "parent")
281
- index = create_category(path: "parent/child/index")
282
- index.parent.should == category
283
- end
284
-
285
- it "should be able to find permalink of index" do
286
- index = create_category(path: "parent/child/index")
287
- index.permalink.should == 'child'
288
- end
289
- end
290
-
291
- describe "(with missing nested page)" do
292
- it "should consider grandparent to be parent" do
293
- grandparent = create_category(path: 'grandparent')
294
- child = create_category(path: 'grandparent/parent/child')
295
- child.parent.should == grandparent
296
- end
297
-
298
- it "should consider grandparent home page to be parent" do
299
- home = create_category(path: 'index')
300
- child = create_category(path: 'parent/child')
301
- child.parent.should == home
302
- end
303
- end
304
-
305
- describe "when assigned to categories" do
306
- before(:each) do
307
- create_category(heading: "Apple", path: "the-apple")
308
- create_category(heading: "Banana", path: "banana")
309
- @article = create_article(
310
- metadata: { "categories" => "banana, the-apple" })
311
- end
312
-
313
- it "should be possible to list the categories" do
314
- @article.categories.should have(2).items
315
- @article.should be_in_category("the-apple")
316
- @article.should be_in_category("banana")
317
- @article.should_not be_in_category("orange")
318
- end
319
-
320
- it "should not be assigned to non-existant category" do
321
- delete_page(:category, "banana", @extension)
322
- @article.should_not be_in_category("banana")
323
- end
324
- end
325
-
326
- it "should set parent to nil when at root" do
327
- create_category(path: "top-level").parent.should be_nil
328
- end
329
-
330
- describe "when not assigned to category" do
331
- it "should have empty category list" do
332
- article = create_article
333
- Nesta::Page.find_by_path(article.path).categories.should be_empty
334
- end
335
- end
336
-
337
- describe "with no content" do
338
- it "should produce no HTML output" do
339
- create_article do |path|
340
- file = File.open(path, 'w')
341
- file.close
342
- end
343
- Nesta::Page.find_all.first.to_html.should match(/^\s*$/)
344
- end
345
- end
346
-
347
- describe "without metadata" do
348
- before(:each) do
349
- create_article
350
- @article = Nesta::Page.find_all.first
351
- end
352
-
353
- it "should use default layout" do
354
- @article.layout.should == :layout
355
- end
356
-
357
- it "should use default template" do
358
- @article.template.should == :page
359
- end
360
-
361
- it "should parse heading correctly" do
362
- @article.to_html.should have_selector("h1", content: "My article")
363
- end
364
-
365
- it "should use heading as link text" do
366
- @article.link_text.should == "My article"
367
- end
368
-
369
- it "should have default read more link text" do
370
- @article.read_more.should == "Continue reading"
371
- end
372
-
373
- it "should not have description" do
374
- @article.description.should be_nil
375
- end
376
-
377
- it "should not have keywords" do
378
- @article.keywords.should be_nil
379
- end
380
- end
381
-
382
- describe "with metadata" do
383
- before(:each) do
384
- @layout = 'my_layout'
385
- @template = 'my_template'
386
- @date = '07 September 2009'
387
- @keywords = 'things, stuff'
388
- @description = 'Page about stuff'
389
- @summary = 'Multiline\n\nsummary'
390
- @read_more = 'Continue at your leisure'
391
- @skillz = 'ruby, guitar, bowstaff'
392
- @link_text = 'Link to stuff page'
393
- @article = create_article(metadata: {
394
- 'date' => @date.gsub('September', 'Sep'),
395
- 'description' => @description,
396
- 'flags' => 'draft, orange',
397
- 'keywords' => @keywords,
398
- 'layout' => @layout,
399
- 'read more' => @read_more,
400
- 'skillz' => @skillz,
401
- 'summary' => @summary,
402
- 'template' => @template,
403
- 'link text' => @link_text,
404
- })
405
- end
406
-
407
- it "should override default layout" do
408
- @article.layout.should == @layout.to_sym
409
- end
410
-
411
- it "should override default template" do
412
- @article.template.should == @template.to_sym
413
- end
414
-
415
- it "should set permalink to basename of filename" do
416
- @article.permalink.should == 'my-article'
417
- end
418
-
419
- it "should set path from filename" do
420
- @article.path.should == 'article-prefix/my-article'
421
- end
422
-
423
- it "should retrieve heading" do
424
- @article.heading.should == 'My article'
425
- end
426
-
427
- it "should be possible to convert an article to HTML" do
428
- @article.to_html.should have_selector("h1", content: "My article")
429
- end
430
-
431
- it "should not include metadata in the HTML" do
432
- @article.to_html.should_not have_selector("p:contains('Date')")
433
- end
434
-
435
- it "should not include heading in body markup" do
436
- @article.body_markup.should_not include("My article")
437
- end
438
-
439
- it "should not include heading in body" do
440
- @article.body.should_not have_selector("h1", content: "My article")
441
- end
442
-
443
- it "should retrieve description from metadata" do
444
- @article.description.should == @description
445
- end
446
-
447
- it "should retrieve keywords from metadata" do
448
- @article.keywords.should == @keywords
449
- end
450
-
451
- it "should retrieve date published from metadata" do
452
- @article.date.strftime("%d %B %Y").should == @date
453
- end
454
-
455
- it "should retrieve read more link from metadata" do
456
- @article.read_more.should == @read_more
457
- end
458
-
459
- it "should retrieve summary text from metadata" do
460
- @article.summary.should match(/#{@summary.split('\n\n').first}/)
461
- end
462
-
463
- it "should treat double newline chars as paragraph break in summary" do
464
- @article.summary.should match(/#{@summary.split('\n\n').last}/)
465
- end
466
-
467
- it "should allow access to metadata" do
468
- @article.metadata('skillz').should == @skillz
469
- end
470
-
471
- it "should allow access to flags" do
472
- @article.should be_flagged_as('draft')
473
- @article.should be_flagged_as('orange')
474
- end
475
-
476
- it "should know whether or not it's a draft" do
477
- @article.should be_draft
478
- end
479
-
480
- it "should allow link text to be specified explicitly" do
481
- @article.link_text.should == @link_text
482
- end
483
- end
484
-
485
- describe "when checking last modification time" do
486
- before(:each) do
487
- create_article
488
- @article = Nesta::Page.find_all.first
489
- end
490
-
491
- it "should check filesystem" do
492
- mock_file_stat(:should_receive, @article.filename, "3 January 2009")
493
- @article.last_modified.should == Time.parse("3 January 2009")
494
- end
495
- end
496
-
497
- describe "with no heading" do
498
- before(:each) do
499
- @no_heading_page = create_page(path: 'page-with-no-heading')
500
- end
501
-
502
- it "should raise a HeadingNotSet exception if you call heading" do
503
- lambda do
504
- @no_heading_page.heading
505
- end.should raise_error(Nesta::HeadingNotSet, /page-with-no-heading/);
506
- end
507
-
508
- it "should raise a LinkTextNotSet exception if you call link_text" do
509
- lambda do
510
- @no_heading_page.link_text
511
- end.should raise_error(Nesta::LinkTextNotSet, /page-with-no-heading/);
512
- end
513
- end
514
- end
515
-
516
- describe "All types of page" do
517
- include ModelFactory
518
-
519
- include_context "Page testing"
520
-
521
- it "should still return top level menu items" do
522
- # Page.menu_items is deprecated; we're keeping it for the moment so
523
- # that we don't break themes or code in a local app.rb (just yet).
524
- page1 = create_category(path: "page-1")
525
- page2 = create_category(path: "page-2")
526
- create_menu([page1.path, page2.path].join("\n"))
527
- Nesta::Page.menu_items.should == [page1, page2]
528
- end
529
- end
530
-
531
- describe "Markdown page" do
532
- include ModelFactory
533
-
534
- context "mdown extension" do
535
- before(:each) do
536
- @extension = :mdown
537
- end
538
-
539
- include_context "Page testing"
540
- it_should_behave_like "Page"
541
-
542
- it "should set heading from first h1 tag" do
543
- page = create_page(
544
- path: "a-page",
545
- heading: "First heading",
546
- content: "# Second heading"
547
- )
548
- page.heading.should == "First heading"
549
- end
550
-
551
- it "should ignore trailing # characters in headings" do
552
- article = create_article(heading: 'With trailing #')
553
- article.heading.should == 'With trailing'
554
- end
555
- end
556
-
557
- context "md extension" do
558
- before(:each) do
559
- @extension = :md
560
- end
561
-
562
- include_context "Page testing"
563
- it_should_behave_like "Page"
564
-
565
- it "should set heading from first h1 tag" do
566
- page = create_page(
567
- path: "a-page",
568
- heading: "First heading",
569
- content: "# Second heading"
570
- )
571
- page.heading.should == "First heading"
572
- end
573
-
574
- it "should ignore trailing # characters in headings" do
575
- article = create_article(heading: 'With trailing #')
576
- article.heading.should == 'With trailing'
577
- end
578
- end
579
- end
580
-
581
- describe "Haml page" do
582
- include ModelFactory
583
-
584
- before(:each) do
585
- @extension = :haml
586
- end
587
-
588
- include_context "Page testing"
589
- it_should_behave_like "Page"
590
-
591
- it "should set heading from first h1 tag" do
592
- page = create_page(
593
- path: "a-page",
594
- heading: "First heading",
595
- content: "%h1 Second heading"
596
- )
597
- page.heading.should == "First heading"
598
- end
599
-
600
- it "should wrap <p> tags around one line summary text" do
601
- page = create_page(
602
- path: "a-page",
603
- heading: "First para",
604
- metadata: { "Summary" => "Wrap me" }
605
- )
606
- page.summary.should include("<p>Wrap me</p>")
607
- end
608
-
609
- it "should wrap <p> tags around multiple lines of summary text" do
610
- page = create_page(
611
- path: "a-page",
612
- heading: "First para",
613
- metadata: { "Summary" => 'Wrap me\nIn paragraph tags' }
614
- )
615
- page.summary.should include("<p>Wrap me</p>")
616
- page.summary.should include("<p>In paragraph tags</p>")
617
- end
618
- end
619
-
620
- describe "Textile page" do
621
- include ModelFactory
622
-
623
- before(:each) do
624
- @extension = :textile
625
- end
626
-
627
- include_context "Page testing"
628
- it_should_behave_like "Page"
629
-
630
- it "should set heading from first h1 tag" do
631
- page = create_page(
632
- path: "a-page",
633
- heading: "First heading",
634
- content: "h1. Second heading"
635
- )
636
- page.heading.should == "First heading"
637
- end
638
- end
639
-
640
- describe "Menu" do
641
- include ModelFactory
642
-
643
- before(:each) do
644
- stub_configuration
645
- @page = create_page(path: "page-1")
646
- end
647
-
648
- after(:each) do
649
- remove_temp_directory
650
- Nesta::FileModel.purge_cache
651
- end
652
-
653
- it "should find top level menu items" do
654
- text = ["no-such-page", @page.path].join("\n")
655
- create_menu(text)
656
- Nesta::Menu.top_level.should == [@page]
657
- end
658
-
659
- it "should find all items in the menu" do
660
- create_menu(@page.path)
661
- Nesta::Menu.full_menu.should == [@page]
662
- Nesta::Menu.for_path('/').should == [@page]
663
- end
664
-
665
- describe "with nested sub menus" do
666
- before(:each) do
667
- (2..6).each do |i|
668
- instance_variable_set("@page#{i}", create_page(path: "page-#{i}"))
669
- end
670
- text = <<-EOF
671
- #{@page.path}
672
- #{@page2.path}
673
- #{@page3.path}
674
- #{@page4.path}
675
- "no-such-page"
676
- "another-missing-page"
677
- #{@page5.path}
678
- #{@page6.path}
679
- EOF
680
- create_menu(text)
681
- end
682
-
683
- it "should return top level menu items" do
684
- Nesta::Menu.top_level.should == [@page, @page5]
685
- end
686
-
687
- it "should return full tree of menu items" do
688
- Nesta::Menu.full_menu.should ==
689
- [@page, [@page2, [@page3, @page4]], @page5, [@page6]]
690
- end
691
-
692
- it "should return part of the tree of menu items" do
693
- Nesta::Menu.for_path(@page2.path).should == [@page2, [@page3, @page4]]
694
- end
695
-
696
- it "should deem menu for path that isn't in menu to be nil" do
697
- Nesta::Menu.for_path('wibble').should be_nil
698
- end
699
- end
700
- end