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
@@ -0,0 +1,35 @@
1
+ require 'test_helper'
2
+ require_relative '../../../../lib/nesta/commands'
3
+
4
+ describe 'nesta theme:create' do
5
+ include TemporaryFiles
6
+
7
+ def theme_path(path = '')
8
+ File.join('themes', 'theme-name', path)
9
+ end
10
+
11
+ before do
12
+ FileUtils.mkdir_p(project_root)
13
+ end
14
+
15
+ after do
16
+ remove_temp_directory
17
+ end
18
+
19
+ it 'creates default files in the theme directory' do
20
+ Dir.chdir(project_root) do
21
+ Nesta::Commands::Theme::Create.new('theme-name').execute
22
+ end
23
+ assert_exists_in_project theme_path('README.md')
24
+ assert_exists_in_project theme_path('app.rb')
25
+ end
26
+
27
+ it 'copies default view templates into views directory' do
28
+ Dir.chdir(project_root) do
29
+ Nesta::Commands::Theme::Create.new('theme-name').execute
30
+ end
31
+ %w(layout.haml page.haml master.sass).each do |template|
32
+ assert_exists_in_project theme_path("views/#{template}")
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,22 @@
1
+ require 'test_helper'
2
+ require_relative '../../../../lib/nesta/commands'
3
+
4
+ describe 'nesta theme:enable' do
5
+ include TemporaryFiles
6
+
7
+ before do
8
+ FileUtils.mkdir_p(File.join(project_root, 'config'))
9
+ File.open(File.join(project_root, 'config', 'config.yml'), 'w').close
10
+ end
11
+
12
+ after do
13
+ remove_temp_directory
14
+ end
15
+
16
+ it 'enables the theme' do
17
+ Dir.chdir(project_root) do
18
+ Nesta::Commands::Theme::Enable.new('theme-name').execute
19
+ assert_match /^theme: theme-name/, File.read('config/config.yml')
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,62 @@
1
+ require 'test_helper'
2
+ require_relative '../../../support/silence_commands_during_tests'
3
+ require_relative '../../../../lib/nesta/commands'
4
+
5
+ Nesta::Commands::Theme::Install.send(:include, SilenceCommandsDuringTests)
6
+
7
+ describe 'nesta theme:install' do
8
+ include TemporaryFiles
9
+
10
+ def theme_name
11
+ 'test'
12
+ end
13
+
14
+ def repo_url
15
+ "../../fixtures/nesta-theme-#{theme_name}.git"
16
+ end
17
+
18
+ def theme_dir
19
+ project_path("themes/#{theme_name}")
20
+ end
21
+
22
+ before do
23
+ FileUtils.mkdir_p(project_root)
24
+ end
25
+
26
+ after do
27
+ remove_temp_directory
28
+ end
29
+
30
+ it 'clones the repository' do
31
+ in_temporary_project do
32
+ Nesta::Commands::Theme::Install.new(repo_url).execute
33
+ assert File.directory?(theme_dir), 'theme not cloned'
34
+ end
35
+ end
36
+
37
+ it "removes the theme's .git directory" do
38
+ in_temporary_project do
39
+ Nesta::Commands::Theme::Install.new(repo_url).execute
40
+ refute File.exist?("#{theme_dir}/.git"), '.git folder found'
41
+ end
42
+ end
43
+
44
+ it 'enables the freshly installed theme' do
45
+ in_temporary_project do
46
+ Nesta::Commands::Theme::Install.new(repo_url).execute
47
+ assert_match /theme: #{theme_name}/, File.read('config/config.yml')
48
+ end
49
+ end
50
+
51
+ it 'determines name of theme from name of repository' do
52
+ url = 'git://foobar.com/path/to/nesta-theme-the-name.git'
53
+ command = Nesta::Commands::Theme::Install.new(url)
54
+ assert_equal 'the-name', command.theme_name
55
+ end
56
+
57
+ it "falls back to name of repo when theme name doesn't match correct format" do
58
+ url = 'git://foobar.com/path/to/mytheme.git'
59
+ command = Nesta::Commands::Theme::Install.new(url)
60
+ assert_equal 'mytheme', command.theme_name
61
+ end
62
+ end
@@ -0,0 +1,220 @@
1
+ require 'integration_test_helper'
2
+
3
+ describe 'Default theme' do
4
+ include Nesta::IntegrationTest
5
+
6
+ def in_categories(*categories)
7
+ { 'categories' => categories.map(&:path).join(', ') }
8
+ end
9
+
10
+ it 'includes description meta tag' do
11
+ with_temp_content_directory do
12
+ model = create(:page, metadata: { 'Description' => 'A good page' })
13
+ visit model.path
14
+ xpath = "//meta[@name='description'][@content='A good page']"
15
+ assert_has_xpath xpath, visible: false
16
+ end
17
+ end
18
+
19
+ it 'includes keywords meta tag' do
20
+ with_temp_content_directory do
21
+ model = create(:page, metadata: { 'Keywords' => 'good, content' })
22
+ visit model.path
23
+ xpath = "//meta[@name='keywords'][@content='good, content']"
24
+ assert_has_xpath xpath, visible: false
25
+ end
26
+ end
27
+
28
+ it "doesn't include Google Analytics JavaScript snippet by default" do
29
+ with_temp_content_directory do
30
+ visit '/'
31
+ assert_has_no_css 'script', text: 'google-analytics.com'
32
+ end
33
+ end
34
+
35
+ it 'includes Google Analytics JavaScript when configured' do
36
+ analytics_code = { 'google_analytics_code' => 'UA-1234' }
37
+ stub_config(temp_content.merge('test' => analytics_code)) do
38
+ visit '/'
39
+ assert_nil all('script').find { |s| s[:src].match /analytics\.js/ }
40
+ end
41
+ end
42
+
43
+ it 'displays site title' do
44
+ site_config = {
45
+ 'title' => 'My blog',
46
+ 'subtitle' => 'about stuff',
47
+ }
48
+ stub_config(temp_content.merge(site_config)) do
49
+ visit '/'
50
+ assert_has_css 'h1', text: 'My blog'
51
+ assert_has_css 'h2', text: 'about stuff'
52
+ end
53
+ end
54
+
55
+ describe 'menus' do
56
+ def create_pages_in_menu
57
+ pages
58
+ end
59
+
60
+ it "doesn't include menu markup if menu not configured" do
61
+ with_temp_content_directory do
62
+ visit '/'
63
+ assert_has_no_css 'ul.menu'
64
+ end
65
+ end
66
+
67
+ it 'only displays first two levels of menu items' do
68
+ with_temp_content_directory do
69
+ level1, level2, level3 = (0..2).map { create(:page) }
70
+ text = "%s\n %s\n %s\n" % [level1, level2, level3].map(&:abspath)
71
+ create_menu(text)
72
+ visit '/'
73
+ assert_has_css "ul.menu li a:contains('#{level1.link_text}')"
74
+ assert_has_css "ul.menu li ul li a:contains('#{level2.link_text}')"
75
+ assert_has_no_css "ul.menu a:contains('#{level3.link_text}')"
76
+ end
77
+ end
78
+
79
+ def create_page_and_menu
80
+ model = create(:page)
81
+ create_menu(model.path)
82
+ model
83
+ end
84
+
85
+ it "highlights current page's menu item" do
86
+ with_temp_content_directory do
87
+ model = create_page_and_menu
88
+ visit model.path
89
+ assert_has_css "ul.menu li[class='current']:contains('#{model.link_text}')"
90
+ end
91
+ end
92
+
93
+ it "highlights current page's menu item when app mounted at /prefix" do
94
+ Capybara.app = Rack::Builder.new do
95
+ map '/prefix' do
96
+ run Nesta::App.new
97
+ end
98
+ end
99
+
100
+ with_temp_content_directory do
101
+ model = create_page_and_menu
102
+ visit "/prefix/#{model.path}"
103
+ assert_has_css "ul.menu li[class='current']:contains('#{model.link_text}')"
104
+ end
105
+ end
106
+ end
107
+
108
+ it 'only displays read more link for summarised pages' do
109
+ with_temp_content_directory do
110
+ category = create(:category)
111
+ metadata = in_categories(category)
112
+ summarised = create(:page, metadata: metadata.merge('summary' => 'Summary'))
113
+ not_summarised = create(:page, metadata: metadata)
114
+ visit category.path
115
+ assert_has_css 'li:nth-child(1) p', text: summarised.read_more
116
+ assert_has_no_css 'li:nth-child(2) p', text: not_summarised.read_more
117
+ end
118
+ end
119
+
120
+ it 'displays page summaries or full content of unsummarised pages' do
121
+ with_temp_content_directory do
122
+ category = create(:category)
123
+ metadata = in_categories(category)
124
+ summarised = create(:page,
125
+ content: 'Summarised content',
126
+ metadata: metadata.merge(summary: 'Summary'))
127
+ not_summarised = create(:page,
128
+ content: 'Unsummarised content',
129
+ metadata: metadata)
130
+ visit category.path
131
+
132
+ # Page with a summary
133
+ assert_has_css 'li:nth-child(1) p', text: 'Summary'
134
+ assert_has_no_css 'li:nth-child(1) p', text: 'content'
135
+
136
+ # Page without a summary
137
+ assert_has_css 'li:nth-child(2) p', text: 'Unsummarised content'
138
+ assert_has_no_css 'li:nth-child(2) p', text: 'Summary'
139
+ end
140
+ end
141
+
142
+ it 'displays contents of page' do
143
+ with_temp_content_directory do
144
+ model = create(:page, content: 'Body of page')
145
+ visit model.path
146
+ assert_has_css 'p', text: 'Body of page'
147
+ end
148
+ end
149
+
150
+ describe 'category' do
151
+ it 'displays its "articles heading" above the articles' do
152
+ with_temp_content_directory do
153
+ category = create(:category, metadata: {
154
+ 'articles heading' => 'Articles on this topic'
155
+ })
156
+ create(:article, metadata: in_categories(category))
157
+ visit category.path
158
+ assert_has_css 'h1', text: 'Articles on this topic'
159
+ end
160
+ end
161
+
162
+ it 'links to articles in category using article title' do
163
+ with_temp_content_directory do
164
+ category = create(:category)
165
+ article = create(:article, metadata: in_categories(category))
166
+ visit category.path
167
+ link_text, href = article.link_text, article.abspath
168
+ assert_has_css "ol h1 a[href$='#{href}']", text: link_text
169
+ end
170
+ end
171
+ end
172
+
173
+ describe 'article' do
174
+ it 'displays the date' do
175
+ with_temp_content_directory do
176
+ article = create(:article)
177
+ visit article.path
178
+ assert_has_css "time[datetime='#{article.date}']"
179
+ end
180
+ end
181
+
182
+ it 'links to parent page in breadcrumb' do
183
+ with_temp_content_directory do
184
+ parent = create(:category)
185
+ article = create(:article, path: "#{parent.path}/child")
186
+ visit article.path
187
+ href, link_text = parent.abspath, parent.link_text
188
+ assert_has_css "nav.breadcrumb a[href='#{href}']", text: link_text
189
+ end
190
+ end
191
+
192
+ it 'links to its categories at end of article' do
193
+ with_temp_content_directory do
194
+ categories = [create(:category), create(:category)]
195
+ article = create(:article, metadata: in_categories(*categories))
196
+ visit article.path
197
+ categories.each do |category|
198
+ href, link_text = category.abspath, category.link_text
199
+ assert_has_css "p.meta a[href$='#{href}']", text: link_text
200
+ end
201
+ end
202
+ end
203
+
204
+ it 'displays comments from Disqus' do
205
+ stub_config(temp_content.merge('disqus_short_name' => 'mysite')) do
206
+ article = create(:article)
207
+ visit article.path
208
+ assert_has_css '#disqus_thread'
209
+ assert_has_css 'script[src*="mysite.disqus.com"]', visible: false
210
+ end
211
+ end
212
+
213
+ it "doesn't use Disqus if it's not configured" do
214
+ with_temp_content_directory do
215
+ visit create(:article).path
216
+ assert_has_no_css '#disqus_thread'
217
+ end
218
+ end
219
+ end
220
+ end
@@ -0,0 +1,118 @@
1
+ require 'integration_test_helper'
2
+
3
+ describe 'Overriding files in gem and themes' do
4
+ include Nesta::IntegrationTest
5
+
6
+ def in_nesta_project(config = {}, &block)
7
+ app_root = temp_path('root')
8
+ content_config = { 'content' => File.join(app_root, 'content') }
9
+ stub_config(content_config.merge(config)) do
10
+ with_app_root(app_root) do
11
+ yield
12
+ end
13
+ end
14
+ ensure
15
+ remove_temp_directory
16
+ end
17
+
18
+ def theme_name
19
+ 'my-theme'
20
+ end
21
+
22
+ def create_fixture(type, name, content)
23
+ base_path = {
24
+ local: Nesta::Path.local,
25
+ theme: Nesta::Path.themes(theme_name)
26
+ }[type]
27
+ path = File.join(base_path, name)
28
+ FileUtils.mkdir_p(File.dirname(path))
29
+ open(path, 'w') { |file| file.write(content) }
30
+ end
31
+
32
+ def create_app_file(type)
33
+ create_fixture(type, 'app.rb', "FROM_#{type.to_s.upcase} = true")
34
+ end
35
+
36
+ describe 'app.rb' do
37
+ it 'loads app.rb from configured theme' do
38
+ in_nesta_project('theme' => theme_name) do
39
+ create_app_file(:theme)
40
+ Nesta::Overrides.load_theme_app
41
+ assert Object.const_get(:FROM_THEME), 'should load app.rb in theme'
42
+ end
43
+ end
44
+
45
+ it 'loads both local and theme app.rb files' do
46
+ in_nesta_project('theme' => theme_name) do
47
+ create_app_file(:local)
48
+ Nesta::Overrides.load_local_app
49
+ create_app_file(:theme)
50
+ Nesta::Overrides.load_theme_app
51
+ assert Object.const_get(:FROM_THEME), 'should load app.rb in theme'
52
+ assert Object.const_get(:FROM_LOCAL), 'should load local app.rb'
53
+ end
54
+ end
55
+ end
56
+
57
+ def create_view(type, name, content)
58
+ create_fixture(type, File.join('views', name), content)
59
+ end
60
+
61
+ describe 'rendering stylesheets' do
62
+ it 'renders Sass stylesheets' do
63
+ in_nesta_project do
64
+ create_view(:local, 'master.sass', "body\n width: 10px * 2")
65
+ visit '/css/master.css'
66
+ assert_match /width: 20px;/, body, 'should match /width: 20px;/'
67
+ end
68
+ end
69
+
70
+ it 'renders SCSS stylesheets' do
71
+ in_nesta_project do
72
+ create_view(:local, 'master.scss', "body {\n width: 10px * 2;\n}")
73
+ visit '/css/master.css'
74
+ assert_match /width: 20px;/, body, 'should match /width: 20px;/'
75
+ end
76
+ end
77
+
78
+ it 'renders stylesheet in the the gem if no others found' do
79
+ in_nesta_project do
80
+ visit '/css/master.css'
81
+ assert_equal 200, page.status_code
82
+ end
83
+ end
84
+ end
85
+
86
+ def create_haml(type, name, content)
87
+ create_view(type, 'layout.haml', '= yield')
88
+ create_view(type, name, content)
89
+ end
90
+
91
+ describe 'rendering Haml' do
92
+ it 'uses local template in place of default' do
93
+ in_nesta_project do
94
+ create_haml(:local, 'page.haml', '%p Local template')
95
+ visit create(:category).abspath
96
+ assert_has_xpath '//p', text: 'Local template'
97
+ end
98
+ end
99
+
100
+ it 'uses theme template in place of default' do
101
+ in_nesta_project('theme' => theme_name) do
102
+ create_haml(:theme, 'page.haml', '%p Theme template')
103
+ visit create(:category).abspath
104
+ assert_has_xpath '//p', text: 'Theme template'
105
+ end
106
+ end
107
+
108
+ it 'prioritise local templates over theme templates' do
109
+ in_nesta_project('theme' => theme_name) do
110
+ create_haml(:local, 'page.haml', '%p Local template')
111
+ create_haml(:theme, 'page.haml', '%p Theme template')
112
+ visit create(:category).abspath
113
+ assert_has_xpath '//p', text: 'Local template'
114
+ assert_has_no_xpath '//p', text: 'Theme template'
115
+ end
116
+ end
117
+ end
118
+ end