fun_with_files 0.0.15 → 0.0.18
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.
- checksums.yaml +5 -5
- data/CHANGELOG.markdown +15 -3
- data/Gemfile +17 -7
- data/{README.rdoc → README.markdown} +11 -10
- data/VERSION +1 -1
- data/lib/fun_with/files/bootstrapper.rb +87 -0
- data/lib/fun_with/files/digest_methods.rb +30 -16
- data/lib/fun_with/files/directory_builder.rb +4 -0
- data/lib/fun_with/files/downloader.rb +3 -19
- data/lib/fun_with/files/errors.rb +9 -1
- data/lib/fun_with/files/file_manipulation_methods.rb +25 -15
- data/lib/fun_with/files/file_path.rb +147 -150
- data/lib/fun_with/files/file_path_class_methods.rb +23 -2
- data/lib/fun_with/files/file_permission_methods.rb +18 -7
- data/lib/fun_with/files/file_requirements.rb +63 -7
- data/lib/fun_with/files/requirements/manager.rb +104 -0
- data/lib/fun_with/files/root_path.rb +3 -3
- data/lib/fun_with/files/stat_methods.rb +33 -0
- data/lib/fun_with/files/string_behavior.rb +6 -2
- data/lib/fun_with/files/utils/byte_size.rb +143 -0
- data/lib/fun_with/files/utils/opts.rb +26 -0
- data/lib/fun_with/files/utils/succession.rb +47 -0
- data/lib/fun_with/files/utils/timestamp.rb +47 -0
- data/lib/fun_with/files/utils/timestamp_format.rb +31 -0
- data/lib/fun_with/files/watcher.rb +157 -0
- data/lib/fun_with/files/watchers/directory_watcher.rb +67 -0
- data/lib/fun_with/files/watchers/file_watcher.rb +45 -0
- data/lib/fun_with/files/watchers/missing_watcher.rb +23 -0
- data/lib/fun_with/files/watchers/node_watcher.rb +44 -0
- data/lib/fun_with/testing/assertions/fun_with_files.rb +91 -0
- data/lib/fun_with/testing/test_case_extensions.rb +12 -0
- data/lib/fun_with_files.rb +5 -75
- data/test/helper.rb +13 -5
- data/test/test_core_extensions.rb +5 -0
- data/test/test_directory_builder.rb +29 -10
- data/test/test_extension_methods.rb +62 -0
- data/test/test_file_manipulation.rb +2 -2
- data/test/test_file_path.rb +18 -39
- data/test/test_file_requirements.rb +36 -0
- data/test/test_fun_with_files.rb +1 -1
- data/test/test_fwf_assertions.rb +62 -0
- data/test/test_moving_files.rb +111 -0
- data/test/test_permission_methods.rb +22 -0
- data/test/test_root_path.rb +9 -0
- data/test/test_stat_methods.rb +17 -0
- data/test/test_timestamping.rb +74 -0
- data/test/test_utils_bytesize.rb +71 -0
- data/test/test_utils_succession.rb +30 -0
- data/test/test_watchers.rb +196 -0
- metadata +54 -16
@@ -0,0 +1,62 @@
|
|
1
|
+
module FunWith
|
2
|
+
module Testing
|
3
|
+
class TestFwfAssertions < FunWith::Testing::AssertionsTestCase
|
4
|
+
context "testing assertions" do
|
5
|
+
setup do
|
6
|
+
extended_test_case # sets @case, which is used to access to assertions
|
7
|
+
@case_class.install_fun_with_files_assertions
|
8
|
+
end
|
9
|
+
|
10
|
+
context "testing :assert_fwf_filepath()" do
|
11
|
+
should "pass all tests" do
|
12
|
+
testing_method :assert_fwf_filepath do
|
13
|
+
nope __FILE__
|
14
|
+
yep __FILE__.fwf_filepath
|
15
|
+
|
16
|
+
nope nil
|
17
|
+
nope :five
|
18
|
+
nope 5
|
19
|
+
nope [5]
|
20
|
+
nope "five"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "testing :assert_file()" do
|
26
|
+
should "pass all tests" do
|
27
|
+
testing_method :assert_file do
|
28
|
+
yep __FILE__.fwf_filepath
|
29
|
+
|
30
|
+
nope __FILE__
|
31
|
+
nope nil
|
32
|
+
nope :five
|
33
|
+
nope 5
|
34
|
+
nope [5]
|
35
|
+
nope "five"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "testing :assert_directory()" do
|
41
|
+
should "pass all tests" do
|
42
|
+
testing_method :assert_directory do
|
43
|
+
nope __FILE__
|
44
|
+
nope __FILE__.fwf_filepath
|
45
|
+
|
46
|
+
yep __FILE__.fwf_filepath.dirname
|
47
|
+
yep __FILE__.fwf_filepath.up
|
48
|
+
yep FunWith::Files.root
|
49
|
+
|
50
|
+
nope nil
|
51
|
+
nope :five
|
52
|
+
nope 5
|
53
|
+
nope [5]
|
54
|
+
nope "five"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestMovingFiles < FunWith::Files::TestCase
|
4
|
+
context "inside a tmpdir" do
|
5
|
+
setup do
|
6
|
+
@src_dir = FilePath.tmpdir
|
7
|
+
@dst_dir = FilePath.tmpdir
|
8
|
+
|
9
|
+
assert_directory @src_dir
|
10
|
+
assert_directory @dst_dir
|
11
|
+
|
12
|
+
assert_empty_directory @src_dir
|
13
|
+
assert_empty_directory @dst_dir
|
14
|
+
end
|
15
|
+
|
16
|
+
teardown do
|
17
|
+
@src_dir.rm
|
18
|
+
@dst_dir.rm
|
19
|
+
assert_not_directory @src_dir
|
20
|
+
assert_not_directory @dst_dir
|
21
|
+
end
|
22
|
+
|
23
|
+
context "with a source file" do
|
24
|
+
setup do
|
25
|
+
@src_file = @src_dir / "file.txt"
|
26
|
+
@src_file.write( "Hello world" )
|
27
|
+
|
28
|
+
assert_file_not_empty( @src_file )
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
should "successfully move a file into a directory" do
|
33
|
+
dest = @dst_dir / "file.txt"
|
34
|
+
|
35
|
+
assert_no_file dest
|
36
|
+
|
37
|
+
@src_file.move @dst_dir
|
38
|
+
|
39
|
+
assert_file dest
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
# Seems dangerous to not have a concrete idea of what should happen when a move
|
45
|
+
# remove / create request takes place. Ideas:
|
46
|
+
# be able to mark a destination as a directory, so that it knows the file move
|
47
|
+
# is saying to
|
48
|
+
#
|
49
|
+
# a directory should be created
|
50
|
+
# a directory must exist for the move to occur
|
51
|
+
# nothing exists at the destination, so the file is given the name of <thing_what_didnt_exist>
|
52
|
+
#
|
53
|
+
should "fail to move a file to a non-existent directory" do
|
54
|
+
flunk "this actually moves the file (the file getting the name of the 'missing' directory, and I'm not sure that's wrong)"
|
55
|
+
not_a_dir = @dst_dir / "humblebrag"
|
56
|
+
|
57
|
+
assert_raises( Errno::ENOENT ) do
|
58
|
+
@src_file.move( not_a_dir )
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
should "fail to move a file owing to lack of privileges" do
|
63
|
+
write_protected_dir = @dst_dir / "write_protected_dir"
|
64
|
+
write_protected_dir.touch_dir
|
65
|
+
|
66
|
+
temporarily_write_protect( write_protected_dir ) do
|
67
|
+
assert_raises( Errno::EACCES ) do
|
68
|
+
@src_file.move( write_protected_dir )
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
should "fail to move a non-existent file" do
|
77
|
+
f = @src_dir.join( "file.txt" )
|
78
|
+
|
79
|
+
assert_no_file( f )
|
80
|
+
|
81
|
+
assert_raises( Errno::ENOENT ) do
|
82
|
+
f.move( @dst_dir )
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# should "successfully move a directory" do
|
89
|
+
# flunk "write test"
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# should "fail to move a non-existent directory" do
|
93
|
+
# flunk "write test"
|
94
|
+
# end
|
95
|
+
#
|
96
|
+
# should "fail to move a directory to a non-existent directory" do
|
97
|
+
# flunk "write test"
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
# should "fail to move a directory owing to lack of privileges" do
|
101
|
+
#
|
102
|
+
# flunk "write test"
|
103
|
+
# end
|
104
|
+
# end
|
105
|
+
|
106
|
+
def temporarily_write_protect( f, &block )
|
107
|
+
f.chmod( "a-w" )
|
108
|
+
yield
|
109
|
+
f.chmod( "a+w" )
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestPermissionMethods < FunWith::Files::TestCase
|
4
|
+
context "checking for availability of permission methods" do
|
5
|
+
setup do
|
6
|
+
@filepath = FunWith::Files::FilePath.new("/")
|
7
|
+
end
|
8
|
+
|
9
|
+
should "have permission methods" do
|
10
|
+
assert_respond_to @filepath, :readable?
|
11
|
+
assert_respond_to @filepath, :writable?
|
12
|
+
assert_respond_to @filepath, :executable?
|
13
|
+
assert_respond_to @filepath, :chown
|
14
|
+
assert_respond_to @filepath, :chmod
|
15
|
+
assert_respond_to @filepath, :owner
|
16
|
+
end
|
17
|
+
|
18
|
+
should "have a root owner" do
|
19
|
+
assert_equal "root", @filepath.owner
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/test/test_root_path.rb
CHANGED
@@ -13,6 +13,15 @@ class TestRootPath < FunWith::Files::TestCase
|
|
13
13
|
rootify_and_test( obj, path )
|
14
14
|
end
|
15
15
|
|
16
|
+
context "FunWith::Files.root" do
|
17
|
+
should "be a directory" do
|
18
|
+
assert_directory( FunWith::Files.root )
|
19
|
+
assert_empty_directory( FunWith::Files.root( :test, :tmp ) )
|
20
|
+
assert_empty_directory( FunWith::Files.root / :test / :tmp )
|
21
|
+
assert_empty_directory( FunWith::Files.root / "test" / "tmp" )
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
16
25
|
def rootify_and_test( obj, path )
|
17
26
|
RootPath.rootify( obj, path )
|
18
27
|
assert obj.respond_to?(:root)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestStatMethods < FunWith::Files::TestCase
|
4
|
+
|
5
|
+
context "checking for availability of stat-enabling methods" do
|
6
|
+
setup do
|
7
|
+
@filepath = FunWith::Files::FilePath.new("/")
|
8
|
+
end
|
9
|
+
|
10
|
+
should "have stat methods" do
|
11
|
+
assert_respond_to @filepath, :stat
|
12
|
+
assert_respond_to @filepath, :inode
|
13
|
+
assert_respond_to @filepath, :birthtime # this (and many others) come from Pathname
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestTimestamping < FunWith::Files::TestCase
|
4
|
+
context "testing timestamping" do
|
5
|
+
setup do
|
6
|
+
@tmp_dir = FunWith::Files.root( 'test', 'tmp' )
|
7
|
+
@logfile = @tmp_dir / "apache.log"
|
8
|
+
@stamp_time = Time.new( 2000, 10, 13, 23, 59, 59 )
|
9
|
+
end
|
10
|
+
|
11
|
+
teardown do
|
12
|
+
`rm -rf #{@tmp_dir.join('*')}`
|
13
|
+
end
|
14
|
+
|
15
|
+
should "sequence files with datestamps" do
|
16
|
+
dates = %w(2012-11-30 1900-12-01 2727-06-14)
|
17
|
+
|
18
|
+
for date in dates
|
19
|
+
d = Date.new( * date.split("-").map(&:to_i) )
|
20
|
+
|
21
|
+
f = @logfile.timestamp( format: :ymd, time: d )
|
22
|
+
f.write( date )
|
23
|
+
|
24
|
+
fy = @logfile.timestamp( format: :y, time: d )
|
25
|
+
fy.write date[0..3]
|
26
|
+
end
|
27
|
+
|
28
|
+
for str in dates + %w(2012 1900 2727)
|
29
|
+
file = @tmp_dir / "apache.#{str}.log"
|
30
|
+
assert_file file
|
31
|
+
assert_file_contents file, str
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
should "timestamp files using the timestamp() method" do
|
36
|
+
timestampable_file = @tmp_dir / "timestamped.dat"
|
37
|
+
|
38
|
+
timestamped_file1 = timestampable_file.timestamp
|
39
|
+
timestamped_file2 = timestampable_file.timestamp( format: :y )
|
40
|
+
|
41
|
+
assert timestamped_file1 =~ /timestamped.\d{17}.dat$/
|
42
|
+
assert timestamped_file2 =~ /timestamped.\d{4}.dat$/
|
43
|
+
end
|
44
|
+
|
45
|
+
should "raise an error when invalid format requested" do
|
46
|
+
f = @tmp_dir / "apache.log"
|
47
|
+
|
48
|
+
stamped = f.timestamp
|
49
|
+
|
50
|
+
assert_raises Errors::TimestampFormatUnrecognized do
|
51
|
+
f.timestamp( format: :zztop )
|
52
|
+
end
|
53
|
+
|
54
|
+
# Symbols only!
|
55
|
+
assert_raises Errors::TimestampFormatUnrecognized do
|
56
|
+
f.timestamp( format: "ymd" )
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
should "update the timestamp of a file that already has one" do
|
61
|
+
f = "apache.19931020235959000.tgz".fwf_filepath
|
62
|
+
timestamped_file = f.timestamp( time: @stamp_time )
|
63
|
+
|
64
|
+
assert_equal "apache.20001013235959000.tgz", timestamped_file.path
|
65
|
+
end
|
66
|
+
|
67
|
+
should "be able to give the timestamp method a custom format" do
|
68
|
+
fmt = Utils::TimestampFormat.new.recognizer( /^\d{2}_\d{2}_\d{2}$/ ).strftime( "%m_%d_%y" )
|
69
|
+
|
70
|
+
timestamped_file = @logfile.timestamp( format: fmt, time: @stamp_time )
|
71
|
+
assert_equal "apache.10_13_00.log", timestamped_file.basename.path
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestUtilsByteSize < FunWith::Files::TestCase
|
4
|
+
context "testing the thing" do
|
5
|
+
setup do
|
6
|
+
@bytie = Object.new
|
7
|
+
@bytie.extend FunWith::Files::Utils::ByteSize
|
8
|
+
end
|
9
|
+
|
10
|
+
should "respond to :to_bytes" do
|
11
|
+
assert_respond_to @bytie, :to_bytes
|
12
|
+
end
|
13
|
+
|
14
|
+
should "accurately convert strings to bytes" do
|
15
|
+
assert_bytes 1_000, "1000b"
|
16
|
+
assert_bytes 1_000, "1 kb"
|
17
|
+
assert_bytes 1_000, "0.001 MB"
|
18
|
+
assert_bytes 1_000, "0.000001 GB"
|
19
|
+
|
20
|
+
assert_bytes 1_234, "1234"
|
21
|
+
assert_bytes 1_234, " 1.234 kb "
|
22
|
+
assert_bytes 9_001, "9.001k" # it's over 9000!
|
23
|
+
end
|
24
|
+
|
25
|
+
context "converting expressions between units" do
|
26
|
+
should "handle simple cases" do
|
27
|
+
assert_converts "1KB", "B", "1000B"
|
28
|
+
assert_converts "2MB", "KB", "2000KB"
|
29
|
+
assert_converts "3GB", "MB", "3000MB"
|
30
|
+
assert_converts "4TB", "GB", "4000GB"
|
31
|
+
assert_converts "5PB", "TB", "5000TB"
|
32
|
+
end
|
33
|
+
|
34
|
+
should "be case insensitive" do
|
35
|
+
assert_converts "1kb", "B", "1000B"
|
36
|
+
assert_converts "1000k", "mb", "1mb"
|
37
|
+
assert_converts "1000m", "GB", "1GB"
|
38
|
+
assert_converts "2000 PB", " EB", "2 EB"
|
39
|
+
end
|
40
|
+
|
41
|
+
should "sometimes put space between number and unit" do
|
42
|
+
assert_converts "2000 PB", " EB", "2 EB"
|
43
|
+
end
|
44
|
+
|
45
|
+
should "reflect the unit styling that the caller sends" do
|
46
|
+
assert_converts "1kb", "b", "1000b" # uses the unit capitalization that the caller sends
|
47
|
+
end
|
48
|
+
|
49
|
+
should "sometimes use decimal points" do
|
50
|
+
assert_converts "900kb", "MB", "0.9MB"
|
51
|
+
assert_converts "930kb", "mb", "0.9mb"
|
52
|
+
|
53
|
+
assert_converts "99500b", "kb", "99.5kb"
|
54
|
+
assert_converts "1200MB", "gb", "1.2gb"
|
55
|
+
end
|
56
|
+
|
57
|
+
should "sometimes not use decimal points" do
|
58
|
+
assert_converts "100372b", "k", "100k"
|
59
|
+
assert_converts "1b", "GB", "0GB"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def assert_bytes( n, expr )
|
65
|
+
assert_equal n, @bytie.to_bytes( expr ), "to_bytes( #{expr} ) should resolve to #{n}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def assert_converts( old_expr, new_units, new_expr )
|
69
|
+
assert_equal new_expr, @bytie.convert( old_expr, new_units )
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestUtilsSuccession < FunWith::Files::TestCase
|
4
|
+
USucc = FunWith::Files::Utils::Succession
|
5
|
+
|
6
|
+
context "testing Succession.get_successor_name()" do
|
7
|
+
should "succeed" do
|
8
|
+
with_digit_count( 4 ) do
|
9
|
+
assert_succession "file.0001.txt", "file.0002.txt"
|
10
|
+
assert_succession "file.txt", "file.0000.txt"
|
11
|
+
assert_succession "", "0000"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def with_digit_count( i, &block )
|
17
|
+
@digit_count = i
|
18
|
+
yield
|
19
|
+
end
|
20
|
+
|
21
|
+
def assert_succession( input, expected )
|
22
|
+
if defined?( @digit_count )
|
23
|
+
actual = USucc.get_successor_name( input, @digit_count )
|
24
|
+
else
|
25
|
+
actual = USucc.get_successor_name( input )
|
26
|
+
end
|
27
|
+
|
28
|
+
assert_equal( expected, actual, "Utils::Succession.get_successor_name() failed:\n\tinput: #{input}(#{input.class})\n\texpected: #{expected}(#{expected.class})\n\tactual: #{actual}(#{actual.class})")
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestWatchers < FunWith::Files::TestCase
|
4
|
+
context "testing Watcher as it benevolently watches over the files placed under its care" do
|
5
|
+
setup do
|
6
|
+
tmpdir # assigns @tmpdir a freshly created temp directory
|
7
|
+
self.watch @tmpdir
|
8
|
+
end
|
9
|
+
|
10
|
+
teardown do
|
11
|
+
@tmpdir.rm
|
12
|
+
end
|
13
|
+
|
14
|
+
should "watch an empty directory as a subdirectory and a file are added" do
|
15
|
+
@tmpdir.touch_dir :lethe do |d|
|
16
|
+
file = d.join( "forgotten_file.txt" )
|
17
|
+
file.write( "someone help me remember this" )
|
18
|
+
|
19
|
+
get_changes do
|
20
|
+
assert_changes :created, d, file
|
21
|
+
end
|
22
|
+
|
23
|
+
file.append( "\nbecause I don't trust my brain to keep track of things" )
|
24
|
+
|
25
|
+
get_changes(1) do
|
26
|
+
assert_changes :modified, file
|
27
|
+
end
|
28
|
+
|
29
|
+
d.rm
|
30
|
+
|
31
|
+
get_changes do
|
32
|
+
assert_changes :deleted, d, file
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
should "watch an empty directory as a bunch of changes happen" do
|
38
|
+
@tmpdir.touch_dir( :battles ) do |d0|
|
39
|
+
@tmpdir.touch_dir( :bunker_hill ) do |d1|
|
40
|
+
file0 = d1.join( "troop_movements.csv" )
|
41
|
+
file0.write( "My dearest Sarah,\n\tI fear this may be the last time I write to you. Our forces are outnumbered." )
|
42
|
+
|
43
|
+
get_changes do
|
44
|
+
assert_changes :created, d0, d1, file0
|
45
|
+
end
|
46
|
+
|
47
|
+
file0.append "Supplies are scarce and the horses have lost their patience with us."
|
48
|
+
|
49
|
+
get_changes(1) do
|
50
|
+
assert_changes :modified, file0
|
51
|
+
end
|
52
|
+
|
53
|
+
d1.rm
|
54
|
+
|
55
|
+
get_changes(2) do
|
56
|
+
assert_changes :deleted, d1, file0
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
d0.rm
|
61
|
+
|
62
|
+
get_changes(1) do
|
63
|
+
assert_changes :deleted, d0
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
should "watch for a file that doesn't exist yet" do
|
69
|
+
@tmpdir.touch_dir( "web_app" ) do |d|
|
70
|
+
watch( d.join( "restart.txt" ) )
|
71
|
+
|
72
|
+
get_changes(0)
|
73
|
+
|
74
|
+
restart_file = d.touch( "restart.txt" )
|
75
|
+
|
76
|
+
get_changes(1) do
|
77
|
+
assert_changes :created, restart_file
|
78
|
+
end
|
79
|
+
|
80
|
+
restart_file.rm
|
81
|
+
|
82
|
+
get_changes(1) do
|
83
|
+
assert_changes :deleted, restart_file
|
84
|
+
end
|
85
|
+
|
86
|
+
get_changes(0)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
should "build out a filesystem using DirectoryBuilder" do
|
91
|
+
@tmpdir.touch_dir( :ebook ) do |ebook|
|
92
|
+
watch ebook
|
93
|
+
|
94
|
+
DirectoryBuilder.create( ebook ) do |builder|
|
95
|
+
builder.dir( :html ) do
|
96
|
+
builder.file "title_page.xhtml", "Make sure we get some neato art to go here."
|
97
|
+
builder.file "chapter1.xhtml", "Besta times, worsta times, y'know?"
|
98
|
+
builder.file "chapter2.xhtml", "I see a magpie perched on the roof."
|
99
|
+
end
|
100
|
+
|
101
|
+
builder.dir( :css ) do
|
102
|
+
builder.file "main.css", "p{ background-color: painfully-pink}"
|
103
|
+
builder.file "title_page.css", "body{ width: 80% }"
|
104
|
+
end
|
105
|
+
|
106
|
+
builder.dir( :images ) do
|
107
|
+
builder.file "cover.png", "We shoulda hired a graphic designer"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
html_dir = ebook / :html
|
112
|
+
|
113
|
+
images_dir = ebook / :images
|
114
|
+
cover_file = images_dir / "cover.png"
|
115
|
+
|
116
|
+
get_changes(9) do
|
117
|
+
assert_changes :created,
|
118
|
+
# ebook, # already existed when the watcher started
|
119
|
+
html_dir,
|
120
|
+
html_dir / "title_page.xhtml",
|
121
|
+
ebook / :css,
|
122
|
+
ebook / :css / "main.css",
|
123
|
+
images_dir,
|
124
|
+
cover_file
|
125
|
+
end
|
126
|
+
|
127
|
+
cover_file.append ", Trevor worked out okay last time, can we use him again?"
|
128
|
+
|
129
|
+
# debugger
|
130
|
+
|
131
|
+
get_changes(2) do
|
132
|
+
assert_changes :modified, cover_file, images_dir, html_dir
|
133
|
+
end
|
134
|
+
|
135
|
+
images_dir.rm
|
136
|
+
|
137
|
+
get_changes(2) do
|
138
|
+
assert_changes :deleted, images_dir, cover_file, html_dir
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
should "only notice changes that aren't excluded by filters" do
|
144
|
+
|
145
|
+
@tmpdir.touch_dir( :application_code ) do |code|
|
146
|
+
watch( code )
|
147
|
+
|
148
|
+
@watcher.filter( notice: /\.cpp$/, ignore: /main.cpp$/ )
|
149
|
+
|
150
|
+
f0 = code.touch( "main.cpp" )
|
151
|
+
f1 = code.touch( "counter.cpp" )
|
152
|
+
|
153
|
+
get_changes( count: 1 ) do
|
154
|
+
assert_changes :added, f1
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def watch( *paths )
|
161
|
+
@watcher = Watcher.watch( *paths ).sleep_interval( 0.01 )
|
162
|
+
end
|
163
|
+
|
164
|
+
def get_changes( count: nil, expected: nil, &block )
|
165
|
+
@changes = @watcher.update
|
166
|
+
yield if block_given?
|
167
|
+
assert_change_count( count ) unless count.nil?
|
168
|
+
assert_change_set( expected ) unless expected.nil?
|
169
|
+
end
|
170
|
+
|
171
|
+
def assert_changes( status, *paths )
|
172
|
+
assert_kind_of Hash, @changes
|
173
|
+
|
174
|
+
oopsies = {}
|
175
|
+
|
176
|
+
for path in paths
|
177
|
+
path_to_report = path.relative_path_from(@tmpdir).to_s
|
178
|
+
|
179
|
+
if @changes.has_key?( path )
|
180
|
+
oopsies[path_to_report] = :change_not_reported
|
181
|
+
elsif status != @changes[path]
|
182
|
+
oopsies[path_to_report] = { :expected => status, :actual => @changes[path] }
|
183
|
+
end
|
184
|
+
|
185
|
+
unless oopsies.fwf_blank?
|
186
|
+
assert false, "Unexpected:" + oopsies.inspect
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def assert_change_count( i )
|
192
|
+
assert defined?( @changes )
|
193
|
+
assert_kind_of Hash, @changes
|
194
|
+
assert_length i, @changes
|
195
|
+
end
|
196
|
+
end
|