antw-kin 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,34 @@
1
+ namespace :kin do
2
+
3
+ desc "Regenerates the sprite images. Any sprites which haven't been " \
4
+ "changed won't be regenerated."
5
+
6
+ task 'sprites' do
7
+ generate_sprites!(false)
8
+ end
9
+
10
+ desc "Regenerates the sprite images, even those which have not been " \
11
+ "changed."
12
+
13
+ task 'sprites:force' do
14
+ generate_sprites!(true)
15
+ end
16
+
17
+ ##
18
+ # Generates the sprites for the current Merb application.
19
+ #
20
+ # @param [Boolean] force
21
+ # Defines whether to regenerate sprites which haven't been changed.
22
+ #
23
+ def generate_sprites!(force)
24
+ require 'kin/sprites'
25
+ require 'kin/sprites/rake_runner'
26
+
27
+ Kin::Sprites::RakeRunner.new(
28
+ File.join(Merb.dir_for(:config), 'sprites.yml'),
29
+ File.join(Merb.dir_for(:image), 'sprites'),
30
+ File.join(Merb.dir_for(:stylesheet), 'sass', '_sprites.sass')
31
+ ).generate!(force)
32
+ end
33
+
34
+ end
@@ -0,0 +1,9 @@
1
+ :ruby
2
+ Kin::Nav.setup(:test, Kin::Nav::Formatters::HasRight(:right_one, :right_two)) do |nav|
3
+ # Items with titles.
4
+ nav.add(:left, 'Left')
5
+ nav.add(:right_one, 'Right one')
6
+ nav.add(:right_two, 'Right one')
7
+ end
8
+
9
+ = display_navigation(:test)
@@ -0,0 +1,7 @@
1
+ :ruby
2
+ Kin::Nav.setup(:test, Kin::Nav::Formatters::Subnav) do |nav|
3
+ nav.add(:one, 'One')
4
+ nav.add(:two, 'Two')
5
+ end
6
+
7
+ = display_navigation(:test)
@@ -0,0 +1,11 @@
1
+ ---
2
+ # Used in the RakeRunner specs to test
3
+ # a sprite definition being changed.
4
+
5
+ general:
6
+ - one
7
+ - three
8
+
9
+ more:
10
+ - two
11
+ - three
@@ -0,0 +1,9 @@
1
+ ---
2
+ general:
3
+ - one
4
+ - two
5
+ - three
6
+
7
+ more:
8
+ - two
9
+ - three
@@ -1,52 +1,10 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
2
2
 
3
- # Masthead::Builder Specs ======================================================
4
-
5
- describe 'masthead builder setter', :shared => true do
6
- it 'should set the attribute if a value is given' do
7
- @builder.send(@method, 'my_value').should == 'my_value'
8
- end
9
-
10
- it 'should not change the attribute value if nil is given' do
11
- @builder.send(@method, 'my_value')
12
- @builder.send(@method).should == 'my_value'
13
- @builder.send(@method, nil).should == 'my_value'
14
- end
15
-
16
- it 'should set the extra options' do
17
- @builder.send(@method, 'my_value', { :link => '/' })
18
- @builder.options[@method].should == { :link => '/' }
19
- end
20
- end
21
-
22
3
  describe Kin::Masthead::Builder do
23
4
  before(:each) do
24
5
  @builder = Kin::Masthead::Builder.new
25
6
  end
26
7
 
27
- # -------
28
- # Setters
29
-
30
- describe '#title' do
31
- before(:each) { @method = :title }
32
- it_should_behave_like 'masthead builder setter'
33
- end
34
-
35
- describe '#subtitle' do
36
- before(:each) { @method = :subtitle }
37
- it_should_behave_like 'masthead builder setter'
38
- end
39
-
40
- describe '#right_title' do
41
- before(:each) { @method = :right_title }
42
- it_should_behave_like 'masthead builder setter'
43
- end
44
-
45
- describe '#right_subtitle' do
46
- before(:each) { @method = :right_subtitle }
47
- it_should_behave_like 'masthead builder setter'
48
- end
49
-
50
8
  # -----
51
9
  # build
52
10
 
@@ -98,7 +56,7 @@ describe Kin::Masthead::Builder do
98
56
  it 'should render an empty right title when no right title is set, but ' +
99
57
  'a right subtitle is set' do
100
58
  @c.render(:right_subtitle).should have_selector('.extra .main') do |main|
101
- main.to_s.should =~ / /
59
+ main.to_xhtml.should include(' ') # Unicode non-breaking space.
102
60
  end
103
61
  end
104
62
 
@@ -130,16 +88,6 @@ describe Kin::Masthead::Builder do
130
88
  @c.render(:right_subtitle).should have_selector('.extra .subtitle')
131
89
  end
132
90
 
133
- # Border.
134
-
135
- it 'should not have a "no_border" class by default' do
136
- @c.render(:border).should_not have_selector('.no_border')
137
- end
138
-
139
- it 'should have a "no_border" class when no_border = true' do
140
- @c.render(:no_border).should have_selector('.no_border')
141
- end
142
-
143
91
  # Links.
144
92
 
145
93
  it 'should add links to fields when a :link option is present' do
@@ -202,27 +150,3 @@ describe Kin::Masthead::Builder do
202
150
  end
203
151
 
204
152
  end
205
-
206
- # Masthead::Helper Specs =====================================================
207
-
208
- describe 'Masthead helper mixin' do
209
- include Kin::Masthead::Helper
210
-
211
- describe '#masthead' do
212
- it 'should pass along the :no_border option' do
213
- masthead(:no_border => true) { |_| }
214
- masthead_builder.no_border.should be_true
215
- end
216
-
217
- it 'should pass the block along to #build' do
218
- masthead { |m| m.title('Title') }
219
- masthead_builder.title.should == 'Title'
220
- end
221
- end
222
-
223
- describe '#masthead_builder' do
224
- it 'should return the same instance each time' do
225
- masthead_builder.object_id.should == masthead_builder.object_id
226
- end
227
- end
228
- end
data/spec/nav_spec.rb CHANGED
@@ -145,6 +145,38 @@ describe Kin::Nav do
145
145
  end
146
146
  end
147
147
 
148
+ # ------------------
149
+ # HasRight formatter
150
+
151
+ describe 'with the HasRight formatter' do
152
+ before(:each) do
153
+ @html = @c.render(:has_right_formatter)
154
+ end
155
+
156
+ it 'should apply a custom style the right-aligned items' do
157
+ %w( right_one right_two ).each do |name|
158
+ @html.should have_selector("#nav_#{name} span.right_border")
159
+ end
160
+ end
161
+
162
+ it 'should use the default style for items not right-aligned' do
163
+ @html.should_not have_selector('#nav_left span.right_border')
164
+ end
165
+ end
166
+
167
+ # ----------------
168
+ # Subnav formatter
169
+
170
+ describe 'with the Subnav formatter' do
171
+ it 'should apply a custom style to all items' do
172
+ html = @c.render(:subnav_formatter)
173
+
174
+ %w( one two ).each do |name|
175
+ html.should have_selector("#nav_#{name} span.pill")
176
+ end
177
+ end
178
+ end
179
+
148
180
  # ------
149
181
  # titles
150
182
 
data/spec/spec_helper.rb CHANGED
@@ -19,6 +19,37 @@ Spec::Runner.configure do |config|
19
19
  config.include(Merb::Test::ViewHelper)
20
20
  config.include(Merb::Test::RouteHelper)
21
21
  config.include(Merb::Test::ControllerHelper)
22
+ config.include(Module.new do
23
+ ##
24
+ # Returns a path to the fixture directory. Any additional string
25
+ # parameters will be joined with the path.
26
+ #
27
+ def fixture_path(*dirs)
28
+ File.join(File.dirname(__FILE__), 'fixture', *dirs)
29
+ end
30
+
31
+ ##
32
+ # Returns a path to the tmp/spec folder. Any additional string
33
+ # parameters will be joined with the path.
34
+ #
35
+ def tmp_path(*dirs)
36
+ File.join(File.dirname(__FILE__), '..', 'tmp', 'spec', *dirs)
37
+ end
38
+
39
+ ##
40
+ # Does exactly what it says on the tin.
41
+ #
42
+ def capture_stdout
43
+ orig, $stdout = $stdout, StringIO.new
44
+
45
+ begin
46
+ yield
47
+ return $stdout.string
48
+ ensure
49
+ $stdout = orig
50
+ end
51
+ end
52
+ end)
22
53
  end
23
54
 
24
55
  ##
@@ -0,0 +1,349 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
2
+
3
+ sprites = File.join(File.dirname(__FILE__), '..', 'lib', 'kin', 'sprites')
4
+
5
+ require sprites
6
+ require File.join(sprites, 'rake_runner')
7
+
8
+ # IconSet ====================================================================
9
+
10
+ describe Kin::Sprites::IconSet do
11
+ it 'should include Enumerable' do
12
+ Kin::Sprites::IconSet.ancestors.should include(Enumerable)
13
+ end
14
+
15
+ describe '#each' do
16
+ it 'should yield each icon in turn' do
17
+ icons, yielded = %w(one two), []
18
+
19
+ Kin::Sprites::IconSet.new(icons).each do |icon|
20
+ yielded << icon
21
+ end
22
+
23
+ yielded.should == icons
24
+ end
25
+ end
26
+
27
+ describe '#location_of' do
28
+ before(:each) do
29
+ @set = Kin::Sprites::IconSet.new(%w(one two))
30
+ end
31
+
32
+ it 'should return 0 if the given icon is first' do
33
+ @set.location_of('one').should == 0
34
+ end
35
+
36
+ it 'should return 40 if the given icon is second' do
37
+ @set.location_of('two').should == 40
38
+ end
39
+ end
40
+
41
+ describe '#length' do
42
+ it 'should return the number of icons in the set' do
43
+ Kin::Sprites::IconSet.new([]).length.should == 0
44
+ Kin::Sprites::IconSet.new(['one']).length.should == 1
45
+ Kin::Sprites::IconSet.new(['one', 'two']).length.should == 2
46
+ end
47
+ end
48
+ end
49
+
50
+ # ImageGenerator =============================================================
51
+
52
+ # Requires:
53
+ #
54
+ # @gen (Kin::Sprites::ImageGenerator)
55
+ # An image generator instance.
56
+ # @sprite_path (String)
57
+ # A path to where a sprite should be saved.
58
+ #
59
+ describe 'saving a sprite', :shared => true do
60
+ it 'should save the image to the specified path' do
61
+ lambda { @gen.save(@sprite_path) }.should \
62
+ change(&lambda { File.exists?(@sprite_path) })
63
+ end
64
+
65
+ it 'should silently overwrite any existing file at the specified path' do
66
+ FileUtils.touch(@sprite_path)
67
+ orig_size = File.size(@sprite_path)
68
+ @gen.save(@sprite_path)
69
+
70
+ # Using touch should create a zero-byte file (as near as makes no
71
+ # difference, anyway). Saving the PNG should result in a larger file.
72
+ File.exists?(@sprite_path).should be_true
73
+ File.size(@sprite_path).should > orig_size
74
+ end
75
+
76
+ it 'should save a 32-bit PNG' do
77
+ @gen.save(@sprite_path)
78
+ image = Magick::Image.ping(@sprite_path).first
79
+ image.format.should == 'PNG'
80
+ image.quantum_depth.should == 8 # 8-bits per channel.
81
+ end
82
+
83
+ it 'should create a 16 pixel wide image' do
84
+ @gen.save(@sprite_path)
85
+ Magick::Image.ping(@sprite_path).first.columns.should == 16
86
+ end
87
+ end
88
+
89
+ describe Kin::Sprites::ImageGenerator, '#save' do
90
+ ##
91
+ # Creates an ImageGenerator instance suitable for use in specs.
92
+ #
93
+ # @param [Array<String>] An array of icons to use.
94
+ #
95
+ def create_image_generator(icons)
96
+ Kin::Sprites::ImageGenerator.new(
97
+ Kin::Sprites::IconSet.new(icons),
98
+ fixture_path('public', 'images', 'sprites', 'src')
99
+ )
100
+ end
101
+
102
+ before(:all) do
103
+ @dir = tmp_path('sprites')
104
+ @sprite_path = tmp_path('sprites', 'sprite.png')
105
+ FileUtils.mkdir_p(@dir)
106
+ end
107
+
108
+ after(:all) do
109
+ FileUtils.rmdir(@dir)
110
+ end
111
+
112
+ after(:each) do
113
+ FileUtils.rm(@sprite_path) if @sprite_path && File.exists?(@sprite_path)
114
+ end
115
+
116
+ # On with the specs...
117
+
118
+ describe 'when creating a sprite with a single icon' do
119
+ before(:each) do
120
+ @gen = create_image_generator(['one'])
121
+ end
122
+
123
+ it_should_behave_like 'saving a sprite'
124
+
125
+ it 'should create a 16 pixel high image' do
126
+ # 40 pixels with the top and bottom 12 (blank) cropped off
127
+ @gen.save(@sprite_path)
128
+ Magick::Image.ping(@sprite_path).first.rows.should == 16
129
+ end
130
+ end
131
+
132
+ describe 'when creating a sprite with a three icons' do
133
+ before(:each) do
134
+ @gen = create_image_generator(['one', 'two', 'three'])
135
+ end
136
+
137
+ it_should_behave_like 'saving a sprite'
138
+
139
+ it 'should create a 96 pixel high image' do
140
+ # 120 pixels with the top and bottom 12 (blank) cropped off
141
+ @gen.save(@sprite_path)
142
+ Magick::Image.ping(@sprite_path).first.rows.should == 96
143
+ end
144
+ end
145
+
146
+ it 'should raise IconNotReadable when one of the icons does not exist' do
147
+ block = lambda { create_image_generator(['not_here']).save(@sprite_path) }
148
+ block.should raise_error(
149
+ Kin::Sprites::ImageGenerator::IconNotReadable, /unable to open/)
150
+ end
151
+
152
+ it 'should raise TargetNotWriteable when the sprite path is not ' \
153
+ 'writeable' do
154
+ gen = create_image_generator(['one'])
155
+ orig_perms = File.stat(@dir).mode
156
+ File.chmod(0000, @dir)
157
+
158
+ begin
159
+ lambda { gen.save(@sprite_path) }.should raise_error(
160
+ Kin::Sprites::ImageGenerator::TargetNotWriteable, /Permission denied/)
161
+ ensure
162
+ File.chmod(orig_perms, @dir)
163
+ end
164
+ end
165
+ end
166
+
167
+ # SassGenerator ==============================================================
168
+
169
+ describe Kin::Sprites::SassGenerator, '#to_sass' do
170
+ before(:each) do
171
+ @set = Kin::Sprites::IconSet.new(%w(one two three))
172
+ @gen = Kin::Sprites::SassGenerator.new(@set, 'mysprites')
173
+ @sass = @gen.to_sass('/images/sprites')
174
+ end
175
+
176
+ it 'should not indent mixin definitions' do
177
+ @sass.each_line do |line|
178
+ line.should =~ /^=/ if line =~ /=\w+-icon/
179
+ end
180
+ end
181
+
182
+ it 'should indent if statements with two spaces' do
183
+ @sass.each_line do |line|
184
+ line.should =~ /^ @/ if line =~ /@(?:else|if)/
185
+ end
186
+ end
187
+
188
+ it 'should indent position assigments with four spaces' do
189
+ @sass.each_line do |line|
190
+ line.should =~ /^ !pos/ if line =~ /@pos = -\d+px/
191
+ end
192
+ end
193
+
194
+ it 'should indent background statements with two spaces' do
195
+ @sass.each_line do |line|
196
+ line.should =~ / :background/ if line =~ /:background/
197
+ end
198
+ end
199
+
200
+ it 'should include statements for all the icons' do
201
+ @sass.should include('!icon == "one"')
202
+ @sass.should include('!icon == "two"')
203
+ @sass.should include('!icon == "three"')
204
+ end
205
+
206
+ it 'should use an `@if` statement for the first icon' do
207
+ @sass.should include('@if !icon == "one"')
208
+ @sass.should_not include('@if !icon == "two"')
209
+ @sass.should_not include('@if !icon == "three"')
210
+ end
211
+
212
+ it 'should use an `@else if` statement for subsequence icons' do
213
+ @sass.should_not include('@else if !icon == "one"')
214
+ @sass.should include('@else if !icon == "two"')
215
+ @sass.should include('@else if !icon == "three"')
216
+ end
217
+
218
+ it 'should use the given base directory when creating the sprite path' do
219
+ @sass.should =~ %r{url\(/images/sprites}
220
+ end
221
+
222
+ it 'should use the generator name when creating the sprite path' do
223
+ @sass.should include('mysprites.png')
224
+ end
225
+ end
226
+
227
+ # RakeRunner =================================================================
228
+
229
+ ##
230
+ # Copies the icons source files from fixture/public/images/sprites/src to
231
+ # the tmp/spec/sprites/src directory. Removes tmp/spec/sprites when done.
232
+ #
233
+ describe Kin::Sprites::RakeRunner do
234
+ before(:each) do
235
+ FileUtils.mkdir_p(tmp_path('sprites'))
236
+ FileUtils.cp_r(fixture_path('public', 'images', 'sprites'), tmp_path)
237
+ end
238
+
239
+ after(:each) do
240
+ FileUtils.rm_r(tmp_path('sprites'))
241
+ end
242
+
243
+ def rake_runner(sprites_yml = 'sprites.yml')
244
+ Kin::Sprites::RakeRunner.new(
245
+ fixture_path('config', sprites_yml),
246
+ tmp_path('sprites'),
247
+ tmp_path('sprites', '_sprites.sass'))
248
+ end
249
+
250
+ it 'should raise an error when sprites.yml could not be found' do
251
+ lambda {
252
+ Kin::Sprites::RakeRunner.new(
253
+ 'not_here.yml',
254
+ fixture_path('public', 'images', 'sprites'),
255
+ fixture_path('public', 'stylesheets', 'sass', '_sprites.sass')
256
+ )
257
+ }.should raise_error(Kin::Sprites::SpriteError)
258
+ end
259
+
260
+ describe 'when no sprites have been previously generated' do
261
+ it 'should generate the sprite files' do
262
+ out = capture_stdout { rake_runner.generate! }
263
+ out.should =~ /Regenerated "general"/
264
+ out.should =~ /Regenerated "more"/
265
+ end
266
+
267
+ it 'should generate the SASS partial' do
268
+ out = capture_stdout { rake_runner.generate! }
269
+ out.should =~ /Saved SASS/
270
+ end
271
+ end
272
+
273
+ describe 'when the sprites have been previously generated,' do
274
+ describe 'and one has changed' do
275
+ before(:each) do
276
+ capture_stdout { rake_runner.generate! }
277
+ end
278
+
279
+ it 'should regenerate the changed sprite file' do
280
+ out = capture_stdout { rake_runner('sprites.different.yml').generate! }
281
+ out.should =~ /Regenerated "general"/
282
+ end
283
+
284
+ it 'should not regenerate the unchanged sprite file' do
285
+ out = capture_stdout { rake_runner('sprites.different.yml').generate! }
286
+ out.should =~ /Ignoring "more"/
287
+ end
288
+
289
+ it 'should regenerate the SASS partial' do
290
+ out = capture_stdout { rake_runner('sprites.different.yml').generate! }
291
+ out.should =~ /Saved SASS/
292
+ end
293
+ end
294
+
295
+ describe 'have not changed,' do
296
+ before(:each) do
297
+ capture_stdout { rake_runner.generate! }
298
+ end
299
+
300
+ describe 'and :force is false' do
301
+ it 'should not regenerate the sprite files' do
302
+ out = capture_stdout { rake_runner.generate! }
303
+ out.should =~ /Ignoring "general"/
304
+ out.should =~ /Ignoring "more"/
305
+ end
306
+
307
+ it 'should not regenerate the SASS partial' do
308
+ out = capture_stdout { rake_runner.generate! }
309
+ out.should_not =~ /Saved SASS/
310
+ end
311
+ end
312
+
313
+ describe 'and :force is true' do
314
+ it 'should regenerate the sprite files' do
315
+ out = capture_stdout { rake_runner.generate!(true) }
316
+ out.should =~ /Regenerated "general"/
317
+ out.should =~ /Regenerated "more"/
318
+ end
319
+
320
+ it 'should regenerate the SASS partial' do
321
+ out = capture_stdout { rake_runner.generate!(true) }
322
+ out.should =~ /Saved SASS/
323
+ end
324
+ end
325
+
326
+ describe 'and a sprite has been deleted' do
327
+ before(:each) do
328
+ FileUtils.rm(tmp_path('sprites', 'general.png'))
329
+ end
330
+
331
+ it 'should regenerate the deleted sprite' do
332
+ out = capture_stdout { rake_runner.generate! }
333
+ out.should =~ /Regenerated "general"/
334
+ end
335
+
336
+ it 'should not regenereate the unchanged sprite' do
337
+ out = capture_stdout { rake_runner.generate! }
338
+ out.should =~ /Ignoring "more"/
339
+ end
340
+
341
+ it 'should regenerate the SASS partial' do
342
+ out = capture_stdout { rake_runner.generate!(true) }
343
+ out.should =~ /Saved SASS/
344
+ end
345
+ end
346
+ end
347
+ end
348
+
349
+ end