require 'spec_helper' describe Listen::Listener do let(:listener) { Listen::Listener.new(options) } let(:options) { {} } let(:registry) { double(Celluloid::Registry, :[]= => true) } let(:supervisor) { double(Celluloid::SupervisionGroup, add: true, pool: true) } let(:record) { double(Listen::Record, terminate: true, build: true) } let(:silencer) { double(Listen::Silencer, terminate: true) } let(:adapter) { double(Listen::Adapter::Base) } let(:change_pool) { double(Listen::Change, terminate: true) } let(:change_pool_async) { double('ChangePoolAsync') } before { Celluloid::Registry.stub(:new) { registry } Celluloid::SupervisionGroup.stub(:run!) { supervisor } registry.stub(:[]).with(:silencer) { silencer } registry.stub(:[]).with(:adapter) { adapter } registry.stub(:[]).with(:record) { record } registry.stub(:[]).with(:change_pool) { change_pool } } describe "initialize" do it "sets paused to false" do expect(listener).not_to be_paused end it "sets block" do block = Proc.new { |modified, added, removed| } listener = Listen::Listener.new('lib', &block) expect(listener.block).not_to be_nil end it "sets directories with realpath" do listener = Listen::Listener.new('lib', 'spec') expect(listener.directories).to eq [Pathname.new("#{Dir.pwd}/lib"), Pathname.new("#{Dir.pwd}/spec")] end end describe "options" do it "sets default options" do expect(listener.options).to eq({ debug: false, latency: nil, wait_for_delay: 0.1, force_polling: false, polling_fallback_message: nil }) end it "sets new options on initialize" do listener = Listen::Listener.new('lib', latency: 1.234, wait_for_delay: 0.85) expect(listener.options).to eq({ debug: false, latency: 1.234, wait_for_delay: 0.85, force_polling: false, polling_fallback_message: nil }) end end describe "#start" do before { adapter.stub_chain(:async, :start) } it "traps INT signal" do expect(Signal).to receive(:trap).with('INT') listener.start end it "registers silencer" do expect(supervisor).to receive(:add).with(Listen::Silencer, as: :silencer, args: listener) listener.start end it "supervises change_pool" do expect(supervisor).to receive(:pool).with(Listen::Change, as: :change_pool, args: listener) listener.start end it "supervises adaper" do Listen::Adapter.stub(:select) { Listen::Adapter::Polling } expect(supervisor).to receive(:add).with(Listen::Adapter::Polling, as: :adapter, args: listener) listener.start end it "supervises record" do expect(supervisor).to receive(:add).with(Listen::Record, as: :record, args: listener) listener.start end it "builds record" do expect(record).to receive(:build) listener.start end it "sets paused to false" do listener.start expect(listener.paused).to be_false end it "starts adapter asynchronously" do async_stub = double expect(adapter).to receive(:async) { async_stub } expect(async_stub).to receive(:start) listener.start end it "starts adapter asynchronously" do async_stub = double expect(adapter).to receive(:async) { async_stub } expect(async_stub).to receive(:start) listener.start end it "calls block on changes" do listener.changes = [{ modified: 'foo' }] block_stub = double('block') listener.block = block_stub expect(block_stub).to receive(:call).with(['foo'], [], []) listener.start sleep 0.01 end end describe "#stop" do let(:thread) { double(join: true) } before { listener.stub(:thread) { thread } } it "joins thread" do expect(thread).to receive(:join) listener.stop end end describe "#pause" do it "sets paused to true" do listener.pause expect(listener.paused).to be_true end end describe "#unpause" do it "builds record" do expect(record).to receive(:build) listener.unpause end it "sets paused to false" do record.stub(:build) listener.unpause expect(listener.paused).to be_false end end describe "#paused?" do it "returns true when paused" do listener.paused = true expect(listener).to be_paused end it "returns false when not paused (nil)" do listener.paused = nil expect(listener).not_to be_paused end it "returns false when not paused (false)" do listener.paused = false expect(listener).not_to be_paused end end describe "#listen?" do it "returns true when not paused (false)" do listener.paused = false listener.stopping = false expect(listener.listen?).to be_true end it "returns false when not paused (nil)" do listener.paused = nil listener.stopping = false expect(listener.listen?).to be_false end it "returns false when paused" do listener.paused = true listener.stopping = false expect(listener.listen?).to be_false end it "returns false when stopped" do listener.paused = false listener.stopping = true expect(listener.listen?).to be_false end end describe "#ignore" do let(:new_silencer) { double(Listen::Silencer) } before { Celluloid::Actor.stub(:[]=) } it "resets silencer actor" do expect(Listen::Silencer).to receive(:new).with(listener) { new_silencer } expect(registry).to receive(:[]=).with(:silencer, new_silencer) listener.ignore(/foo/) end context "with existing ignore options" do let(:options) { { ignore: /bar/ } } it "adds up to existing ignore options" do expect(Listen::Silencer).to receive(:new).with(listener) listener.ignore(/foo/) expect(listener.options).to include(ignore: [/bar/, /foo/]) end end context "with existing ignore options (array)" do let(:options) { { ignore: [/bar/] } } it "adds up to existing ignore options" do expect(Listen::Silencer).to receive(:new).with(listener) listener.ignore(/foo/) expect(listener.options).to include(ignore: [[/bar/], /foo/]) end end end describe "#ignore!" do let(:new_silencer) { double(Listen::Silencer) } before { Celluloid::Actor.stub(:[]=) } it "resets silencer actor" do expect(Listen::Silencer).to receive(:new).with(listener) { new_silencer } expect(registry).to receive(:[]=).with(:silencer, new_silencer) listener.ignore!(/foo/) expect(listener.options).to include(ignore!: /foo/) end context "with existing ignore! options" do let(:options) { { ignore!: /bar/ } } it "overwrites existing ignore options" do expect(Listen::Silencer).to receive(:new).with(listener) listener.ignore!([/foo/]) expect(listener.options).to include(ignore!: [/foo/]) end end context "with existing ignore options" do let(:options) { { ignore: /bar/ } } it "deletes ignore options" do expect(Listen::Silencer).to receive(:new).with(listener) listener.ignore!([/foo/]) expect(listener.options).to_not include(ignore: /bar/) end end end describe "#only" do let(:new_silencer) { double(Listen::Silencer) } before { Celluloid::Actor.stub(:[]=) } it "resets silencer actor" do expect(Listen::Silencer).to receive(:new).with(listener) { new_silencer } expect(registry).to receive(:[]=).with(:silencer, new_silencer) listener.only(/foo/) end context "with existing only options" do let(:options) { { only: /bar/ } } it "overwrites existing ignore options" do expect(Listen::Silencer).to receive(:new).with(listener) listener.only([/foo/]) expect(listener.options).to include(only: [/foo/]) end end end end