nesta 0.9.11 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -11
  3. data/.gitmodules +6 -0
  4. data/.hound.yml +2 -0
  5. data/{spec/spec.opts → .rspec} +0 -0
  6. data/.travis.yml +11 -0
  7. data/CHANGES +250 -2
  8. data/Gemfile +2 -2
  9. data/Gemfile.lock +89 -33
  10. data/Guardfile +7 -0
  11. data/LICENSE +1 -1
  12. data/README.md +38 -6
  13. data/RELEASING.md +21 -0
  14. data/Rakefile +20 -4
  15. data/bin/nesta +131 -14
  16. data/config.ru +3 -0
  17. data/lib/nesta.rb +9 -1
  18. data/lib/nesta/app.rb +21 -107
  19. data/lib/nesta/commands.rb +5 -256
  20. data/lib/nesta/commands/command.rb +57 -0
  21. data/lib/nesta/commands/demo.rb +1 -0
  22. data/lib/nesta/commands/demo/content.rb +56 -0
  23. data/lib/nesta/commands/edit.rb +21 -0
  24. data/lib/nesta/commands/new.rb +57 -0
  25. data/lib/nesta/commands/plugin.rb +1 -0
  26. data/lib/nesta/commands/plugin/create.rb +82 -0
  27. data/lib/nesta/commands/theme.rb +3 -0
  28. data/lib/nesta/commands/theme/create.rb +36 -0
  29. data/lib/nesta/commands/theme/enable.rb +22 -0
  30. data/lib/nesta/commands/theme/install.rb +31 -0
  31. data/lib/nesta/config.rb +51 -22
  32. data/lib/nesta/helpers.rb +115 -0
  33. data/lib/nesta/models.rb +111 -70
  34. data/lib/nesta/navigation.rb +36 -12
  35. data/lib/nesta/overrides.rb +10 -5
  36. data/lib/nesta/plugin.rb +10 -8
  37. data/lib/nesta/version.rb +1 -1
  38. data/nesta.gemspec +14 -13
  39. data/templates/Gemfile +6 -3
  40. data/templates/config.ru +3 -0
  41. data/templates/config/config.yml +14 -14
  42. data/templates/config/deploy.rb +2 -2
  43. data/templates/index.haml +2 -0
  44. data/templates/plugins/Gemfile +4 -0
  45. data/templates/plugins/README.md +13 -0
  46. data/templates/plugins/Rakefile +58 -0
  47. data/templates/plugins/gitignore +3 -0
  48. data/templates/plugins/lib/init.rb +13 -0
  49. data/templates/plugins/lib/required.rb +3 -0
  50. data/templates/plugins/lib/version.rb +5 -0
  51. data/templates/plugins/plugin.gemspec +28 -0
  52. data/templates/themes/README.md +1 -1
  53. data/templates/themes/app.rb +1 -1
  54. data/templates/themes/views/layout.haml +7 -0
  55. data/templates/themes/views/master.sass +3 -0
  56. data/templates/themes/views/page.haml +1 -0
  57. data/{spec → test}/fixtures/nesta-plugin-test/Gemfile +0 -0
  58. data/{spec → test}/fixtures/nesta-plugin-test/Rakefile +0 -0
  59. data/{spec → test}/fixtures/nesta-plugin-test/lib/nesta-plugin-test.rb +0 -0
  60. data/{spec → test}/fixtures/nesta-plugin-test/lib/nesta-plugin-test/init.rb +1 -3
  61. data/{spec → test}/fixtures/nesta-plugin-test/lib/nesta-plugin-test/version.rb +0 -0
  62. data/{spec → test}/fixtures/nesta-plugin-test/nesta-plugin-test.gemspec +0 -0
  63. data/test/integration/atom_feed_test.rb +178 -0
  64. data/test/integration/commands/demo/content_test.rb +31 -0
  65. data/test/integration/commands/edit_test.rb +21 -0
  66. data/test/integration/commands/new_test.rb +120 -0
  67. data/test/integration/commands/plugin/create_test.rb +128 -0
  68. data/test/integration/commands/theme/create_test.rb +35 -0
  69. data/test/integration/commands/theme/enable_test.rb +22 -0
  70. data/test/integration/commands/theme/install_test.rb +62 -0
  71. data/test/integration/default_theme_test.rb +220 -0
  72. data/test/integration/overrides_test.rb +118 -0
  73. data/test/integration/route_handlers_test.rb +96 -0
  74. data/test/integration/sitemap_test.rb +85 -0
  75. data/test/integration_test_helper.rb +61 -0
  76. data/test/support/model_factory.rb +169 -0
  77. data/test/support/silence_commands_during_tests.rb +5 -0
  78. data/test/support/temporary_files.rb +33 -0
  79. data/test/support/test_configuration.rb +19 -0
  80. data/test/test_helper.rb +26 -0
  81. data/test/unit/commands_test.rb +23 -0
  82. data/test/unit/config_test.rb +138 -0
  83. data/test/unit/file_model_test.rb +71 -0
  84. data/test/unit/menu_test.rb +82 -0
  85. data/test/unit/page_test.rb +571 -0
  86. data/test/unit/path_test.rb +41 -0
  87. data/test/unit/plugin_test.rb +47 -0
  88. data/views/analytics.haml +9 -10
  89. data/views/atom.haml +4 -4
  90. data/views/comments.haml +1 -1
  91. data/views/error.haml +1 -1
  92. data/views/feed.haml +1 -1
  93. data/views/layout.haml +6 -3
  94. data/views/master.sass +144 -134
  95. data/views/mixins.sass +53 -28
  96. data/views/normalize.scss +396 -0
  97. data/views/page_meta.haml +2 -2
  98. data/views/sitemap.haml +2 -2
  99. data/views/summaries.haml +2 -2
  100. metadata +258 -232
  101. data/lib/nesta/cache.rb +0 -139
  102. data/lib/nesta/nesta.rb +0 -7
  103. data/spec/atom_spec.rb +0 -138
  104. data/spec/commands_spec.rb +0 -364
  105. data/spec/config_spec.rb +0 -67
  106. data/spec/model_factory.rb +0 -92
  107. data/spec/models_spec.rb +0 -588
  108. data/spec/overrides_spec.rb +0 -132
  109. data/spec/page_spec.rb +0 -498
  110. data/spec/path_spec.rb +0 -28
  111. data/spec/plugin_spec.rb +0 -51
  112. data/spec/sitemap_spec.rb +0 -100
  113. data/spec/spec_helper.rb +0 -76
@@ -0,0 +1,7 @@
1
+ <!DOCTYPE html>
2
+ %html(lang="en")
3
+ %head
4
+ %meta(charset="utf-8")
5
+ %title
6
+ %body
7
+ = yield
@@ -0,0 +1,3 @@
1
+ // Master Sass stylesheet
2
+ // http://sass-lang.com/
3
+
@@ -0,0 +1 @@
1
+ ~ @page.to_html(self)
@@ -2,9 +2,7 @@ module Nesta
2
2
  module Plugin
3
3
  module Test
4
4
  module Helpers
5
- helpers do
6
- # If your plugin needs any helper methods, add them here...
7
- end
5
+ # If your plugin needs any helper methods, add them here...
8
6
  end
9
7
  end
10
8
  end
@@ -0,0 +1,178 @@
1
+ require 'integration_test_helper'
2
+
3
+ describe 'Atom feed' do
4
+ include Nesta::IntegrationTest
5
+
6
+ def visit_feed
7
+ visit '/articles.xml'
8
+ end
9
+
10
+ describe 'site' do
11
+ it 'renders successfully' do
12
+ with_temp_content_directory do
13
+ visit_feed
14
+ assert_equal 200, page.status_code
15
+ end
16
+ end
17
+
18
+ it "uses Atom's XML namespace" do
19
+ with_temp_content_directory do
20
+ visit_feed
21
+ assert_has_xpath '//feed[@xmlns="http://www.w3.org/2005/Atom"]'
22
+ end
23
+ end
24
+
25
+ it 'has an ID element' do
26
+ with_temp_content_directory do
27
+ visit_feed
28
+ assert page.has_selector?('id:contains("tag:www.example.com,2009:/")')
29
+ end
30
+ end
31
+
32
+ it 'has an alternate link element' do
33
+ with_temp_content_directory do
34
+ visit_feed
35
+ assert_has_xpath(
36
+ '//feed/link[@rel="alternate"][@href="http://www.example.com/"]')
37
+ end
38
+ end
39
+
40
+ it 'has a self link element' do
41
+ with_temp_content_directory do
42
+ visit_feed
43
+ assert_has_xpath(
44
+ '//feed/link[@rel="self"][@href="http://www.example.com/articles.xml"]')
45
+ end
46
+ end
47
+
48
+ it 'has title and subtitle' do
49
+ site_config = {
50
+ 'title' => 'My blog',
51
+ 'subtitle' => 'about stuff',
52
+ }
53
+ stub_config(temp_content.merge(site_config)) do
54
+ visit_feed
55
+ assert_has_xpath '//feed/title[@type="text"]', text: 'My blog'
56
+ assert_has_xpath '//feed/subtitle[@type="text"]', text: 'about stuff'
57
+ end
58
+ end
59
+
60
+ it 'includes the author details' do
61
+ author_config = temp_content.merge('author' => {
62
+ 'name' => 'Fred Bloggs',
63
+ 'uri' => 'http://fredbloggs.com',
64
+ 'email' => 'fred@fredbloggs.com'
65
+ })
66
+ stub_config(temp_content.merge(author_config)) do
67
+ visit_feed
68
+ assert_has_xpath '//feed/author/name', text: 'Fred Bloggs'
69
+ assert_has_xpath '//feed/author/uri', text: 'http://fredbloggs.com'
70
+ assert_has_xpath '//feed/author/email', text: 'fred@fredbloggs.com'
71
+ end
72
+ end
73
+ end
74
+
75
+ describe 'site with articles' do
76
+ it 'only lists latest 10' do
77
+ with_temp_content_directory do
78
+ 11.times { create(:article) }
79
+ visit_feed
80
+ end
81
+ assert page.has_selector?('entry', count: 10), 'expected 10 articles'
82
+ end
83
+ end
84
+
85
+ def with_category(options = {})
86
+ with_temp_content_directory do
87
+ model = create(:category, options)
88
+ visit_feed
89
+ yield(model)
90
+ end
91
+ end
92
+
93
+ def with_article(options = {})
94
+ with_temp_content_directory do
95
+ article = create(:article, options)
96
+ visit_feed
97
+ yield(article)
98
+ end
99
+ end
100
+
101
+ def with_article_in_category(options = {})
102
+ with_temp_content_directory do
103
+ category = create(:category, options)
104
+ article_options = options.merge(metadata: {
105
+ 'categories' => category.path
106
+ })
107
+ article = create(:article, article_options)
108
+ visit_feed
109
+ yield(article, category)
110
+ end
111
+ end
112
+
113
+ describe 'article' do
114
+ it 'sets the title' do
115
+ with_article do |article|
116
+ assert_has_xpath '//entry/title', text: article.heading
117
+ end
118
+ end
119
+
120
+ it 'links to the HTML version' do
121
+ with_article do |article|
122
+ url = "http://www.example.com/#{article.path}"
123
+ assert_has_xpath(
124
+ "//entry/link[@href='#{url}'][@rel='alternate'][@type='text/html']")
125
+ end
126
+ end
127
+
128
+ it 'defines unique ID' do
129
+ with_article do |article|
130
+ assert_has_xpath(
131
+ '//entry/id', text: "tag:www.example.com,2008-12-29:#{article.abspath}")
132
+ end
133
+ end
134
+
135
+ it 'uses pre-defined ID if specified' do
136
+ with_article(metadata: { 'atom id' => 'use-this-id' }) do
137
+ assert_has_xpath '//entry/id', text: 'use-this-id'
138
+ end
139
+ end
140
+
141
+ it 'specifies date published' do
142
+ with_article do
143
+ assert_has_xpath '//entry/published', text: '2008-12-29T00:00:00+00:00'
144
+ end
145
+ end
146
+
147
+ it 'specifies article categories' do
148
+ with_article_in_category do |article, category|
149
+ assert_has_xpath "//category[@term='#{category.permalink}']"
150
+ end
151
+ end
152
+
153
+ it 'has article content' do
154
+ with_article do
155
+ assert_has_xpath '//entry/content[@type="html"]', text: 'Content'
156
+ end
157
+ end
158
+
159
+ it 'includes hostname in URLs' do
160
+ with_article(content: '[a link](/foo)') do
161
+ url = 'http://www.example.com/foo'
162
+ assert_has_xpath '//entry/content', text: url
163
+ end
164
+ end
165
+
166
+ it 'does not include article heading in content' do
167
+ with_article do |article|
168
+ assert page.has_no_selector?("summary:contains('#{article.heading}')")
169
+ end
170
+ end
171
+
172
+ it 'does not include pages with no date in feed' do
173
+ with_category(path: 'no-date') do
174
+ assert page.has_no_selector?('entry id:contains("no-date")')
175
+ end
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,31 @@
1
+ require 'test_helper'
2
+ require_relative '../../../support/silence_commands_during_tests'
3
+ require_relative '../../../../lib/nesta/commands'
4
+
5
+ Nesta::Commands::Demo::Content.send(:include, SilenceCommandsDuringTests)
6
+
7
+ describe 'nesta demo:content' do
8
+ include TemporaryFiles
9
+
10
+ before do
11
+ Nesta::Commands::Demo::Content.demo_repository = '../../fixtures/demo-content.git'
12
+ end
13
+
14
+ it 'clones the demo repository and configures project to use it' do
15
+ in_temporary_project do
16
+ Nesta::Commands::Demo::Content.new.execute
17
+ assert_exists_in_project 'content-demo/pages/index.haml'
18
+
19
+ yaml = File.read(File.join(project_root, 'config', 'config.yml'))
20
+ assert_match /content: content-demo/, yaml
21
+ end
22
+ end
23
+
24
+ it 'ensures demo repository is ignored by git' do
25
+ in_temporary_project do
26
+ FileUtils.mkdir('.git')
27
+ Nesta::Commands::Demo::Content.new.execute
28
+ assert_match /content-demo/, File.read(project_path('.git/info/exclude'))
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ require 'test_helper'
2
+ require_relative '../../../lib/nesta/commands'
3
+
4
+ describe 'nesta edit' do
5
+ include TestConfiguration
6
+
7
+ after do
8
+ remove_temp_directory
9
+ end
10
+
11
+ it 'launches the editor' do
12
+ ENV['EDITOR'] = 'touch'
13
+ edited_file = 'path/to/page.md'
14
+ with_temp_content_directory do
15
+ FileUtils.mkdir_p(Nesta::Config.page_path(File.dirname(edited_file)))
16
+ command = Nesta::Commands::Edit.new(edited_file)
17
+ command.execute
18
+ assert File.exist?(Nesta::Config.page_path(edited_file)), 'editor not run'
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,120 @@
1
+ require 'test_helper'
2
+ require_relative '../../support/silence_commands_during_tests'
3
+ require_relative '../../../lib/nesta/commands'
4
+
5
+ Nesta::Commands::New.send(:include, SilenceCommandsDuringTests)
6
+
7
+ describe 'nesta new' do
8
+ include TemporaryFiles
9
+
10
+ def gemfile_source
11
+ File.read(project_path('Gemfile'))
12
+ end
13
+
14
+ def rakefile_source
15
+ File.read(project_path('Rakefile'))
16
+ end
17
+
18
+ after do
19
+ remove_temp_directory
20
+ end
21
+
22
+ describe 'without options' do
23
+ it 'creates the content directories' do
24
+ Nesta::Commands::New.new(project_root).execute
25
+ assert_exists_in_project 'content/attachments'
26
+ assert_exists_in_project 'content/pages'
27
+ end
28
+
29
+ it 'creates the home page' do
30
+ Nesta::Commands::New.new(project_root).execute
31
+ assert_exists_in_project 'content/pages/index.haml'
32
+ end
33
+
34
+ it 'creates the rackup file' do
35
+ Nesta::Commands::New.new(project_root).execute
36
+ assert_exists_in_project 'config.ru'
37
+ end
38
+
39
+ it 'creates the config.yml file' do
40
+ Nesta::Commands::New.new(project_root).execute
41
+ assert_exists_in_project 'config/config.yml'
42
+ end
43
+
44
+ it 'creates a Gemfile' do
45
+ Nesta::Commands::New.new(project_root).execute
46
+ assert_exists_in_project 'Gemfile'
47
+ assert_match /gem 'nesta'/, gemfile_source
48
+ end
49
+ end
50
+
51
+ describe 'with --git option' do
52
+ it 'creates a .gitignore file' do
53
+ command = Nesta::Commands::New.new(project_root, 'git' => '')
54
+ command.stub(:run_process, nil) do
55
+ command.execute
56
+ assert_match /\.bundle/, File.read(project_path('.gitignore'))
57
+ end
58
+ end
59
+
60
+ def disabling_git_hooks
61
+ # I (@gma) have got a git repository template setup on my computer
62
+ # containing git hooks that automatically run ctags in a
63
+ # background process whenever I run `git commit`. The hooks are
64
+ # copied into new repositories when I run `git init`.
65
+ #
66
+ # The generation of the ctags file (in a forked process) causes a
67
+ # race condition; sometimes ctags will recreate a test's project
68
+ # folder and git directory after the test's `after` block has
69
+ # deleted it. If the project directory isn't removed after each
70
+ # test, the New command will throw an error in the subsequent
71
+ # test (complaining that the project directory already exists).
72
+ #
73
+ templates = temp_path('git_template')
74
+ FileUtils.mkdir_p(templates)
75
+ ENV['GIT_TEMPLATE_DIR'] = templates
76
+ yield
77
+ ENV.delete('GIT_TEMPLATE_DIR')
78
+ FileUtils.rm_r(templates)
79
+ end
80
+
81
+ it 'creates a git repo' do
82
+ disabling_git_hooks do
83
+ command = Nesta::Commands::New.new(project_root, 'git' => '')
84
+ command.execute
85
+ assert_exists_in_project '.git/config'
86
+ end
87
+ end
88
+
89
+ it 'commits the blank project' do
90
+ disabling_git_hooks do
91
+ command = Nesta::Commands::New.new(project_root, 'git' => '')
92
+ command.execute
93
+ Dir.chdir(project_root) do
94
+ assert_match /Initial commit/, `git log --pretty=oneline | head -n 1`
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ describe 'with --vlad option' do
101
+ it 'adds vlad to Gemfile' do
102
+ Nesta::Commands::New.new(project_root, 'vlad' => '').execute
103
+ assert_match /gem 'vlad', '2.1.0'/, gemfile_source
104
+ assert_match /gem 'vlad-git', '2.2.0'/, gemfile_source
105
+ end
106
+
107
+ it 'configures the vlad rake tasks' do
108
+ Nesta::Commands::New.new(project_root, 'vlad' => '').execute
109
+ assert_exists_in_project 'Rakefile'
110
+ assert_match /require 'vlad'/, rakefile_source
111
+ end
112
+
113
+ it 'creates deploy.rb' do
114
+ Nesta::Commands::New.new(project_root, 'vlad' => '').execute
115
+ assert_exists_in_project 'config/deploy.rb'
116
+ deploy_source = File.read(project_path('config/deploy.rb'))
117
+ assert_match /set :application, 'mysite.com'/, deploy_source
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,128 @@
1
+ require 'test_helper'
2
+ require_relative '../../../../lib/nesta/commands'
3
+
4
+ describe 'nesta plugin:create' do
5
+ include TemporaryFiles
6
+
7
+ def working_directory
8
+ temp_path('plugins')
9
+ end
10
+
11
+ before do
12
+ FileUtils.mkdir_p(working_directory)
13
+ end
14
+
15
+ after do
16
+ remove_temp_directory
17
+ end
18
+
19
+ def plugin_name
20
+ 'my-feature'
21
+ end
22
+
23
+ def gem_name
24
+ "nesta-plugin-#{plugin_name}"
25
+ end
26
+
27
+ def create_plugin(&block)
28
+ Dir.chdir(working_directory) do
29
+ command = Nesta::Commands::Plugin::Create.new(plugin_name)
30
+ command.stub(:run_process, nil) do
31
+ command.execute
32
+ yield
33
+ end
34
+ end
35
+ end
36
+
37
+ def assert_exists_in_plugin(path)
38
+ full_path = File.join(gem_name, path)
39
+ assert File.exist?(full_path), "#{path} not found in plugin"
40
+ end
41
+
42
+ def assert_file_contains(path, pattern)
43
+ assert_match pattern, File.read(File.join(gem_name, path))
44
+ end
45
+
46
+ it "creates the gem's directory" do
47
+ create_plugin { assert File.directory?(gem_name), 'gem directory not found' }
48
+ end
49
+
50
+ it 'creates README.md file' do
51
+ create_plugin { assert_exists_in_plugin('README.md') }
52
+ end
53
+
54
+ it 'includes installation instructions in README.md' do
55
+ create_plugin do
56
+ assert_file_contains('README.md', /echo 'gem "#{gem_name}"' >> Gemfile/)
57
+ end
58
+ end
59
+
60
+ it 'creates .gitignore file' do
61
+ create_plugin { assert_exists_in_plugin('.gitignore') }
62
+ end
63
+
64
+ it 'creates the gemspec' do
65
+ create_plugin do
66
+ gemspec = "#{gem_name}.gemspec"
67
+ assert_exists_in_plugin(gemspec)
68
+ assert_file_contains(gemspec, %r{require "#{gem_name}/version"})
69
+ assert_file_contains(gemspec, %r{Nesta::Plugin::My::Feature::VERSION})
70
+ end
71
+ end
72
+
73
+ it 'creates a Gemfile' do
74
+ create_plugin { assert_exists_in_plugin('Gemfile') }
75
+ end
76
+
77
+ it 'creates Rakefile for packaging the gem' do
78
+ create_plugin { assert_exists_in_plugin('Rakefile') }
79
+ end
80
+
81
+ it "creates default folder for Ruby files" do
82
+ create_plugin do
83
+ code_directory = File.join(gem_name, 'lib', gem_name)
84
+ assert File.directory?(code_directory), 'directory for code not found'
85
+ end
86
+ end
87
+
88
+ it 'creates file required when gem loaded' do
89
+ create_plugin do
90
+ path = "#{File.join('lib', gem_name)}.rb"
91
+ assert_exists_in_plugin(path)
92
+ assert_file_contains(path, %r{require "#{gem_name}/version"})
93
+ end
94
+ end
95
+
96
+ it 'creates version.rb' do
97
+ create_plugin do
98
+ version = File.join('lib', gem_name, 'version.rb')
99
+ assert_exists_in_plugin(version)
100
+ assert_file_contains version, <<-EOF
101
+ module Nesta
102
+ module Plugin
103
+ module My
104
+ module Feature
105
+ VERSION = '0.1.0'
106
+ end
107
+ end
108
+ end
109
+ end
110
+ EOF
111
+ end
112
+ end
113
+
114
+ it 'creates skeleton code for the plugin in init.rb' do
115
+ create_plugin do
116
+ init = File.join('lib', gem_name, 'init.rb')
117
+ assert_exists_in_plugin(init)
118
+
119
+ assert_file_contains init, <<-MODULE
120
+ module Nesta
121
+ module Plugin
122
+ module My::Feature
123
+ MODULE
124
+
125
+ assert_file_contains init, 'helpers Nesta::Plugin::My::Feature::Helpers'
126
+ end
127
+ end
128
+ end