usmu 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -2
  3. data/.travis.yml +3 -0
  4. data/CHANGELOG.md +21 -0
  5. data/Gemfile +7 -0
  6. data/Guardfile +7 -7
  7. data/README.md +5 -1
  8. data/Rakefile +16 -5
  9. data/lib/usmu.rb +3 -1
  10. data/lib/usmu/configuration.rb +25 -13
  11. data/lib/usmu/deployment.rb +12 -0
  12. data/lib/usmu/deployment/directory_diff.rb +64 -0
  13. data/lib/usmu/deployment/remote_file_interface.rb +25 -0
  14. data/lib/usmu/plugin.rb +5 -1
  15. data/lib/usmu/template/layout.rb +24 -17
  16. data/lib/usmu/version.rb +1 -1
  17. data/{test/spec → spec}/acceptance/full_site_build.feature +2 -2
  18. data/{test/spec → spec}/acceptance/steps/full_site_build_steps.rb +0 -0
  19. data/spec/configuration_spec.rb +257 -0
  20. data/spec/deployment/directory_diff_spec.rb +126 -0
  21. data/{test/spec → spec}/mock/usmu/mock_plugin.rb +0 -0
  22. data/spec/mock/usmu/mock_remote_files.rb +19 -0
  23. data/{test/spec → spec}/plugin/core_spec.rb +0 -0
  24. data/{test/spec → spec}/plugin_spec.rb +0 -0
  25. data/{test/spec → spec}/site_generator_spec.rb +1 -1
  26. data/{test/spec → spec}/spec_helper.rb +18 -4
  27. data/{test/spec → spec}/support/shared_layout.rb +0 -0
  28. data/{test/spec → spec}/template/layout_spec.rb +1 -1
  29. data/{test/spec → spec}/template/page_spec.rb +0 -0
  30. data/{test/spec → spec}/template/static_file_spec.rb +2 -2
  31. data/{test/spec → spec}/ui/console_spec.rb +4 -4
  32. data/{test/expected-site → test-site/content}/.dotfiletest.txt +0 -0
  33. data/{test/site → test-site}/content/css/_partial.scss +0 -0
  34. data/{test/site → test-site}/content/css/app.scss +0 -0
  35. data/{test/site → test-site}/content/default.md +0 -0
  36. data/{test/site → test-site}/content/embedded.md +0 -0
  37. data/{test/site → test-site}/content/embedded.meta.yml +0 -0
  38. data/{test/site → test-site}/content/index.md +0 -0
  39. data/{test/site → test-site}/content/index.meta.yml +0 -0
  40. data/{test/site → test-site}/content/posts/test-post.md +0 -0
  41. data/{test/expected-site → test-site/content}/robots.txt +0 -0
  42. data/{test/site/content → test-site/expected-site}/.dotfiletest.txt +0 -0
  43. data/{test → test-site}/expected-site/css/app.css +0 -0
  44. data/{test → test-site}/expected-site/default.html +0 -0
  45. data/{test → test-site}/expected-site/embedded.html +0 -0
  46. data/{test → test-site}/expected-site/index.html +0 -0
  47. data/{test → test-site}/expected-site/posts/test-post.html +0 -0
  48. data/{test/site/content → test-site/expected-site}/robots.txt +0 -0
  49. data/{test/site → test-site}/includes/footer.meta.yml +0 -0
  50. data/{test/site → test-site}/includes/footer.slim +0 -0
  51. data/{test/site → test-site}/layouts/embedded.meta.yml +0 -0
  52. data/{test/site → test-site}/layouts/embedded.slim +0 -0
  53. data/{test/site → test-site}/layouts/html.slim +0 -0
  54. data/{test/site → test-site}/usmu.yml +0 -0
  55. data/usmu-jruby.gemspec +1 -0
  56. data/usmu.gemspec +1 -2
  57. metadata +73 -105
  58. data/.cane +0 -4
  59. data/.simplecov +0 -4
  60. data/test/spec/configuration_spec.rb +0 -176
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Usmu
3
3
  # The current version string for the gem
4
- VERSION = '0.3.1'
4
+ VERSION = '0.3.2'
5
5
  end
@@ -10,7 +10,7 @@ Feature:
10
10
 
11
11
 
12
12
  Scenario:
13
- Given I have a site at "test/site"
13
+ Given I have a site at "test-site"
14
14
  When I run usmu with the arguments "generate"
15
- Then the directory "test/site/site" should match "test/expected-site"
15
+ Then the directory "test-site/site" should match "test-site/expected-site"
16
16
  And the modification time for the input file "index.md" should match the output file "index.html"
@@ -0,0 +1,257 @@
1
+ require 'usmu/configuration'
2
+
3
+ RSpec.describe Usmu::Configuration do
4
+ let (:configuration_hash) {
5
+ {
6
+ 'source' => 'source',
7
+ 'destination' => 'destination',
8
+ 'layouts' => 'templates',
9
+ 'includes' => 'inc',
10
+ }
11
+ }
12
+ let (:configuration) { Usmu::Configuration.from_hash(configuration_hash, 'test/usmu.yaml') }
13
+ let (:empty_configuration) { Usmu::Configuration.from_hash({}) }
14
+
15
+ context '#initialize' do
16
+ it 'should set class variables correctly' do
17
+ expect(configuration.config_dir).to eq('test')
18
+ expect(configuration.config_file).to eq('test/usmu.yaml')
19
+ expect(configuration.send :config).to eq(configuration_hash)
20
+ expect(configuration.send(:log).class).to eq(Logging::Logger)
21
+ expect(configuration.send(:log).name).to eq(described_class.name)
22
+ end
23
+
24
+ it 'should set config_path to the current directory for a bare filename' do
25
+ configuration = Usmu::Configuration.from_hash(configuration_hash, 'usmu.yaml')
26
+ expect(configuration.config_dir).to eq('.')
27
+ end
28
+
29
+ it 'should set config_dir to nil if no config_path is set' do
30
+ configuration = Usmu::Configuration.from_hash(configuration_hash)
31
+ expect(configuration.config_dir).to eq(nil)
32
+ end
33
+ end
34
+
35
+ context '.from_file' do
36
+ it 'should raise an error if no filename is specified' do
37
+ expect { Usmu::Configuration.from_file(nil) }.to raise_error(ArgumentError, 'File not found: ')
38
+ end
39
+
40
+ it 'should raise an error if file does not exist' do
41
+ expect { Usmu::Configuration.from_file('nonexistent.yml') }.to raise_error(ArgumentError, 'File not found: nonexistent.yml')
42
+ end
43
+
44
+ it 'should pass through the contents of the named file to constructor' do
45
+ allow(YAML).to receive(:load_file).with('usmu.yml').and_return(configuration_hash)
46
+ allow(File).to receive(:exist?).with('usmu.yml').and_return(true)
47
+ expect(Usmu::Configuration).to receive(:new).with(configuration_hash, 'usmu.yml')
48
+ Usmu::Configuration.from_file('usmu.yml')
49
+ expect(@log_output.readline).to eq(" DEBUG Usmu::Configuration : Loading configuration from usmu.yml\n")
50
+ end
51
+ end
52
+
53
+ context '.from_hash' do
54
+ it 'should pass through it\'s arguments through to constructor' do
55
+ expect(Usmu::Configuration).to receive(:new).with(configuration_hash, 'usmu.yml')
56
+ Usmu::Configuration.from_hash(configuration_hash, 'usmu.yml')
57
+ end
58
+
59
+ it 'should have a default of nil for the configuration name' do
60
+ expect(Usmu::Configuration).to receive(:new).with(configuration_hash, nil)
61
+ Usmu::Configuration.from_hash(configuration_hash)
62
+ end
63
+ end
64
+
65
+ context '#source_path' do
66
+ it 'should prepend configuration folder' do
67
+ expect(configuration.source_path).to eq('test/source')
68
+ end
69
+
70
+ it 'should have a default path' do
71
+ expect(empty_configuration.source_path).to eq('src')
72
+ end
73
+ end
74
+
75
+ context '#destination_path' do
76
+ it 'should prepend configuration folder' do
77
+ expect(configuration.destination_path).to eq('test/destination')
78
+ end
79
+
80
+ it 'should have a default path' do
81
+ expect(empty_configuration.destination_path).to eq('site')
82
+ end
83
+ end
84
+
85
+ context '#layouts_path' do
86
+ it 'should prepend configuration folder' do
87
+ expect(configuration.layouts_path).to eq('test/templates')
88
+ end
89
+
90
+ it 'should have a default path' do
91
+ expect(empty_configuration.layouts_path).to eq('layouts')
92
+ end
93
+ end
94
+
95
+ context '#includes_path' do
96
+ it 'should prepend configuration folder' do
97
+ expect(configuration.includes_path).to eq('test/inc')
98
+ end
99
+
100
+ it 'should have a default path' do
101
+ expect(empty_configuration.includes_path).to eq('includes')
102
+ end
103
+ end
104
+
105
+ context '#source_files' do
106
+ it 'should return a list of source files' do
107
+ allow(Dir).to receive(:'[]').with('src/**/{*,.??*}').and_return(%w(src/index.md src/test.md))
108
+ expect(empty_configuration.source_files).to eq(%w(index.md test.md))
109
+ end
110
+ end
111
+
112
+ context '#layouts_files' do
113
+ it 'should have a list of layouts files' do
114
+ allow(Dir).to receive(:'[]').with('layouts/**/{*,.??*}').and_return(%w(layouts/html.slim layouts/page.slim))
115
+ expect(empty_configuration.layouts_files).to eq(%w(html.slim page.slim))
116
+ end
117
+
118
+ it 'should ignore metadata files in the layouts folder' do
119
+ allow(Dir).to receive(:'[]').with('layouts/**/{*,.??*}').and_return(%w(layouts/html.slim layouts/html.meta.yml layouts/page.slim))
120
+ expect(empty_configuration.layouts_files).to eq(%w(html.slim page.slim))
121
+ end
122
+ end
123
+
124
+ context '#includes_files' do
125
+ it 'should have a list of includes files' do
126
+ allow(Dir).to receive(:'[]').with('includes/**/{*,.??*}').and_return(%w(includes/footer.slim))
127
+ expect(empty_configuration.includes_files).to eq(%w(footer.slim))
128
+ end
129
+
130
+ it 'should ignore metadata files in the includes folder' do
131
+ allow(Dir).to receive(:'[]').with('includes/**/{*,.??*}').and_return(%w(includes/footer.slim includes/footer.meta.yml))
132
+ expect(empty_configuration.includes_files).to eq(%w(footer.slim))
133
+ end
134
+ end
135
+
136
+ context '#exclude' do
137
+ it 'returns the exclude option in the configuration array' do
138
+ expect(Usmu::Configuration.from_hash({'exclude' => ['test.md']}).exclude).to eq(['test.md'])
139
+ end
140
+
141
+ it 'has a default value of an empty array' do
142
+ expect(empty_configuration.exclude).to eq([])
143
+ end
144
+ end
145
+
146
+ context '#[]' do
147
+ it 'should remember arbitrary configuration' do
148
+ configuration = Usmu::Configuration.from_hash({:test => 'foo'})
149
+ expect(configuration[:test]).to eq('foo')
150
+ end
151
+
152
+ it 'should allow indexing the configuration file' do
153
+ configuration = Usmu::Configuration.from_hash({test: 'foo'})
154
+ expect(configuration[:test]).to eq('foo')
155
+ end
156
+
157
+ it 'should allow indexing the configuration file with a default value' do
158
+ configuration = Usmu::Configuration.from_hash({test: 'foo'})
159
+ expect(configuration[:bar, default: 'baz']).to eq('baz')
160
+ end
161
+
162
+ it 'should allow indexing the configuration file using a path of indices' do
163
+ configuration = Usmu::Configuration.from_hash({test: {bar: 'foo'}})
164
+ expect(configuration[:test, :bar]).to eq('foo')
165
+ end
166
+
167
+ it 'should return nil if the element does not exist' do
168
+ expect(empty_configuration[:test]).to eq(nil)
169
+ end
170
+ end
171
+
172
+ context '#get_path' do
173
+ it 'should return input if config_dir is nil' do
174
+ expect(empty_configuration.send :get_path, 'source').to eq('source')
175
+ end
176
+
177
+ it 'should prepend input with config_dir if it is not nil' do
178
+ expect(configuration.send :get_path, 'source').to eq('test/source')
179
+ end
180
+ end
181
+
182
+ context '#get_files' do
183
+ it 'should ignore metadata files' do
184
+ allow(Dir).to receive(:'[]').with('src/**/{*,.??*}').and_return(%w(src/index.md src/index.meta.yml src/test.md))
185
+ expect(empty_configuration.send :get_files, 'src').to eq(%w(index.md test.md))
186
+ end
187
+
188
+ it 'should not return folders' do
189
+ allow(File).to receive(:directory?).and_return(false)
190
+ allow(File).to receive(:directory?).with('src/test').and_return(true)
191
+ allow(Dir).to receive(:'[]').with('src/**/{*,.??*}').and_return(%w(src/index.md src/index.meta.yml src/test src/test/test.md))
192
+ expect(empty_configuration.send :get_files, 'src').to eq(%w(index.md test/test.md))
193
+ end
194
+
195
+ it 'should exclude files' do
196
+ allow(Dir).to receive(:'[]').with('src/**/{*,.??*}').and_return(%w(src/foo.md))
197
+ allow(configuration).to receive(:excluded?).with('foo.md').and_return(true)
198
+ expect(configuration.send :get_files, 'src').to eq([])
199
+ end
200
+ end
201
+
202
+ context '#excluded?' do
203
+ it 'should ignore files in folders if a trailing "/" is used' do
204
+ configuration = Usmu::Configuration.from_hash({'exclude' => ['test/']})
205
+ expect(configuration.send :excluded?, 'test/foo/test.md').to eq(true)
206
+ end
207
+
208
+ it 'should honor *' do
209
+ configuration = Usmu::Configuration.from_hash({'exclude' => ['*/foo.md']})
210
+ expect(configuration.send :excluded?, 'test/foo.md').to eq(true)
211
+ end
212
+
213
+ it 'should ignore folders specified with * without a trailing /' do
214
+ configuration = Usmu::Configuration.from_hash({'exclude' => ['*']})
215
+ expect(configuration.send :excluded?, 'test/foo.md').to eq(false)
216
+ end
217
+
218
+ it 'should ignore files inside folders specified via globs with trailing "/"' do
219
+ configuration = Usmu::Configuration.from_hash({'exclude' => ['test/*/']})
220
+ expect(configuration.send :excluded?, 'test/foot/foo.md').to eq(true)
221
+ end
222
+
223
+ it 'should honor **' do
224
+ configuration = Usmu::Configuration.from_hash({'exclude' => ['**/foo.md']})
225
+ expect(configuration.send :excluded?, 'test/foo/foo.md').to eq(true)
226
+ end
227
+
228
+ it 'should honor []' do
229
+ configuration = Usmu::Configuration.from_hash({'exclude' => ['[ab].md']})
230
+ expect(configuration.send :excluded?, 'a.md').to eq(true)
231
+ expect(configuration.send :excluded?, 'b.md').to eq(true)
232
+ expect(configuration.send :excluded?, 'index.md').to eq(false)
233
+ end
234
+
235
+ # FNM_EXTGLOB is supported from MRI 2.0 onwards. We also support the 1.9.3 ABI for JRuby and Rubinius sake. Only
236
+ # run this test if it's possible for it to pass.
237
+ if defined?(File::FNM_EXTGLOB)
238
+ it 'should honor {a,b}' do
239
+ configuration = Usmu::Configuration.from_hash({'exclude' => ['{a,b}.md']})
240
+ expect(configuration.send :excluded?, 'a.md').to eq(true)
241
+ expect(configuration.send :excluded?, 'b.md').to eq(true)
242
+ expect(configuration.send :excluded?, 'index.md').to eq(false)
243
+ end
244
+ end
245
+
246
+ it 'should honor \\ as an escape' do
247
+ configuration = Usmu::Configuration.from_hash({'exclude' => ['\*.md']})
248
+ expect(configuration.send :excluded?, '*.md').to eq(true)
249
+ expect(configuration.send :excluded?, 'index.md').to eq(false)
250
+ end
251
+
252
+ it 'should honor ?' do
253
+ configuration = Usmu::Configuration.from_hash({'exclude' => ['?.md']})
254
+ expect(configuration.send :excluded?, 'a.md').to eq(true)
255
+ end
256
+ end
257
+ end
@@ -0,0 +1,126 @@
1
+ require 'usmu/deployment/directory_diff'
2
+ require 'usmu/mock_remote_files'
3
+ require 'ostruct'
4
+ require 'digest'
5
+
6
+ RSpec.describe Usmu::Deployment::DirectoryDiff do
7
+ context '#get_diffs' do
8
+ let (:configuration) { Usmu::Configuration.from_hash({}) }
9
+ let (:file) { 'Hello world!' }
10
+ let (:now) { Time.at(1420875742) }
11
+
12
+ before do
13
+ allow(File).to receive(:stat).with('site/index.html').and_return(OpenStruct.new({mtime: now}))
14
+ allow(File).to receive(:read).with('site/index.html').and_return(file)
15
+ end
16
+
17
+ it 'returns remote only files' do
18
+ allow(Dir).to receive(:'[]').with('site/**/{*,.??*}').and_return(%w())
19
+ remote_files = Usmu::MockRemoteFiles.new(
20
+ {
21
+ 'index.html' => {
22
+ :mtime => now + 100,
23
+ },
24
+ }
25
+ )
26
+ diff = Usmu::Deployment::DirectoryDiff.new(configuration, remote_files)
27
+
28
+ expect(diff.get_diffs).to eq({remote: ['index.html'], local: [], updated: []})
29
+ end
30
+
31
+ it 'returns local only files' do
32
+ allow(Dir).to receive(:'[]').with('site/**/{*,.??*}').and_return(%w(site/index.html))
33
+ remote_files = Usmu::MockRemoteFiles.new({})
34
+ diff = Usmu::Deployment::DirectoryDiff.new(configuration, remote_files)
35
+
36
+ expect(diff.get_diffs).to eq({local: ['index.html'], remote: [], updated: []})
37
+ end
38
+
39
+ it 'hides identical files' do
40
+ allow(Dir).to receive(:'[]').with('site/**/{*,.??*}').and_return(%w(site/index.html))
41
+ remote_files = Usmu::MockRemoteFiles.new(
42
+ {
43
+ 'index.html' => {
44
+ :mtime => now,
45
+ },
46
+ }
47
+ )
48
+ diff = Usmu::Deployment::DirectoryDiff.new(configuration, remote_files)
49
+
50
+ expect(diff.get_diffs).to eq({local: [], remote: [], updated: []})
51
+ end
52
+
53
+ it 'hides files newer on remote' do
54
+ allow(Dir).to receive(:'[]').with('site/**/{*,.??*}').and_return(%w(site/index.html))
55
+ remote_files = Usmu::MockRemoteFiles.new(
56
+ {
57
+ 'index.html' => {
58
+ :mtime => now + 100,
59
+ },
60
+ }
61
+ )
62
+ diff = Usmu::Deployment::DirectoryDiff.new(configuration, remote_files)
63
+
64
+ expect(diff.get_diffs).to eq({local: [], remote: [], updated: []})
65
+ end
66
+
67
+ it 'returns files newer on local' do
68
+ allow(Dir).to receive(:'[]').with('site/**/{*,.??*}').and_return(%w(site/index.html))
69
+ remote_files = Usmu::MockRemoteFiles.new(
70
+ {
71
+ 'index.html' => {
72
+ :mtime => now - 100,
73
+ },
74
+ }
75
+ )
76
+ diff = Usmu::Deployment::DirectoryDiff.new(configuration, remote_files)
77
+
78
+ expect(diff.get_diffs).to eq({local: [], remote: [], updated: ['index.html']})
79
+ end
80
+
81
+ it 'returns files with different md5 hashes' do
82
+ allow(Dir).to receive(:'[]').with('site/**/{*,.??*}').and_return(%w(site/index.html))
83
+ remote_files = Usmu::MockRemoteFiles.new(
84
+ {
85
+ 'index.html' => {
86
+ :mtime => now,
87
+ :md5 => Digest::MD5.hexdigest(file + 'foo'),
88
+ },
89
+ }
90
+ )
91
+ diff = Usmu::Deployment::DirectoryDiff.new(configuration, remote_files)
92
+
93
+ expect(diff.get_diffs).to eq({local: [], remote: [], updated: ['index.html']})
94
+ end
95
+
96
+ it 'returns files with different sha1 hashes' do
97
+ allow(Dir).to receive(:'[]').with('site/**/{*,.??*}').and_return(%w(site/index.html))
98
+ remote_files = Usmu::MockRemoteFiles.new(
99
+ {
100
+ 'index.html' => {
101
+ :mtime => now,
102
+ :sha1 => Digest::SHA1.hexdigest(file + 'foo'),
103
+ },
104
+ }
105
+ )
106
+ diff = Usmu::Deployment::DirectoryDiff.new(configuration, remote_files)
107
+
108
+ expect(diff.get_diffs).to eq({local: [], remote: [], updated: ['index.html']})
109
+ end
110
+
111
+ it 'returns files with different hashes and newer remote file' do
112
+ allow(Dir).to receive(:'[]').with('site/**/{*,.??*}').and_return(%w(site/index.html))
113
+ remote_files = Usmu::MockRemoteFiles.new(
114
+ {
115
+ 'index.html' => {
116
+ :mtime => now + 100,
117
+ :md5 => Digest::MD5.hexdigest(file + 'foo'),
118
+ },
119
+ }
120
+ )
121
+ diff = Usmu::Deployment::DirectoryDiff.new(configuration, remote_files)
122
+
123
+ expect(diff.get_diffs).to eq({local: [], remote: [], updated: ['index.html']})
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,19 @@
1
+ require 'usmu/deployment/remote_file_interface'
2
+
3
+ module Usmu
4
+ class MockRemoteFiles
5
+ include Usmu::Deployment::RemoteFileInterface
6
+
7
+ def initialize(files)
8
+ @files = files
9
+ end
10
+
11
+ def files_list
12
+ @files.keys
13
+ end
14
+
15
+ def stat(filename)
16
+ @files[filename]
17
+ end
18
+ end
19
+ end
File without changes
File without changes
@@ -1,7 +1,7 @@
1
1
  require 'usmu/site_generator'
2
2
 
3
3
  RSpec.describe Usmu::SiteGenerator do
4
- let(:configuration) { Usmu::Configuration.from_file('test/site/usmu.yml') }
4
+ let(:configuration) { Usmu::Configuration.from_file('test-site/usmu.yml') }
5
5
  let(:generator) { Usmu::SiteGenerator.new(configuration) }
6
6
 
7
7
  it 'should have layouts' do
@@ -1,7 +1,12 @@
1
- require 'simplecov'
2
- SimpleCov.command_name 'RSpec'
1
+ begin
2
+ require 'codeclimate-test-reporter'
3
+ CodeClimate::TestReporter.start
4
+ rescue LoadError
5
+ end
3
6
 
4
7
  require 'logging'
8
+ require 'rspec/logging_helper'
9
+ require 'timeout'
5
10
 
6
11
  # This file was generated by the `rspec --init` command. Conventionally, all
7
12
  # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
@@ -87,10 +92,19 @@ RSpec.configure do |config|
87
92
  # test failures related to randomization by passing the same `--seed` value
88
93
  # as the one that triggered the failure.
89
94
  Kernel.srand config.seed
95
+
96
+ # Set a timeout on individual tests
97
+ config.around(:each) do |example|
98
+ Timeout.timeout(5, &example)
99
+ end
100
+
101
+ # Configure RSpec to capture log messages for tests.
102
+ include RSpec::LoggingHelper
103
+ config.capture_log_messages
90
104
  end
91
105
 
92
106
  # Load turnip step definitions
93
- Dir['test/spec/**/*_steps.rb'].each {|f| require f[10..f.length] }
107
+ Dir['spec/**/*_steps.rb'].each {|f| require f[5..f.length] }
94
108
 
95
109
  # Allow loading of mocks
96
- $LOAD_PATH.unshift(File.realpath('./test/spec/mock'))
110
+ $LOAD_PATH.unshift(File.realpath('spec/mock'))