nesta 0.11.1 → 0.12.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 (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