listen 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Listen::Adapter::BSD do
4
+
5
+ if bsd?
6
+ let(:listener) { double(Listen::Listener) }
7
+ let(:adapter) { described_class.new(listener) }
8
+
9
+ describe ".usable?" do
10
+ it "returns always true" do
11
+ expect(described_class).to be_usable
12
+ end
13
+
14
+ it 'requires rb-kqueue and find gem' do
15
+ described_class.usable?
16
+ expect(defined?(KQueue)).to be_true
17
+ expect(defined?(Find)).to be_true
18
+ end
19
+ end
20
+ end
21
+
22
+ if darwin?
23
+ it "isn't usable on Darwin" do
24
+ expect(described_class).to_not be_usable
25
+ end
26
+ end
27
+
28
+ if linux?
29
+ it "isn't usable on Linux" do
30
+ expect(described_class).to_not be_usable
31
+ end
32
+ end
33
+
34
+ if windows?
35
+ it "isn't usable on Windows" do
36
+ expect(described_class).to_not be_usable
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Listen::Adapter::Darwin do
4
+ if darwin?
5
+ let(:listener) { double(Listen::Listener) }
6
+ let(:adapter) { described_class.new(listener) }
7
+
8
+ describe ".usable?" do
9
+ it "returns always true" do
10
+ expect(described_class).to be_usable
11
+ end
12
+ end
13
+
14
+ describe '#initialize' do
15
+ it 'requires rb-fsevent gem' do
16
+ described_class.new(listener)
17
+ expect(defined?(FSEvent)).to be_true
18
+ end
19
+ end
20
+ end
21
+
22
+ if windows?
23
+ it "isn't usable on Windows" do
24
+ expect(described_class).to_not be_usable
25
+ end
26
+ end
27
+
28
+ if linux?
29
+ it "isn't usable on Linux" do
30
+ expect(described_class).to_not be_usable
31
+ end
32
+ end
33
+
34
+ if bsd?
35
+ it "isn't usable on BSD" do
36
+ expect(described_class).to_not be_usable
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Listen::Adapter::Linux do
4
+ if linux?
5
+ let(:listener) { double(Listen::Listener) }
6
+ let(:adapter) { described_class.new(listener) }
7
+
8
+ describe ".usable?" do
9
+ it "returns always true" do
10
+ expect(described_class).to be_usable
11
+ end
12
+ end
13
+
14
+ describe '#initialize' do
15
+ it 'requires rb-inotify gem' do
16
+ described_class.new(listener)
17
+ expect(defined?(INotify)).to be_true
18
+ end
19
+ end
20
+ end
21
+
22
+ if darwin?
23
+ it "isn't usable on Darwin" do
24
+ expect(described_class).to_not be_usable
25
+ end
26
+ end
27
+
28
+ if windows?
29
+ it "isn't usable on Windows" do
30
+ expect(described_class).to_not be_usable
31
+ end
32
+ end
33
+
34
+ if bsd?
35
+ it "isn't usable on BSD" do
36
+ expect(described_class).to_not be_usable
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe Listen::Adapter::Polling do
4
+ let(:listener) { double(Listen::Listener, options: {}) }
5
+ let(:adapter) { described_class.new(listener) }
6
+
7
+ describe ".usable?" do
8
+ it "returns always true" do
9
+ expect(described_class).to be_usable
10
+ end
11
+ end
12
+
13
+ describe "#start" do
14
+ let(:directories) { ['directory_path'] }
15
+ before {
16
+ listener.stub(:options) { {} }
17
+ listener.stub(:directories) { directories }
18
+ }
19
+
20
+ it "notifies change on every listener directories path" do
21
+ adapter.should_receive(:_notify_change).with('directory_path', type: 'Dir', recursive: true)
22
+ t = Thread.new { adapter.start }
23
+ sleep 0.01
24
+ t.kill
25
+ end
26
+ end
27
+
28
+ describe "#_latency" do
29
+ it "returns default_latency with listener actor latency not present" do
30
+ expect(adapter.send(:_latency)).to eq Listen::Adapter::Polling::DEFAULT_POLLING_LATENCY
31
+ end
32
+
33
+ it "returns latency from listener actor if present" do
34
+ listener.stub(:options) { { latency: 1234 } }
35
+ expect(adapter.send(:_latency)).to eq 1234
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Listen::Adapter::Windows do
4
+ if windows?
5
+ let(:listener) { double(Listen::Listener) }
6
+ let(:adapter) { described_class.new(listener) }
7
+
8
+ describe ".usable?" do
9
+ it "returns always true" do
10
+ expect(described_class).to be_usable
11
+ end
12
+
13
+ it 'requires wdm gem' do
14
+ described_class.usable?
15
+ expect(defined?(WDM)).to be_true
16
+ end
17
+ end
18
+ end
19
+
20
+ if darwin?
21
+ it "isn't usable on Darwin" do
22
+ expect(described_class).to_not be_usable
23
+ end
24
+ end
25
+
26
+ if linux?
27
+ it "isn't usable on Linux" do
28
+ expect(described_class).to_not be_usable
29
+ end
30
+ end
31
+
32
+ if bsd?
33
+ it "isn't usable on BSD" do
34
+ expect(described_class).to_not be_usable
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ describe Listen::Adapter do
4
+ let(:adapter) { Listen::Adapter.new(listener) }
5
+ let(:listener) { double(Listen::Listener, options: {}) }
6
+ before {
7
+ Listen::Adapter::BSD.stub(:usable?) { false }
8
+ Listen::Adapter::Darwin.stub(:usable?) { false }
9
+ Listen::Adapter::Linux.stub(:usable?) { false }
10
+ Listen::Adapter::Windows.stub(:usable?) { false }
11
+ }
12
+
13
+ describe ".new" do
14
+ it "returns Polling adapter if forced" do
15
+ listener.stub(:options) { { force_polling: true } }
16
+ expect(adapter).to be_kind_of Listen::Adapter::Polling
17
+ end
18
+
19
+ it "returns Polling adapter if not on MRI" do
20
+ stub_const("RUBY_ENGINE", 'foo')
21
+ Listen::Adapter::Linux.stub(:usable?) { true }
22
+ expect(adapter).to be_kind_of Listen::Adapter::Polling
23
+ end
24
+
25
+ if RUBY_ENGINE == 'ruby'
26
+ it "returns BSD adapter when usable" do
27
+ Listen::Adapter::BSD.stub(:usable?) { true }
28
+ expect(Listen::Adapter::BSD).to receive(:new)
29
+ adapter
30
+ end
31
+
32
+ it "returns Darwin adapter when usable" do
33
+ Listen::Adapter::Darwin.stub(:usable?) { true }
34
+ expect(Listen::Adapter::Darwin).to receive(:new)
35
+ adapter
36
+ end
37
+
38
+ it "returns Linux adapter when usable" do
39
+ Listen::Adapter::Linux.stub(:usable?) { true }
40
+ expect(Listen::Adapter::Linux).to receive(:new)
41
+ adapter
42
+ end
43
+
44
+ it "returns Windows adapter when usable" do
45
+ Listen::Adapter::Windows.stub(:usable?) { true }
46
+ expect(Listen::Adapter::Windows).to receive(:new)
47
+ adapter
48
+ end
49
+
50
+ context "no usable adapters" do
51
+ before { Kernel.stub(:warn) }
52
+
53
+ it "returns Polling adapter" do
54
+ expect(adapter).to be_kind_of Listen::Adapter::Polling
55
+ end
56
+
57
+ it "warns polling fallback with default message" do
58
+ expect(Kernel).to receive(:warn).with("[Listen warning]:\n #{described_class::POLLING_FALLBACK_MESSAGE}")
59
+ adapter
60
+ end
61
+
62
+ it "doesn't warn if polling_fallback_message is false" do
63
+ listener.stub(:options) { { polling_fallback_message: false } }
64
+ expect(Kernel).to_not receive(:warn)
65
+ adapter
66
+ end
67
+
68
+ it "warns polling fallback with custom message if set" do
69
+ listener.stub(:options) { { polling_fallback_message: 'custom fallback message' } }
70
+ expect(Kernel).to receive(:warn).with("[Listen warning]:\n custom fallback message")
71
+ adapter
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ end
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+
3
+ describe Listen::Change do
4
+ let(:change) { Listen::Change.new(listener) }
5
+ let(:listener) { double(Listen::Listener, options: {}) }
6
+ let(:listener_changes) { double("listener_changes") }
7
+ before {
8
+ listener.stub(:changes) { listener_changes }
9
+ }
10
+
11
+ describe "#change" do
12
+ let(:silencer) { double(Listen::Silencer, silenced?: false) }
13
+ before { Celluloid::Actor.stub(:[]).with(:listen_silencer) { silencer } }
14
+
15
+ context "file path" do
16
+ context "with known change" do
17
+ it "notifies change directly to listener" do
18
+ expect(listener_changes).to receive(:<<).with(modified: 'file_path')
19
+ change.change('file_path', type: 'File', change: :modified)
20
+ end
21
+
22
+ it "doesn't notify to listener if path is silenced" do
23
+ expect(silencer).to receive(:silenced?).with('file_path') { true }
24
+ expect(listener_changes).to_not receive(:<<)
25
+ change.change('file_path', type: 'File', change: :modified)
26
+ end
27
+ end
28
+
29
+ context "with unknown change" do
30
+ let(:file) { double(Listen::File) }
31
+ before { Listen::File.stub(:new) { file } }
32
+
33
+ it "calls Listen::File#change" do
34
+ expect(Listen::File).to receive(:new).with('file_path') { file }
35
+ expect(file).to receive(:change)
36
+ change.change('file_path', type: 'File')
37
+ end
38
+
39
+ it "doesn't call Listen::File#change if path is silenced" do
40
+ expect(silencer).to receive(:silenced?).with('file_path') { true }
41
+ expect(Listen::File).to_not receive(:new)
42
+ change.change('file_path', type: 'File')
43
+ end
44
+
45
+ context "that returns a change" do
46
+ before { file.stub(:change) { :modified } }
47
+
48
+ context "listener listen" do
49
+ before { listener.stub(:listen?) { true } }
50
+
51
+ it "notifies change to listener" do
52
+ expect(listener_changes).to receive(:<<).with(modified: 'file_path')
53
+ change.change('file_path', type: 'File')
54
+ end
55
+
56
+ context "silence option" do
57
+ it "notifies change to listener" do
58
+ expect(listener_changes).to_not receive(:<<)
59
+ change.change('file_path', type: 'File', silence: true)
60
+ end
61
+ end
62
+ end
63
+
64
+ context "listener doesn't listen" do
65
+ before { listener.stub(:listen?) { false } }
66
+
67
+ it "notifies change to listener" do
68
+ expect(listener_changes).to_not receive(:<<)
69
+ change.change('file_path', type: 'File')
70
+ end
71
+ end
72
+ end
73
+
74
+ context "that returns no change" do
75
+ before { file.stub(:change) { nil } }
76
+
77
+ it "doesn't notifies no change" do
78
+ expect(listener_changes).to_not receive(:<<)
79
+ change.change('file_path', type: 'File')
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ context "directory path" do
86
+ let(:dir) { double(Listen::Directory) }
87
+ let(:dir_options) { { type: 'Dir', recursive: true } }
88
+ before { Listen::Directory.stub(:new) { dir } }
89
+
90
+ it "calls Listen::Directory#scan" do
91
+ expect(Listen::Directory).to receive(:new).with('dir_path', dir_options) { dir }
92
+ expect(dir).to receive(:scan)
93
+ change.change('dir_path', dir_options)
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,153 @@
1
+ require 'spec_helper'
2
+
3
+ describe Listen::Directory do
4
+ let(:record) { double(Listen::Record, async: double(set_path: true, unset_path: true)) }
5
+ let(:change_pool) { double(Listen::Change) }
6
+ let(:change_pool_async) { double('ChangePoolAsync') }
7
+ let(:path) { Pathname.new(Dir.pwd) }
8
+ around { |example| fixtures { |path| example.run } }
9
+ before {
10
+ change_pool.stub(:async) { change_pool_async }
11
+ Celluloid::Actor.stub(:[]).with(:listen_record) { record }
12
+ Celluloid::Actor.stub(:[]).with(:listen_change_pool) { change_pool }
13
+ }
14
+
15
+ describe "#scan" do
16
+ let(:dir_path) { path.join('dir') }
17
+ let(:file_path) { dir_path.join('file.rb') }
18
+ let(:other_file_path) { dir_path.join('other_file.rb') }
19
+ let(:inside_dir_path) { dir_path.join('inside_dir') }
20
+ let(:other_inside_dir_path) { dir_path.join('other_inside_dir') }
21
+ let(:dir) { Listen::Directory.new(dir_path, options) }
22
+
23
+ context "with recursive off" do
24
+ let(:options) { { recursive: false } }
25
+
26
+ context "file & inside_dir paths present in record" do
27
+ let(:record_dir_entries) { {
28
+ 'file.rb' => { type: 'File' },
29
+ 'inside_dir' => { type: 'Dir' } } }
30
+ before {
31
+ record.stub_chain(:future, :dir_entries) { double(value: record_dir_entries) }
32
+ change_pool_async.stub(:change)
33
+ }
34
+
35
+ context "empty dir" do
36
+ around { |example| mkdir dir_path; example.run }
37
+
38
+ it "sets record dir path" do
39
+ expect(record.async).to receive(:set_path).with(dir_path, type: 'Dir')
40
+ dir.scan
41
+ end
42
+
43
+ it "calls change for file path and dir that doesn't exist" do
44
+ expect(change_pool_async).to receive(:change).with(file_path, type: 'File', recursive: false)
45
+ expect(change_pool_async).to receive(:change).with(inside_dir_path, type: 'Dir', recursive: false)
46
+ dir.scan
47
+ end
48
+ end
49
+
50
+ context "other file path present in dir" do
51
+ around { |example|
52
+ mkdir dir_path;
53
+ touch other_file_path;
54
+ example.run }
55
+
56
+ it "calls change for file & other_file paths and dir that doesn't exist" do
57
+ expect(change_pool_async).to receive(:change).with(file_path, type: 'File', recursive: false)
58
+ expect(change_pool_async).to receive(:change).with(other_file_path, type: 'File', recursive: false)
59
+ expect(change_pool_async).to receive(:change).with(inside_dir_path, type: 'Dir', recursive: false)
60
+ dir.scan
61
+ end
62
+ end
63
+ end
64
+
65
+ context "dir paths not present in record" do
66
+ before { record.stub_chain(:future, :dir_entries) { double(value: {}) } }
67
+
68
+ context "non-existing dir path" do
69
+ it "calls change only for file path" do
70
+ expect(change_pool_async).to_not receive(:change)
71
+ dir.scan
72
+ end
73
+
74
+ it "unsets record dir path" do
75
+ expect(record.async).to receive(:unset_path).with(dir_path)
76
+ dir.scan
77
+ end
78
+ end
79
+
80
+ context "other file path present in dir" do
81
+ around { |example|
82
+ mkdir dir_path;
83
+ touch file_path;
84
+ example.run }
85
+
86
+ it "calls change for file & other_file paths" do
87
+ expect(change_pool_async).to receive(:change).with(file_path, type: 'File', recursive: false)
88
+ expect(change_pool_async).to_not receive(:change).with(other_file_path, type: 'File', recursive: false)
89
+ expect(change_pool_async).to_not receive(:change).with(inside_dir_path, type: 'Dir', recursive: false)
90
+ dir.scan
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ context "with recursive on" do
97
+ let(:options) { { recursive: true } }
98
+
99
+ context "file & inside_dir paths present in record" do
100
+ let(:record_dir_entries) { {
101
+ 'file.rb' => { type: 'File' },
102
+ 'inside_dir' => { type: 'Dir' } } }
103
+ before { record.stub_chain(:future, :dir_entries) { double(value: record_dir_entries) } }
104
+
105
+ context "empty dir" do
106
+ it "calls change for file & inside_dir path" do
107
+ expect(change_pool_async).to receive(:change).with(file_path, type: 'File', recursive: true)
108
+ expect(change_pool_async).to receive(:change).with(inside_dir_path, type: 'Dir', recursive: true)
109
+ dir.scan
110
+ end
111
+ end
112
+
113
+ context "other inside_dir path present in dir" do
114
+ around { |example|
115
+ mkdir dir_path;
116
+ mkdir other_inside_dir_path;
117
+ example.run }
118
+
119
+ it "calls change for file, other_file & inside_dir paths" do
120
+ expect(change_pool_async).to receive(:change).with(file_path, type: 'File', recursive: true)
121
+ expect(change_pool_async).to receive(:change).with(inside_dir_path, type: 'Dir', recursive: true)
122
+ expect(change_pool_async).to receive(:change).with(other_inside_dir_path, type: 'Dir', recursive: true)
123
+ dir.scan
124
+ end
125
+ end
126
+ end
127
+
128
+ context "dir paths not present in record" do
129
+ before { record.stub_chain(:future, :dir_entries) { double(value: {}) } }
130
+
131
+ context "non-existing dir path" do
132
+ it "calls change only for file path" do
133
+ expect(change_pool_async).to_not receive(:change)
134
+ dir.scan
135
+ end
136
+ end
137
+
138
+ context "other file path present in dir" do
139
+ around { |example|
140
+ mkdir dir_path;
141
+ mkdir other_inside_dir_path;
142
+ example.run }
143
+
144
+ it "calls change for file & other_file paths" do
145
+ expect(change_pool_async).to receive(:change).with(other_inside_dir_path, type: 'Dir', recursive: true)
146
+ dir.scan
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ end