require File.expand_path(File.dirname(__FILE__) + '/spec_helper') require File.expand_path(File.dirname(__FILE__) + '/fixtures/pyload_queue_data') require 'yaml' describe Junkie::Pyload::Observer do include EMHelper # remove the Config module behaviour before(:each) do Junkie::Config.stub!(:get_config) do |clas| clas.class::DEFAULT_CONFIG end stub_const("Junkie::CONFIG_FILE", '/dev/null') end let(:channels) { {episodes: EM::Channel.new, info: EM::Channel.new} } let(:epi_channel) { channels[:episodes]} let(:episode) do epi = Junkie::Episode.new( "One Tree Hill", "http://local.host/12345", "One.Tree.Hill.S09E01.Testepisode") epi.status = :found epi end context "monitor the pyload progress" do let(:observer) do ob = Junkie::Pyload::Observer.new(channels) ob.api.stub(:call).and_return(nil) ob.instance_variable_set(:@found_episodes, [episode]) ob.instance_variable_set(:@ready_for_new_links, true) ob.send(:add_next_episode_to_pyload) episode.pid = 10 ob end context "#get_queue_data" do it "should throw InvalidResponse on empty string" do observer.api.should_receive(:call).and_return("") expect { observer.send(:get_queue_data) }.to raise_error(Junkie::InvalidResponse) end it "should throw InvalidResponse on empty response" do observer.api.should_receive(:call).and_return(nil) expect { observer.send(:get_queue_data) }.to raise_error(Junkie::InvalidResponse) end it "should return the valid response" do response = [ {pid: 13} ] observer.api.should_receive(:call).and_return(response) observer.send(:get_queue_data).should eq response end end context "#monitor_progress" do let(:response) do Junkie::Pyload::Observer::TestData::get_fixture end it "should catch InvalidResponse raised from #get_queue_data" do observer.api.should_receive(:call).and_return("") expect { observer.send(:monitor_progress) }.to_not raise_error(Junkie::InvalidResponse) end context "#check_for_empty_queue" do it "should be an active watchdog timer" do observer.instance_variable_get(:@watchdog_enabled).should be true end it "should disable the watchdog if there isn't an active download" do observer.instance_variable_set(:@active_episode, nil) # it double checks for emptiness observer.should_receive(:get_queue_data).and_return([]) expect { observer.send(:check_for_empty_queue, []) }.to throw_symbol(:break) observer.instance_variable_get(:@watchdog_enabled).should be false end it "shouldn't disable the watchdog if double check fails" do observer.instance_variable_set(:@active_episode, nil) observer.should_receive(:get_queue_data).and_return(response) observer.send(:check_for_empty_queue, []) observer.instance_variable_get(:@watchdog_enabled).should be true end it "shouldn't disable the watchdog if there is an active download" do observer.send(:check_for_empty_queue, []) observer.instance_variable_get(:@watchdog_enabled).should be true end end context "#update_package_ids" do it "should update the package id" do observer.send(:update_package_ids, response) episode.pid.should eq 11 end it "should update the pid also if it is not incremented by 1" do response[0]['pid'] = 12 expect { observer.send(:update_package_ids, response) }.to_not raise_error(Junkie::InvalidStateError) episode.pid.should eq 12 end end context "#react_on_failed_links" do let(:failed_id){ Junkie::Pyload::Api::FILE_STATUS.key(:failed) } it "should call restartFailed on the Api if there are failed links" do response[0]['links'][0]['status'] = failed_id observer.api.should_receive(:call).with(:restartFailed) expect { observer.send(:check_for_failed_links, response) }.to throw_symbol(:break) end end context "#check_for_complete_packages" do let(:file_status){ Junkie::Pyload::Api::FILE_STATUS } let(:complete_response) do copy = response.clone new_links = copy[0]['links'].map do |e| e['status'] = file_status.key(:done) e end copy[0]['links'] = new_links copy[0]['linksdone'] = new_links.size copy[0]['sizedone'] = 12345 copy[0]['sizetotal'] = 12345 copy[0]['pid'] = 12 copy end context "#get_complete_downloads" do it "should return pids where alle links are done and size is right" do pids = observer.send(:get_complete_downloads, complete_response) pids.should include(12) end it "should treat :skipped and :done links as complete" do complete_response[0]['links'][1]['status'] = file_status.key(:skipped) complete_response[0]['links'][3]['status'] = file_status.key(:skipped) pids = observer.send(:get_complete_downloads, complete_response) pids.should include(12) end it "should take file status more seriously than sizedone" do complete_response[0]['links'][1]['status'] = file_status.key(:failed) pids = observer.send(:get_complete_downloads, complete_response) pids.should_not include(12) end end context "detected complete package the first time" do it "should set a flag if a complete package has been detected" do observer.send(:check_for_complete_packages, complete_response) observer.instance_variable_get( :@skipped_timer_at_first_complete_detection).should eq true end end context "detected complete package second time" do it "should remove the complete packages from Queue" do observer.api.should_receive(:call).with(:deletePackages, {pids: [12]}) observer.instance_variable_set( :@skipped_timer_at_first_complete_detection, true) em { observer.send(:check_for_complete_packages, complete_response) } end it "should send out the active episode out on the channel" do observer.instance_variable_set( :@skipped_timer_at_first_complete_detection, true) episode.pid = 12 observer.send(:check_for_complete_packages, complete_response) observer.instance_variable_get(:@active_episode).should be_nil observer.send(:is_ready?).should be true end end end end end end