filewatcher 0.5.4 → 1.0.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.
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Filewatcher
4
+ # Module for all cycles in `Filewatcher#watch`
5
+ module Cycles
6
+ private
7
+
8
+ def main_cycle
9
+ while @keep_watching
10
+ @end_snapshot = mtime_snapshot if @pausing
11
+
12
+ pausing_cycle
13
+
14
+ watching_cycle
15
+
16
+ # test and clear @changes to prevent yielding the last
17
+ # changes twice if @keep_watching has just been set to false
18
+ trigger_changes
19
+ end
20
+ end
21
+
22
+ def pausing_cycle
23
+ while @keep_watching && @pausing
24
+ update_spinner('Pausing')
25
+ sleep @interval
26
+ end
27
+ end
28
+
29
+ def watching_cycle
30
+ while @keep_watching && !filesystem_updated? && !@pausing
31
+ update_spinner('Watching')
32
+ sleep @interval
33
+ end
34
+ end
35
+
36
+ def trigger_changes(on_update = @on_update)
37
+ thread = Thread.new do
38
+ changes = @every ? @changes : @changes.first(1)
39
+ changes.each do |filename, event|
40
+ on_update.call(filename, event)
41
+ end
42
+ @changes.clear
43
+ end
44
+ thread.join
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname'
4
+ require_relative '../filewatcher'
5
+
6
+ class Filewatcher
7
+ # Class for building ENV variables for executable
8
+ class Env
9
+ def initialize(filename, event)
10
+ @filename = filename
11
+ @event = event
12
+ @path = Pathname.new(@filename)
13
+ @realpath = @path.realpath
14
+ @current_dir = Pathname.new(Dir.pwd)
15
+ end
16
+
17
+ def to_h
18
+ {
19
+ 'FILEPATH' => (@realpath.to_s if @event != :deleted),
20
+ 'FILENAME' => @filename,
21
+ 'BASENAME' => @path.basename.to_s,
22
+ 'EVENT' => @event.to_s,
23
+ 'DIRNAME' => @path.parent.realpath.to_s,
24
+ 'ABSOLUTE_FILENAME' => @realpath.to_s,
25
+ 'RELATIVE_FILENAME' => @realpath.relative_path_from(@current_dir).to_s
26
+ }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Filewatcher
4
+ ## Get runner command by filename
5
+ class Runner
6
+ ## Define runners for `--exec` option
7
+ RUNNERS = {
8
+ python: %w[py],
9
+ node: %w[js],
10
+ ruby: %w[rb],
11
+ perl: %w[pl],
12
+ awk: %w[awk],
13
+ php: %w[php phtml php4 php3 php5 phps]
14
+ }.freeze
15
+
16
+ def initialize(filename)
17
+ @filename = filename
18
+ @ext = File.extname(filename).delete('.')
19
+ end
20
+
21
+ def command
22
+ "env #{runner} #{@filename}" if runner
23
+ end
24
+
25
+ private
26
+
27
+ def runner
28
+ return @runner if defined?(@runner)
29
+ @runner, _exts = RUNNERS.find { |_cmd, exts| exts.include? @ext }
30
+ @runner
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../filewatcher'
4
+
5
+ class Filewatcher
6
+ VERSION = '1.0.0'.freeze
7
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../helper'
4
+
5
+ dump_to_env_file(
6
+ %w[
7
+ FILENAME BASENAME EVENT DIRNAME ABSOLUTE_FILENAME
8
+ RELATIVE_FILENAME
9
+ ].map { |var| ENV[var] }.join(', ')
10
+ )
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../helper'
4
+
5
+ dump_to_env_file 'watched'
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../lib/filewatcher/env'
4
+
5
+ describe Filewatcher::Env do
6
+ describe '#initialize' do
7
+ it 'should recieve filename and event' do
8
+ -> { Filewatcher::Env.new(__FILE__, :updated) }
9
+ .should.not.raise ArgumentError
10
+ end
11
+ end
12
+
13
+ describe '#to_h' do
14
+ before do
15
+ @init = proc do |file: __FILE__, event: :updated|
16
+ Filewatcher::Env.new(file, event).to_h
17
+ end
18
+ @env = @init.call
19
+ end
20
+
21
+ it 'should return Hash' do
22
+ @env.should.be.kind_of Hash
23
+ end
24
+
25
+ it 'should return Hash with FILEPATH key for created event' do
26
+ @init.call(event: :created)['FILEPATH']
27
+ .should.equal File.join(Dir.pwd, __FILE__)
28
+ end
29
+
30
+ it 'should return Hash with FILEPATH key for updated event' do
31
+ @init.call(event: :updated)['FILEPATH']
32
+ .should.equal File.join(Dir.pwd, __FILE__)
33
+ end
34
+
35
+ it 'should return Hash without FILEPATH key for deleted event' do
36
+ @init.call(event: :deleted)['FILEPATH']
37
+ .should.equal nil
38
+ end
39
+
40
+ it 'should return Hash with FILENAME key' do
41
+ @init.call(file: __FILE__)['FILENAME']
42
+ .should.equal __FILE__
43
+ end
44
+
45
+ it 'should return Hash with BASENAME key' do
46
+ @init.call(file: __FILE__)['BASENAME']
47
+ .should.equal File.basename(__FILE__)
48
+ end
49
+
50
+ it 'should return Hash with EVENT key' do
51
+ @init.call(event: :updated)['EVENT']
52
+ .should.equal 'updated'
53
+ end
54
+
55
+ it 'should return Hash with DIRNAME key' do
56
+ @init.call(file: __FILE__)['DIRNAME']
57
+ .should.equal File.dirname(File.join(Dir.pwd, __FILE__))
58
+ end
59
+
60
+ it 'should return Hash with ABSOLUTE_FILENAME key' do
61
+ @init.call(file: __FILE__)['ABSOLUTE_FILENAME']
62
+ .should.equal File.join(Dir.pwd, __FILE__)
63
+ end
64
+
65
+ it 'should return Hash with RELATIVE_FILENAME key' do
66
+ @init.call(file: __FILE__)['RELATIVE_FILENAME']
67
+ .should.equal __FILE__
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../lib/filewatcher/runner'
4
+
5
+ describe Filewatcher::Runner do
6
+ before do
7
+ @init = proc do |filename|
8
+ Filewatcher::Runner.new(filename)
9
+ end
10
+ end
11
+
12
+ describe '#initialize' do
13
+ it 'should recieve filename' do
14
+ -> { @init.call('file.txt') }
15
+ .should.not.raise ArgumentError
16
+ end
17
+ end
18
+
19
+ describe '#command' do
20
+ it 'should return correct command for file with .py extension' do
21
+ @init.call('file.py').command
22
+ .should.equal 'env python file.py'
23
+ end
24
+
25
+ it 'should return correct command for file with .js extension' do
26
+ @init.call('file.js').command
27
+ .should.equal 'env node file.js'
28
+ end
29
+
30
+ it 'should return correct command for file with .rb extension' do
31
+ @init.call('file.rb').command
32
+ .should.equal 'env ruby file.rb'
33
+ end
34
+
35
+ it 'should return correct command for file with .pl extension' do
36
+ @init.call('file.pl').command
37
+ .should.equal 'env perl file.pl'
38
+ end
39
+
40
+ it 'should return correct command for file with .awk extension' do
41
+ @init.call('file.awk').command
42
+ .should.equal 'env awk file.awk'
43
+ end
44
+
45
+ it 'should return correct command for file with .php extension' do
46
+ @init.call('file.php').command
47
+ .should.equal 'env php file.php'
48
+ end
49
+
50
+ it 'should return correct command for file with .phtml extension' do
51
+ @init.call('file.phtml').command
52
+ .should.equal 'env php file.phtml'
53
+ end
54
+
55
+ it 'should return correct command for file with .php4 extension' do
56
+ @init.call('file.php4').command
57
+ .should.equal 'env php file.php4'
58
+ end
59
+
60
+ it 'should return correct command for file with .php3 extension' do
61
+ @init.call('file.php3').command
62
+ .should.equal 'env php file.php3'
63
+ end
64
+
65
+ it 'should return correct command for file with .php5 extension' do
66
+ @init.call('file.php5').command
67
+ .should.equal 'env php file.php5'
68
+ end
69
+
70
+ it 'should return correct command for file with .phps extension' do
71
+ @init.call('file.phps').command
72
+ .should.equal 'env php file.phps'
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../lib/filewatcher/version'
4
+
5
+ describe Filewatcher::VERSION do
6
+ it 'should exist as constant' do
7
+ Filewatcher.const_defined?(:VERSION).should.be.true
8
+ end
9
+
10
+ it 'should be an instance of String' do
11
+ Filewatcher::VERSION.class.should.equal String
12
+ end
13
+ end
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bacon'
4
+ require 'bacon/custom_matchers_messages'
5
+
6
+ begin
7
+ require 'pry-byebug'
8
+ rescue LoadError
9
+ nil
10
+ end
11
+
12
+ class WatchRun
13
+ TMP_DIR = File.join(__dir__, 'tmp')
14
+
15
+ attr_reader :filename, :filewatcher, :thread, :watched, :processed
16
+
17
+ def initialize(
18
+ filename: 'tmp_file.txt',
19
+ directory: false,
20
+ every: false,
21
+ filewatcher: Filewatcher.new(
22
+ File.join(TMP_DIR, '**', '*'), interval: 0.1, every: every
23
+ ),
24
+ action: :update
25
+ )
26
+ @filename =
27
+ filename.start_with?('/', '~') ? filename : File.join(TMP_DIR, filename)
28
+ @directory = directory
29
+ @filewatcher = filewatcher
30
+ @action = action
31
+ end
32
+
33
+ def start
34
+ File.write(@filename, 'content1') unless @action == :create
35
+
36
+ @thread = thread_initialize
37
+ sleep 3 # thread needs a chance to start
38
+ end
39
+
40
+ def run
41
+ start
42
+
43
+ make_changes
44
+ # Some OS, filesystems and Ruby interpretators
45
+ # doesn't catch milliseconds of `File.mtime`
46
+ sleep 3
47
+
48
+ stop
49
+ end
50
+
51
+ def stop
52
+ FileUtils.rm_r(@filename) if File.exist?(@filename)
53
+ @thread.exit
54
+ sleep 3
55
+ end
56
+
57
+ private
58
+
59
+ def thread_initialize
60
+ @watched ||= 0
61
+ Thread.new(
62
+ @filewatcher, @processed = []
63
+ ) do |filewatcher, processed|
64
+ filewatcher.watch do |filename, event|
65
+ increment_watched
66
+ processed.push([filename, event])
67
+ end
68
+ end
69
+ end
70
+
71
+ def increment_watched
72
+ @watched += 1
73
+ end
74
+
75
+ def make_changes
76
+ return FileUtils.remove(@filename) if @action == :delete
77
+ return FileUtils.mkdir_p(@filename) if @directory
78
+ File.write(@filename, 'content2')
79
+ end
80
+ end
81
+
82
+ class ShellWatchRun
83
+ EXECUTABLE = "#{'ruby ' if Gem.win_platform?}" \
84
+ "#{File.realpath File.join(__dir__, '..', 'bin', 'filewatcher')}".freeze
85
+
86
+ attr_reader :output
87
+
88
+ def initialize(
89
+ options: '',
90
+ dumper: :watched,
91
+ output: File.join(WatchRun::TMP_DIR, 'env')
92
+ )
93
+ @options = options
94
+ @dumper = dumper
95
+ @output = output
96
+ end
97
+
98
+ def start
99
+ @pid = spawn(
100
+ "#{EXECUTABLE} #{@options} \"#{WatchRun::TMP_DIR}/foo*\"" \
101
+ " \"ruby #{File.join(__dir__, 'dumpers', "#{@dumper}_dumper.rb")}\""
102
+ )
103
+ Process.detach(@pid)
104
+ sleep 12
105
+ end
106
+
107
+ def run
108
+ start
109
+
110
+ make_changes
111
+
112
+ stop
113
+ end
114
+
115
+ def stop
116
+ Process.kill('KILL', @pid)
117
+ sleep 6
118
+ end
119
+
120
+ private
121
+
122
+ def make_changes
123
+ FileUtils.touch "#{WatchRun::TMP_DIR}/foo.txt"
124
+ sleep 12
125
+ end
126
+ end
127
+
128
+ custom_matcher :include_all_files do |obj, elements|
129
+ elements.all? { |element| obj.include? File.expand_path(element) }
130
+ end
131
+
132
+ def dump_to_env_file(content)
133
+ File.write File.join(WatchRun::TMP_DIR, 'env'), content
134
+ end
@@ -1,181 +1,305 @@
1
- require 'rubygems'
2
- require 'bacon'
1
+ # frozen_string_literal: true
2
+
3
3
  require 'fileutils'
4
- require File.expand_path("../lib/filewatcher.rb",File.dirname(__FILE__))
4
+ require_relative '../lib/filewatcher'
5
5
 
6
+ describe Filewatcher do
7
+ before do
8
+ FileUtils.mkdir_p WatchRun::TMP_DIR
9
+ end
6
10
 
11
+ after do
12
+ FileUtils.rm_r WatchRun::TMP_DIR
13
+ end
7
14
 
8
- describe FileWatcher do
15
+ describe '#initialize' do
16
+ it 'should exclude selected file patterns' do
17
+ wr = WatchRun.new(
18
+ filewatcher: Filewatcher.new(
19
+ File.expand_path('test/tmp/**/*'),
20
+ exclude: File.expand_path('test/tmp/**/*.txt')
21
+ )
22
+ )
9
23
 
10
- fixtures =
11
- %w(test/fixtures/file4.rb
12
- test/fixtures/subdir/file6.rb
13
- test/fixtures/subdir/file5.rb
14
- test/fixtures/file2.txt
15
- test/fixtures/file1.txt
16
- test/fixtures/file3.rb)
24
+ wr.run
17
25
 
18
- explicit_relative_fixtures = fixtures.map { |it| "./#{it}" }
26
+ wr.processed.should.be.empty
27
+ end
19
28
 
20
- subfolder = 'test/fixtures/new_sub_folder'
29
+ it 'should handle absolute paths with globs' do
30
+ wr = WatchRun.new(
31
+ filewatcher: Filewatcher.new(
32
+ File.expand_path('test/tmp/**/*')
33
+ )
34
+ )
21
35
 
22
- after do
23
- FileUtils.rm_rf subfolder
24
- end
36
+ wr.run
25
37
 
26
- def includes_all(elements)
27
- lambda { |it| elements.all? { |element| it.include? element }}
28
- end
38
+ wr.processed.should.equal(
39
+ [[wr.filename, :updated]]
40
+ )
41
+ end
29
42
 
30
- it "should exclude selected file patterns" do
31
- filewatcher = FileWatcher.new(File.expand_path('test/fixtures/**/*'), :exclude => [File.expand_path("test/fixtures/**/*.txt")])
32
- filtered_fixtures =
33
- %w(test/fixtures/file4.rb
34
- test/fixtures/subdir/file6.rb
35
- test/fixtures/subdir/file5.rb
36
- test/fixtures/file3.rb)
37
- filewatcher.filenames.should.satisfy &includes_all(filtered_fixtures.map { |it| File.expand_path(it) })
38
- end
39
-
40
- it "should handle absolute paths with globs" do
41
- filewatcher = FileWatcher.new(File.expand_path('test/fixtures/**/*'))
43
+ it 'should handle globs' do
44
+ wr = WatchRun.new(
45
+ filewatcher: Filewatcher.new('test/tmp/**/*')
46
+ )
42
47
 
43
- filewatcher.filenames.should.satisfy &includes_all(fixtures.map { |it| File.expand_path(it) })
44
- end
45
-
46
- it "should handle globs" do
47
- filewatcher = FileWatcher.new('test/fixtures/**/*')
48
+ wr.run
48
49
 
49
- filewatcher.filenames.should.satisfy &includes_all(fixtures)
50
- end
50
+ wr.processed.should.equal(
51
+ [[wr.filename, :updated]]
52
+ )
53
+ end
51
54
 
55
+ it 'should handle explicit relative paths with globs' do
56
+ wr = WatchRun.new(
57
+ filewatcher: Filewatcher.new('./test/tmp/**/*')
58
+ )
52
59
 
53
- it "should handle explicit relative paths with globs" do
54
- filewatcher = FileWatcher.new('./test/fixtures/**/*')
60
+ wr.run
55
61
 
56
- filewatcher.filenames.should.satisfy &includes_all(explicit_relative_fixtures)
57
- end
62
+ wr.processed.should.equal(
63
+ [[wr.filename, :updated]]
64
+ )
65
+ end
58
66
 
59
- it "should handle explicit relative paths" do
60
- filewatcher = FileWatcher.new('./test/fixtures')
67
+ it 'should handle explicit relative paths' do
68
+ wr = WatchRun.new(
69
+ filewatcher: Filewatcher.new('./test/tmp')
70
+ )
61
71
 
62
- filewatcher.filenames.should.satisfy &includes_all(explicit_relative_fixtures)
63
- end
72
+ wr.run
73
+
74
+ wr.processed.should.equal(
75
+ [[wr.filename, :updated]]
76
+ )
77
+ end
64
78
 
65
- it "should handle tilde expansion" do
66
- filename = File.expand_path('~/file_watcher_1.txt')
67
- open(filename, 'w') { |f| f.puts 'content1' }
79
+ it 'should handle tilde expansion' do
80
+ filename = File.expand_path('~/file_watcher_1.txt')
68
81
 
69
- filewatcher = FileWatcher.new('~/file_watcher_1.txt')
82
+ wr = WatchRun.new(
83
+ filename: filename,
84
+ filewatcher: Filewatcher.new('~/file_watcher_1.txt')
85
+ )
70
86
 
71
- begin
72
- filewatcher.filenames.should == [filename]
73
- ensure
74
- FileUtils.rm(filename)
87
+ wr.run
88
+
89
+ wr.processed.should.equal(
90
+ [[filename, :updated]]
91
+ )
75
92
  end
76
- end
77
93
 
78
- it "should detect file deletions" do
79
- filename = "test/fixtures/file1.txt"
80
- open(filename,"w") { |f| f.puts "content1" }
81
- filewatcher = FileWatcher.new(["test/fixtures"])
82
- filewatcher.filesystem_updated?.should.be.false
83
- FileUtils.rm(filename)
84
- filewatcher.filesystem_updated?.should.be.true
85
- end
94
+ it 'should immediately run with corresponding option' do
95
+ wr = WatchRun.new(
96
+ filewatcher: Filewatcher.new('**/*', immediate: true)
97
+ )
86
98
 
87
- it "should detect file additions" do
88
- filename = "test/fixtures/file1.txt"
89
- FileUtils.rm(filename) if File.exists?(filename)
90
- filewatcher = FileWatcher.new(["test/fixtures"])
91
- filewatcher.filesystem_updated?.should.be.false
92
- open(filename,"w") { |f| f.puts "content1" }
93
- filewatcher.filesystem_updated?.should.be.true
94
- end
99
+ wr.start
100
+ wr.stop
95
101
 
96
- it "should detect file updates" do
97
- filename = "test/fixtures/file1.txt"
98
- open(filename,"w") { |f| f.puts "content1" }
99
- filewatcher = FileWatcher.new(["test/fixtures"])
100
- filewatcher.filesystem_updated?.should.be.false
101
- sleep 1
102
- open(filename,"w") { |f| f.puts "content2" }
103
- filewatcher.filesystem_updated?.should.be.true
104
- end
102
+ wr.processed.should.equal [['', '']]
103
+ wr.watched.should.be > 0
104
+ end
105
105
 
106
- it "should detect new files in subfolders" do
107
- FileUtils::mkdir_p subfolder
106
+ it 'should not be executed without immediate option and changes' do
107
+ wr = WatchRun.new(
108
+ filewatcher: Filewatcher.new('**/*', immediate: false)
109
+ )
108
110
 
109
- filewatcher = FileWatcher.new(["./test/fixtures"])
110
- filewatcher.filesystem_updated?.should.be.false
111
+ wr.start
112
+ wr.stop
111
113
 
112
- open(subfolder + "/file.txt","w") { |f| f.puts "xyz" }
113
- filewatcher.filesystem_updated?.should.be.true
114
+ wr.processed.should.be.empty
115
+ wr.watched.should.equal 0
116
+ end
114
117
  end
115
118
 
116
- it "should detect new subfolders" do
117
- filewatcher = FileWatcher.new(["test/fixtures"])
118
- filewatcher.filesystem_updated?.should.be.false
119
+ describe '#watch' do
120
+ it 'should detect file deletions' do
121
+ wr = WatchRun.new(action: :delete)
122
+
123
+ wr.run
124
+
125
+ wr.processed.should.equal(
126
+ [[wr.filename, :deleted]]
127
+ )
128
+ end
129
+
130
+ it 'should detect file additions' do
131
+ wr = WatchRun.new(action: :create)
132
+
133
+ wr.run
134
+
135
+ wr.processed.should.equal(
136
+ [[wr.filename, :created]]
137
+ )
138
+ end
139
+
140
+ it 'should detect file updates' do
141
+ wr = WatchRun.new(action: :update)
142
+
143
+ wr.run
144
+
145
+ wr.processed.should.equal(
146
+ [[wr.filename, :updated]]
147
+ )
148
+ end
149
+
150
+ it 'should detect new files in subfolders' do
151
+ FileUtils.mkdir_p subfolder = File.expand_path('test/tmp/new_sub_folder')
152
+
153
+ wr = WatchRun.new(
154
+ filename: File.join(subfolder, 'file.txt'),
155
+ action: :create,
156
+ every: true
157
+ )
158
+ wr.run
159
+ wr.processed.should.equal(
160
+ [
161
+ [subfolder, :updated],
162
+ [wr.filename, :created]
163
+ ]
164
+ )
165
+ end
119
166
 
120
- FileUtils::mkdir_p subfolder
121
- filewatcher.filesystem_updated?.should.be.true
167
+ it 'should detect new subfolders' do
168
+ subfolder = 'new_sub_folder'
169
+
170
+ wr = WatchRun.new(
171
+ filename: subfolder,
172
+ directory: true,
173
+ action: :create
174
+ )
175
+
176
+ wr.run
177
+
178
+ wr.processed.should.equal(
179
+ [[wr.filename, :created]]
180
+ )
181
+ end
122
182
  end
123
183
 
124
- it "should be stoppable" do
125
- filewatcher = FileWatcher.new(["test/fixtures"])
126
- thread = Thread.new(filewatcher){filewatcher.watch(0.1)}
127
- sleep 0.2 # thread needs a chance to start
128
- filewatcher.stop
129
- thread.join.should.equal thread # Proves thread successfully joined
184
+ describe '#stop' do
185
+ it 'should work' do
186
+ wr = WatchRun.new
187
+
188
+ wr.start
189
+
190
+ wr.filewatcher.stop
191
+
192
+ # Proves thread successfully joined
193
+ wr.thread.join.should.equal wr.thread
194
+ end
130
195
  end
131
196
 
132
- it "should be pauseable/resumable" do
133
- filewatcher = FileWatcher.new(["test/fixtures"])
134
- filewatcher.filesystem_updated?.should.be.false
135
- processed = []
136
- thread = Thread.new(filewatcher,processed) do
137
- filewatcher.watch(0.1){|f,e| processed << f }
138
- end
139
- sleep 0.2 # thread needs a chance to start
140
- filewatcher.pause
141
- (1..4).each do |n|
142
- open("test/fixtures/file#{n}.txt","w") { |f| f.puts "content#{n}" }
143
- end
144
- sleep 0.2 # Give filewatcher time to respond
145
- processed.should.equal [] #update block should not have been called
146
- filewatcher.resume
147
- sleep 0.2 # Give filewatcher time to respond
148
- processed.should.equal [] #update block still should not have been called
149
- added_files = []
150
- (5..7).each do |n|
151
- added_files << "test/fixtures/file#{n}.txt"
152
- open(added_files.last,"w") { |f| f.puts "content#{n}" }
153
- end
154
- sleep 0.2 # Give filewatcher time to respond
155
- filewatcher.stop
156
- processed.should.satisfy &includes_all(added_files)
197
+ describe '#pause, #resume' do
198
+ it 'should work' do
199
+ wr = WatchRun.new(action: :create, every: true)
200
+
201
+ wr.start
202
+
203
+ wr.filewatcher.pause
204
+
205
+ (1..4).each do |n|
206
+ File.write("test/tmp/file#{n}.txt", "content#{n}")
207
+ end
208
+ sleep 0.2 # Give filewatcher time to respond
209
+
210
+ # update block should not have been called
211
+ wr.processed.should.be.empty
212
+
213
+ wr.filewatcher.resume
214
+ sleep 0.2 # Give filewatcher time to respond
215
+
216
+ # update block still should not have been called
217
+ wr.processed.should.be.empty
218
+
219
+ added_files = (5..7).to_a.map do |n|
220
+ File.write(file = "test/tmp/file#{n}.txt", "content#{n}")
221
+ file
222
+ end
223
+ sleep 0.2 # Give filewatcher time to respond
224
+
225
+ wr.filewatcher.stop
226
+ wr.stop
227
+ wr.processed.map(&:first).should include_all_files(added_files)
228
+ end
157
229
  end
158
230
 
159
- it "should process all remaining changes at finalize" do
160
- filewatcher = FileWatcher.new(["test/fixtures"])
161
- filewatcher.filesystem_updated?.should.be.false
162
- processed = []
163
- thread = Thread.new(filewatcher,processed) do
164
- filewatcher.watch(0.1){|f,e| processed << f }
165
- end
166
- sleep 0.2 # thread needs a chance to start
167
- filewatcher.stop
168
- thread.join
169
- added_files = []
170
- (1..4).each do |n|
171
- added_files << "test/fixtures/file#{n}.txt"
172
- open(added_files.last,"w") { |f| f.puts "content#{n}" }
173
- end
174
- filewatcher.finalize
175
- puts "What is wrong with finalize:"
176
- puts "Expect: #{added_files.inspect}"
177
- puts "Actual: #{processed.inspect}"
178
- # processed.should.satisfy &includes_all(added_files)
231
+ describe '#finalize' do
232
+ it 'should process all remaining changes' do
233
+ wr = WatchRun.new(action: :create, every: true)
234
+
235
+ wr.start
236
+
237
+ wr.filewatcher.stop
238
+ wr.thread.join
239
+
240
+ added_files = (1..4).to_a.map do |n|
241
+ File.write(file = "test/tmp/file#{n}.txt", "content#{n}")
242
+ file
243
+ end
244
+
245
+ wr.filewatcher.finalize
246
+
247
+ wr.processed.map(&:first).should include_all_files(added_files)
248
+ end
179
249
  end
180
250
 
251
+ describe 'executable' do
252
+ tmp_dir = WatchRun::TMP_DIR
253
+
254
+ it 'should run' do
255
+ null_output = Gem.win_platform? ? 'NUL' : '/dev/null'
256
+ system("#{ShellWatchRun::EXECUTABLE} > #{null_output}")
257
+ .should.be.true
258
+ end
259
+
260
+ it 'should set correct ENV variables' do
261
+ swr = ShellWatchRun.new(
262
+ dumper: :env
263
+ )
264
+
265
+ swr.run
266
+
267
+ File.read(swr.output)
268
+ .should.equal(
269
+ %W[
270
+ #{tmp_dir}/foo.txt
271
+ foo.txt
272
+ created
273
+ #{tmp_dir}
274
+ #{tmp_dir}/foo.txt
275
+ test/tmp/foo.txt
276
+ ].join(', ')
277
+ )
278
+ end
279
+
280
+ it 'should be executed immediately with corresponding option' do
281
+ swr = ShellWatchRun.new(
282
+ options: '--immediate',
283
+ dumper: :watched
284
+ )
285
+
286
+ swr.start
287
+ swr.stop
288
+
289
+ File.exist?(swr.output).should.be.true
290
+ File.read(swr.output).should.equal 'watched'
291
+ end
292
+
293
+ it 'should not be executed without immediate option and changes' do
294
+ swr = ShellWatchRun.new(
295
+ options: '',
296
+ dumper: :watched
297
+ )
298
+
299
+ swr.start
300
+ swr.stop
301
+
302
+ File.exist?(swr.output).should.be.false
303
+ end
304
+ end
181
305
  end