usmu 0.3.1 → 0.3.2

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 (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'))