nanoc-filesystem-i18n 0.1.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,61 @@
1
+ require 'helper'
2
+
3
+ class TestNanocFilesystemI18n < MiniTest::Unit::TestCase
4
+
5
+ include Nanoc3::TestHelpers
6
+
7
+ def new_data_source(params=nil)
8
+ # Mock site
9
+ site = Nanoc3::Site.new({})
10
+
11
+ # Create data source
12
+ data_source = Nanoc3::DataSources::FilesystemI18n.new(site, nil, nil, params)
13
+ data_source.up
14
+
15
+ # Done
16
+ data_source
17
+ end
18
+
19
+ def test_create_object_not_at_root
20
+ # Create item
21
+ data_source = new_data_source
22
+ data_source.send(:create_object, 'foobar', 'content here', { :foo => 'bar' }, '/asdf/')
23
+
24
+ # Check file existance
25
+ assert File.directory?('foobar')
26
+ assert !File.directory?('foobar/content')
27
+ assert !File.directory?('foobar/asdf')
28
+ assert File.file?('foobar/asdf.yaml')
29
+ assert File.file?('foobar/asdf.html')
30
+
31
+ # Check file meta
32
+ expected = "--- \nfoo: bar\n"
33
+ assert_equal expected, File.read('foobar/asdf.yaml')
34
+
35
+ # Check file content
36
+ expected = "content here"
37
+ assert_equal expected, File.read('foobar/asdf.html')
38
+ end
39
+
40
+ def test_create_object_at_root
41
+ # Create item
42
+ data_source = new_data_source
43
+ data_source.send(:create_object, 'foobar', 'content here', { :foo => 'bar' }, '/')
44
+
45
+ # Check file existance
46
+ assert File.directory?('foobar')
47
+ assert !File.directory?('foobar/index')
48
+ assert !File.directory?('foobar/foobar')
49
+ assert File.file?('foobar/index.yaml')
50
+ assert File.file?('foobar/index.html')
51
+
52
+ # Check file meta
53
+ expected = "--- \nfoo: bar\n"
54
+ assert_equal expected, File.read('foobar/index.yaml')
55
+
56
+ # Check file content
57
+ expected = "content here"
58
+ assert_equal expected, File.read('foobar/index.html')
59
+ end
60
+
61
+ end
@@ -0,0 +1,461 @@
1
+ # encoding: utf-8
2
+
3
+ require 'test/helper'
4
+
5
+ class Nanoc3::DataSources::FilesystemUnifiedTest < MiniTest::Unit::TestCase
6
+
7
+ include Nanoc3::TestHelpers
8
+
9
+ def new_data_source(params=nil)
10
+ # Mock site
11
+ site = Nanoc3::Site.new({})
12
+
13
+ # Create data source
14
+ # I18n: call `up` to setup locale config
15
+ data_source = Nanoc3::DataSources::FilesystemI18n.new(site, nil, nil, params)
16
+ data_source.up
17
+
18
+ # Done
19
+ data_source
20
+ end
21
+
22
+ def test_load_objects
23
+ # Create data source
24
+ data_source = new_data_source
25
+
26
+ # Create a fake class
27
+ klass = Class.new do
28
+ attr_reader :stuff
29
+ def initialize(*stuff)
30
+ @stuff = stuff
31
+ end
32
+ def ==(other)
33
+ @stuff == other.stuff
34
+ end
35
+ end
36
+
37
+ # Create sample files
38
+ FileUtils.mkdir_p('foo')
39
+ FileUtils.mkdir_p('foo/a/b')
40
+ File.open('foo/bar.html', 'w') { |io| io.write("---\nnum: 1\n---\ntest 1") }
41
+ File.open('foo/b.c.html', 'w') { |io| io.write("---\nnum: 2\n---\ntest 2") }
42
+ File.open('foo/a/b/c.html', 'w') { |io| io.write("---\nnum: 3\n---\ntest 3") }
43
+ File.open('foo/ugly.html~', 'w') { |io| io.write("---\nnum: 4\n---\ntest 4") }
44
+ File.open('foo/ugly.html.orig', 'w') { |io| io.write("---\nnum: 5\n---\ntest 5") }
45
+ File.open('foo/ugly.html.rej', 'w') { |io| io.write("---\nnum: 6\n---\ntest 6") }
46
+ File.open('foo/ugly.html.bak', 'w') { |io| io.write("---\nnum: 7\n---\ntest 7") }
47
+
48
+ # Get expected and actual output
49
+ expected_out = [
50
+ klass.new(
51
+ 'test 1',
52
+ { 'num' => 1, :filename => 'foo/bar.html', :extension => 'html', :file => File.open('foo/bar.html') },
53
+ '/bar/',
54
+ :binary => false, :mtime => File.mtime('foo/bar.html')
55
+ ),
56
+ klass.new(
57
+ 'test 2',
58
+ { 'num' => 2, :filename => 'foo/b.c.html', :extension => 'c.html', :file => File.open('foo/b.c.html') },
59
+ '/b/',
60
+ :binary => false, :mtime => File.mtime('foo/b.c.html')
61
+ ),
62
+ klass.new(
63
+ 'test 3',
64
+ { 'num' => 3, :filename => 'foo/a/b/c.html', :extension => 'html', :file => File.open('foo/a/b/c.html') },
65
+ '/a/b/c/',
66
+ :binary => false, :mtime => File.mtime('foo/a/b/c.html')
67
+ )
68
+ ]
69
+ actual_out = data_source.send(:load_objects, 'foo', 'The Foo', klass).sort_by { |i| i.stuff[0] }
70
+
71
+ # Check
72
+ (0..expected_out.size-1).each do |i|
73
+ assert_equal expected_out[i].stuff[0], actual_out[i].stuff[0], 'content must match'
74
+ assert_equal expected_out[i].stuff[2], actual_out[i].stuff[2], 'identifier must match'
75
+ assert_equal expected_out[i].stuff[3][:mtime], actual_out[i].stuff[3][:mtime], 'mtime must match'
76
+ assert_equal expected_out[i].stuff[1][:file].path, actual_out[i].stuff[1][:file].path, 'file paths must match'
77
+ [ 'num', :filename, :extension ].each do |key|
78
+ assert_equal expected_out[i].stuff[1][key], actual_out[i].stuff[1][key], "attribute key #{key} must match"
79
+ end
80
+ end
81
+ end
82
+
83
+ def test_load_binary_objects
84
+ # Create data source
85
+ data_source = new_data_source
86
+
87
+ # Create sample files
88
+ FileUtils.mkdir_p('foo')
89
+ File.open('foo/stuff.dat', 'w') { |io| io.write("random binary data") }
90
+
91
+ # Load
92
+ items = data_source.send(:load_objects, 'foo', 'item', Nanoc3::Item)
93
+
94
+ # Check
95
+ assert_equal 1, items.size
96
+ assert items[0].binary?
97
+ assert_equal 'foo/stuff.dat', items[0].raw_filename
98
+ assert_nil items[0].raw_content
99
+ end
100
+
101
+ def test_load_binary_layouts
102
+ # Create data source
103
+ data_source = new_data_source
104
+
105
+ # Create sample files
106
+ FileUtils.mkdir_p('foo')
107
+ File.open('foo/stuff.dat', 'w') { |io| io.write("random binary data") }
108
+
109
+ # Load
110
+ items = data_source.send(:load_objects, 'foo', 'item', Nanoc3::Layout)
111
+
112
+ # Check
113
+ assert_equal 1, items.size
114
+ assert_equal 'random binary data', items[0].raw_content
115
+ end
116
+
117
+ def test_identifier_for_filename_allowing_periods_in_identifiers
118
+ # Create data source
119
+ data_source = new_data_source(:allow_periods_in_identifiers => true)
120
+
121
+ # Get input and expected output
122
+ expected = {
123
+ '/foo' => '/foo/',
124
+ '/foo.html' => '/foo/',
125
+ '/foo/index.html' => '/foo/',
126
+ '/foo.entry.html' => '/foo.entry/'
127
+ }
128
+
129
+ # Check
130
+ expected.each_pair do |input, expected_output|
131
+ actual_output = data_source.send(:identifier_for_filename, input)
132
+ assert_equal(
133
+ expected_output, actual_output,
134
+ "identifier_for_filename(#{input.inspect}) should equal #{expected_output.inspect}, not #{actual_output.inspect}"
135
+ )
136
+ end
137
+ end
138
+
139
+ def test_identifier_for_filename_disallowing_periods_in_identifiers
140
+ # Create data source
141
+ data_source = new_data_source
142
+
143
+ # Get input and expected output
144
+ expected = {
145
+ '/foo' => '/foo/',
146
+ '/foo.html' => '/foo/',
147
+ '/foo/index.html' => '/foo/',
148
+ '/foo.html.erb' => '/foo/'
149
+ }
150
+
151
+ # Check
152
+ expected.each_pair do |input, expected_output|
153
+ actual_output = data_source.send(:identifier_for_filename, input)
154
+ assert_equal(
155
+ expected_output, actual_output,
156
+ "identifier_for_filename(#{input.inspect}) should equal #{expected_output.inspect}, not #{actual_output.inspect}"
157
+ )
158
+ end
159
+ end
160
+
161
+ def test_identifier_for_filename_with_subfilename_allowing_periods_in_identifiers
162
+ # Create data source
163
+ data_source = new_data_source(:allow_periods_in_identifiers => true)
164
+
165
+ # Build directory
166
+ FileUtils.mkdir_p('foo')
167
+ File.open('foo/bar.yaml', 'w') { |io| io.write('test') }
168
+ File.open('foo/bar.html', 'w') { |io| io.write('test') }
169
+ File.open('foo/quxbar.yaml', 'w') { |io| io.write('test') }
170
+ File.open('foo/quxbar.html', 'w') { |io| io.write('test') }
171
+ File.open('foo/barqux.yaml', 'w') { |io| io.write('test') }
172
+ File.open('foo/barqux.html', 'w') { |io| io.write('test') }
173
+ File.open('foo/quxbarqux.yaml', 'w') { |io| io.write('test') }
174
+ File.open('foo/quxbarqux.html', 'w') { |io| io.write('test') }
175
+ File.open('foo/qux.bar.yaml', 'w') { |io| io.write('test') }
176
+ File.open('foo/qux.bar.html', 'w') { |io| io.write('test') }
177
+ File.open('foo/bar.qux.yaml', 'w') { |io| io.write('test') }
178
+ File.open('foo/bar.qux.html', 'w') { |io| io.write('test') }
179
+ File.open('foo/qux.bar.qux.yaml', 'w') { |io| io.write('test') }
180
+ File.open('foo/qux.bar.qux.html', 'w') { |io| io.write('test') }
181
+
182
+ # Check content filename
183
+ {
184
+ 'foo/bar.yaml' => '/foo/bar/',
185
+ 'foo/quxbar.yaml' => '/foo/quxbar/',
186
+ 'foo/barqux.yaml' => '/foo/barqux/',
187
+ 'foo/quxbarqux.yaml' => '/foo/quxbarqux/',
188
+ 'foo/qux.bar.yaml' => '/foo/qux.bar/',
189
+ 'foo/bar.qux.yaml' => '/foo/bar.qux/',
190
+ 'foo/qux.bar.qux.yaml' => '/foo/qux.bar.qux/'
191
+ }.each_pair do |meta_filename, expected_identifier|
192
+ assert_equal(
193
+ expected_identifier,
194
+ data_source.instance_eval { identifier_for_filename(meta_filename) }
195
+ )
196
+ end
197
+ end
198
+
199
+ def test_identifier_for_filename_with_subfilename_disallowing_periods_in_identifiers
200
+ # Create data source
201
+ data_source = new_data_source
202
+
203
+ # Build directory
204
+ FileUtils.mkdir_p('foo')
205
+ File.open('foo/bar.yaml', 'w') { |io| io.write('test') }
206
+ File.open('foo/bar.html', 'w') { |io| io.write('test') }
207
+ File.open('foo/quxbar.yaml', 'w') { |io| io.write('test') }
208
+ File.open('foo/quxbar.html', 'w') { |io| io.write('test') }
209
+ File.open('foo/barqux.yaml', 'w') { |io| io.write('test') }
210
+ File.open('foo/barqux.html', 'w') { |io| io.write('test') }
211
+ File.open('foo/quxbarqux.yaml', 'w') { |io| io.write('test') }
212
+ File.open('foo/quxbarqux.html', 'w') { |io| io.write('test') }
213
+ File.open('foo/qux.bar.yaml', 'w') { |io| io.write('test') }
214
+ File.open('foo/qux.bar.html', 'w') { |io| io.write('test') }
215
+ File.open('foo/bar.qux.yaml', 'w') { |io| io.write('test') }
216
+ File.open('foo/bar.qux.html', 'w') { |io| io.write('test') }
217
+ File.open('foo/qux.bar.qux.yaml', 'w') { |io| io.write('test') }
218
+ File.open('foo/qux.bar.qux.html', 'w') { |io| io.write('test') }
219
+
220
+ # Check content filename
221
+ {
222
+ 'foo/bar.yaml' => '/foo/bar/',
223
+ 'foo/quxbar.yaml' => '/foo/quxbar/',
224
+ 'foo/barqux.yaml' => '/foo/barqux/',
225
+ 'foo/quxbarqux.yaml' => '/foo/quxbarqux/',
226
+ 'foo/qux.bar.yaml' => '/foo/qux/',
227
+ 'foo/bar.qux.yaml' => '/foo/bar/',
228
+ 'foo/qux.bar.qux.yaml' => '/foo/qux/'
229
+ }.each_pair do |meta_filename, expected_identifier|
230
+ assert_equal(
231
+ expected_identifier,
232
+ data_source.instance_eval { identifier_for_filename(meta_filename) }
233
+ )
234
+ end
235
+ end
236
+
237
+ def test_load_objects_allowing_periods_in_identifiers
238
+ # Create data source
239
+ data_source = new_data_source(:allow_periods_in_identifiers => true)
240
+
241
+ # Create a fake class
242
+ klass = Class.new do
243
+ attr_reader :stuff
244
+ def initialize(*stuff)
245
+ @stuff = stuff
246
+ end
247
+ def ==(other)
248
+ @stuff == other.stuff
249
+ end
250
+ end
251
+
252
+ # Create sample files
253
+ FileUtils.mkdir_p('foo')
254
+ FileUtils.mkdir_p('foo/a/b')
255
+ File.open('foo/a/b/c.yaml', 'w') { |io| io.write("---\nnum: 1\n") }
256
+ File.open('foo/b.c.yaml', 'w') { |io| io.write("---\nnum: 2\n") }
257
+ File.open('foo/b.c.html', 'w') { |io| io.write("test 2") }
258
+ File.open('foo/car.html', 'w') { |io| io.write("test 3") }
259
+ File.open('foo/ugly.yaml~', 'w') { |io| io.write("blah") }
260
+ File.open('foo/ugly.html~', 'w') { |io| io.write("blah") }
261
+ File.open('foo/ugly.html.orig', 'w') { |io| io.write("blah") }
262
+ File.open('foo/ugly.html.rej', 'w') { |io| io.write("blah") }
263
+ File.open('foo/ugly.html.bak', 'w') { |io| io.write("blah") }
264
+
265
+ # Get expected output
266
+ expected_out = [
267
+ klass.new(
268
+ '',
269
+ {
270
+ 'num' => 1,
271
+ :content_filename => nil,
272
+ :meta_filename => 'foo/a/b/c.yaml',
273
+ :extension => nil,
274
+ :file => nil
275
+ },
276
+ '/a/b/c/',
277
+ :binary => false, :mtime => File.mtime('foo/a/b/c.yaml')
278
+ ),
279
+ klass.new(
280
+ 'test 2',
281
+ {
282
+ 'num' => 2,
283
+ :content_filename => 'foo/b.c.html',
284
+ :meta_filename => 'foo/b.c.yaml',
285
+ :extension => 'html',
286
+ :file => File.open('foo/b.c.html')
287
+ },
288
+ '/b.c/',
289
+ :binary => false, :mtime => File.mtime('foo/b.c.html') > File.mtime('foo/b.c.yaml') ? File.mtime('foo/b.c.html') : File.mtime('foo/b.c.yaml')
290
+ ),
291
+ klass.new(
292
+ 'test 3',
293
+ {
294
+ :content_filename => 'foo/car.html',
295
+ :meta_filename => nil,
296
+ :extension => 'html',
297
+ :file => File.open('foo/car.html')
298
+ },
299
+ '/car/',
300
+ :binary => false, :mtime => File.mtime('foo/car.html')
301
+ )
302
+ ]
303
+
304
+ # Get actual output ordered by identifier
305
+ actual_out = data_source.send(:load_objects, 'foo', 'The Foo', klass).sort_by { |i| i.stuff[2] }
306
+
307
+ # Check
308
+ (0..expected_out.size-1).each do |i|
309
+ assert_equal expected_out[i].stuff[0], actual_out[i].stuff[0], 'content must match'
310
+ assert_equal expected_out[i].stuff[2], actual_out[i].stuff[2], 'identifier must match'
311
+ assert_equal expected_out[i].stuff[3][:mtime], actual_out[i].stuff[3][:mtime], 'mtime must match'
312
+
313
+ actual_file = actual_out[i].stuff[1][:file]
314
+ expected_file = expected_out[i].stuff[1][:file]
315
+ assert(actual_file == expected_file || actual_file.path == expected_file.path, 'file paths must match')
316
+
317
+ [ 'num', :content_filename, :meta_filename, :extension ].each do |key|
318
+ assert_equal expected_out[i].stuff[1][key], actual_out[i].stuff[1][key], "attribute key #{key} must match"
319
+ end
320
+ end
321
+ end
322
+
323
+ def test_load_objects_disallowing_periods_in_identifiers
324
+ # Create data source
325
+ data_source = new_data_source
326
+
327
+ # Create a fake class
328
+ klass = Class.new do
329
+ attr_reader :stuff
330
+ def initialize(*stuff)
331
+ @stuff = stuff
332
+ end
333
+ def ==(other)
334
+ @stuff == other.stuff
335
+ end
336
+ end
337
+
338
+ # Create sample files
339
+ FileUtils.mkdir_p('foo')
340
+ FileUtils.mkdir_p('foo/a/b')
341
+ File.open('foo/a/b/c.yaml', 'w') { |io| io.write("---\nnum: 1\n") }
342
+ File.open('foo/b.yaml', 'w') { |io| io.write("---\nnum: 2\n") }
343
+ File.open('foo/b.html.erb', 'w') { |io| io.write("test 2") }
344
+ File.open('foo/car.html', 'w') { |io| io.write("test 3") }
345
+ File.open('foo/ugly.yaml~', 'w') { |io| io.write("blah") }
346
+ File.open('foo/ugly.html~', 'w') { |io| io.write("blah") }
347
+ File.open('foo/ugly.html.orig', 'w') { |io| io.write("blah") }
348
+ File.open('foo/ugly.html.rej', 'w') { |io| io.write("blah") }
349
+ File.open('foo/ugly.html.bak', 'w') { |io| io.write("blah") }
350
+
351
+ # Get expected output
352
+ expected_out = [
353
+ klass.new(
354
+ '',
355
+ {
356
+ 'num' => 1,
357
+ :content_filename => nil,
358
+ :meta_filename => 'foo/a/b/c.yaml',
359
+ :extension => nil,
360
+ :file => nil
361
+ },
362
+ '/a/b/c/',
363
+ :binary => false, :mtime => File.mtime('foo/a/b/c.yaml')
364
+ ),
365
+ klass.new(
366
+ 'test 2',
367
+ {
368
+ 'num' => 2,
369
+ :content_filename => 'foo/b.html.erb',
370
+ :meta_filename => 'foo/b.yaml',
371
+ :extension => 'html.erb',
372
+ :file => File.open('foo/b.html.erb')
373
+ },
374
+ '/b/',
375
+ :binary => false, :mtime => File.mtime('foo/b.html.erb') > File.mtime('foo/b.yaml') ? File.mtime('foo/b.html.erb') : File.mtime('foo/b.yaml')
376
+ ),
377
+ klass.new(
378
+ 'test 3',
379
+ {
380
+ :content_filename => 'foo/car.html',
381
+ :meta_filename => nil,
382
+ :extension => 'html',
383
+ :file => File.open('foo/car.html')
384
+ },
385
+ '/car/',
386
+ :binary => false, :mtime => File.mtime('foo/car.html')
387
+ )
388
+ ]
389
+
390
+ # Get actual output ordered by identifier
391
+ actual_out = data_source.send(:load_objects, 'foo', 'The Foo', klass).sort_by { |i| i.stuff[2] }
392
+
393
+ # Check
394
+ (0..expected_out.size-1).each do |i|
395
+ assert_equal expected_out[i].stuff[0], actual_out[i].stuff[0], 'content must match'
396
+ assert_equal expected_out[i].stuff[2], actual_out[i].stuff[2], 'identifier must match'
397
+ assert_equal expected_out[i].stuff[3][:mtime], actual_out[i].stuff[3][:mtime], 'mtime must match'
398
+
399
+ actual_file = actual_out[i].stuff[1][:file]
400
+ expected_file = expected_out[i].stuff[1][:file]
401
+ assert(actual_file == expected_file || actual_file.path == expected_file.path, 'file paths must match')
402
+
403
+ [ 'num', :content_filename, :meta_filename, :extension ].each do |key|
404
+ assert_equal expected_out[i].stuff[1][key], actual_out[i].stuff[1][key], "attribute key #{key} must match"
405
+ end
406
+ end
407
+ end
408
+
409
+ def test_create_object_allowing_periods_in_identifiers
410
+ # Create data source
411
+ data_source = new_data_source(:allow_periods_in_identifiers => true)
412
+
413
+ # Create object without period
414
+ data_source.send(:create_object, 'foo', 'some content', { :some => 'attributes' }, '/asdf/')
415
+ assert File.file?('foo/asdf.html')
416
+ data = data_source.send(:parse, 'foo/asdf.html', 'foo/asdf.yaml', 'moo', false)
417
+ assert_equal({ 'some' => 'attributes' }, data[0])
418
+ assert_equal('some content', data[1])
419
+
420
+ # Create object with period
421
+ data_source.send(:create_object, 'foo', 'some content', { :some => 'attributes' }, '/as.df/')
422
+ assert File.file?('foo/as.df.html')
423
+ data = data_source.send(:parse, 'foo/as.df.html', 'foo/asdf.yaml', 'moo', false)
424
+ assert_equal({ 'some' => 'attributes' }, data[0])
425
+ assert_equal('some content', data[1])
426
+ end
427
+
428
+ def test_create_object_disallowing_periods_in_identifiers
429
+ # Create data source
430
+ data_source = new_data_source
431
+
432
+ # Create object without period
433
+ data_source.send(:create_object, 'foo', 'some content', { :some => 'attributes' }, '/asdf/')
434
+ assert File.file?('foo/asdf.html')
435
+ data = data_source.send(:parse, 'foo/asdf.html', 'foo/asdf.yaml', 'moo', false)
436
+ assert_equal({ 'some' => 'attributes' }, data[0])
437
+ assert_equal('some content', data[1])
438
+
439
+ # Create object with period
440
+ assert_raises(RuntimeError) do
441
+ data_source.send(:create_object, 'foo', 'some content', { :some => 'attributes' }, '/as.df/')
442
+ end
443
+ end
444
+
445
+ def test_compile_huge_site
446
+ # Create data source
447
+ data_source = new_data_source
448
+
449
+ # Create a lot of items
450
+ count = Process.getrlimit(Process::RLIMIT_NOFILE)[0] + 5
451
+ count.times do |i|
452
+ FileUtils.mkdir_p("content/#{i}")
453
+ File.open("content/#{i}/#{i}.html", 'w') { |io| io << "This is item #{i}." }
454
+ File.open("content/#{i}/#{i}.yaml", 'w') { |io| io << "title: Item #{i}" }
455
+ end
456
+
457
+ # Read all items
458
+ data_source.items
459
+ end
460
+
461
+ end