cuprum-cli 0.1.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 (65) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +34 -0
  3. data/CODE_OF_CONDUCT.md +10 -0
  4. data/LICENSE +21 -0
  5. data/README.md +163 -0
  6. data/lib/cuprum/cli/argument.rb +172 -0
  7. data/lib/cuprum/cli/arguments/class_methods.rb +283 -0
  8. data/lib/cuprum/cli/arguments.rb +16 -0
  9. data/lib/cuprum/cli/coercion.rb +131 -0
  10. data/lib/cuprum/cli/command.rb +102 -0
  11. data/lib/cuprum/cli/commands/ci/report.rb +121 -0
  12. data/lib/cuprum/cli/commands/ci/rspec_command.rb +108 -0
  13. data/lib/cuprum/cli/commands/ci/rspec_each_command.rb +185 -0
  14. data/lib/cuprum/cli/commands/ci.rb +12 -0
  15. data/lib/cuprum/cli/commands/echo_command.rb +76 -0
  16. data/lib/cuprum/cli/commands/file/generate_file.rb +141 -0
  17. data/lib/cuprum/cli/commands/file/new_command.rb +86 -0
  18. data/lib/cuprum/cli/commands/file/render_erb.rb +88 -0
  19. data/lib/cuprum/cli/commands/file/resolve_template.rb +136 -0
  20. data/lib/cuprum/cli/commands/file/templates/rspec.rb.erb +14 -0
  21. data/lib/cuprum/cli/commands/file/templates/ruby.rb.erb +29 -0
  22. data/lib/cuprum/cli/commands/file/templates.rb +71 -0
  23. data/lib/cuprum/cli/commands/file.rb +14 -0
  24. data/lib/cuprum/cli/commands.rb +12 -0
  25. data/lib/cuprum/cli/dependencies/file_system/mock.rb +297 -0
  26. data/lib/cuprum/cli/dependencies/file_system.rb +247 -0
  27. data/lib/cuprum/cli/dependencies/standard_io/helpers.rb +138 -0
  28. data/lib/cuprum/cli/dependencies/standard_io/mock.rb +85 -0
  29. data/lib/cuprum/cli/dependencies/standard_io.rb +110 -0
  30. data/lib/cuprum/cli/dependencies/system_command/mock.rb +57 -0
  31. data/lib/cuprum/cli/dependencies/system_command.rb +147 -0
  32. data/lib/cuprum/cli/dependencies.rb +25 -0
  33. data/lib/cuprum/cli/errors/files/file_not_writeable.rb +42 -0
  34. data/lib/cuprum/cli/errors/files/missing_parameter.rb +71 -0
  35. data/lib/cuprum/cli/errors/files/missing_template.rb +36 -0
  36. data/lib/cuprum/cli/errors/files/template_error.rb +37 -0
  37. data/lib/cuprum/cli/errors/files/template_not_resolved.rb +54 -0
  38. data/lib/cuprum/cli/errors/files.rb +19 -0
  39. data/lib/cuprum/cli/errors/system_command_failure.rb +44 -0
  40. data/lib/cuprum/cli/errors.rb +11 -0
  41. data/lib/cuprum/cli/integrations/thor/arguments_parser.rb +99 -0
  42. data/lib/cuprum/cli/integrations/thor/registry.rb +42 -0
  43. data/lib/cuprum/cli/integrations/thor/task.rb +211 -0
  44. data/lib/cuprum/cli/integrations/thor.rb +14 -0
  45. data/lib/cuprum/cli/integrations.rb +8 -0
  46. data/lib/cuprum/cli/metadata.rb +215 -0
  47. data/lib/cuprum/cli/option.rb +165 -0
  48. data/lib/cuprum/cli/options/class_methods.rb +232 -0
  49. data/lib/cuprum/cli/options/quiet.rb +32 -0
  50. data/lib/cuprum/cli/options/verbose.rb +32 -0
  51. data/lib/cuprum/cli/options.rb +18 -0
  52. data/lib/cuprum/cli/registry.rb +141 -0
  53. data/lib/cuprum/cli/rspec/deferred/arguments_examples.rb +203 -0
  54. data/lib/cuprum/cli/rspec/deferred/ci/report_examples.rb +450 -0
  55. data/lib/cuprum/cli/rspec/deferred/ci.rb +8 -0
  56. data/lib/cuprum/cli/rspec/deferred/dependencies/file_system_examples.rb +1469 -0
  57. data/lib/cuprum/cli/rspec/deferred/dependencies.rb +8 -0
  58. data/lib/cuprum/cli/rspec/deferred/metadata_examples.rb +856 -0
  59. data/lib/cuprum/cli/rspec/deferred/options_examples.rb +234 -0
  60. data/lib/cuprum/cli/rspec/deferred/registry_examples.rb +451 -0
  61. data/lib/cuprum/cli/rspec/deferred.rb +8 -0
  62. data/lib/cuprum/cli/rspec.rb +8 -0
  63. data/lib/cuprum/cli/version.rb +59 -0
  64. data/lib/cuprum/cli.rb +47 -0
  65. metadata +173 -0
@@ -0,0 +1,1469 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec/sleeping_king_studios/deferred/provider'
4
+
5
+ require 'cuprum/cli/rspec/deferred/dependencies'
6
+
7
+ module Cuprum::Cli::RSpec::Deferred::Dependencies
8
+ # Deferred examples for testing the FileSystem dependency.
9
+ module FileSystemExamples
10
+ include RSpec::SleepingKingStudios::Deferred::Provider
11
+
12
+ deferred_examples 'should implement the file_system dependency' do
13
+ describe '#create_directory', :writeable_root_path do
14
+ let(:base_path) { nil }
15
+ let(:path) { nil }
16
+
17
+ include_deferred 'with valid file paths'
18
+
19
+ include_deferred 'when created directories are cleaned up'
20
+
21
+ it 'should define the method' do
22
+ expect(subject)
23
+ .to respond_to(:create_directory)
24
+ .with(1).argument
25
+ .and_keywords(:recursive)
26
+ end
27
+
28
+ it 'should define the aliased method' do
29
+ expect(subject)
30
+ .to have_aliased_method(:create_directory)
31
+ .as(:make_directory)
32
+ end
33
+
34
+ describe 'with nil' do
35
+ let(:error_message) do
36
+ tools.assertions.error_message_for('presence', as: :path)
37
+ end
38
+
39
+ it 'should raise an exception' do
40
+ expect { subject.create_directory(nil) }
41
+ .to raise_error ArgumentError, error_message
42
+ end
43
+ end
44
+
45
+ describe 'with an Object' do
46
+ let(:error_message) do
47
+ tools.assertions.error_message_for('name', as: :path)
48
+ end
49
+
50
+ it 'should raise an exception' do
51
+ expect { subject.create_directory(Object.new.freeze) }
52
+ .to raise_error ArgumentError, error_message
53
+ end
54
+ end
55
+
56
+ describe 'with an empty String' do
57
+ let(:error_message) do
58
+ tools.assertions.error_message_for('presence', as: :path)
59
+ end
60
+
61
+ it 'should raise an exception' do
62
+ expect { subject.create_directory('') }
63
+ .to raise_error ArgumentError, error_message
64
+ end
65
+ end
66
+
67
+ describe 'with an absolute path' do
68
+ let(:base_path) { absolute_directory_path }
69
+ let(:path) { File.join(base_path, 'custom_dir') }
70
+
71
+ it { expect(subject.create_directory(path)).to be == path }
72
+
73
+ it 'should create the directory' do
74
+ expect { subject.create_directory(path) }.to(
75
+ change { subject.directory?(path) }.to(be true)
76
+ )
77
+ end
78
+
79
+ describe 'with a multi-segment path' do
80
+ let(:path) { File.join(base_path, 'custom_dir/inner/path') }
81
+ let(:error_class) do
82
+ Cuprum::Cli::Dependencies::FileSystem::DirectoryNotFoundError
83
+ end
84
+ let(:error_message) do
85
+ "unable to create directory #{path} - directory not found"
86
+ end
87
+
88
+ it 'should raise an exception' do
89
+ expect { subject.create_directory(path) }
90
+ .to raise_error(error_class, error_message)
91
+ end
92
+
93
+ describe 'with recursive: true' do
94
+ it 'should return the path' do
95
+ expect(subject.create_directory(path, recursive: true))
96
+ .to be == path
97
+ end
98
+
99
+ it 'should create the directory' do
100
+ expect { subject.create_directory(path, recursive: true) }.to(
101
+ change { subject.directory?(path) }.to(be true)
102
+ )
103
+ end
104
+
105
+ context 'when the directory already exists' do
106
+ before(:example) do
107
+ subject.create_directory(path, recursive: true)
108
+ end
109
+
110
+ it { expect(subject.create_directory(path)).to be == path }
111
+ end
112
+
113
+ context 'when the path includes a file' do
114
+ let(:error_class) do
115
+ Cuprum::Cli::Dependencies::FileSystem::DirectoryIsAFileError
116
+ end
117
+ let(:error_message) do
118
+ "unable to create directory #{path} - directory is a file"
119
+ end
120
+ let(:file_path) { File.join(base_path, 'custom_dir') }
121
+
122
+ before(:example) do
123
+ subject.write_file(file_path, '')
124
+ end
125
+
126
+ include_deferred 'when created files are cleaned up'
127
+
128
+ it 'should raise an exception' do
129
+ expect { subject.create_directory(path, recursive: true) }
130
+ .to raise_error(error_class, error_message)
131
+ end
132
+
133
+ it 'should not create the directory' do
134
+ subject.create_directory(path, recursive: true)
135
+ rescue error_class
136
+ expect(subject.directory?(path)).to be false
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ context 'when the directory already exists' do
143
+ before(:example) { subject.create_directory(path) }
144
+
145
+ it { expect(subject.create_directory(path)).to be == path }
146
+ end
147
+
148
+ context 'when the path includes a file' do
149
+ let(:error_class) do
150
+ Cuprum::Cli::Dependencies::FileSystem::DirectoryIsAFileError
151
+ end
152
+ let(:error_message) do
153
+ "unable to create directory #{path} - directory is a file"
154
+ end
155
+
156
+ before(:example) { subject.write_file(path, '') }
157
+
158
+ include_deferred 'when created files are cleaned up'
159
+
160
+ it 'should raise an exception' do
161
+ expect { subject.create_directory(path) }
162
+ .to raise_error(error_class, error_message)
163
+ end
164
+
165
+ it 'should not create the directory' do
166
+ subject.create_directory(path)
167
+ rescue error_class
168
+ expect(subject.directory?(path)).to be false
169
+ end
170
+ end
171
+ end
172
+
173
+ describe 'with a qualified path' do
174
+ let(:base_path) { qualified_directory_path }
175
+ let(:path) { File.join(base_path, 'custom_dir') }
176
+
177
+ it { expect(subject.create_directory(path)).to be == path }
178
+
179
+ describe 'with a multi-segment path' do
180
+ let(:path) { File.join(base_path, 'custom_dir/inner/path') }
181
+ let(:error_class) do
182
+ Cuprum::Cli::Dependencies::FileSystem::DirectoryNotFoundError
183
+ end
184
+ let(:error_message) do
185
+ "unable to create directory #{path} - directory not found"
186
+ end
187
+
188
+ it 'should raise an exception' do
189
+ expect { subject.create_directory(path) }
190
+ .to raise_error(error_class, error_message)
191
+ end
192
+
193
+ describe 'with recursive: true' do
194
+ it 'should return the path' do
195
+ expect(subject.create_directory(path, recursive: true))
196
+ .to be == path
197
+ end
198
+
199
+ it 'should create the directory' do
200
+ expect { subject.create_directory(path, recursive: true) }.to(
201
+ change { subject.directory?(path) }.to(be true)
202
+ )
203
+ end
204
+
205
+ context 'when the directory already exists' do
206
+ before(:example) do
207
+ subject.create_directory(path, recursive: true)
208
+ end
209
+
210
+ it { expect(subject.create_directory(path)).to be == path }
211
+ end
212
+
213
+ context 'when the path includes a file' do
214
+ let(:error_class) do
215
+ Cuprum::Cli::Dependencies::FileSystem::DirectoryIsAFileError
216
+ end
217
+ let(:error_message) do
218
+ "unable to create directory #{path} - directory is a file"
219
+ end
220
+ let(:file_path) { File.join(base_path, 'custom_dir') }
221
+
222
+ before(:example) do
223
+ subject.write_file(file_path, '')
224
+ end
225
+
226
+ include_deferred 'when created files are cleaned up'
227
+
228
+ it 'should raise an exception' do
229
+ expect { subject.create_directory(path, recursive: true) }
230
+ .to raise_error(error_class, error_message)
231
+ end
232
+
233
+ it 'should not create the directory' do
234
+ subject.create_directory(path, recursive: true)
235
+ rescue error_class
236
+ expect(subject.directory?(path)).to be false
237
+ end
238
+ end
239
+ end
240
+ end
241
+
242
+ context 'when the directory already exists' do
243
+ before(:example) { subject.create_directory(path) }
244
+
245
+ it { expect(subject.create_directory(path)).to be == path }
246
+ end
247
+
248
+ context 'when the path includes a file' do
249
+ let(:error_class) do
250
+ Cuprum::Cli::Dependencies::FileSystem::DirectoryIsAFileError
251
+ end
252
+ let(:error_message) do
253
+ "unable to create directory #{path} - directory is a file"
254
+ end
255
+
256
+ before(:example) { subject.write_file(path, '') }
257
+
258
+ include_deferred 'when created files are cleaned up'
259
+
260
+ it 'should raise an exception' do
261
+ expect { subject.create_directory(path) }
262
+ .to raise_error(error_class, error_message)
263
+ end
264
+
265
+ it 'should not create the directory' do
266
+ subject.create_directory(path)
267
+ rescue error_class
268
+ expect(subject.directory?(path)).to be false
269
+ end
270
+ end
271
+ end
272
+
273
+ describe 'with a relative path' do
274
+ let(:base_path) { relative_directory_path }
275
+ let(:path) { File.join(base_path, 'custom_dir') }
276
+
277
+ it { expect(subject.create_directory(path)).to be == path }
278
+
279
+ describe 'with a multi-segment path' do
280
+ let(:path) { File.join(base_path, 'custom_dir/inner/path') }
281
+ let(:error_class) do
282
+ Cuprum::Cli::Dependencies::FileSystem::DirectoryNotFoundError
283
+ end
284
+ let(:error_message) do
285
+ "unable to create directory #{path} - directory not found"
286
+ end
287
+
288
+ it 'should raise an exception' do
289
+ expect { subject.create_directory(path) }
290
+ .to raise_error(error_class, error_message)
291
+ end
292
+
293
+ describe 'with recursive: true' do
294
+ it 'should return the path' do
295
+ expect(subject.create_directory(path, recursive: true))
296
+ .to be == path
297
+ end
298
+
299
+ it 'should create the directory' do
300
+ expect { subject.create_directory(path, recursive: true) }.to(
301
+ change { subject.directory?(path) }.to(be true)
302
+ )
303
+ end
304
+
305
+ context 'when the directory already exists' do
306
+ before(:example) do
307
+ subject.create_directory(path, recursive: true)
308
+ end
309
+
310
+ it { expect(subject.create_directory(path)).to be == path }
311
+ end
312
+
313
+ context 'when the path includes a file' do
314
+ let(:error_class) do
315
+ Cuprum::Cli::Dependencies::FileSystem::DirectoryIsAFileError
316
+ end
317
+ let(:error_message) do
318
+ "unable to create directory #{path} - directory is a file"
319
+ end
320
+ let(:file_path) { File.join(base_path, 'custom_dir') }
321
+
322
+ before(:example) do
323
+ subject.write_file(file_path, '')
324
+ end
325
+
326
+ include_deferred 'when created files are cleaned up'
327
+
328
+ it 'should raise an exception' do
329
+ expect { subject.create_directory(path, recursive: true) }
330
+ .to raise_error(error_class, error_message)
331
+ end
332
+
333
+ it 'should not create the directory' do
334
+ subject.create_directory(path, recursive: true)
335
+ rescue error_class
336
+ expect(subject.directory?(path)).to be false
337
+ end
338
+ end
339
+ end
340
+ end
341
+
342
+ context 'when the directory already exists' do
343
+ before(:example) { subject.create_directory(path) }
344
+
345
+ it { expect(subject.create_directory(path)).to be == path }
346
+ end
347
+
348
+ context 'when the path includes a file' do
349
+ let(:error_class) do
350
+ Cuprum::Cli::Dependencies::FileSystem::DirectoryIsAFileError
351
+ end
352
+ let(:error_message) do
353
+ "unable to create directory #{path} - directory is a file"
354
+ end
355
+
356
+ before(:example) { subject.write_file(path, '') }
357
+
358
+ include_deferred 'when created files are cleaned up'
359
+
360
+ it 'should raise an exception' do
361
+ expect { subject.create_directory(path) }
362
+ .to raise_error(error_class, error_message)
363
+ end
364
+
365
+ it 'should not create the directory' do
366
+ subject.create_directory(path)
367
+ rescue error_class
368
+ expect(subject.directory?(path)).to be false
369
+ end
370
+ end
371
+ end
372
+
373
+ wrap_deferred 'when initialized with root_path: value' do
374
+ describe 'with a qualified path' do
375
+ let(:base_path) { File.join('..', '..', 'tmp', 'files') }
376
+ let(:path) { File.join(base_path, 'custom_dir') }
377
+
378
+ it { expect(subject.create_directory(path)).to be == path }
379
+
380
+ it 'should create the directory' do
381
+ expect { subject.create_directory(path) }.to(
382
+ change { subject.directory?(path) }.to(be true)
383
+ )
384
+ end
385
+
386
+ describe 'with a multi-segment path' do
387
+ let(:path) { File.join(base_path, 'custom_dir/inner/path') }
388
+
389
+ describe 'with recursive: true' do
390
+ it 'should return the path' do
391
+ expect(subject.create_directory(path, recursive: true))
392
+ .to be == path
393
+ end
394
+
395
+ it 'should create the directory' do
396
+ expect { subject.create_directory(path, recursive: true) }.to(
397
+ change { subject.directory?(path) }.to(be true)
398
+ )
399
+ end
400
+ end
401
+ end
402
+ end
403
+
404
+ describe 'with a relative path' do
405
+ let(:base_path) { 'nested' }
406
+ let(:path) { File.join(base_path, 'custom_dir') }
407
+
408
+ it { expect(subject.create_directory(path)).to be == path }
409
+
410
+ it 'should create the directory' do
411
+ expect { subject.create_directory(path) }.to(
412
+ change { subject.directory?(path) }.to(be true)
413
+ )
414
+ end
415
+
416
+ describe 'with a multi-segment path' do
417
+ let(:path) { File.join(base_path, 'custom_dir/inner/path') }
418
+
419
+ describe 'with recursive: true' do
420
+ it 'should return the path' do
421
+ expect(subject.create_directory(path, recursive: true))
422
+ .to be == path
423
+ end
424
+
425
+ it 'should create the directory' do
426
+ expect { subject.create_directory(path, recursive: true) }.to(
427
+ change { subject.directory?(path) }.to(be true)
428
+ )
429
+ end
430
+ end
431
+ end
432
+ end
433
+ end
434
+ end
435
+
436
+ describe '#directory?' do
437
+ let(:invalid_absolute_path) do
438
+ defined?(super()) ? super() : '/invalid-absolute-path'
439
+ end
440
+ let(:invalid_qualified_path) do
441
+ defined?(super()) ? super() : '../invalid-qualified-path'
442
+ end
443
+ let(:invalid_relative_path) do
444
+ defined?(super()) ? super() : 'invalid-absolute-path'
445
+ end
446
+
447
+ include_deferred 'with valid file paths'
448
+
449
+ it 'should define the method' do
450
+ expect(subject).to respond_to(:directory?).with(1).argument
451
+ end
452
+
453
+ it 'should define the aliased method' do
454
+ expect(subject)
455
+ .to have_aliased_method(:directory?)
456
+ .as(:directory_exists?)
457
+ end
458
+
459
+ describe 'with nil' do
460
+ let(:error_message) do
461
+ tools.assertions.error_message_for('presence', as: 'path')
462
+ end
463
+
464
+ it 'should raise an exception' do
465
+ expect { subject.directory?(nil) }
466
+ .to raise_error ArgumentError, error_message
467
+ end
468
+ end
469
+
470
+ describe 'with an Object' do
471
+ let(:error_message) do
472
+ tools.assertions.error_message_for('name', as: 'path')
473
+ end
474
+
475
+ it 'should raise an exception' do
476
+ expect { subject.directory?(Object.new.freeze) }
477
+ .to raise_error ArgumentError, error_message
478
+ end
479
+ end
480
+
481
+ describe 'with an empty String' do
482
+ let(:error_message) do
483
+ tools.assertions.error_message_for('presence', as: 'path')
484
+ end
485
+
486
+ it 'should raise an exception' do
487
+ expect { subject.directory?('') }
488
+ .to raise_error ArgumentError, error_message
489
+ end
490
+ end
491
+
492
+ describe 'with an invalid absolute path' do
493
+ let(:path) { invalid_absolute_path }
494
+
495
+ it { expect(subject.directory?(path)).to be false }
496
+ end
497
+
498
+ describe 'with an invalid qualified path' do
499
+ let(:path) { invalid_qualified_path }
500
+
501
+ it { expect(subject.directory?(path)).to be false }
502
+ end
503
+
504
+ describe 'with an invalid relative path' do
505
+ let(:path) { invalid_relative_path }
506
+
507
+ it { expect(subject.directory?(path)).to be false }
508
+ end
509
+
510
+ describe 'with an absolute path to a directory' do
511
+ let(:path) { absolute_directory_path }
512
+
513
+ it { expect(subject.directory?(path)).to be true }
514
+ end
515
+
516
+ describe 'with an absolute path to a file' do
517
+ let(:path) { absolute_file_path }
518
+
519
+ it { expect(subject.directory?(path)).to be false }
520
+ end
521
+
522
+ describe 'with a qualified path to a directory' do
523
+ let(:path) { qualified_directory_path }
524
+
525
+ it { expect(subject.directory?(path)).to be true }
526
+ end
527
+
528
+ describe 'with a qualified path to a file' do
529
+ let(:path) { qualified_file_path }
530
+
531
+ it { expect(subject.directory?(path)).to be false }
532
+ end
533
+
534
+ describe 'with a relative path to a directory' do
535
+ let(:path) { relative_directory_path }
536
+
537
+ it { expect(subject.directory?(path)).to be true }
538
+ end
539
+
540
+ describe 'with a relative path to a file' do
541
+ let(:path) { relative_file_path }
542
+
543
+ it { expect(subject.directory?(path)).to be false }
544
+ end
545
+
546
+ wrap_deferred 'when initialized with root_path: value' do
547
+ describe 'with a qualified path to a directory' do
548
+ let(:path) { qualified_directory_path }
549
+
550
+ it { expect(subject.directory?(path)).to be true }
551
+ end
552
+
553
+ describe 'with a qualified path to a file' do
554
+ let(:path) { qualified_file_path }
555
+
556
+ it { expect(subject.directory?(path)).to be false }
557
+ end
558
+
559
+ describe 'with a relative path to a directory' do
560
+ let(:path) { relative_directory_path }
561
+
562
+ it { expect(subject.directory?(path)).to be true }
563
+ end
564
+
565
+ describe 'with a relative path to a file' do
566
+ let(:path) { relative_file_path }
567
+
568
+ it { expect(subject.directory?(path)).to be false }
569
+ end
570
+ end
571
+ end
572
+
573
+ describe '#each_file' do
574
+ deferred_examples 'should return or yield the matching file names' do
575
+ describe 'without a block' do
576
+ it { expect(subject.each_file(pattern)).to be_a Enumerator }
577
+
578
+ it 'should return the matching file names' do
579
+ expect(subject.each_file(pattern).to_a).to be == expected_files
580
+ end
581
+ end
582
+
583
+ describe 'with a block' do
584
+ it { expect(subject.each_file(pattern) { nil }).to be nil }
585
+
586
+ it 'should yield the matching file names' do
587
+ expect { |block| subject.each_file(pattern, &block) }.then \
588
+ do |expectation|
589
+ if expected_files.empty?
590
+ expectation.not_to(yield_control)
591
+ else
592
+ expectation.to yield_successive_args(*expected_files)
593
+ end
594
+ end
595
+ end
596
+ end
597
+ end
598
+
599
+ let(:pattern) { '**/*.rb' }
600
+ let(:matching_files) do
601
+ defined?(super()) ? super() : []
602
+ end
603
+ let(:expected_files) { matching_files }
604
+
605
+ it 'should define the method' do
606
+ expect(subject)
607
+ .to respond_to(:each_file)
608
+ .with(1).argument
609
+ .and_a_block
610
+ end
611
+
612
+ include_deferred 'should return or yield the matching file names'
613
+
614
+ wrap_deferred 'with valid file paths' do
615
+ describe 'with a pattern that does not match any files' do
616
+ let(:pattern) { '*.xml' }
617
+ let(:matching_files) { [] }
618
+
619
+ include_deferred 'should return or yield the matching file names'
620
+ end
621
+
622
+ describe 'with a globbed pattern' do
623
+ let(:pattern) { '*.txt' }
624
+ let(:expected_files) do
625
+ rxp = /\A\w+\.txt\z/
626
+
627
+ matching_files.select do |str|
628
+ str[(1 + subject.root_path.size)..].match?(rxp)
629
+ end
630
+ end
631
+
632
+ include_deferred 'should return or yield the matching file names'
633
+ end
634
+
635
+ describe 'with a globbed pattern with fixed segments' do
636
+ let(:pattern) { File.join(files_directory, '*.txt') }
637
+ let(:expected_files) do
638
+ rxp = %r{\A#{files_directory}/\w+\.txt\z}
639
+
640
+ matching_files.select do |str|
641
+ str[(1 + subject.root_path.size)..].match?(rxp)
642
+ end
643
+ end
644
+
645
+ include_deferred 'should return or yield the matching file names'
646
+ end
647
+
648
+ describe 'with a recursive globbed pattern' do
649
+ let(:pattern) { File.join('**', '*.txt') }
650
+ let(:expected_files) do
651
+ rxp = /\.txt\z/
652
+
653
+ matching_files.select do |str|
654
+ str[(1 + subject.root_path.size)..].match?(rxp)
655
+ end
656
+ end
657
+
658
+ include_deferred 'should return or yield the matching file names'
659
+ end
660
+ end
661
+ end
662
+
663
+ describe '#file?' do
664
+ let(:invalid_absolute_path) do
665
+ defined?(super()) ? super() : '/invalid-absolute-path'
666
+ end
667
+ let(:invalid_qualified_path) do
668
+ defined?(super()) ? super() : '../invalid-qualified-path'
669
+ end
670
+ let(:invalid_relative_path) do
671
+ defined?(super()) ? super() : 'invalid-absolute-path'
672
+ end
673
+
674
+ include_deferred 'with valid file paths'
675
+
676
+ it 'should define the method' do
677
+ expect(subject).to respond_to(:file?).with(1).argument
678
+ end
679
+
680
+ it 'should define the aliased method' do
681
+ expect(subject)
682
+ .to have_aliased_method(:file?)
683
+ .as(:file_exists?)
684
+ end
685
+
686
+ describe 'with nil' do
687
+ let(:error_message) do
688
+ tools.assertions.error_message_for('presence', as: 'path')
689
+ end
690
+
691
+ it 'should raise an exception' do
692
+ expect { subject.file?(nil) }
693
+ .to raise_error ArgumentError, error_message
694
+ end
695
+ end
696
+
697
+ describe 'with an Object' do
698
+ let(:error_message) do
699
+ tools.assertions.error_message_for('name', as: 'path')
700
+ end
701
+
702
+ it 'should raise an exception' do
703
+ expect { subject.file?(Object.new.freeze) }
704
+ .to raise_error ArgumentError, error_message
705
+ end
706
+ end
707
+
708
+ describe 'with an empty String' do
709
+ let(:error_message) do
710
+ tools.assertions.error_message_for('presence', as: 'path')
711
+ end
712
+
713
+ it 'should raise an exception' do
714
+ expect { subject.file?('') }
715
+ .to raise_error ArgumentError, error_message
716
+ end
717
+ end
718
+
719
+ describe 'with an invalid absolute path' do
720
+ let(:path) { invalid_absolute_path }
721
+
722
+ it { expect(subject.file?(path)).to be false }
723
+ end
724
+
725
+ describe 'with an invalid qualified path' do
726
+ let(:path) { invalid_qualified_path }
727
+
728
+ it { expect(subject.file?(path)).to be false }
729
+ end
730
+
731
+ describe 'with an invalid relative path' do
732
+ let(:path) { invalid_relative_path }
733
+
734
+ it { expect(subject.file?(path)).to be false }
735
+ end
736
+
737
+ describe 'with an absolute path to a directory' do
738
+ let(:path) { absolute_directory_path }
739
+
740
+ it { expect(subject.file?(path)).to be false }
741
+ end
742
+
743
+ describe 'with an absolute path to a file' do
744
+ let(:path) { absolute_file_path }
745
+
746
+ it { expect(subject.file?(path)).to be true }
747
+ end
748
+
749
+ describe 'with a qualified path to a directory' do
750
+ let(:path) { qualified_directory_path }
751
+
752
+ it { expect(subject.file?(path)).to be false }
753
+ end
754
+
755
+ describe 'with a qualified path to a file' do
756
+ let(:path) { qualified_file_path }
757
+
758
+ it { expect(subject.file?(path)).to be true }
759
+ end
760
+
761
+ describe 'with a relative path to a directory' do
762
+ let(:path) { relative_directory_path }
763
+
764
+ it { expect(subject.file?(path)).to be false }
765
+ end
766
+
767
+ describe 'with a relative path to a file' do
768
+ let(:path) { relative_file_path }
769
+
770
+ it { expect(subject.file?(path)).to be true }
771
+ end
772
+
773
+ wrap_deferred 'when initialized with root_path: value' do
774
+ describe 'with a qualified path to a directory' do
775
+ let(:path) { qualified_directory_path }
776
+
777
+ it { expect(subject.file?(path)).to be false }
778
+ end
779
+
780
+ describe 'with a qualified path to a file' do
781
+ let(:path) { qualified_file_path }
782
+
783
+ it { expect(subject.file?(path)).to be true }
784
+ end
785
+
786
+ describe 'with a relative path to a directory' do
787
+ let(:path) { relative_directory_path }
788
+
789
+ it { expect(subject.file?(path)).to be false }
790
+ end
791
+
792
+ describe 'with a relative path to a file' do
793
+ let(:path) { relative_file_path }
794
+
795
+ it { expect(subject.file?(path)).to be true }
796
+ end
797
+ end
798
+ end
799
+
800
+ describe '#read_file', replace_file_contents: true do
801
+ let(:invalid_absolute_path) do
802
+ defined?(super()) ? super() : '/invalid-absolute-path'
803
+ end
804
+ let(:invalid_qualified_path) do
805
+ defined?(super()) ? super() : '../invalid-qualified-path'
806
+ end
807
+ let(:invalid_relative_path) do
808
+ defined?(super()) ? super() : 'invalid-relative-path'
809
+ end
810
+ let(:expected_contents) do
811
+ path = self.path
812
+
813
+ if path.start_with?('.')
814
+ path = File.expand_path(File.join(subject.root_path, path))
815
+ end
816
+
817
+ path = path.sub(%r{\A#{subject.root_path}/?}, '')
818
+
819
+ "Contents of #{path}"
820
+ end
821
+
822
+ it { expect(subject).to respond_to(:read_file).with(1).argument }
823
+
824
+ it 'should define the aliased method' do
825
+ expect(subject).to have_aliased_method(:read_file).as(:read)
826
+ end
827
+
828
+ describe 'with nil' do
829
+ let(:error_message) do
830
+ tools.assertions.error_message_for('presence', as: :file)
831
+ end
832
+
833
+ it 'should raise an exception' do
834
+ expect { subject.read_file(nil) }
835
+ .to raise_error ArgumentError, error_message
836
+ end
837
+ end
838
+
839
+ describe 'with an Object' do
840
+ let(:error_message) do
841
+ 'file is not a String or IO stream'
842
+ end
843
+
844
+ it 'should raise an exception' do
845
+ expect { subject.read_file(Object.new.freeze) }
846
+ .to raise_error ArgumentError, error_message
847
+ end
848
+ end
849
+
850
+ describe 'with an empty String' do
851
+ let(:error_message) do
852
+ tools.assertions.error_message_for('presence', as: :file)
853
+ end
854
+
855
+ it 'should raise an exception' do
856
+ expect { subject.read_file('') }
857
+ .to raise_error ArgumentError, error_message
858
+ end
859
+ end
860
+
861
+ describe 'with an IO stream' do
862
+ let(:stream) { StringIO.new('Greetings, programs!') }
863
+
864
+ it { expect(subject.read_file(stream)).to be == stream.string }
865
+ end
866
+
867
+ describe 'with an invalid absolute path' do
868
+ let(:path) { invalid_absolute_path }
869
+ let(:error_class) do
870
+ Cuprum::Cli::Dependencies::FileSystem::FileNotFoundError
871
+ end
872
+ let(:error_message) do
873
+ "unable to read file #{path} - file not found"
874
+ end
875
+
876
+ it 'should raise an exception' do
877
+ expect { subject.read_file(path) }
878
+ .to raise_error(error_class, error_message)
879
+ end
880
+ end
881
+
882
+ describe 'with an invalid qualified path' do
883
+ let(:path) { invalid_qualified_path }
884
+ let(:error_class) do
885
+ Cuprum::Cli::Dependencies::FileSystem::FileNotFoundError
886
+ end
887
+ let(:error_message) do
888
+ "unable to read file #{path} - file not found"
889
+ end
890
+
891
+ it 'should raise an exception' do
892
+ expect { subject.read_file(path) }
893
+ .to raise_error(error_class, error_message)
894
+ end
895
+ end
896
+
897
+ describe 'with an invalid relative path' do
898
+ let(:path) { invalid_relative_path }
899
+ let(:error_class) do
900
+ Cuprum::Cli::Dependencies::FileSystem::FileNotFoundError
901
+ end
902
+ let(:error_message) do
903
+ "unable to read file #{path} - file not found"
904
+ end
905
+
906
+ it 'should raise an exception' do
907
+ expect { subject.read_file(path) }
908
+ .to raise_error(error_class, error_message)
909
+ end
910
+ end
911
+
912
+ wrap_deferred 'with valid file paths' do
913
+ describe 'with an absolute path to a directory' do
914
+ let(:path) { absolute_directory_path }
915
+ let(:error_class) do
916
+ Cuprum::Cli::Dependencies::FileSystem::FileIsADirectoryError
917
+ end
918
+ let(:error_message) do
919
+ "unable to read file #{path} - file is a directory"
920
+ end
921
+
922
+ it 'should raise an exception' do
923
+ expect { subject.read_file(path) }
924
+ .to raise_error(error_class, error_message)
925
+ end
926
+ end
927
+
928
+ describe 'with an absolute path to a file' do
929
+ let(:path) { absolute_file_path }
930
+
931
+ it { expect(subject.read_file(path)).to be == expected_contents }
932
+ end
933
+
934
+ describe 'with a qualified path to a directory' do
935
+ let(:path) { qualified_directory_path }
936
+ let(:error_class) do
937
+ Cuprum::Cli::Dependencies::FileSystem::FileIsADirectoryError
938
+ end
939
+ let(:error_message) do
940
+ "unable to read file #{path} - file is a directory"
941
+ end
942
+
943
+ it 'should raise an exception' do
944
+ expect { subject.read_file(path) }
945
+ .to raise_error(error_class, error_message)
946
+ end
947
+ end
948
+
949
+ describe 'with a qualified path to a file' do
950
+ let(:path) { qualified_file_path }
951
+
952
+ it { expect(subject.read_file(path)).to be == expected_contents }
953
+ end
954
+
955
+ describe 'with a relative path to a directory' do
956
+ let(:path) { relative_directory_path }
957
+ let(:error_class) do
958
+ Cuprum::Cli::Dependencies::FileSystem::FileIsADirectoryError
959
+ end
960
+ let(:error_message) do
961
+ "unable to read file #{path} - file is a directory"
962
+ end
963
+
964
+ it 'should raise an exception' do
965
+ expect { subject.read_file(path) }
966
+ .to raise_error(error_class, error_message)
967
+ end
968
+ end
969
+
970
+ describe 'with a relative path to a file' do
971
+ let(:path) { relative_file_path }
972
+
973
+ it { expect(subject.read_file(path)).to be == expected_contents }
974
+ end
975
+
976
+ wrap_deferred 'with valid file paths' do
977
+ describe 'with a qualified path to a directory' do
978
+ let(:path) { qualified_directory_path }
979
+ let(:error_class) do
980
+ Cuprum::Cli::Dependencies::FileSystem::FileIsADirectoryError
981
+ end
982
+ let(:error_message) do
983
+ "unable to read file #{path} - file is a directory"
984
+ end
985
+
986
+ it 'should raise an exception' do
987
+ expect { subject.read_file(path) }
988
+ .to raise_error(error_class, error_message)
989
+ end
990
+ end
991
+
992
+ describe 'with a qualified path to a file' do
993
+ let(:path) { qualified_file_path }
994
+
995
+ it { expect(subject.read_file(path)).to be == expected_contents }
996
+ end
997
+
998
+ describe 'with a relative path to a directory' do
999
+ let(:path) { relative_directory_path }
1000
+ let(:error_class) do
1001
+ Cuprum::Cli::Dependencies::FileSystem::FileIsADirectoryError
1002
+ end
1003
+ let(:error_message) do
1004
+ "unable to read file #{path} - file is a directory"
1005
+ end
1006
+
1007
+ it 'should raise an exception' do
1008
+ expect { subject.read_file(path) }
1009
+ .to raise_error(error_class, error_message)
1010
+ end
1011
+ end
1012
+
1013
+ describe 'with a relative path to a file' do
1014
+ let(:path) { relative_file_path }
1015
+
1016
+ it { expect(subject.read_file(path)).to be == expected_contents }
1017
+ end
1018
+ end
1019
+ end
1020
+ end
1021
+
1022
+ describe '#root_path' do
1023
+ include_examples 'should define reader', :root_path, Dir.pwd
1024
+
1025
+ wrap_deferred 'when initialized with root_path: value' do
1026
+ it { expect(subject.root_path).to be == root_path }
1027
+ end
1028
+ end
1029
+
1030
+ describe '#with_tempfile' do
1031
+ let(:expected_tempfile) do
1032
+ respond_to(:read)
1033
+ .and(respond_to(:write)
1034
+ .and(respond_to(:path)))
1035
+ end
1036
+
1037
+ it 'should define the method' do
1038
+ expect(subject)
1039
+ .to respond_to(:with_tempfile)
1040
+ .with(0).arguments
1041
+ .and_a_block
1042
+ end
1043
+
1044
+ it 'should yield the file object' do
1045
+ expect { |block| subject.with_tempfile(&block) }
1046
+ .to yield_with_args(expected_tempfile)
1047
+ end
1048
+ end
1049
+
1050
+ describe '#write_file', writeable_root_path: true do
1051
+ let(:invalid_absolute_path) do
1052
+ defined?(super()) ? super() : '/invalid-absolute-path'
1053
+ end
1054
+ let(:invalid_qualified_path) do
1055
+ defined?(super()) ? super() : '../invalid-qualified-path'
1056
+ end
1057
+ let(:invalid_relative_path) do
1058
+ defined?(super()) ? super() : 'invalid-relative-path'
1059
+ end
1060
+ let(:file_name) { "#{SecureRandom.uuid}.txt" }
1061
+ let(:data) { "Greetings, programs!\n" }
1062
+
1063
+ include_deferred 'with valid file paths'
1064
+
1065
+ it { expect(subject).to respond_to(:write_file).with(2).arguments }
1066
+
1067
+ it 'should define the aliased method' do
1068
+ expect(subject).to have_aliased_method(:write_file).as(:write)
1069
+ end
1070
+
1071
+ describe 'with data: nil' do
1072
+ let(:data) { nil }
1073
+ let(:stream) { StringIO.new }
1074
+
1075
+ it 'should not write to the stream' do
1076
+ expect { subject.write_file(stream, data) }
1077
+ .not_to change(stream, :string)
1078
+ end
1079
+ end
1080
+
1081
+ describe 'with data: an Object' do
1082
+ let(:data) { Object.new.freeze }
1083
+ let(:stream) { StringIO.new }
1084
+
1085
+ it 'should write the object to the stream' do
1086
+ expect { subject.write_file(stream, data) }
1087
+ .to change(stream, :string)
1088
+ .to be == data.inspect
1089
+ end
1090
+ end
1091
+
1092
+ describe 'with data: an empty String' do
1093
+ let(:data) { '' }
1094
+ let(:stream) { StringIO.new }
1095
+
1096
+ it 'should not write to the stream' do
1097
+ expect { subject.write_file(stream, data) }
1098
+ .not_to change(stream, :string)
1099
+ end
1100
+ end
1101
+
1102
+ describe 'with file: nil' do
1103
+ let(:error_message) do
1104
+ tools.assertions.error_message_for('presence', as: :file)
1105
+ end
1106
+
1107
+ it 'should raise an exception' do
1108
+ expect { subject.write_file(nil, data) }
1109
+ .to raise_error ArgumentError, error_message
1110
+ end
1111
+ end
1112
+
1113
+ describe 'with file: an Object' do
1114
+ let(:error_message) do
1115
+ 'file is not a String or IO stream'
1116
+ end
1117
+
1118
+ it 'should raise an exception' do
1119
+ expect { subject.write_file(Object.new.freeze, data) }
1120
+ .to raise_error ArgumentError, error_message
1121
+ end
1122
+ end
1123
+
1124
+ describe 'with file: an empty String' do
1125
+ let(:error_message) do
1126
+ tools.assertions.error_message_for('presence', as: :file)
1127
+ end
1128
+
1129
+ it 'should raise an exception' do
1130
+ expect { subject.write_file('', data) }
1131
+ .to raise_error ArgumentError, error_message
1132
+ end
1133
+ end
1134
+
1135
+ describe 'with file: an IO stream' do
1136
+ let(:stream) { StringIO.new }
1137
+
1138
+ it 'should write the data to the stream' do
1139
+ expect { subject.write_file(stream, data) }
1140
+ .to change(stream, :string)
1141
+ .to be == data
1142
+ end
1143
+ end
1144
+
1145
+ describe 'with an absolute path' do
1146
+ let(:directory) do
1147
+ File.join(subject.root_path, writeable_path)
1148
+ end
1149
+ let(:path) do
1150
+ File.join(directory, "#{SecureRandom.uuid}.txt")
1151
+ end
1152
+
1153
+ include_deferred 'when created files are cleaned up'
1154
+
1155
+ it 'should write the data to a new file' do
1156
+ subject.write_file(path, data)
1157
+
1158
+ expect(subject.read_file(path)).to be == data
1159
+ end
1160
+
1161
+ context 'when the directory is not writeable' do
1162
+ let(:directory) { invalid_absolute_path }
1163
+ let(:error_class) do
1164
+ Cuprum::Cli::Dependencies::FileSystem::DirectoryNotFoundError
1165
+ end
1166
+ let(:error_message) do
1167
+ "unable to write file #{path} - directory not found"
1168
+ end
1169
+
1170
+ it 'should raise an exception' do
1171
+ expect { subject.write_file(path, data) }
1172
+ .to raise_error(error_class, error_message)
1173
+ end
1174
+ end
1175
+
1176
+ context 'when the file already exists' do
1177
+ before(:example) do
1178
+ subject.write_file(path, "Existing contents...\n")
1179
+ end
1180
+
1181
+ it 'should replace the contents of the file' do
1182
+ subject.write_file(path, data)
1183
+
1184
+ expect(subject.read_file(path)).to be == data
1185
+ end
1186
+ end
1187
+
1188
+ context 'when the file is a directory' do
1189
+ let(:path) { directory }
1190
+ let(:error_class) do
1191
+ Cuprum::Cli::Dependencies::FileSystem::FileIsADirectoryError
1192
+ end
1193
+ let(:error_message) do
1194
+ "unable to write file #{path} - file is a directory"
1195
+ end
1196
+
1197
+ it 'should raise an exception' do
1198
+ expect { subject.write_file(path, data) }
1199
+ .to raise_error(error_class, error_message)
1200
+ end
1201
+ end
1202
+
1203
+ context 'when the path includes a file' do
1204
+ let(:directory) { File.join(super(), 'a_file') }
1205
+ let(:error_class) do
1206
+ Cuprum::Cli::Dependencies::FileSystem::DirectoryIsAFileError
1207
+ end
1208
+ let(:error_message) do
1209
+ "unable to write file #{path} - directory is a file"
1210
+ end
1211
+
1212
+ before(:example) do
1213
+ subject.write_file(directory, "Existing contents...\n")
1214
+ end
1215
+
1216
+ it 'should raise an exception' do
1217
+ expect { subject.write_file(path, data) }
1218
+ .to raise_error(error_class, error_message)
1219
+ end
1220
+ end
1221
+
1222
+ context 'when the path includes missing directories' do
1223
+ let(:directory) do
1224
+ File.join(super(), 'missing', 'directories')
1225
+ end
1226
+ let(:error_class) do
1227
+ Cuprum::Cli::Dependencies::FileSystem::DirectoryNotFoundError
1228
+ end
1229
+ let(:error_message) do
1230
+ "unable to write file #{path} - directory not found"
1231
+ end
1232
+
1233
+ it 'should raise an exception' do
1234
+ expect { subject.write_file(path, data) }
1235
+ .to raise_error(error_class, error_message)
1236
+ end
1237
+ end
1238
+ end
1239
+
1240
+ describe 'with a qualified path' do
1241
+ let(:directory) do
1242
+ File.join('.', writeable_path)
1243
+ end
1244
+ let(:path) do
1245
+ File.join(directory, "#{SecureRandom.uuid}.txt")
1246
+ end
1247
+
1248
+ include_deferred 'when created files are cleaned up'
1249
+
1250
+ it 'should write the data to a new file' do
1251
+ subject.write_file(path, data)
1252
+
1253
+ expect(subject.read_file(path)).to be == data
1254
+ end
1255
+
1256
+ context 'when the directory is not writeable' do
1257
+ let(:directory) { invalid_absolute_path }
1258
+ let(:error_class) do
1259
+ Cuprum::Cli::Dependencies::FileSystem::DirectoryNotFoundError
1260
+ end
1261
+ let(:error_message) do
1262
+ "unable to write file #{path} - directory not found"
1263
+ end
1264
+
1265
+ it 'should raise an exception' do
1266
+ expect { subject.write_file(path, data) }
1267
+ .to raise_error(error_class, error_message)
1268
+ end
1269
+ end
1270
+
1271
+ context 'when the file already exists' do
1272
+ before(:example) do
1273
+ subject.write_file(path, "Existing contents...\n")
1274
+ end
1275
+
1276
+ it 'should replace the contents of the file' do
1277
+ subject.write_file(path, data)
1278
+
1279
+ expect(subject.read_file(path)).to be == data
1280
+ end
1281
+ end
1282
+
1283
+ context 'when the file is a directory' do
1284
+ let(:path) { directory }
1285
+ let(:error_class) do
1286
+ Cuprum::Cli::Dependencies::FileSystem::FileIsADirectoryError
1287
+ end
1288
+ let(:error_message) do
1289
+ "unable to write file #{path} - file is a directory"
1290
+ end
1291
+
1292
+ it 'should raise an exception' do
1293
+ expect { subject.write_file(path, data) }
1294
+ .to raise_error(error_class, error_message)
1295
+ end
1296
+ end
1297
+
1298
+ context 'when the path includes a file' do
1299
+ let(:directory) { File.join(super(), 'a_file') }
1300
+ let(:error_class) do
1301
+ Cuprum::Cli::Dependencies::FileSystem::DirectoryIsAFileError
1302
+ end
1303
+ let(:error_message) do
1304
+ "unable to write file #{path} - directory is a file"
1305
+ end
1306
+
1307
+ before(:example) do
1308
+ subject.write_file(directory, "Existing contents...\n")
1309
+ end
1310
+
1311
+ it 'should raise an exception' do
1312
+ expect { subject.write_file(path, data) }
1313
+ .to raise_error(error_class, error_message)
1314
+ end
1315
+ end
1316
+
1317
+ context 'when the path includes missing directories' do
1318
+ let(:directory) do
1319
+ File.join(super(), 'missing', 'directories')
1320
+ end
1321
+ let(:error_class) do
1322
+ Cuprum::Cli::Dependencies::FileSystem::DirectoryNotFoundError
1323
+ end
1324
+ let(:error_message) do
1325
+ "unable to write file #{path} - directory not found"
1326
+ end
1327
+
1328
+ it 'should raise an exception' do
1329
+ expect { subject.write_file(path, data) }
1330
+ .to raise_error(error_class, error_message)
1331
+ end
1332
+ end
1333
+ end
1334
+
1335
+ describe 'with a relative path' do
1336
+ let(:directory) do
1337
+ writeable_path
1338
+ end
1339
+ let(:path) do
1340
+ File.join(directory, "#{SecureRandom.uuid}.txt")
1341
+ end
1342
+
1343
+ include_deferred 'when created files are cleaned up'
1344
+
1345
+ it 'should write the data to a new file' do
1346
+ subject.write_file(path, data)
1347
+
1348
+ expect(subject.read_file(path)).to be == data
1349
+ end
1350
+
1351
+ context 'when the directory is not writeable' do
1352
+ let(:directory) { invalid_absolute_path }
1353
+ let(:error_class) do
1354
+ Cuprum::Cli::Dependencies::FileSystem::DirectoryNotFoundError
1355
+ end
1356
+ let(:error_message) do
1357
+ "unable to write file #{path} - directory not found"
1358
+ end
1359
+
1360
+ it 'should raise an exception' do
1361
+ expect { subject.write_file(path, data) }
1362
+ .to raise_error(error_class, error_message)
1363
+ end
1364
+ end
1365
+
1366
+ context 'when the file already exists' do
1367
+ before(:example) do
1368
+ subject.write_file(path, "Existing contents...\n")
1369
+ end
1370
+
1371
+ it 'should replace the contents of the file' do
1372
+ subject.write_file(path, data)
1373
+
1374
+ expect(subject.read_file(path)).to be == data
1375
+ end
1376
+ end
1377
+
1378
+ context 'when the file is a directory' do
1379
+ let(:path) { directory }
1380
+ let(:error_class) do
1381
+ Cuprum::Cli::Dependencies::FileSystem::FileIsADirectoryError
1382
+ end
1383
+ let(:error_message) do
1384
+ "unable to write file #{path} - file is a directory"
1385
+ end
1386
+
1387
+ it 'should raise an exception' do
1388
+ expect { subject.write_file(path, data) }
1389
+ .to raise_error(error_class, error_message)
1390
+ end
1391
+ end
1392
+
1393
+ context 'when the path includes a file' do
1394
+ let(:directory) { File.join(super(), 'a_file') }
1395
+ let(:error_class) do
1396
+ Cuprum::Cli::Dependencies::FileSystem::DirectoryIsAFileError
1397
+ end
1398
+ let(:error_message) do
1399
+ "unable to write file #{path} - directory is a file"
1400
+ end
1401
+
1402
+ before(:example) do
1403
+ subject.write_file(directory, "Existing contents...\n")
1404
+ end
1405
+
1406
+ it 'should raise an exception' do
1407
+ expect { subject.write_file(path, data) }
1408
+ .to raise_error(error_class, error_message)
1409
+ end
1410
+ end
1411
+
1412
+ context 'when the path includes missing directories' do
1413
+ let(:directory) do
1414
+ File.join(super(), 'missing', 'directories')
1415
+ end
1416
+ let(:error_class) do
1417
+ Cuprum::Cli::Dependencies::FileSystem::DirectoryNotFoundError
1418
+ end
1419
+ let(:error_message) do
1420
+ "unable to write file #{path} - directory not found"
1421
+ end
1422
+
1423
+ it 'should raise an exception' do
1424
+ expect { subject.write_file(path, data) }
1425
+ .to raise_error(error_class, error_message)
1426
+ end
1427
+ end
1428
+ end
1429
+
1430
+ wrap_deferred 'when initialized with root_path: value' do
1431
+ include_deferred 'when created files are cleaned up'
1432
+
1433
+ describe 'with a qualified path' do
1434
+ let(:directory) do
1435
+ File.join('..', '..', 'tmp', 'files')
1436
+ end
1437
+ let(:path) do
1438
+ File.join(directory, "#{SecureRandom.uuid}.txt")
1439
+ end
1440
+ let(:expanded_path) do
1441
+ File.expand_path(File.join(root_path, path))
1442
+ end
1443
+
1444
+ it 'should write the data to a new file' do
1445
+ subject.write_file(path, data)
1446
+
1447
+ expect(subject.read_file(path)).to be == data
1448
+ end
1449
+ end
1450
+
1451
+ describe 'with a relative path' do
1452
+ let(:path) do
1453
+ File.join('nested', "#{SecureRandom.uuid}.txt")
1454
+ end
1455
+ let(:expanded_path) do
1456
+ File.expand_path(File.join(root_path, path))
1457
+ end
1458
+
1459
+ it 'should write the data to a new file' do
1460
+ subject.write_file(path, data)
1461
+
1462
+ expect(subject.read_file(path)).to be == data
1463
+ end
1464
+ end
1465
+ end
1466
+ end
1467
+ end
1468
+ end
1469
+ end