nanoc3 3.1.7 → 3.1.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. data/.gemtest +0 -0
  2. data/LICENSE +1 -1
  3. data/NEWS.md +9 -0
  4. data/doc/yardoc_templates/default/layout/html/footer.erb +10 -0
  5. data/lib/nanoc3/base/item.rb +1 -1
  6. data/lib/nanoc3/base/item_rep.rb +1 -0
  7. data/lib/nanoc3/base/layout.rb +1 -1
  8. data/lib/nanoc3/cli/base.rb +4 -2
  9. data/lib/nanoc3/cli/commands/view.rb +1 -0
  10. data/lib/nanoc3/data_sources/filesystem.rb +25 -6
  11. data/lib/nanoc3/data_sources/filesystem_unified.rb +5 -5
  12. data/lib/nanoc3/extra/validators/links.rb +1 -1
  13. data/lib/nanoc3/filters/rdiscount.rb +2 -1
  14. data/lib/nanoc3/filters/sass.rb +20 -8
  15. data/lib/nanoc3/filters/sass.rb.orig +75 -0
  16. data/lib/nanoc3.rb +1 -1
  17. data/nanoc3.gemspec +41 -0
  18. data/tasks/clean.rake +11 -0
  19. data/tasks/doc.rake +14 -0
  20. data/tasks/gem.rake +13 -0
  21. data/tasks/test.rake +38 -0
  22. data/test/base/core_ext/array_spec.rb +23 -0
  23. data/test/base/core_ext/hash_spec.rb +41 -0
  24. data/test/base/core_ext/string_spec.rb +27 -0
  25. data/test/base/test_code_snippet.rb +33 -0
  26. data/test/base/test_compiler.rb +410 -0
  27. data/test/base/test_compiler_dsl.rb +121 -0
  28. data/test/base/test_context.rb +33 -0
  29. data/test/base/test_data_source.rb +48 -0
  30. data/test/base/test_dependency_tracker.rb +510 -0
  31. data/test/base/test_directed_graph.rb +91 -0
  32. data/test/base/test_filter.rb +85 -0
  33. data/test/base/test_item.rb +141 -0
  34. data/test/base/test_item_rep.rb +953 -0
  35. data/test/base/test_layout.rb +44 -0
  36. data/test/base/test_notification_center.rb +36 -0
  37. data/test/base/test_plugin.rb +32 -0
  38. data/test/base/test_rule.rb +21 -0
  39. data/test/base/test_rule_context.rb +63 -0
  40. data/test/base/test_site.rb +366 -0
  41. data/test/cli/commands/test_compile.rb +12 -0
  42. data/test/cli/commands/test_create_item.rb +12 -0
  43. data/test/cli/commands/test_create_layout.rb +28 -0
  44. data/test/cli/commands/test_create_site.rb +24 -0
  45. data/test/cli/commands/test_help.rb +12 -0
  46. data/test/cli/commands/test_info.rb +12 -0
  47. data/test/cli/commands/test_update.rb +12 -0
  48. data/test/cli/test_logger.rb +12 -0
  49. data/test/data_sources/test_filesystem.rb +420 -0
  50. data/test/data_sources/test_filesystem_unified.rb +538 -0
  51. data/test/data_sources/test_filesystem_verbose.rb +359 -0
  52. data/test/extra/core_ext/test_enumerable.rb +32 -0
  53. data/test/extra/core_ext/test_time.rb +17 -0
  54. data/test/extra/deployers/test_rsync.rb +234 -0
  55. data/test/extra/test_auto_compiler.rb +482 -0
  56. data/test/extra/test_file_proxy.rb +21 -0
  57. data/test/extra/test_vcs.rb +24 -0
  58. data/test/extra/validators/test_links.rb +53 -0
  59. data/test/extra/validators/test_w3c.rb +49 -0
  60. data/test/filters/test_bluecloth.rb +20 -0
  61. data/test/filters/test_coderay.rb +46 -0
  62. data/test/filters/test_colorize_syntax.rb +56 -0
  63. data/test/filters/test_erb.rb +72 -0
  64. data/test/filters/test_erubis.rb +72 -0
  65. data/test/filters/test_haml.rb +98 -0
  66. data/test/filters/test_kramdown.rb +20 -0
  67. data/test/filters/test_less.rb +59 -0
  68. data/test/filters/test_markaby.rb +26 -0
  69. data/test/filters/test_maruku.rb +20 -0
  70. data/test/filters/test_rainpress.rb +31 -0
  71. data/test/filters/test_rdiscount.rb +33 -0
  72. data/test/filters/test_rdoc.rb +18 -0
  73. data/test/filters/test_redcloth.rb +20 -0
  74. data/test/filters/test_relativize_paths.rb +231 -0
  75. data/test/filters/test_rubypants.rb +20 -0
  76. data/test/filters/test_sass.rb +170 -0
  77. data/test/filters/test_sass.rb.orig +103 -0
  78. data/test/gem_loader.rb +11 -0
  79. data/test/helper.rb +99 -0
  80. data/test/helpers/test_blogging.rb +808 -0
  81. data/test/helpers/test_breadcrumbs.rb +83 -0
  82. data/test/helpers/test_capturing.rb +42 -0
  83. data/test/helpers/test_filtering.rb +108 -0
  84. data/test/helpers/test_html_escape.rb +18 -0
  85. data/test/helpers/test_link_to.rb +251 -0
  86. data/test/helpers/test_rendering.rb +109 -0
  87. data/test/helpers/test_tagging.rb +89 -0
  88. data/test/helpers/test_text.rb +26 -0
  89. data/test/helpers/test_xml_sitemap.rb +69 -0
  90. data/test/tasks/test_clean.rb +71 -0
  91. metadata +83 -8
@@ -0,0 +1,953 @@
1
+ # encoding: utf-8
2
+
3
+ require 'test/helper'
4
+
5
+ class Nanoc3::ItemRepTest < MiniTest::Unit::TestCase
6
+
7
+ include Nanoc3::TestHelpers
8
+
9
+ def test_created_modified_compiled
10
+ # TODO implement
11
+ end
12
+
13
+ def test_not_outdated
14
+ # Mock item
15
+ item = Nanoc3::Item.new(
16
+ 'blah blah blah', {}, '/',
17
+ :mtime => Time.now-500
18
+ )
19
+
20
+ # Mock layouts
21
+ layouts = [ mock ]
22
+ layouts[0].stubs(:mtime).returns(Time.now-800)
23
+
24
+ # Mock code snippets
25
+ code_snippets = [ mock ]
26
+ code_snippets[0].stubs(:mtime).returns(Time.now-900)
27
+
28
+ # Mock site
29
+ site = mock
30
+ site.stubs(:layouts).returns(layouts)
31
+ site.stubs(:code_snippets).returns(code_snippets)
32
+ site.stubs(:config_mtime).returns(Time.now-1100)
33
+ site.stubs(:rules_mtime).returns(Time.now-1200)
34
+ item.stubs(:site).returns(site)
35
+
36
+ # Create output file
37
+ File.open('output.html', 'w') { |io| io.write('Testing testing 123...') }
38
+ File.utime(Time.now-100, Time.now-200, 'output.html')
39
+
40
+ # Create rep
41
+ rep = Nanoc3::ItemRep.new(item, 'blah')
42
+ rep.instance_eval { @raw_path = 'output.html' }
43
+
44
+ # Test
45
+ refute(rep.outdated?)
46
+ ensure
47
+ FileUtils.rm_f('output.html')
48
+ end
49
+
50
+ def test_outdated_if_mtime_nil
51
+ # Mock item
52
+ item = Nanoc3::Item.new(
53
+ 'blah blah blah', {}, '/'
54
+ )
55
+
56
+ # Mock layouts
57
+ layouts = [ mock ]
58
+ layouts[0].stubs(:mtime).returns(Time.now-800)
59
+
60
+ # Mock code snippets
61
+ code_snippets = [ mock ]
62
+ code_snippets[0].stubs(:mtime).returns(Time.now-900)
63
+
64
+ # Mock site
65
+ site = mock
66
+ site.stubs(:layouts).returns(layouts)
67
+ site.stubs(:code_snippets).returns(code_snippets)
68
+ item.stubs(:site).returns(site)
69
+
70
+ # Create output file
71
+ File.open('output.html', 'w') { |io| io.write('Testing testing 123...') }
72
+ File.utime(Time.now-100, Time.now-200, 'output.html')
73
+
74
+ # Create rep
75
+ rep = Nanoc3::ItemRep.new(item, 'blah')
76
+ rep.instance_eval { @raw_path = 'output.html' }
77
+
78
+ # Test
79
+ assert(rep.outdated?)
80
+ ensure
81
+ FileUtils.rm_f('output.html')
82
+ end
83
+
84
+ def test_outdated_if_force_outdated
85
+ # Mock item
86
+ item = Nanoc3::Item.new(
87
+ 'blah blah blah', {}, '/',
88
+ :mtime => Time.now-500, :binary => false
89
+ )
90
+
91
+ # Mock layouts
92
+ layouts = [ mock ]
93
+ layouts[0].stubs(:mtime).returns(Time.now-800)
94
+
95
+ # Mock code snippets
96
+ code_snippets = [ mock ]
97
+ code_snippets[0].stubs(:mtime).returns(Time.now-900)
98
+
99
+ # Mock site
100
+ site = mock
101
+ site.stubs(:layouts).returns(layouts)
102
+ site.stubs(:code_snippets).returns(code_snippets)
103
+ item.stubs(:site).returns(site)
104
+
105
+ # Create output file
106
+ File.open('output.html', 'w') { |io| io.write('Testing testing 123...') }
107
+ File.utime(Time.now-100, Time.now-200, 'output.html')
108
+
109
+ # Create rep
110
+ rep = Nanoc3::ItemRep.new(item, 'blah')
111
+ rep.instance_eval { @raw_path = 'output.html' }
112
+ rep.instance_eval { @force_outdated = true }
113
+
114
+ # Test
115
+ assert(rep.outdated?)
116
+ ensure
117
+ FileUtils.rm_f('output.html')
118
+ end
119
+
120
+ def test_outdated_if_compiled_file_doesnt_exist
121
+ # Mock item
122
+ item = Nanoc3::Item.new(
123
+ 'blah blah blah', {}, '/',
124
+ :binary => false, :mtime => Time.now-500
125
+ )
126
+
127
+ # Mock layouts
128
+ layouts = [ mock ]
129
+ layouts[0].stubs(:mtime).returns(Time.now-800)
130
+
131
+ # Mock code snippets
132
+ code_snippets = [ mock ]
133
+ code_snippets[0].stubs(:mtime).returns(Time.now-900)
134
+
135
+ # Mock site
136
+ site = mock
137
+ site.stubs(:layouts).returns(layouts)
138
+ site.stubs(:code_snippets).returns(code_snippets)
139
+ item.stubs(:site).returns(site)
140
+
141
+ # Create rep
142
+ rep = Nanoc3::ItemRep.new(item, 'blah')
143
+ rep.instance_eval { @raw_path = 'output.html' }
144
+
145
+ # Test
146
+ assert(rep.outdated?)
147
+ ensure
148
+ FileUtils.rm_f('output.html')
149
+ end
150
+
151
+ def test_outdated_if_source_file_too_old
152
+ # Mock item
153
+ item = Nanoc3::Item.new(
154
+ 'blah blah blah', {}, '/',
155
+ :binary => false, :mtime => Time.now-100
156
+ )
157
+
158
+ # Mock layouts
159
+ layouts = [ mock ]
160
+ layouts[0].stubs(:mtime).returns(Time.now-800)
161
+
162
+ # Mock code snippets
163
+ code_snippets = [ mock ]
164
+ code_snippets[0].stubs(:mtime).returns(Time.now-900)
165
+
166
+ # Mock site
167
+ site = mock
168
+ site.stubs(:layouts).returns(layouts)
169
+ site.stubs(:code_snippets).returns(code_snippets)
170
+ item.stubs(:site).returns(site)
171
+
172
+ # Create output file
173
+ File.open('output.html', 'w') { |io| io.write('Testing testing 123...') }
174
+ File.utime(Time.now-500, Time.now-600, 'output.html')
175
+
176
+ # Create rep
177
+ rep = Nanoc3::ItemRep.new(item, 'blah')
178
+ rep.instance_eval { @raw_path = 'output.html' }
179
+
180
+ # Test
181
+ assert(rep.outdated?)
182
+ ensure
183
+ FileUtils.rm_f('output.html')
184
+ end
185
+
186
+ def test_outdated_if_layouts_outdated
187
+ # Mock item
188
+ item = Nanoc3::Item.new(
189
+ 'blah blah blah', {}, '/',
190
+ :binary => false, :mtime => Time.now-500
191
+ )
192
+
193
+ # Mock layouts
194
+ layouts = [ mock ]
195
+ layouts[0].stubs(:mtime).returns(Time.now-100)
196
+
197
+ # Mock code snippets
198
+ code_snippets = [ mock ]
199
+ code_snippets[0].stubs(:mtime).returns(Time.now-900)
200
+
201
+ # Mock site
202
+ site = mock
203
+ site.stubs(:layouts).returns(layouts)
204
+ site.stubs(:code_snippets).returns(code_snippets)
205
+ item.stubs(:site).returns(site)
206
+
207
+ # Create output file
208
+ File.open('output.html', 'w') { |io| io.write('Testing testing 123...') }
209
+ File.utime(Time.now-200, Time.now-300, 'output.html')
210
+
211
+ # Create rep
212
+ rep = Nanoc3::ItemRep.new(item, 'blah')
213
+ rep.instance_eval { @raw_path = 'output.html' }
214
+
215
+ # Test
216
+ assert(rep.outdated?)
217
+ ensure
218
+ FileUtils.rm_f('output.html')
219
+ end
220
+
221
+ def test_outdated_if_code_snippets_outdated
222
+ # Mock item
223
+ item = Nanoc3::Item.new(
224
+ 'blah blah blah', {}, '/',
225
+ :binary => false, :mtime => Time.now-500
226
+ )
227
+
228
+ # Mock layouts
229
+ layouts = [ mock ]
230
+ layouts[0].stubs(:mtime).returns(Time.now-800)
231
+
232
+ # Mock code snippets
233
+ code_snippets = [ mock ]
234
+ code_snippets[0].stubs(:mtime).returns(Time.now-100)
235
+
236
+ # Mock site
237
+ site = mock
238
+ site.stubs(:layouts).returns(layouts)
239
+ site.stubs(:code_snippets).returns(code_snippets)
240
+ item.stubs(:site).returns(site)
241
+
242
+ # Create output file
243
+ File.open('output.html', 'w') { |io| io.write('Testing testing 123...') }
244
+ File.utime(Time.now-200, Time.now-300, 'output.html')
245
+
246
+ # Create rep
247
+ rep = Nanoc3::ItemRep.new(item, 'blah')
248
+ rep.instance_eval { @raw_path = 'output.html' }
249
+
250
+ # Test
251
+ assert(rep.outdated?)
252
+ ensure
253
+ FileUtils.rm_f('output.html')
254
+ end
255
+
256
+ def test_outdated_if_config_outdated
257
+ # Mock item
258
+ item = Nanoc3::Item.new(
259
+ 'blah blah blah', {}, '/',
260
+ :binary => false, :mtime => Time.now-500
261
+ )
262
+
263
+ # Mock layouts
264
+ layouts = [ mock ]
265
+ layouts[0].stubs(:mtime).returns(Time.now-800)
266
+
267
+ # Mock code snippets
268
+ code_snippets = [ mock ]
269
+ code_snippets[0].stubs(:mtime).returns(Time.now-900)
270
+
271
+ # Mock site
272
+ site = mock
273
+ site.stubs(:layouts).returns(layouts)
274
+ site.stubs(:code_snippets).returns(code_snippets)
275
+ site.stubs(:config_mtime).returns(Time.now-100)
276
+ item.stubs(:site).returns(site)
277
+
278
+ # Create output file
279
+ File.open('output.html', 'w') { |io| io.write('Testing testing 123...') }
280
+ File.utime(Time.now-200, Time.now-300, 'output.html')
281
+
282
+ # Create rep
283
+ rep = Nanoc3::ItemRep.new(item, 'blah')
284
+ rep.instance_eval { @raw_path = 'output.html' }
285
+
286
+ # Test
287
+ assert(rep.outdated?)
288
+ ensure
289
+ FileUtils.rm_f('output.html')
290
+ end
291
+
292
+ def test_outdated_if_config_mtime_missing
293
+ # Mock item
294
+ item = Nanoc3::Item.new(
295
+ 'blah blah blah', {}, '/',
296
+ :binary => false, :mtime => Time.now-500
297
+ )
298
+
299
+ # Mock layouts
300
+ layouts = [ mock ]
301
+ layouts[0].stubs(:mtime).returns(Time.now-800)
302
+
303
+ # Mock code snippets
304
+ code_snippets = [ mock ]
305
+ code_snippets[0].stubs(:mtime).returns(Time.now-900)
306
+
307
+ # Mock site
308
+ site = mock
309
+ site.stubs(:layouts).returns(layouts)
310
+ site.stubs(:code_snippets).returns(code_snippets)
311
+ site.stubs(:config_mtime).returns(nil)
312
+ item.stubs(:site).returns(site)
313
+
314
+ # Create output file
315
+ File.open('output.html', 'w') { |io| io.write('Testing testing 123...') }
316
+ File.utime(Time.now-200, Time.now-300, 'output.html')
317
+
318
+ # Create rep
319
+ rep = Nanoc3::ItemRep.new(item, 'blah')
320
+ rep.instance_eval { @raw_path = 'output.html' }
321
+
322
+ # Test
323
+ assert(rep.outdated?)
324
+ ensure
325
+ FileUtils.rm_f('output.html')
326
+ end
327
+
328
+ def test_outdated_if_rules_outdated
329
+ # Mock item
330
+ item = Nanoc3::Item.new(
331
+ 'blah blah blah', {}, '/',
332
+ :binary => false, :mtime => Time.now-500
333
+ )
334
+
335
+ # Mock layouts
336
+ layouts = [ mock ]
337
+ layouts[0].stubs(:mtime).returns(Time.now-800)
338
+
339
+ # Mock code snippets
340
+ code_snippets = [ mock ]
341
+ code_snippets[0].stubs(:mtime).returns(Time.now-900)
342
+
343
+ # Mock site
344
+ site = mock
345
+ site.stubs(:layouts).returns(layouts)
346
+ site.stubs(:code_snippets).returns(code_snippets)
347
+ site.stubs(:config_mtime).returns(Time.now-1100)
348
+ site.stubs(:rules_mtime).returns(Time.now-100)
349
+ item.stubs(:site).returns(site)
350
+
351
+ # Create output file
352
+ File.open('output.html', 'w') { |io| io.write('Testing testing 123...') }
353
+ File.utime(Time.now-200, Time.now-300, 'output.html')
354
+
355
+ # Create rep
356
+ rep = Nanoc3::ItemRep.new(item, 'blah')
357
+ rep.instance_eval { @raw_path = 'output.html' }
358
+
359
+ # Test
360
+ assert(rep.outdated?)
361
+ ensure
362
+ FileUtils.rm_f('output.html')
363
+ end
364
+
365
+ def test_compiled_content_with_only_last_available
366
+ # Create rep
367
+ item = Nanoc3::Item.new(
368
+ 'blah blah blah', {}, '/',
369
+ :binary => false, :mtime => Time.now-500
370
+ )
371
+ rep = Nanoc3::ItemRep.new(item, nil)
372
+ rep.instance_eval { @content = { :last => 'last content' } }
373
+ rep.expects(:compiled?).returns(true)
374
+
375
+ # Check
376
+ assert_equal 'last content', rep.compiled_content
377
+ end
378
+
379
+ def test_compiled_content_with_pre_and_last_available
380
+ # Create rep
381
+ item = Nanoc3::Item.new(
382
+ 'blah blah blah', {}, '/',
383
+ :binary => false, :mtime => Time.now-500
384
+ )
385
+ rep = Nanoc3::ItemRep.new(item, nil)
386
+ rep.instance_eval { @content = { :pre => 'pre content', :last => 'last content' } }
387
+ rep.expects(:compiled?).returns(true)
388
+
389
+ # Check
390
+ assert_equal 'pre content', rep.compiled_content
391
+ end
392
+
393
+ def test_compiled_content_with_custom_snapshot
394
+ # Create rep
395
+ item = Nanoc3::Item.new(
396
+ 'blah blah blah', {}, '/',
397
+ :binary => false, :mtime => Time.now-500
398
+ )
399
+ rep = Nanoc3::ItemRep.new(item, nil)
400
+ rep.instance_eval { @content = { :pre => 'pre content', :last => 'last content' } }
401
+ rep.expects(:compiled?).returns(true)
402
+
403
+ # Check
404
+ assert_equal 'last content', rep.compiled_content(:snapshot => :last)
405
+ end
406
+
407
+ def test_compiled_content_with_invalid_snapshot
408
+ # Create rep
409
+ item = Nanoc3::Item.new(
410
+ 'blah blah blah', {}, '/',
411
+ :binary => false, :mtime => Time.now-500
412
+ )
413
+ rep = Nanoc3::ItemRep.new(item, nil)
414
+ rep.instance_eval { @content = { :pre => 'pre content', :last => 'last content' } }
415
+ rep.expects(:compiled?).returns(true)
416
+
417
+ # Check
418
+ assert_equal nil, rep.compiled_content(:snapshot => :klsjflkasdfl)
419
+ end
420
+
421
+ def test_compiled_content_with_uncompiled_content
422
+ # Create rep
423
+ item = Nanoc3::Item.new(
424
+ "blah blah", {}, '/',
425
+ :binary => false
426
+ )
427
+ rep = Nanoc3::ItemRep.new(item, nil)
428
+ rep.expects(:compiled?).returns(false)
429
+
430
+ # Check
431
+ assert_raises(Nanoc3::Errors::UnmetDependency) do
432
+ rep.compiled_content
433
+ end
434
+ end
435
+
436
+ def test_filter
437
+ # Mock site
438
+ site = MiniTest::Mock.new
439
+ site.expect(:items, [])
440
+ site.expect(:config, [])
441
+ site.expect(:layouts, [])
442
+
443
+ # Mock item
444
+ item = Nanoc3::Item.new(
445
+ %[<%= '<%= "blah" %' + '>' %>], {}, '/',
446
+ :binary => false
447
+ )
448
+ item.site = site
449
+
450
+ # Create item rep
451
+ item_rep = Nanoc3::ItemRep.new(item, '/foo/')
452
+ item_rep.instance_eval do
453
+ @content[:raw] = item.raw_content
454
+ @content[:last] = @content[:raw]
455
+ end
456
+
457
+ # Filter once
458
+ item_rep.filter(:erb)
459
+ assert_equal(%[<%= "blah" %>], item_rep.instance_eval { @content[:last] })
460
+
461
+ # Filter twice
462
+ item_rep.filter(:erb)
463
+ assert_equal(%[blah], item_rep.instance_eval { @content[:last] })
464
+ end
465
+
466
+ def test_layout
467
+ # Mock layout
468
+ layout = mock
469
+ layout.stubs(:identifier).returns('/somelayout/')
470
+ layout.stubs(:raw_content).returns(%[<%= "blah" %>])
471
+
472
+ # Mock compiler
473
+ stack = mock
474
+ stack.expects(:push).with(layout)
475
+ stack.expects(:pop)
476
+ compiler = mock
477
+ compiler.stubs(:stack).returns(stack)
478
+ compiler.expects(:filter_for_layout).with(layout).returns([ :erb, {} ])
479
+
480
+ # Mock site
481
+ site = mock
482
+ site.stubs(:items).returns([])
483
+ site.stubs(:config).returns([])
484
+ site.stubs(:layouts).returns([ layout ])
485
+ site.stubs(:compiler).returns(compiler)
486
+
487
+ # Mock item
488
+ item = Nanoc3::Item.new(
489
+ "blah blah", {}, '/',
490
+ :binary => false
491
+ )
492
+ item.site = site
493
+
494
+ # Create item rep
495
+ item_rep = Nanoc3::ItemRep.new(item, '/foo/')
496
+ item_rep.instance_eval do
497
+ @content[:raw] = item.raw_content
498
+ @content[:last] = @content[:raw]
499
+ end
500
+
501
+ # Layout
502
+ item_rep.layout('/somelayout/')
503
+ assert_equal(%[blah], item_rep.instance_eval { @content[:last] })
504
+ end
505
+
506
+ def test_layout_multiple
507
+ # Mock layout 1
508
+ layouts = [ mock, mock ]
509
+ layouts[0].stubs(:identifier).returns('/one/')
510
+ layouts[0].stubs(:raw_content).returns('{one}<%= yield %>{/one}')
511
+ layouts[1].stubs(:identifier).returns('/two/')
512
+ layouts[1].stubs(:raw_content).returns('{two}<%= yield %>{/two}')
513
+
514
+ # Mock compiler
515
+ stack = mock
516
+ stack.stubs(:push)
517
+ stack.stubs(:pop)
518
+ compiler = mock
519
+ compiler.stubs(:stack).returns(stack)
520
+ compiler.stubs(:filter_for_layout).returns([ :erb, {} ])
521
+
522
+ # Mock site
523
+ site = mock
524
+ site.stubs(:items).returns([])
525
+ site.stubs(:config).returns([])
526
+ site.stubs(:layouts).returns(layouts)
527
+ site.stubs(:compiler).returns(compiler)
528
+
529
+ # Mock item
530
+ item = Nanoc3::Item.new('blah', {}, '/', :binary => false)
531
+ item.site = site
532
+
533
+ # Create item rep
534
+ item_rep = Nanoc3::ItemRep.new(item, '/foo/')
535
+ item_rep.instance_eval do
536
+ @content[:raw] = item.raw_content
537
+ @content[:last] = @content[:raw]
538
+ end
539
+
540
+ # Layout
541
+ item_rep.layout('/one/')
542
+ item_rep.layout('/two/')
543
+ assert_equal('blah', item_rep.instance_eval { @content[:pre] })
544
+ assert_equal('{two}{one}blah{/one}{/two}', item_rep.instance_eval { @content[:post] })
545
+ assert_equal('{two}{one}blah{/one}{/two}', item_rep.instance_eval { @content[:last] })
546
+ end
547
+
548
+ def test_snapshot
549
+ # Mock site
550
+ site = MiniTest::Mock.new
551
+ site.expect(:items, [])
552
+ site.expect(:config, [])
553
+ site.expect(:layouts, [])
554
+
555
+ # Mock item
556
+ item = Nanoc3::Item.new(
557
+ %[<%= '<%= "blah" %' + '>' %>], {}, '/foobar/',
558
+ :binary => false
559
+ )
560
+ item.site = site
561
+
562
+ # Create item rep
563
+ item_rep = Nanoc3::ItemRep.new(item, '/foo/')
564
+ item_rep.instance_eval do
565
+ @content[:raw] = item.raw_content
566
+ @content[:last] = @content[:raw]
567
+ end
568
+
569
+ # Filter while taking snapshots
570
+ item_rep.snapshot(:foo)
571
+ item_rep.filter(:erb)
572
+ item_rep.snapshot(:bar)
573
+ item_rep.filter(:erb)
574
+ item_rep.snapshot(:qux)
575
+
576
+ # Check snapshots
577
+ assert_equal(%[<%= '<%= "blah" %' + '>' %>], item_rep.instance_eval { @content[:foo] })
578
+ assert_equal(%[<%= "blah" %>], item_rep.instance_eval { @content[:bar] })
579
+ assert_equal(%[blah], item_rep.instance_eval { @content[:qux] })
580
+ end
581
+
582
+ def test_write
583
+ # Mock item
584
+ item = Nanoc3::Item.new(
585
+ "blah blah", {}, '/',
586
+ :binary => false
587
+ )
588
+
589
+ # Create rep
590
+ item_rep = Nanoc3::ItemRep.new(item, '/foo/')
591
+ item_rep.instance_eval { @content[:last] = 'Lorem ipsum, etc.' }
592
+ item_rep.raw_path = 'foo/bar/baz/quux.txt'
593
+
594
+ # Write
595
+ item_rep.write
596
+
597
+ # Check
598
+ assert(File.file?('foo/bar/baz/quux.txt'))
599
+ assert_equal('Lorem ipsum, etc.', File.read('foo/bar/baz/quux.txt'))
600
+ end
601
+
602
+ def test_write_should_not_touch_identical_textual_files
603
+ # Mock item
604
+ item = Nanoc3::Item.new(
605
+ "blah blah", {}, '/',
606
+ :binary => false
607
+ )
608
+
609
+ # Create rep
610
+ item_rep = Nanoc3::ItemRep.new(item, '/foo/')
611
+ def item_rep.generate_diff ; end
612
+ item_rep.instance_eval { @content[:last] = 'Lorem ipsum, etc.' }
613
+ item_rep.raw_path = 'foo/bar/baz/quux.txt'
614
+
615
+ # Write once
616
+ item_rep.write
617
+ a_long_time_ago = Time.now-1_000_000
618
+ File.utime(a_long_time_ago, a_long_time_ago, item_rep.raw_path)
619
+
620
+ # Write again
621
+ assert_equal a_long_time_ago.to_s, File.mtime(item_rep.raw_path).to_s
622
+ item_rep.write
623
+ assert_equal a_long_time_ago.to_s, File.mtime(item_rep.raw_path).to_s
624
+ end
625
+
626
+ def test_write_should_not_touch_identical_binary_files
627
+ # Create temporary source file
628
+ File.open('blahblah', 'w') { |io| io.write("Blah blah…") }
629
+ full_file_path = File.expand_path('blahblah')
630
+
631
+ # Mock item
632
+ item = Nanoc3::Item.new(
633
+ full_file_path, {}, '/',
634
+ :binary => true
635
+ )
636
+
637
+ # Create rep
638
+ item_rep = Nanoc3::ItemRep.new(item, '/foo/')
639
+ item_rep.raw_path = 'foo/bar/baz/quux'
640
+
641
+ # Write once
642
+ item_rep.write
643
+ a_long_time_ago = Time.now-1_000_000
644
+ File.utime(a_long_time_ago, a_long_time_ago, item_rep.raw_path)
645
+
646
+ # Write again
647
+ assert_equal a_long_time_ago.to_s, File.mtime(item_rep.raw_path).to_s
648
+ item_rep.write
649
+ assert_equal a_long_time_ago.to_s, File.mtime(item_rep.raw_path).to_s
650
+ end
651
+
652
+ def test_filter_for_layout_with_unmapped_layout
653
+ # Mock site
654
+ site = mock
655
+
656
+ # Mock item
657
+ item = Nanoc3::Item.new(
658
+ "blah blah", {}, '/',
659
+ :binary => false
660
+ )
661
+ item.site = site
662
+
663
+ # Create rep
664
+ rep = Nanoc3::ItemRep.new(item, '/foo/')
665
+
666
+ # Create compiler
667
+ compiler = Nanoc3::Compiler.new(site)
668
+ site.expects(:compiler).returns(compiler)
669
+ compiler.layout_filter_mapping.replace({})
670
+
671
+ # Mock layout
672
+ layout = MiniTest::Mock.new
673
+ layout.expect(:identifier, '/some_layout/')
674
+
675
+ # Check
676
+ assert_raises(Nanoc3::Errors::CannotDetermineFilter) do
677
+ rep.send :filter_for_layout, layout
678
+ end
679
+ end
680
+
681
+ def test_hash
682
+ # Mock item
683
+ item = Nanoc3::Item.new(
684
+ "blah blah", {}, '/',
685
+ :binary => false
686
+ )
687
+
688
+ # Create rep
689
+ rep = Nanoc3::ItemRep.new(item, '/foo/')
690
+
691
+ # Create files
692
+ File.open('one', 'w') { |io| io.write('abc') }
693
+ File.open('two', 'w') { |io| io.write('abcdefghijklmnopqrstuvwxyz') }
694
+
695
+ # Test
696
+ assert_equal 'a9993e364706816aba3e25717850c26c9cd0d89d',
697
+ rep.send(:hash_for_file, 'one')
698
+ assert_equal '32d10c7b8cf96570ca04ce37f2a19d84240d3a89',
699
+ rep.send(:hash_for_file, 'two')
700
+ end
701
+
702
+ def test_filter_text_to_binary
703
+ # Mock item
704
+ item = Nanoc3::Item.new(
705
+ "blah blah", {}, '/',
706
+ :binary => false
707
+ )
708
+
709
+ # Create rep
710
+ rep = Nanoc3::ItemRep.new(item, '/foo/')
711
+ def rep.assigns ; {} ; end
712
+
713
+ # Create fake filter
714
+ def rep.filter_named(name)
715
+ @filter ||= Class.new(::Nanoc3::Filter) do
716
+ type :text => :binary
717
+ def run(content, params={})
718
+ File.open(output_filename, 'w') { |io| io.write(content) }
719
+ end
720
+ end
721
+ end
722
+
723
+ # Run
724
+ rep.filter(:foo)
725
+
726
+ # Check
727
+ assert rep.binary?
728
+ end
729
+
730
+ def test_filter_with_textual_rep_and_binary_filter
731
+ # Mock item
732
+ item = Nanoc3::Item.new(
733
+ "blah blah", {}, '/',
734
+ :binary => false
735
+ )
736
+
737
+ # Create rep
738
+ rep = Nanoc3::ItemRep.new(item, '/foo/')
739
+ def rep.assigns ; {} ; end
740
+
741
+ # Create fake filter
742
+ def rep.filter_named(name)
743
+ @filter ||= Class.new(::Nanoc3::Filter) do
744
+ type :binary
745
+ def run(content, params={})
746
+ File.open(output_filename, 'w') { |io| io.write(content) }
747
+ end
748
+ end
749
+ end
750
+
751
+ # Run
752
+ assert_raises ::Nanoc3::Errors::CannotUseBinaryFilter do
753
+ rep.filter(:foo)
754
+ end
755
+ end
756
+
757
+ def test_filter_get_compiled_content_from_binary_item
758
+ # Mock item
759
+ item = Nanoc3::Item.new(
760
+ "blah blah", {}, '/',
761
+ :binary => true
762
+ )
763
+
764
+ # Create rep
765
+ rep = Nanoc3::ItemRep.new(item, '/foo/')
766
+ def rep.compiled? ; true ; end
767
+
768
+ # Check
769
+ assert_nil rep.compiled_content
770
+ end
771
+
772
+ def test_using_textual_filters_on_binary_reps_raises
773
+ item = create_binary_item
774
+ site = mock_and_stub(:items => [item],
775
+ :layouts => [],
776
+ :config => []
777
+ )
778
+ item.stubs(:site).returns(site)
779
+ rep = create_rep_for(item, '/foo/')
780
+ create_textual_filter
781
+
782
+ assert rep.binary?
783
+ assert_raises(Nanoc3::Errors::CannotUseTextualFilter) { rep.filter(:text_filter) }
784
+ end
785
+
786
+ def test_writing_binary_reps_uses_content_in_last_filename
787
+ require 'tempfile'
788
+
789
+ in_filename = 'nanoc-in'
790
+ out_filename = 'nanoc-out'
791
+ file_content = 'Some content for this test'
792
+ File.open(in_filename, 'w') { |io| io.write(file_content) }
793
+
794
+ item = create_binary_item
795
+ rep = create_rep_for(item, /foo/)
796
+ rep.instance_eval { @filenames[:last] = in_filename }
797
+ rep.raw_path = out_filename
798
+
799
+ rep.write
800
+
801
+ assert(File.exist?(out_filename))
802
+ assert_equal(file_content, File.read(out_filename))
803
+ end
804
+
805
+ def test_converted_binary_rep_can_be_layed_out
806
+ layout = mock_and_stub(
807
+ :identifier => '/somelayout/',
808
+ :raw_content => %[<%= "blah" %> <%= yield %>]
809
+ )
810
+
811
+ # Mock compiler
812
+ stack = mock_and_stub(:pop => layout)
813
+ stack.stubs(:push).returns(stack)
814
+ compiler = mock_and_stub(
815
+ :stack => stack,
816
+ :filter_for_layout => [ :erb, {} ]
817
+ )
818
+
819
+ # Mock site
820
+ site = mock_and_stub(
821
+ :items => [],
822
+ :config => [],
823
+ :layouts => [ layout ],
824
+ :compiler => compiler
825
+ )
826
+
827
+ item = create_binary_item
828
+ item.site = site
829
+
830
+ rep = create_rep_for(item, '/foo/')
831
+ def rep.filter_named(name)
832
+ @filter ||= Class.new(::Nanoc3::Filter) do
833
+ type :binary => :text
834
+ def run(content, params={})
835
+ "Some textual content"
836
+ end
837
+ end
838
+ end
839
+
840
+ rep.filter(:binary_to_text)
841
+ rep.layout('/somelayout/')
842
+ assert_equal('blah Some textual content', rep.instance_eval { @content[:last] })
843
+ end
844
+
845
+ def test_converted_binary_rep_can_be_filterd_with_textual_filters
846
+ item = create_binary_item
847
+ site = mock_and_stub(:items => [item],
848
+ :layouts => [],
849
+ :config => []
850
+ )
851
+ item.stubs(:site).returns(site)
852
+ rep = create_rep_for(item, /foo/)
853
+ create_textual_filter
854
+
855
+ assert rep.binary?
856
+
857
+ def rep.filter_named(name)
858
+ Class.new(::Nanoc3::Filter) do
859
+ type :binary => :text
860
+ def run(content, params={})
861
+ "Some textual content"
862
+ end
863
+ end
864
+ end
865
+ rep.filter(:binary_to_text)
866
+ assert !rep.binary?
867
+
868
+ def rep.filter_named(name)
869
+ Class.new(::Nanoc3::Filter) do
870
+ type :text
871
+ def run(content, params={})
872
+ "Some textual content"
873
+ end
874
+ end
875
+ end
876
+ rep.filter(:text_filter)
877
+ assert !rep.binary?
878
+ end
879
+
880
+ def test_converted_binary_rep_cannot_be_filterd_with_binary_filters
881
+ item = create_binary_item
882
+ site = mock_and_stub(
883
+ :items => [item],
884
+ :layouts => [],
885
+ :config => []
886
+ )
887
+ item.stubs(:site).returns(site)
888
+ rep = create_rep_for(item, '/foo/')
889
+ create_binary_filter
890
+
891
+ assert rep.binary?
892
+ def rep.filter_named(name)
893
+ @filter ||= Class.new(::Nanoc3::Filter) do
894
+ type :binary => :text
895
+ def run(content, params={})
896
+ "Some textual content"
897
+ end
898
+ end
899
+ end
900
+ rep.filter(:binary_to_text)
901
+ assert ! rep.binary?
902
+ assert_raises(Nanoc3::Errors::CannotUseBinaryFilter) { rep.filter(:binary_filter) }
903
+ end
904
+
905
+ private
906
+
907
+ def create_binary_item
908
+ Nanoc3::Item.new(
909
+ "/a/file/name.dat", {}, '/',
910
+ :binary => true
911
+ )
912
+ end
913
+
914
+ def mock_and_stub(params)
915
+ m = mock
916
+ params.each do |method, return_value|
917
+ m.stubs(method.to_sym).returns( return_value )
918
+ end
919
+ m
920
+ end
921
+
922
+ def create_rep_for(item, name)
923
+ Nanoc3::ItemRep.new(item, name)
924
+ end
925
+
926
+ def create_textual_filter
927
+ f = create_filter(:text)
928
+ f.class_eval do
929
+ def run(content, params={})
930
+ ""
931
+ end
932
+ end
933
+ f
934
+ end
935
+
936
+ def create_binary_filter
937
+ f = create_filter(:binary)
938
+ f.class_eval do
939
+ def run(content, params={})
940
+ File.open(output_filename, 'w') { |io| io.write(content) }
941
+ end
942
+ end
943
+ f
944
+ end
945
+
946
+ def create_filter(type)
947
+ filter_klass = Class.new(Nanoc3::Filter)
948
+ filter_klass.type(type)
949
+ Nanoc3::Filter.register filter_klass, "#{type}_filter".to_sym
950
+ filter_klass
951
+ end
952
+
953
+ end