describe Imap::Backup::Downloader do describe "#run" do subject { described_class.new(folder, serializer, **options) } let(:body) { "blah" } let(:folder) do instance_double( Imap::Backup::Account::Folder, fetch_multi: [{uid: "111", body: body}], name: "folder", uids: remote_uids ) end let(:remote_uids) { %w(111 222 333) } let(:serializer) do instance_double(Imap::Backup::Serializer, append: nil, uids: local_uids) end let(:local_uids) { ["222"] } let(:options) { {} } context "with fetched messages" do specify "are saved" do expect(serializer).to receive(:append).with("111", body) subject.run end end context "with messages which are already present" do specify "are skipped" do expect(serializer).to_not receive(:append).with("222", anything) subject.run end end context "with failed fetches" do specify "are skipped" do allow(folder).to receive(:fetch_multi) { nil } expect(serializer).to_not receive(:append) subject.run end end context "when the block size is greater than one" do let(:remote_uids) { %w(111 999) } let(:local_uids) { [] } let(:options) { {multi_fetch_size: 2} } context "when the first fetch fails" do before do allow(folder).to receive(:fetch_multi).with(["111", "999"]) { nil } allow(folder).to receive(:fetch_multi).with(["111"]). and_return([{uid: "111", body: body}]). and_return([{uid: "999", body: body}]) subject.run end it "retries fetching messages singly" do expect(serializer).to have_received(:append).with("111", body) expect(serializer).to have_received(:append).with("999", body) end end end context "when no body is returned by the fetch" do let(:remote_uids) { %w(111) } before do allow(folder).to receive(:fetch_multi).with(["111"]) { [{uid: "111", body: nil}] } subject.run end it "skips the append" do expect(serializer).to_not have_received(:append) end end context "when the UID is not returned by the fetch" do let(:remote_uids) { %w(111) } before do allow(folder).to receive(:fetch_multi).with(["111"]) { [{uid: nil, body: body}] } subject.run end it "skips the append" do expect(serializer).to_not have_received(:append) end end end end