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
@@ -70,7 +70,7 @@ module Nesta
70
70
  end
71
71
 
72
72
  def current_item?(item)
73
- request.path == item.abspath
73
+ request.path_info == item.abspath
74
74
  end
75
75
 
76
76
  def current_menu_item_class
@@ -1,3 +1,3 @@
1
1
  module Nesta
2
- VERSION = '0.11.1'
2
+ VERSION = '0.12.0'
3
3
  end
@@ -24,8 +24,6 @@ Implementing your site's design is easy, but Nesta also has a small
24
24
  selection of themes to choose from.
25
25
  EOF
26
26
 
27
- s.rubyforge_project = "nesta"
28
-
29
27
  s.files = `git ls-files`.split("\n")
30
28
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
31
29
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
@@ -33,19 +31,20 @@ EOF
33
31
 
34
32
  s.add_dependency('haml', '>= 3.1')
35
33
  s.add_dependency('haml-contrib', '>= 1.0')
36
- s.add_dependency('rack', '>= 1.3')
34
+ s.add_dependency('rack', '~> 2.0')
37
35
  s.add_dependency('rdiscount', '~> 2.1')
38
36
  s.add_dependency('RedCloth', '~> 4.2')
39
- s.add_dependency('sass', '>= 3.1')
40
- s.add_dependency('sinatra', '~> 1.4')
41
- s.add_dependency('tilt', '~> 1.4')
37
+ s.add_dependency('sassc', '>= 2.2')
38
+ s.add_dependency('sinatra', '~> 2.0')
39
+ s.add_dependency('tilt', '~> 2.0')
42
40
 
43
41
  # Useful in development
44
- s.add_development_dependency('mr-sparkle', '>= 0.0.2')
42
+ s.add_development_dependency('mr-sparkle')
45
43
 
46
44
  # Test libraries
47
- s.add_development_dependency('rack-test', '0.6.1')
48
- s.add_development_dependency('rspec', '~> 2.14.0')
49
- s.add_development_dependency('test-unit', '1.2.3')
50
- s.add_development_dependency('webrat', '~> 0.7.3')
45
+ s.add_development_dependency('byebug')
46
+ s.add_development_dependency('capybara', '~> 2.0')
47
+ s.add_development_dependency('minitest', '~> 5.0')
48
+ s.add_development_dependency('minitest-reporters')
49
+ s.add_development_dependency('rake')
51
50
  end
@@ -8,7 +8,7 @@ subtitle: "(change this text in config/config.yml)"
8
8
  # Atom feed. Specify at least one of name, uri or email, and Nesta will
9
9
  # include it in your feed. See the Atom spec for more info:
10
10
  #
11
- # http://www.atomenabled.org/developers/syndication/atom-format-spec.php#element.feed
11
+ # https://tools.ietf.org/html/rfc4287#section-4.1.1
12
12
  #
13
13
  # author:
14
14
  # name: Your Name
@@ -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