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,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