listen 2.0.0 → 2.0.1

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,112 @@
1
+ require 'spec_helper'
2
+
3
+ describe Listen::File do
4
+ let(:record) { double(Listen::Record, async: double(set_path: true, unset_path: true)) }
5
+ let(:path) { Pathname.new(Dir.pwd) }
6
+ around { |example| fixtures { |path| example.run } }
7
+ before { Celluloid::Actor.stub(:[]).with(:listen_record) { record } }
8
+
9
+ describe "#change" do
10
+ let(:file_path) { path.join('file.rb') }
11
+ let(:file) { Listen::File.new(file_path) }
12
+ let(:expected_data) {
13
+ if darwin?
14
+ { type: 'File', mtime: kind_of(Float), mode: kind_of(Integer), md5: kind_of(String) }
15
+ else
16
+ { type: 'File', mtime: kind_of(Float), mode: kind_of(Integer) }
17
+ end
18
+ }
19
+
20
+ context "path present in record" do
21
+ let(:record_mtime) { nil }
22
+ let(:record_md5) { nil }
23
+ let(:record_mode) { nil }
24
+ let(:record_data) { { type: 'File', mtime: record_mtime, md5: record_md5, mode: record_mode } }
25
+ before { record.stub_chain(:future, :file_data) { double(value: record_data) } }
26
+
27
+ context "non-existing path" do
28
+ it "returns added" do
29
+ expect(file.change).to eq :removed
30
+ end
31
+ it "sets path in record" do
32
+ expect(record.async).to receive(:unset_path).with(file_path)
33
+ file.change
34
+ end
35
+ end
36
+
37
+ context "existing path" do
38
+ around { |example| touch file_path; example.run }
39
+
40
+ context "old record path mtime" do
41
+ let(:record_mtime) { (Time.now - 1).to_f }
42
+
43
+ it "returns modified" do
44
+ expect(file.change).to eq :modified
45
+ end
46
+
47
+ it "sets path in record with expected data" do
48
+ expect(record.async).to receive(:set_path).with(file_path, expected_data)
49
+ file.change
50
+ end
51
+ end
52
+
53
+ context "same record path mtime" do
54
+ let(:record_mtime) { ::File.lstat(file_path).mtime.to_f }
55
+ let(:record_mode) { ::File.lstat(file_path).mode }
56
+ let(:record_md5) { Digest::MD5.file(file_path).digest }
57
+
58
+ context "same record path mode" do
59
+ it "returns nil" do
60
+ expect(file.change).to be_nil
61
+ end
62
+ end
63
+
64
+ context "diferent record path mode" do
65
+ let(:record_mode) { 'foo' }
66
+
67
+ it "returns modified" do
68
+ expect(file.change).to eq :modified
69
+ end
70
+ end
71
+
72
+ context "same record path md5" do
73
+ it "returns nil" do
74
+ expect(file.change).to be_nil
75
+ end
76
+ end
77
+
78
+ context "different record path md5" do
79
+ let(:record_md5) { 'foo' }
80
+
81
+ it "returns modified" do
82
+ expect(file.change).to eq :modified
83
+ end
84
+ it "sets path in record with expected data" do
85
+ expect(record.async).to receive(:set_path).with(file_path, expected_data)
86
+ file.change
87
+ end
88
+ end
89
+
90
+ end
91
+ end
92
+ end
93
+
94
+ context "path not present in record" do
95
+ before { record.stub_chain(:future, :file_data) { double(value: {}) } }
96
+
97
+ context "existing path" do
98
+ around { |example| touch file_path; example.run }
99
+
100
+ it "returns added" do
101
+ expect(file.change).to eq :added
102
+ end
103
+
104
+ it "sets path in record with expected data" do
105
+ expect(record.async).to receive(:set_path).with(file_path, expected_data)
106
+ file.change
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ end
@@ -0,0 +1,269 @@
1
+ require 'spec_helper'
2
+
3
+ describe Listen::Listener do
4
+ let(:listener) { Listen::Listener.new(options) }
5
+ let(:options) { {} }
6
+ let(:record) { double(Listen::Record, terminate: true, build: true) }
7
+ let(:silencer) { double(Listen::Silencer, terminate: true) }
8
+ let(:adapter) { double(Listen::Adapter::Base) }
9
+ let(:change_pool) { double(Listen::Change, terminate: true) }
10
+ let(:change_pool_async) { double('ChangePoolAsync') }
11
+ before {
12
+ Celluloid::Actor.stub(:[]).with(:listen_silencer) { silencer }
13
+ Celluloid::Actor.stub(:[]).with(:listen_adapter) { adapter }
14
+ Celluloid::Actor.stub(:[]).with(:listen_record) { record }
15
+ Celluloid::Actor.stub(:[]).with(:listen_change_pool) { change_pool }
16
+ }
17
+
18
+ describe "initialize" do
19
+ it "sets paused to false" do
20
+ expect(listener).not_to be_paused
21
+ end
22
+
23
+ it "sets block" do
24
+ block = Proc.new { |modified, added, removed| }
25
+ listener = Listen::Listener.new('lib', &block)
26
+ expect(listener.block).not_to be_nil
27
+ end
28
+
29
+ it "sets directories with realpath" do
30
+ listener = Listen::Listener.new('lib', 'spec')
31
+ expect(listener.directories).to eq [Pathname.new("#{Dir.pwd}/lib"), Pathname.new("#{Dir.pwd}/spec")]
32
+ end
33
+ end
34
+
35
+ describe "options" do
36
+ it "sets default options" do
37
+ expect(listener.options).to eq({
38
+ debug: false,
39
+ latency: nil,
40
+ force_polling: false,
41
+ polling_fallback_message: nil })
42
+ end
43
+
44
+ it "sets new options on initialize" do
45
+ listener = Listen::Listener.new('lib', latency: 1.234)
46
+ expect(listener.options).to eq({
47
+ debug: false,
48
+ latency: 1.234,
49
+ force_polling: false,
50
+ polling_fallback_message: nil })
51
+ end
52
+ end
53
+
54
+ describe "#start" do
55
+ before {
56
+ Listen::Silencer.stub(:new)
57
+ Listen::Change.stub(:pool)
58
+ Listen::Adapter.stub(:new)
59
+ Listen::Record.stub(:new)
60
+ Celluloid::Actor.stub(:[]=)
61
+ Celluloid.stub(:cores) { 1 }
62
+ adapter.stub_chain(:async, :start)
63
+ }
64
+
65
+ it "traps INT signal" do
66
+ expect(Signal).to receive(:trap).with('INT')
67
+ listener.start
68
+ end
69
+
70
+ it "registers silencer" do
71
+ expect(Listen::Silencer).to receive(:new).with(listener.options) { silencer }
72
+ expect(Celluloid::Actor).to receive(:[]=).with(:listen_silencer, silencer)
73
+ listener.start
74
+ end
75
+
76
+ it "registers change_pool" do
77
+ expect(Listen::Change).to receive(:pool).with(args: listener) { change_pool }
78
+ expect(Celluloid::Actor).to receive(:[]=).with(:listen_change_pool, change_pool)
79
+ listener.start
80
+ end
81
+
82
+ it "registers adaper" do
83
+ expect(Listen::Adapter).to receive(:new).with(listener) { adapter }
84
+ expect(Celluloid::Actor).to receive(:[]=).with(:listen_adapter, adapter)
85
+ listener.start
86
+ end
87
+
88
+ it "registers record" do
89
+ expect(Listen::Record).to receive(:new).with(listener) { record }
90
+ expect(Celluloid::Actor).to receive(:[]=).with(:listen_record, record)
91
+ listener.start
92
+ end
93
+
94
+ it "builds record" do
95
+ expect(record).to receive(:build)
96
+ listener.start
97
+ end
98
+
99
+ it "sets paused to false" do
100
+ listener.start
101
+ expect(listener.paused).to be_false
102
+ end
103
+
104
+ it "starts adapter asynchronously" do
105
+ async_stub = double
106
+ expect(adapter).to receive(:async) { async_stub }
107
+ expect(async_stub).to receive(:start)
108
+ listener.start
109
+ end
110
+
111
+ it "starts adapter asynchronously" do
112
+ async_stub = double
113
+ expect(adapter).to receive(:async) { async_stub }
114
+ expect(async_stub).to receive(:start)
115
+ listener.start
116
+ end
117
+
118
+ it "calls block on changes" do
119
+ listener.changes = [{ modified: 'foo' }]
120
+ block_stub = double('block')
121
+ listener.block = block_stub
122
+ expect(block_stub).to receive(:call).with(['foo'], [], [])
123
+ listener.start
124
+ sleep 0.01
125
+ end
126
+ end
127
+
128
+ describe "#stop" do
129
+ let(:thread) { double(kill: true) }
130
+ before {
131
+ Celluloid::Actor.stub(:kill)
132
+ listener.stub(:thread) { thread }
133
+ }
134
+
135
+ it "kills thread" do
136
+ expect(thread).to receive(:kill)
137
+ listener.stop
138
+ end
139
+
140
+ it "terminates silencer" do
141
+ expect(silencer).to receive(:terminate)
142
+ listener.stop
143
+ end
144
+
145
+ it "kills adapter" do
146
+ expect(Celluloid::Actor).to receive(:kill).with(adapter)
147
+ listener.stop
148
+ end
149
+
150
+ it "terminates change_pool" do
151
+ expect(change_pool).to receive(:terminate)
152
+ listener.stop
153
+ end
154
+
155
+ it "terminates record" do
156
+ expect(record).to receive(:terminate)
157
+ listener.stop
158
+ end
159
+ end
160
+
161
+ describe "#pause" do
162
+ it "sets paused to true" do
163
+ listener.pause
164
+ expect(listener.paused).to be_true
165
+ end
166
+ end
167
+
168
+ describe "#unpause" do
169
+ it "builds record" do
170
+ expect(record).to receive(:build)
171
+ listener.unpause
172
+ end
173
+
174
+ it "sets paused to false" do
175
+ record.stub(:build)
176
+ listener.unpause
177
+ expect(listener.paused).to be_false
178
+ end
179
+ end
180
+
181
+ describe "#paused?" do
182
+ it "returns true when paused" do
183
+ listener.paused = true
184
+ expect(listener).to be_paused
185
+ end
186
+ it "returns false when not paused (nil)" do
187
+ listener.paused = nil
188
+ expect(listener).not_to be_paused
189
+ end
190
+ it "returns false when not paused (false)" do
191
+ listener.paused = false
192
+ expect(listener).not_to be_paused
193
+ end
194
+ end
195
+
196
+ describe "#paused?" do
197
+ it "returns true when not paused (false)" do
198
+ listener.paused = false
199
+ expect(listener.listen?).to be_true
200
+ end
201
+ it "returns false when not paused (nil)" do
202
+ listener.paused = nil
203
+ expect(listener.listen?).to be_false
204
+ end
205
+ it "returns false when paused" do
206
+ listener.paused = true
207
+ expect(listener.listen?).to be_false
208
+ end
209
+ end
210
+
211
+ describe "#ignore" do
212
+ let(:new_silencer) { double(Listen::Silencer) }
213
+ before { Celluloid::Actor.stub(:[]=) }
214
+
215
+ it "resets silencer actor with new pattern" do
216
+ expect(Listen::Silencer).to receive(:new).with(hash_including(ignore: [nil, /foo/])) { new_silencer }
217
+ expect(Celluloid::Actor).to receive(:[]=).with(:listen_silencer, new_silencer)
218
+ listener.ignore(/foo/)
219
+ end
220
+
221
+ context "with existing ignore options" do
222
+ let(:options) { { ignore: /bar/ } }
223
+
224
+ it "adds up to existing ignore options" do
225
+ expect(Listen::Silencer).to receive(:new).with(hash_including(ignore: [/bar/, /foo/]))
226
+ listener.ignore(/foo/)
227
+ end
228
+ end
229
+
230
+ context "with existing ignore options (array)" do
231
+ let(:options) { { ignore: [/bar/] } }
232
+
233
+ it "adds up to existing ignore options" do
234
+ expect(Listen::Silencer).to receive(:new).with(hash_including(ignore: [[/bar/], /foo/]))
235
+ listener.ignore(/foo/)
236
+ end
237
+ end
238
+ end
239
+
240
+ describe "#ignore!" do
241
+ let(:new_silencer) { double(Listen::Silencer) }
242
+ before { Celluloid::Actor.stub(:[]=) }
243
+
244
+ it "resets silencer actor with new pattern" do
245
+ expect(Listen::Silencer).to receive(:new).with(hash_including(ignore!: /foo/)) { new_silencer }
246
+ expect(Celluloid::Actor).to receive(:[]=).with(:listen_silencer, new_silencer)
247
+ listener.ignore!(/foo/)
248
+ end
249
+
250
+ context "with existing ignore! options" do
251
+ let(:options) { { ignore!: /bar/ } }
252
+
253
+ it "overwrites existing ignore options" do
254
+ expect(Listen::Silencer).to receive(:new).with(hash_including(ignore!: [/foo/]))
255
+ listener.ignore!([/foo/])
256
+ end
257
+ end
258
+
259
+ context "with existing ignore options" do
260
+ let(:options) { { ignore: /bar/ } }
261
+
262
+ it "deletes ignore options" do
263
+ expect(Listen::Silencer).to receive(:new).with(hash_not_including(ignore: /bar/))
264
+ listener.ignore!([/foo/])
265
+ end
266
+ end
267
+ end
268
+
269
+ end
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+
3
+ describe Listen::Record do
4
+ let(:listener) { double(Listen::Listener, options: {}) }
5
+ let(:record) { Listen::Record.new(listener) }
6
+ let(:path) { '/dir/path/file.rb' }
7
+ let(:data) { { type: 'File' } }
8
+
9
+ describe "#set_path" do
10
+ it "sets path by spliting direname and basename" do
11
+ record.set_path(path, data)
12
+ expect(record.paths).to eq({ '/dir/path' => { 'file.rb' => data } })
13
+ end
14
+
15
+ it "sets path and keeps old data not overwritten" do
16
+ record.set_path(path, data.merge(foo: 1, bar: 2))
17
+ record.set_path(path, data.merge(foo: 3))
18
+ expect(record.paths).to eq({ '/dir/path' => { 'file.rb' => data.merge(foo: 3, bar: 2) } })
19
+ end
20
+ end
21
+
22
+ describe "#unset_path" do
23
+ context "path is present" do
24
+ before { record.set_path(path, data) }
25
+
26
+ it "unsets path" do
27
+ record.unset_path(path)
28
+ expect(record.paths).to eq({ '/dir/path' => {} })
29
+ end
30
+ end
31
+
32
+ context "path not present" do
33
+ it "unsets path" do
34
+ record.unset_path(path)
35
+ expect(record.paths).to eq({ '/dir/path' => {} })
36
+ end
37
+ end
38
+ end
39
+
40
+ describe "#file_data" do
41
+ context "path is present" do
42
+ before { record.set_path(path, data) }
43
+
44
+ it "returns file data" do
45
+ expect(record.file_data(path)).to eq data
46
+ end
47
+ end
48
+
49
+ context "path not present" do
50
+ it "return empty hash" do
51
+ expect(record.file_data(path)).to be_empty
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "#dir_entries" do
57
+ context "path is present" do
58
+ before { record.set_path(path, data) }
59
+
60
+ it "returns file path" do
61
+ expect(record.dir_entries('/dir/path')).to eq({ 'file.rb' => data })
62
+ end
63
+ end
64
+
65
+ context "path not present" do
66
+ it "unsets path" do
67
+ expect(record.dir_entries('/dir/path')).to eq({})
68
+ end
69
+ end
70
+ end
71
+
72
+ describe "#build" do
73
+ let(:directories) { ['dir_path'] }
74
+ let(:change_pool) { double(Listen::Change, terminate: true) }
75
+ before {
76
+ change_pool.stub(:change)
77
+ Celluloid::Actor.stub(:[]).with(:listen_change_pool) { change_pool }
78
+ listener.stub(:directories) { directories }
79
+ }
80
+
81
+ it "re-inits paths" do
82
+ record.set_path(path, data)
83
+ record.build
84
+ expect(record.file_data(path)).to be_empty
85
+ end
86
+
87
+ it "calls change asynchronously on all directories to build record" do
88
+ expect(change_pool).to receive(:change).with('dir_path', type: 'Dir', recursive: true, silence: true)
89
+ record.build
90
+ end
91
+ end
92
+ end