listen 2.7.5 → 2.7.6

Sign up to get free protection for your applications and to get access to all the features.
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