massimo 0.7.5 → 0.8.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 (48) hide show
  1. data/.document +5 -0
  2. data/.gitignore +6 -0
  3. data/Gemfile +2 -0
  4. data/Gemfile.lock +88 -0
  5. data/README.md +3 -1
  6. data/Rakefile +8 -0
  7. data/bin/massimo +1 -17
  8. data/lib/massimo/cli.rb +63 -0
  9. data/lib/massimo/config.rb +8 -5
  10. data/lib/massimo/javascript.rb +10 -2
  11. data/lib/massimo/reloader.rb +37 -0
  12. data/lib/massimo/site.rb +24 -21
  13. data/lib/massimo/templates/site/config.rb +18 -0
  14. data/lib/massimo/templates/site/javascripts/main.js +0 -0
  15. data/lib/massimo/templates/site/pages/index.erb +5 -0
  16. data/lib/massimo/templates/site/public/.empty_directory +0 -0
  17. data/lib/massimo/templates/site/stylesheets/main.scss +0 -0
  18. data/lib/massimo/templates/site/views/layouts/main.erb +12 -0
  19. data/lib/massimo/ui.rb +2 -2
  20. data/lib/massimo/version.rb +1 -1
  21. data/lib/massimo/watcher.rb +22 -7
  22. data/lib/massimo.rb +3 -11
  23. data/massimo.gemspec +40 -0
  24. data/spec/massimo/cli_spec.rb +254 -0
  25. data/spec/massimo/config_spec.rb +97 -0
  26. data/spec/massimo/helpers_spec.rb +26 -0
  27. data/spec/massimo/javascript_spec.rb +120 -0
  28. data/spec/massimo/massimo_spec.rb +23 -0
  29. data/spec/massimo/page_spec.rb +224 -0
  30. data/spec/massimo/reloader_spec.rb +135 -0
  31. data/spec/massimo/resource_spec.rb +208 -0
  32. data/spec/massimo/server_spec.rb +35 -0
  33. data/spec/massimo/site_spec.rb +299 -0
  34. data/spec/massimo/stylesheet_spec.rb +77 -0
  35. data/spec/massimo/ui_spec.rb +109 -0
  36. data/spec/massimo/view_spec.rb +46 -0
  37. data/spec/massimo/watcher_spec.rb +122 -0
  38. data/spec/spec_helper.rb +65 -0
  39. data/spec/support/matchers/be_a_directory_matcher.rb +5 -0
  40. data/spec/support/matchers/be_a_file_matcher.rb +26 -0
  41. metadata +74 -20
  42. data/lib/massimo/commands/base.rb +0 -85
  43. data/lib/massimo/commands/build.rb +0 -19
  44. data/lib/massimo/commands/generate.rb +0 -62
  45. data/lib/massimo/commands/help.rb +0 -34
  46. data/lib/massimo/commands/server.rb +0 -24
  47. data/lib/massimo/commands/version.rb +0 -9
  48. data/lib/massimo/commands/watch.rb +0 -16
@@ -0,0 +1,254 @@
1
+ require 'spec_helper'
2
+
3
+ describe Massimo::CLI do
4
+ def massimo(args)
5
+ Massimo::CLI.start(args.split(' '))
6
+ end
7
+
8
+ describe '#site' do
9
+ before :each do
10
+ stub(Massimo::Watcher).start { is_a(Massimo::Site) }
11
+ end
12
+
13
+ context "with '--environment staging'" do
14
+ it 'sets the environment option' do
15
+ massimo 'watch --environment staging'
16
+ Massimo.config.environment.should == 'staging'
17
+ end
18
+ end
19
+
20
+ context "with '--production'" do
21
+ it 'sets the environment option' do
22
+ massimo 'watch --production'
23
+ Massimo.config.environment.should == 'production'
24
+ end
25
+ end
26
+
27
+ context "with '--config_path my_site.rb'" do
28
+ it 'sets the config_path option' do
29
+ massimo 'watch --config_path my_site.rb'
30
+ Massimo.config.config_path.should == File.expand_path('my_site.rb')
31
+ end
32
+ end
33
+
34
+ context "with '--source_path source'" do
35
+ it 'sets the source_path option' do
36
+ massimo 'watch --source_path source'
37
+ Massimo.config.source_path.should == File.expand_path('source')
38
+ end
39
+ end
40
+
41
+ context "with '--output_path output'" do
42
+ it 'sets the output_path option' do
43
+ massimo 'watch --output_path output'
44
+ Massimo.config.output_path.should == File.expand_path('output')
45
+ end
46
+ end
47
+ end
48
+
49
+ describe '#build' do
50
+ it 'builds the site' do
51
+ silence(:stdout) do
52
+ mock(Kernel).exit(true)
53
+ mock.instance_of(Massimo::CLI).site { mock!(:process) }
54
+ massimo 'build'
55
+ end
56
+ end
57
+
58
+ context 'with errors' do
59
+ it "exits with status code of 1" do
60
+ silence(:stdout) do
61
+ mock(Kernel).exit(false)
62
+ mock.instance_of(Massimo::CLI).site do
63
+ mock!(:process) { raise 'Error!' }
64
+ end
65
+ massimo 'build'
66
+ end
67
+ end
68
+ end
69
+
70
+ context "with mapping 'b'" do
71
+ it 'builds the site' do
72
+ silence(:stdout) do
73
+ mock(Kernel).exit(true)
74
+ mock.instance_of(Massimo::CLI).site { mock!(:process) }
75
+ massimo 'b'
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ describe '#generate' do
82
+ it 'creates a massimo site directory' do
83
+ within_construct do |c|
84
+ massimo 'generate my_site'
85
+ 'my_site'.should be_a_directory
86
+ end
87
+ end
88
+
89
+ it 'creates resource directories' do
90
+ within_construct do |c|
91
+ massimo 'generate my_site'
92
+ 'my_site/pages'.should be_a_directory
93
+ 'my_site/views'.should be_a_directory
94
+ 'my_site/javascripts'.should be_a_directory
95
+ 'my_site/stylesheets'.should be_a_directory
96
+ end
97
+ end
98
+
99
+ it 'creates an output path' do
100
+ within_construct do |c|
101
+ massimo 'generate my_site'
102
+ 'my_site/public'.should be_a_directory
103
+ end
104
+ end
105
+
106
+ it 'creates an default index page' do
107
+ within_construct do |c|
108
+ massimo 'generate my_site'
109
+ content = <<-EOS.unindent
110
+ ---
111
+ title: Home Page
112
+ ---
113
+ <h1><%= title %></h1>
114
+ <p>Find me in pages/index.erb</p>
115
+ EOS
116
+ 'my_site/pages/index.erb'.should be_a_file.with_content(content)
117
+ end
118
+ end
119
+
120
+ it 'creates a default layout' do
121
+ within_construct do |c|
122
+ massimo 'generate my_site'
123
+ content = <<-EOS.unindent
124
+ <!doctype html>
125
+ <html>
126
+ <head lang="en">
127
+ <meta charset="utf-8">
128
+ <title><%= page.title %></title>
129
+ <%= stylesheet_link_tag 'main' %>
130
+ <%= javascript_include_tag 'main' %>
131
+ </head>
132
+ <body>
133
+ <%= yield %>
134
+ </body>
135
+ </html>
136
+ EOS
137
+ 'my_site/views/layouts/main.erb'.should be_a_file.with_content(content)
138
+ end
139
+ end
140
+
141
+ it 'creates a default javascript file' do
142
+ within_construct do |c|
143
+ massimo 'generate my_site'
144
+ 'my_site/javascripts/main.js'.should be_a_file
145
+ end
146
+ end
147
+
148
+ it 'creates a default stylesheet file' do
149
+ within_construct do |c|
150
+ massimo 'generate my_site'
151
+ 'my_site/stylesheets/main.scss'.should be_a_file
152
+ end
153
+ end
154
+
155
+ it 'creates a default config file' do
156
+ within_construct do |c|
157
+ massimo 'generate my_site'
158
+ content = <<-EOS.unindent
159
+ require 'sass'
160
+ require 'sprockets'
161
+
162
+ # This is an example configuration File
163
+ # Look here for all the available options:
164
+ # http://petebrowne.github.com/massimo/configuration/
165
+
166
+ if config.environment.production?
167
+ # Use JSMin for javascript compression
168
+ # config.javascripts_compressor = :min
169
+
170
+ # Compress the output of Sass stylesheets
171
+ # config.sass = { :style => :compressed }
172
+ end
173
+
174
+ helpers do
175
+ # Define helper methods here
176
+ end
177
+ EOS
178
+ 'my_site/config.rb'.should be_a_file.with_content(content)
179
+ end
180
+ end
181
+
182
+ context "with mapping 'g'" do
183
+ it 'creates a massimo site directory' do
184
+ within_construct do |c|
185
+ silence(:stdout) do
186
+ massimo 'g my_site'
187
+ 'my_site'.should be_a_directory
188
+ end
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+ describe '#server' do
195
+ it 'starts a server at port 3000' do
196
+ silence(:stdout) do
197
+ mock(Massimo::Server).start is_a(Massimo::Site), 3000
198
+ massimo 'server'
199
+ end
200
+ end
201
+
202
+ context 'with a given port number' do
203
+ it 'starts a server at the given port' do
204
+ silence(:stdout) do
205
+ mock(Massimo::Server).start is_a(Massimo::Site), 1234
206
+ massimo 'server 1234'
207
+ end
208
+ end
209
+ end
210
+
211
+ context "with mapping 's'" do
212
+ it 'starts a server at port 3000' do
213
+ silence(:stdout) do
214
+ mock(Massimo::Server).start is_a(Massimo::Site), 3000
215
+ massimo 's'
216
+ end
217
+ end
218
+ end
219
+ end
220
+
221
+ describe '#watch' do
222
+ it 'watches the files for changes' do
223
+ silence(:stdout) do
224
+ mock(Massimo::Watcher).start is_a(Massimo::Site)
225
+ massimo 'watch'
226
+ end
227
+ end
228
+
229
+ context "with mapping 'w'" do
230
+ it 'watches the files for changes' do
231
+ silence(:stdout) do
232
+ mock(Massimo::Watcher).start is_a(Massimo::Site)
233
+ massimo 'w'
234
+ end
235
+ end
236
+ end
237
+ end
238
+
239
+ describe '#version' do
240
+ it 'prints out the current version number' do
241
+ output = capture(:stdout) { Massimo::CLI.start(%w(version)) }
242
+ output.strip.should == Massimo::VERSION
243
+ end
244
+
245
+ %w(v -v --version).each do |mapping|
246
+ context "with mapping '#{mapping}'" do
247
+ it 'prints out the current version number' do
248
+ output = capture(:stdout) { Massimo::CLI.start(%W(#{mapping})) }
249
+ output.strip.should == Massimo::VERSION
250
+ end
251
+ end
252
+ end
253
+ end
254
+ end
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+
3
+ describe Massimo::Config do
4
+ its(:config_path) { should == File.expand_path('config.rb') }
5
+ its(:source_path) { should == File.expand_path('.') }
6
+ its(:output_path) { should == File.expand_path('public') }
7
+ its(:environment) { should == 'development' }
8
+ its(:resources_path) { should == '.' }
9
+ its(:base_url) { should == '/' }
10
+ its(:resources_url) { should == '/' }
11
+ its(:javascripts_url) { should == '/javascripts' }
12
+ its(:stylesheets_url) { should == '/stylesheets' }
13
+
14
+ describe '#initialize' do
15
+ context 'with an options hash' do
16
+ it 'should set the given attributes' do
17
+ config = Massimo::Config.new :source_path => 'source/path'
18
+ config.source_path.should == File.expand_path('source/path')
19
+ end
20
+ end
21
+ end
22
+
23
+ describe '#path_for' do
24
+ it 'should read the configured option' do
25
+ config = Massimo::Config.new :pages_path => 'pages/path'
26
+ config.path_for(:pages).should == File.expand_path('pages/path')
27
+ end
28
+
29
+ it 'should default to a path in the #source_path' do
30
+ Massimo::Config.new.path_for(:pages).should == File.expand_path('pages')
31
+ end
32
+ end
33
+
34
+ describe '#url_for' do
35
+ it 'should read the configured option' do
36
+ config = Massimo::Config.new :pages_url => '/pages'
37
+ config.url_for(:pages).should == '/pages'
38
+ end
39
+
40
+ it "should default to '/'" do
41
+ Massimo::Config.new.url_for(:users).should == '/'
42
+ end
43
+
44
+ context 'with a custom #base_url' do
45
+ it 'should prepend the #base_url' do
46
+ config = Massimo::Config.new :base_url => '/blog'
47
+ config.url_for(:stylesheets).should == '/blog/stylesheets'
48
+ end
49
+ end
50
+ end
51
+
52
+ describe '#files_in' do
53
+ it 'should find each file in the given resource dir' do
54
+ within_construct do |c|
55
+ c.file 'lib/some_file.rb'
56
+ c.file 'lib/another_file.txt'
57
+ files = Massimo::Config.new.files_in(:lib).map { |file| File.basename(file) }
58
+ files.should =~ %w( some_file.rb another_file.txt )
59
+ end
60
+ end
61
+
62
+ it 'should not find directories' do
63
+ within_construct do |c|
64
+ c.directory 'pages/some_dir'
65
+ files = Massimo::Config.new.files_in(:pages)
66
+ files.should_not include(File.expand_path('pages/some_dir'))
67
+ end
68
+ end
69
+
70
+ it 'should find files with the given extension' do
71
+ within_construct do |c|
72
+ c.file 'lib/some_file.rb'
73
+ c.file 'lib/another_file.txt'
74
+ files = Massimo::Config.new.files_in(:lib, 'rb')
75
+ files.should_not include(File.expand_path('lib/another_file.txt'))
76
+ end
77
+ end
78
+ end
79
+
80
+ describe '#options_for' do
81
+ it 'should return the options set for the given name' do
82
+ config = Massimo::Config.new(:sass => { :style => :compressed })
83
+ config.options_for(:sass).should == { :style => :compressed }
84
+ end
85
+
86
+ it 'should return an empty hash if the options have not been set' do
87
+ Massimo::Config.new.options_for(:sass).should == {}
88
+ end
89
+ end
90
+
91
+ describe '#environment' do
92
+ it 'should be a StringInquirer' do
93
+ config = Massimo::Config.new :environment => 'production'
94
+ config.environment.should be_an_instance_of(ActiveSupport::StringInquirer)
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Massimo::Helpers do
4
+ it { should include(SinatraMore::OutputHelpers) }
5
+ it { should include(SinatraMore::TagHelpers) }
6
+ it { should include(SinatraMore::AssetTagHelpers) }
7
+ it { should include(SinatraMore::FormHelpers) }
8
+ it { should include(SinatraMore::FormatHelpers) }
9
+
10
+ let(:helpers) { Object.new.extend(Massimo::Helpers) }
11
+
12
+ describe '#render' do
13
+ it 'should render a view with the given locals' do
14
+ with_file 'views/partial.haml', '= local' do
15
+ helpers.render('partial', :local => 'Local').should == "Local\n"
16
+ end
17
+ end
18
+ end
19
+
20
+ describe '#site' do
21
+ it 'should return the current site instance' do
22
+ site = Massimo::Site.new
23
+ helpers.site.should === site
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,120 @@
1
+ require 'spec_helper'
2
+
3
+ describe Massimo::Javascript do
4
+ context 'with normal .js files' do
5
+ let(:javascript) { Massimo::Javascript.new 'javascripts/main.js' }
6
+
7
+ it 'copies content' do
8
+ with_file 'javascripts/main.js', 'var number = 42;' do
9
+ javascript.render.should == "var number = 42;"
10
+ end
11
+ end
12
+
13
+ it 'concats using Sprockets' do
14
+ within_construct do |c|
15
+ c.file 'javascripts/main.js', '//= require "_plugin.js"'
16
+ c.file 'javascripts/_plugin.js', 'var number = 42;'
17
+ javascript.render.should == "var number = 42;"
18
+ end
19
+ end
20
+ end
21
+
22
+ context 'with .coffee scripts' do
23
+ let(:javascript) { Massimo::Javascript.new 'javascripts/main.coffee' }
24
+
25
+ it 'renders using CoffeeScript' do
26
+ with_file 'javascripts/main.coffee', 'number: 42' do
27
+ mock(CoffeeScript).compile('number: 42', {}) { '' }
28
+ javascript.render
29
+ end
30
+ end
31
+
32
+ it 'outputs .js files' do
33
+ with_file 'javascripts/main.coffee' do
34
+ javascript.output_path.extname.should == '.js'
35
+ end
36
+ end
37
+ end
38
+
39
+ context 'with compression' do
40
+ let(:javascript) { Massimo::Javascript.new 'javascripts/main.js' }
41
+ let(:code) { "function addTwo(number) { return number + 2; }\n" }
42
+
43
+ context 'using :min' do
44
+ it 'compresses using JSMin' do
45
+ Massimo.config.javascripts_compressor = :min
46
+ with_file 'javascripts/main.js', code do
47
+ mock(JSMin).minify(code) { '' }
48
+ javascript.render
49
+ end
50
+ end
51
+ end
52
+
53
+ context 'using :pack' do
54
+ it 'compresses using Packr' do
55
+ Massimo.config.javascripts_compressor = :pack
56
+ with_file 'javascripts/main.js', code do
57
+ mock(Packr).pack(code, :shrink_vars => true) { '' }
58
+ javascript.render
59
+ end
60
+ end
61
+
62
+ context 'with configuration' do
63
+ it 'passes configuration to Packr' do
64
+ Massimo.config.javascripts_compressor = :pack
65
+ Massimo.config.packr = { :shrink_vars => false }
66
+ with_file 'javascripts/main.js', code do
67
+ mock(Packr).pack(code, :shrink_vars => false) { '' }
68
+ javascript.render
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ context 'using :yui' do
75
+ it 'compresses using YUI::JavaScriptCompressor' do
76
+ Massimo.config.javascripts_compressor = :yui
77
+ with_file 'javascripts/main.js', code do
78
+ compressor = mock!.compress(code) { '' }.subject
79
+ mock(YUI::JavaScriptCompressor).new(:munge => true) { compressor }
80
+ javascript.render
81
+ end
82
+ end
83
+
84
+ context 'with configuration' do
85
+ it 'passes configuration to YUI::JavaScriptCompressor' do
86
+ Massimo.config.javascripts_compressor = :yui
87
+ Massimo.config.yui = { :munge => false }
88
+ with_file 'javascripts/main.js', code do
89
+ compressor = mock!.compress(code) { '' }.subject
90
+ mock(YUI::JavaScriptCompressor).new(:munge => false) { compressor }
91
+ javascript.render
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ context 'using :closure' do
98
+ it 'compresses using Closure::Compiler' do
99
+ Massimo.config.javascripts_compressor = :closure
100
+ with_file 'javascripts/main.js', code do
101
+ compiler = mock!.compile(code) { '' }.subject
102
+ mock(Closure::Compiler).new({}) { compiler }
103
+ javascript.render
104
+ end
105
+ end
106
+
107
+ context 'with configuration' do
108
+ it 'passes configuration to Closure::Compiler' do
109
+ Massimo.config.javascripts_compressor = :closure
110
+ Massimo.config.closure = { :compilation_level => 'ADVANCED_OPTIMIZATIONS' }
111
+ with_file 'javascripts/main.js', code do
112
+ compiler = mock!.compile(code) { '' }.subject
113
+ mock(Closure::Compiler).new(:compilation_level => 'ADVANCED_OPTIMIZATIONS') { compiler }
114
+ javascript.render
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Massimo do
4
+ describe '.site' do
5
+ it 'should return a Site' do
6
+ Massimo.site.should be_an_instance_of(Massimo::Site)
7
+ end
8
+
9
+ context 'when a Site has been created' do
10
+ it 'should return that site' do
11
+ site = Massimo::Site.new
12
+ Massimo.site.should === site
13
+ end
14
+ end
15
+ end
16
+
17
+ describe '.config' do
18
+ it 'should return the configuration of the current Site' do
19
+ Massimo::Site.new :source_path => 'source/dir'
20
+ Massimo.config.source_path.should == File.expand_path('source/dir')
21
+ end
22
+ end
23
+ end