listen 2.7.5 → 2.7.6

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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -0
  3. data/.rspec +0 -0
  4. data/.rubocop.yml +0 -0
  5. data/.travis.yml +0 -1
  6. data/.yardopts +0 -0
  7. data/CHANGELOG.md +0 -0
  8. data/CONTRIBUTING.md +0 -0
  9. data/Gemfile +25 -4
  10. data/Guardfile +0 -0
  11. data/LICENSE.txt +0 -0
  12. data/README.md +18 -10
  13. data/Rakefile +0 -0
  14. data/lib/listen.rb +2 -4
  15. data/lib/listen/adapter.rb +13 -4
  16. data/lib/listen/adapter/base.rb +33 -16
  17. data/lib/listen/adapter/bsd.rb +21 -38
  18. data/lib/listen/adapter/darwin.rb +17 -25
  19. data/lib/listen/adapter/linux.rb +34 -52
  20. data/lib/listen/adapter/polling.rb +9 -25
  21. data/lib/listen/adapter/tcp.rb +27 -14
  22. data/lib/listen/adapter/windows.rb +67 -23
  23. data/lib/listen/change.rb +26 -23
  24. data/lib/listen/cli.rb +0 -0
  25. data/lib/listen/directory.rb +47 -58
  26. data/lib/listen/file.rb +66 -101
  27. data/lib/listen/listener.rb +214 -155
  28. data/lib/listen/queue_optimizer.rb +104 -0
  29. data/lib/listen/record.rb +15 -5
  30. data/lib/listen/silencer.rb +14 -10
  31. data/lib/listen/tcp.rb +0 -1
  32. data/lib/listen/tcp/broadcaster.rb +31 -26
  33. data/lib/listen/tcp/message.rb +2 -2
  34. data/lib/listen/version.rb +1 -1
  35. data/listen.gemspec +1 -1
  36. data/spec/acceptance/listen_spec.rb +151 -239
  37. data/spec/acceptance/tcp_spec.rb +125 -134
  38. data/spec/lib/listen/adapter/base_spec.rb +13 -30
  39. data/spec/lib/listen/adapter/bsd_spec.rb +7 -35
  40. data/spec/lib/listen/adapter/darwin_spec.rb +18 -30
  41. data/spec/lib/listen/adapter/linux_spec.rb +49 -55
  42. data/spec/lib/listen/adapter/polling_spec.rb +20 -35
  43. data/spec/lib/listen/adapter/tcp_spec.rb +25 -27
  44. data/spec/lib/listen/adapter/windows_spec.rb +7 -33
  45. data/spec/lib/listen/adapter_spec.rb +10 -10
  46. data/spec/lib/listen/change_spec.rb +55 -57
  47. data/spec/lib/listen/directory_spec.rb +105 -155
  48. data/spec/lib/listen/file_spec.rb +186 -73
  49. data/spec/lib/listen/listener_spec.rb +233 -216
  50. data/spec/lib/listen/record_spec.rb +60 -22
  51. data/spec/lib/listen/silencer_spec.rb +48 -75
  52. data/spec/lib/listen/tcp/broadcaster_spec.rb +78 -69
  53. data/spec/lib/listen/tcp/listener_spec.rb +28 -71
  54. data/spec/lib/listen/tcp/message_spec.rb +48 -14
  55. data/spec/lib/listen_spec.rb +3 -3
  56. data/spec/spec_helper.rb +6 -3
  57. data/spec/support/acceptance_helper.rb +250 -31
  58. data/spec/support/fixtures_helper.rb +6 -4
  59. data/spec/support/platform_helper.rb +2 -2
  60. metadata +5 -5
  61. data/lib/listen/tcp/listener.rb +0 -108
@@ -1,60 +1,45 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Listen::Adapter::Polling do
4
- let(:registry) { double(Celluloid::Registry) }
5
- let(:listener) do
6
- double(Listen::Listener,
7
- registry: registry,
8
- options: {},
9
- listen?: true)
4
+ describe 'class' do
5
+ subject { described_class }
6
+ it { should be_local_fs }
7
+ it { should be_usable }
10
8
  end
11
9
 
12
- let(:adapter) { described_class.new(listener) }
13
- let(:change_pool) { double(Listen::Change, terminate: true) }
14
- let(:change_pool_async) { double('ChangePoolAsync') }
10
+ subject { described_class.new(listener) }
15
11
 
16
- before do
17
- change_pool.stub(:async) { change_pool_async }
18
- registry.stub(:[]).with(:change_pool) { change_pool }
19
- end
12
+ let(:options) { {} }
13
+ let(:listener) { instance_double(Listen::Listener, options: options) }
14
+ let(:worker) { instance_double(Listen::Change) }
20
15
 
21
- describe '.usable?' do
22
- it 'returns always true' do
23
- expect(described_class).to be_usable
24
- end
25
- end
16
+ before { allow(listener).to receive(:async).with(:change_pool) { worker } }
26
17
 
27
18
  describe '#start' do
28
- let(:directories) { ['directory_path'] }
29
- before do
30
- listener.stub(:options) { {} }
31
- listener.stub(:directories) { directories }
32
- end
19
+ before { allow(listener).to receive(:directories) { ['directory_path'] } }
33
20
 
34
21
  it 'notifies change on every listener directories path' do
35
- expect(change_pool_async).to receive(:change).with(
22
+ expect(worker).to receive(:change).with(
23
+ :dir,
36
24
  'directory_path',
37
- type: 'Dir',
38
25
  recursive: true)
39
26
 
40
- t = Thread.new { adapter.start }
27
+ t = Thread.new { subject.start }
41
28
  sleep 0.25
42
29
  t.kill
43
30
  end
44
31
  end
45
32
 
46
33
  describe '#_latency' do
47
- it 'returns default_latency with listener actor latency not present' do
48
- expected_latency = Listen::Adapter::Polling::DEFAULT_POLLING_LATENCY
49
- expect(adapter.send(:_latency)).to eq expected_latency
34
+ subject { described_class.new(listener).send(:_latency) }
35
+
36
+ context 'with no overriding option' do
37
+ it { should eq described_class.const_get('DEFAULT_POLLING_LATENCY') }
50
38
  end
51
39
 
52
- it 'returns latency from listener actor if present' do
53
- listener.stub(:options) { { latency: 1234 } }
54
- expect(adapter.send(:_latency)).to eq 1234
40
+ context 'with custom latency overriding' do
41
+ let(:options) { { latency: 1234 } }
42
+ it { should eq 1234 }
55
43
  end
56
44
  end
57
-
58
- specify { expect(described_class).to be_local_fs }
59
-
60
45
  end
@@ -6,20 +6,23 @@ describe Listen::Adapter::TCP do
6
6
  let(:port) { 4000 }
7
7
 
8
8
  subject { described_class.new(listener) }
9
- let(:registry) { double(Celluloid::Registry) }
9
+ let(:registry) { instance_double(Celluloid::Registry) }
10
10
 
11
11
  let(:listener) do
12
- double(Listen::TCP::Listener,
13
- registry: registry,
14
- options: {},
15
- host: host,
16
- port: port)
12
+ instance_double(
13
+ Listen::Listener,
14
+ registry: registry,
15
+ options: {},
16
+ host: host,
17
+ port: port)
17
18
  end
18
19
 
19
- let(:socket) { double(described_class::TCPSocket, close: true, recv: nil) }
20
+ let(:socket) do
21
+ instance_double(described_class::TCPSocket, close: true, recv: nil)
22
+ end
20
23
 
21
24
  before do
22
- described_class::TCPSocket.stub(:new).and_return socket
25
+ allow(described_class::TCPSocket).to receive(:new).and_return socket
23
26
  end
24
27
 
25
28
  after do
@@ -69,16 +72,19 @@ describe Listen::Adapter::TCP do
69
72
  end
70
73
 
71
74
  describe '#run' do
72
- let(:async) { double('TCP-adapter async', handle_data: true) }
73
-
74
75
  it 'handles data from socket' do
75
- socket.stub(:recv).and_return 'foo', 'bar', nil
76
- subject.stub(:async).and_return async
76
+ allow(socket).to receive(:recv).and_return 'foo', 'bar', nil
77
+
78
+ expect_any_instance_of(described_class).
79
+ to receive(:handle_data).with('foo')
77
80
 
78
- expect(async).to receive(:handle_data).with 'foo'
79
- expect(async).to receive(:handle_data).with 'bar'
81
+ expect_any_instance_of(described_class).
82
+ to receive(:handle_data).with('bar')
80
83
 
81
84
  subject.start
85
+
86
+ # quick workaround because run is called asynchronously
87
+ sleep 0.5
82
88
  end
83
89
  end
84
90
 
@@ -93,7 +99,9 @@ describe Listen::Adapter::TCP do
93
99
  it 'handles messages accordingly' do
94
100
  message = Listen::TCP::Message.new
95
101
 
96
- Listen::TCP::Message.stub(:from_buffer).and_return message, nil
102
+ allow(Listen::TCP::Message).to receive(:from_buffer).
103
+ and_return message, nil
104
+
97
105
  expect(Listen::TCP::Message).to receive(:from_buffer).with 'foo'
98
106
  expect(subject.wrapped_object).to receive(:handle_message).with message
99
107
 
@@ -104,20 +112,10 @@ describe Listen::Adapter::TCP do
104
112
 
105
113
  describe '#handle_message' do
106
114
  it 'notifies listener of path changes' do
107
- message = Listen::TCP::Message.new(
108
- 'modified' => ['/foo', '/bar'],
109
- 'added' => ['/baz'],
110
- 'removed' => []
111
- )
112
-
113
- expect(subject.wrapped_object).
114
- to receive(:_notify_change).with '/foo', change: :modified
115
-
116
- expect(subject.wrapped_object).
117
- to receive(:_notify_change).with '/bar', change: :modified
115
+ message = Listen::TCP::Message.new('file', 'modified', '/foo', {})
118
116
 
119
117
  expect(subject.wrapped_object).
120
- to receive(:_notify_change).with '/baz', change: :added
118
+ to receive(:_notify_change).with :file, '/foo', change: :modified
121
119
 
122
120
  subject.handle_message message
123
121
  end
@@ -1,40 +1,14 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Listen::Adapter::Windows do
4
- if windows?
5
- let(:listener) { double(Listen::Listener) }
6
- let(:adapter) { described_class.new(listener) }
4
+ describe 'class' do
5
+ subject { described_class }
6
+ it { should be_local_fs }
7
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
8
+ if windows?
9
+ it { should be_usable }
10
+ else
11
+ it { should_not be_usable }
35
12
  end
36
13
  end
37
-
38
- specify { expect(described_class).to be_local_fs }
39
-
40
14
  end
@@ -2,12 +2,12 @@ require 'spec_helper'
2
2
 
3
3
  describe Listen::Adapter do
4
4
 
5
- let(:listener) { double(Listen::Listener, options: {}) }
5
+ let(:listener) { instance_double(Listen::Listener, options: {}) }
6
6
  before do
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 }
7
+ allow(Listen::Adapter::BSD).to receive(:usable?) { false }
8
+ allow(Listen::Adapter::Darwin).to receive(:usable?) { false }
9
+ allow(Listen::Adapter::Linux).to receive(:usable?) { false }
10
+ allow(Listen::Adapter::Windows).to receive(:usable?) { false }
11
11
  end
12
12
 
13
13
  describe '.select' do
@@ -22,31 +22,31 @@ describe Listen::Adapter do
22
22
  end
23
23
 
24
24
  it 'returns BSD adapter when usable' do
25
- Listen::Adapter::BSD.stub(:usable?) { true }
25
+ allow(Listen::Adapter::BSD).to receive(:usable?) { true }
26
26
  klass = Listen::Adapter.select
27
27
  expect(klass).to eq Listen::Adapter::BSD
28
28
  end
29
29
 
30
30
  it 'returns Darwin adapter when usable' do
31
- Listen::Adapter::Darwin.stub(:usable?) { true }
31
+ allow(Listen::Adapter::Darwin).to receive(:usable?) { true }
32
32
  klass = Listen::Adapter.select
33
33
  expect(klass).to eq Listen::Adapter::Darwin
34
34
  end
35
35
 
36
36
  it 'returns Linux adapter when usable' do
37
- Listen::Adapter::Linux.stub(:usable?) { true }
37
+ allow(Listen::Adapter::Linux).to receive(:usable?) { true }
38
38
  klass = Listen::Adapter.select
39
39
  expect(klass).to eq Listen::Adapter::Linux
40
40
  end
41
41
 
42
42
  it 'returns Windows adapter when usable' do
43
- Listen::Adapter::Windows.stub(:usable?) { true }
43
+ allow(Listen::Adapter::Windows).to receive(:usable?) { true }
44
44
  klass = Listen::Adapter.select
45
45
  expect(klass).to eq Listen::Adapter::Windows
46
46
  end
47
47
 
48
48
  context 'no usable adapters' do
49
- before { Kernel.stub(:warn) }
49
+ before { allow(Kernel).to receive(:warn) }
50
50
 
51
51
  it 'returns Polling adapter' do
52
52
  klass = Listen::Adapter.select(force_polling: true)
@@ -1,111 +1,109 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Listen::Change do
4
- let(:change) { Listen::Change.new(listener) }
5
- let(:registry) { double(Celluloid::Registry) }
6
- let(:listener) { double(Listen::Listener, registry: registry, options: {}) }
7
- let(:listener_changes) { double('listener_changes') }
4
+ let(:subject) { Listen::Change.new(listener) }
5
+ let(:listener) { instance_double(Listen::Listener, options: {}) }
6
+ let(:record) { instance_double(Listen::Record) }
7
+ let(:file_path) { Pathname.new('file_path') }
8
+
8
9
  before do
9
- listener.stub(:changes) { listener_changes }
10
+ allow(listener).to receive(:sync).with(:record) { record }
11
+ allow(listener).to receive(:async).with(:change_pool) { subject }
10
12
  end
11
13
 
12
14
  describe '#change' do
13
- let(:silencer) { double('Listen::Silencer', silenced?: false) }
14
- before { registry.stub(:[]).with(:silencer) { silencer } }
15
+ let(:silencer) { instance_double(Listen::Silencer, silenced?: false) }
16
+ before { allow(listener).to receive(:silencer) { silencer } }
17
+
18
+ context 'with build options' do
19
+ let(:async_record) do
20
+ instance_double(Listen::Record, still_building!: nil)
21
+ end
15
22
 
16
- context 'file path' do
23
+ it 'calls update_last_build_time on record' do
24
+ allow(listener).to receive(:queue)
25
+ allow(record).to receive(:async) { async_record }
26
+ expect(async_record).to receive(:unset_path)
27
+ subject.change(:file, file_path, build: true)
28
+ end
29
+ end
30
+
31
+ context 'file' do
17
32
  context 'with known change' do
33
+ let(:file_path) { Pathname('file_path') }
18
34
  it 'notifies change directly to listener' do
19
- expect(listener_changes).to receive(:<<).
20
- with(modified: Pathname.new('file_path'))
35
+ expect(listener).to receive(:queue).
36
+ with(:file, :modified, file_path, {})
21
37
 
22
- options = { type: 'File', change: :modified }
23
- change.change(Pathname.new('file_path'), options)
38
+ subject.change(:file, file_path, change: :modified)
24
39
  end
25
40
 
26
41
  it "doesn't notify to listener if path is silenced" do
27
42
  expect(silencer).to receive(:silenced?).and_return(true)
28
- expect(listener_changes).to_not receive(:<<)
29
-
30
- options = { type: 'File', change: :modified }
31
- change.change(Pathname.new('file_path'), options)
43
+ expect(listener).to_not receive(:queue)
44
+ subject.change(:file, file_path, change: :modified)
32
45
  end
33
46
  end
34
47
 
35
48
  context 'with unknown change' do
36
- let(:file) { double('Listen::File') }
37
- before { Listen::File.stub(:new) { file } }
38
49
 
39
50
  it 'calls Listen::File#change' do
40
- expect(Listen::File).to receive(:new).
41
- with(listener, Pathname.new('file_path')) { file }
42
-
43
- expect(file).to receive(:change)
44
- change.change(Pathname.new('file_path'), type: 'File')
51
+ expect(Listen::File).to receive(:change).with(record, file_path)
52
+ subject.change(:file, file_path)
45
53
  end
46
54
 
47
55
  it "doesn't call Listen::File#change if path is silenced" do
48
56
  expect(silencer).to receive(:silenced?).
49
- with(Pathname.new('file_path'), 'File').and_return(true)
50
-
51
- expect(Listen::File).to_not receive(:new)
57
+ with(file_path, :file).and_return(true)
52
58
 
53
- change.change(Pathname.new('file_path'), type: 'File')
59
+ expect(Listen::File).to_not receive(:change)
60
+ subject.change(:file, file_path)
54
61
  end
55
62
 
56
63
  context 'that returns a change' do
57
- before { file.stub(:change) { :modified } }
64
+ before { allow(Listen::File).to receive(:change) { :modified } }
58
65
 
59
66
  context 'listener listen' do
60
- before { listener.stub(:listen?) { true } }
61
-
62
67
  it 'notifies change to listener' do
63
- file_path = double(Pathname, to_s: 'file_path', exist?: true)
64
- expect(listener_changes).to receive(:<<).with(modified: file_path)
65
- change.change(file_path, type: 'File')
68
+ file_path = instance_double(Pathname,
69
+ to_s: 'file_path',
70
+ exist?: true)
71
+
72
+ expect(listener).to receive(:queue).
73
+ with(:file, :modified, file_path)
74
+
75
+ subject.change(:file, file_path)
66
76
  end
67
77
 
68
78
  context 'silence option' do
69
79
  it 'notifies change to listener' do
70
- expect(listener_changes).to_not receive(:<<)
71
- options = { type: 'File', silence: true }
72
- change.change(Pathname.new('file_path'), options)
80
+ expect(listener).to_not receive(:queue)
81
+ subject.change(:file, file_path, silence: true)
73
82
  end
74
83
  end
75
84
  end
76
-
77
- context "listener doesn't listen" do
78
- before { listener.stub(:listen?) { false } }
79
-
80
- it 'notifies change to listener' do
81
- expect(listener_changes).to_not receive(:<<)
82
- change.change(Pathname.new('file_path'), type: 'File')
83
- end
84
- end
85
85
  end
86
86
 
87
87
  context 'that returns no change' do
88
- before { file.stub(:change) { nil } }
88
+ before { allow(Listen::File).to receive(:change) { nil } }
89
89
 
90
90
  it "doesn't notifies no change" do
91
- expect(listener_changes).to_not receive(:<<)
92
- change.change(Pathname.new('file_path'), type: 'File')
91
+ expect(listener).to_not receive(:queue)
92
+ subject.change(:file, file_path)
93
93
  end
94
94
  end
95
95
  end
96
96
  end
97
97
 
98
- context 'directory path' do
99
- let(:dir) { double(Listen::Directory) }
100
- let(:dir_options) { { type: 'Dir', recursive: true } }
101
- before { Listen::Directory.stub(:new) { dir } }
98
+ context 'directory' do
99
+ let(:dir_options) { { recursive: true } }
100
+ let(:dir_path) { Pathname.new('dir_path') }
102
101
 
103
- it 'calls Listen::Directory#scan' do
104
- expect(Listen::Directory).to receive(:new).
105
- with(listener, Pathname.new('dir_path'), dir_options) { dir }
102
+ it 'calls Listen::Directory#new' do
103
+ expect(Listen::Directory).to receive(:scan).
104
+ with(subject, record, dir_path, dir_options)
106
105
 
107
- expect(dir).to receive(:scan)
108
- change.change(Pathname.new('dir_path'), dir_options)
106
+ subject.change(:dir, dir_path, dir_options)
109
107
  end
110
108
  end
111
109
  end
@@ -1,212 +1,162 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Listen::Directory do
4
- let(:registry) { double(Celluloid::Registry) }
5
- let(:listener) { double(Listen::Listener, registry: registry, options: {}) }
3
+ include Listen
6
4
 
7
- let(:record) do
8
- double(Listen::Record, async: double(set_path: true, unset_path: true))
9
- end
5
+ describe Directory do
6
+ let(:path) { Pathname.pwd }
7
+ let(:dir) { path + 'dir' }
8
+ let(:file) { dir + 'file.rb' }
9
+ let(:file2) { dir + 'file2.rb' }
10
+ let(:subdir) { dir + 'subdir' }
11
+ let(:subdir2) { instance_double(Pathname, directory?: true) }
10
12
 
11
- let(:change_pool) { double(Listen::Change) }
12
- let(:change_pool_async) { double('ChangePoolAsync') }
13
- let(:path) { Pathname.new(Dir.pwd) }
14
- around { |example| fixtures { example.run } }
15
- before do
16
- change_pool.stub(:async) { change_pool_async }
17
- registry.stub(:[]).with(:record) { record }
18
- registry.stub(:[]).with(:change_pool) { change_pool }
13
+ let(:queue) { instance_double(Change, change: nil) }
14
+
15
+ let(:async_record) do
16
+ instance_double(Record, set_path: true, unset_path: true)
19
17
  end
20
18
 
21
- describe '#scan' do
22
- let(:dir_path) { path.join('dir') }
23
- let(:file_path) { dir_path.join('file.rb') }
24
- let(:other_file_path) { dir_path.join('other_file.rb') }
25
- let(:inside_dir_path) { dir_path.join('inside_dir') }
26
- let(:other_inside_dir_path) { dir_path.join('other_inside_dir') }
27
- let(:dir) { Listen::Directory.new(listener, dir_path, options) }
28
-
29
- context 'with recursive off' do
30
- let(:options) { { recursive: false } }
31
-
32
- context 'file & inside_dir paths present in record' do
33
- let(:record_dir_entries) do
34
- {
35
- 'file.rb' => { type: 'File' },
36
- 'inside_dir' => { type: 'Dir' }
37
- }
38
- end
19
+ let(:record) do
20
+ instance_double(Record, async: async_record, dir_entries: record_entries)
21
+ end
39
22
 
40
- before do
41
- record.stub_chain(:future, :dir_entries) do
42
- double(value: record_dir_entries)
43
- end
23
+ context '#scan with recursive off' do
24
+ let(:options) { { recursive: false } }
44
25
 
45
- change_pool_async.stub(:change)
46
- end
26
+ context 'with file & subdir in record' do
27
+ let(:record_entries) do
28
+ { 'file.rb' => { type: :file }, 'subdir' => { type: :dir } }
29
+ end
47
30
 
48
- context 'empty dir' do
49
- around do |example|
50
- mkdir dir_path
51
- example.run
52
- end
31
+ context 'with empty dir' do
32
+ before { allow(dir).to receive(:children) { [] } }
53
33
 
54
- it 'sets record dir path' do
55
- expect(record.async).to receive(:set_path).
56
- with(dir_path, type: 'Dir')
57
- dir.scan
58
- end
34
+ it 'sets record dir path' do
35
+ expect(async_record).to receive(:set_path).with(:dir, dir)
36
+ described_class.scan(queue, record, dir, options)
37
+ end
59
38
 
60
- it "calls change for file path and dir that doesn't exist" do
61
- expect(change_pool_async).to receive(:change).
62
- with(file_path, type: 'File', recursive: false)
39
+ it "queues changes for file path and dir that doesn't exist" do
40
+ expect(queue).to receive(:change).with(:file, file)
63
41
 
64
- expect(change_pool_async).to receive(:change).
65
- with(inside_dir_path, type: 'Dir', recursive: false)
42
+ expect(queue).to receive(:change).
43
+ with(:dir, subdir, recursive: false)
66
44
 
67
- dir.scan
68
- end
45
+ described_class.scan(queue, record, dir, options)
69
46
  end
47
+ end
70
48
 
71
- context 'other file path present in dir' do
72
- around do |example|
73
- mkdir dir_path
74
- touch other_file_path
75
- example.run
76
- end
77
-
78
- it 'notices file & other_file and no longer existing dir' do
79
- expect(change_pool_async).to receive(:change).
80
- with(file_path, type: 'File', recursive: false)
49
+ context 'with file2.rb in dir' do
50
+ before { allow(dir).to receive(:children) { [file2] } }
81
51
 
82
- expect(change_pool_async).to receive(:change).
83
- with(other_file_path, type: 'File', recursive: false)
52
+ it 'notices file & file2 and no longer existing dir' do
53
+ expect(queue).to receive(:change).with(:file, file)
54
+ expect(queue).to receive(:change).with(:file, file2)
84
55
 
85
- expect(change_pool_async).to receive(:change).
86
- with(inside_dir_path, type: 'Dir', recursive: false)
56
+ expect(queue).to receive(:change).
57
+ with(:dir, subdir, recursive: false)
87
58
 
88
- dir.scan
89
- end
59
+ described_class.scan(queue, record, dir, options)
90
60
  end
91
61
  end
62
+ end
92
63
 
93
- context 'dir paths not present in record' do
94
- before do
95
- record.stub_chain(:future, :dir_entries) { double(value: {}) }
96
- end
64
+ context 'with empty record' do
65
+ let(:record_entries) { {} }
97
66
 
98
- context 'non-existing dir path' do
99
- it 'calls change only for file path' do
100
- expect(change_pool_async).to_not receive(:change)
101
- dir.scan
102
- end
67
+ context 'with non-existing dir path' do
68
+ before { allow(dir).to receive(:children) { fail Errno::ENOENT } }
103
69
 
104
- it 'unsets record dir path' do
105
- expect(record.async).to receive(:unset_path).with(dir_path)
106
- dir.scan
107
- end
70
+ it 'reports no changes' do
71
+ expect(queue).to_not receive(:change)
72
+ described_class.scan(queue, record, dir, options)
108
73
  end
109
74
 
110
- context 'other file path present in dir' do
111
- around do |example|
112
- mkdir dir_path
113
- touch file_path
114
- example.run
115
- end
75
+ it 'unsets record dir path' do
76
+ expect(async_record).to receive(:unset_path).with(dir)
77
+ described_class.scan(queue, record, dir, options)
78
+ end
79
+ end
116
80
 
117
- it 'calls change for file & other_file paths' do
118
- expect(change_pool_async).to receive(:change).
119
- with(file_path, type: 'File', recursive: false)
81
+ context 'with file.rb in dir' do
82
+ before { allow(dir).to receive(:children) { [file] } }
120
83
 
121
- expect(change_pool_async).to_not receive(:change).
122
- with(other_file_path, type: 'File', recursive: false)
84
+ it 'queues changes for file & file2 paths' do
85
+ expect(queue).to receive(:change).with(:file, file)
86
+ expect(queue).to_not receive(:change).with(:file, file2)
123
87
 
124
- expect(change_pool_async).to_not receive(:change).
125
- with(inside_dir_path, type: 'Dir', recursive: false)
88
+ expect(queue).to_not receive(:change).
89
+ with(:dir, subdir, recursive: false)
126
90
 
127
- dir.scan
128
- end
91
+ described_class.scan(queue, record, dir, options)
129
92
  end
130
93
  end
131
94
  end
95
+ end
132
96
 
133
- context 'with recursive on' do
134
- let(:options) { { recursive: true } }
97
+ context '#scan with recursive on' do
98
+ let(:options) { { recursive: true } }
135
99
 
136
- context 'file & inside_dir paths present in record' do
137
- let(:record_dir_entries) do {
138
- 'file.rb' => { type: 'File' },
139
- 'inside_dir' => { type: 'Dir' } }
140
- end
100
+ context 'with file.rb & subdir in record' do
101
+ let(:record_entries) do
102
+ { 'file.rb' => { type: :file }, 'subdir' => { type: :dir } }
103
+ end
141
104
 
142
- before do
143
- record.stub_chain(:future, :dir_entries) do
144
- double(value: record_dir_entries)
145
- end
146
- end
105
+ context 'with empty dir' do
106
+ before { allow(dir).to receive(:children) { [] } }
147
107
 
148
- context 'empty dir' do
149
- it 'calls change for file & inside_dir path' do
150
- expect(change_pool_async).to receive(:change).
151
- with(file_path, type: 'File', recursive: true)
108
+ it 'queues changes for file & subdir path' do
109
+ expect(queue).to receive(:change).with(:file, file)
152
110
 
153
- expect(change_pool_async).to receive(:change).
154
- with(inside_dir_path, type: 'Dir', recursive: true)
111
+ expect(queue).to receive(:change).
112
+ with(:dir, subdir, recursive: true)
155
113
 
156
- dir.scan
157
- end
114
+ described_class.scan(queue, record, dir, options)
158
115
  end
116
+ end
159
117
 
160
- context 'other inside_dir path present in dir' do
161
- around do |example|
162
- mkdir dir_path
163
- mkdir other_inside_dir_path
164
- example.run
165
- end
118
+ context 'with subdir2 path present in dir' do
119
+ before do
120
+ allow(path).to receive(:children) { [dir] }
121
+ allow(dir).to receive(:children) { [subdir2] }
122
+ end
166
123
 
167
- it 'calls change for file, other_file & inside_dir paths' do
168
- expect(change_pool_async).to receive(:change).
169
- with(file_path, type: 'File', recursive: true)
124
+ it 'queues changes for file, file2 & subdir paths' do
125
+ expect(queue).to receive(:change).with(:file, file)
170
126
 
171
- expect(change_pool_async).to receive(:change).
172
- with(inside_dir_path, type: 'Dir', recursive: true)
127
+ expect(queue).to receive(:change).
128
+ with(:dir, subdir, recursive: true)
173
129
 
174
- expect(change_pool_async).to receive(:change).
175
- with(other_inside_dir_path, type: 'Dir', recursive: true)
130
+ expect(queue).to receive(:change).
131
+ with(:dir, subdir2, recursive: true)
176
132
 
177
- dir.scan
178
- end
133
+ described_class.scan(queue, record, dir, options)
179
134
  end
180
135
  end
136
+ end
181
137
 
182
- context 'dir paths not present in record' do
183
- before do
184
- record.stub_chain(:future, :dir_entries) { double(value: {}) }
185
- end
138
+ context 'with empty record' do
139
+ let(:record_entries) { {} }
186
140
 
187
- context 'non-existing dir path' do
188
- it 'calls change only for file path' do
189
- expect(change_pool_async).to_not receive(:change)
190
- dir.scan
191
- end
141
+ context 'with non-existing dir' do
142
+ before { allow(dir).to receive(:children) { fail Errno::ENOENT } }
143
+
144
+ it 'reports no changes' do
145
+ expect(queue).to_not receive(:change)
146
+ described_class.scan(queue, record, dir, options)
192
147
  end
148
+ end
193
149
 
194
- context 'other file path present in dir' do
195
- around do |example|
196
- mkdir dir_path
197
- mkdir other_inside_dir_path
198
- example.run
199
- end
150
+ context 'with subdir2 present in dir' do
151
+ before { allow(dir).to receive(:children) { [subdir2] } }
200
152
 
201
- it 'calls change for file & other_file paths' do
202
- expect(change_pool_async).to receive(:change).
203
- with(other_inside_dir_path, type: 'Dir', recursive: true)
153
+ it 'queues changes for file & file2 paths' do
154
+ expect(queue).to receive(:change).
155
+ with(:dir, subdir2, recursive: true)
204
156
 
205
- dir.scan
206
- end
157
+ described_class.scan(queue, record, dir, options)
207
158
  end
208
159
  end
209
160
  end
210
161
  end
211
-
212
162
  end