require 'spec_helper' require 'active_fedora' require "rexml/document" describe ActiveFedora::File do let(:file) { described_class.new } describe "#save" do context "with new files" do context "with a string" do before { file.content = "hello" } it "saves" do expect(file.save).to be true end end context "with no content" do before { file.content = nil } it "does not save" do expect(file.save).to be false end end end context "with UploadedFile" do before do module ActionDispatch module Http class UploadedFile def initialize @content = StringIO.new("hello world") end def read(a, b) @content.read(a, b) end def size @content.length end end end end end it "saves" do file.content = ActionDispatch::Http::UploadedFile.new file.save expect(file).not_to be_new_record end end end context "with a sub-resource that autocreates" do before do class MockAFBase < ActiveFedora::Base has_subresource "descMetadata", class_name: 'ActiveFedora::QualifiedDublinCoreDatastream', autocreate: true end end after do Object.send(:remove_const, :MockAFBase) end let(:test_object) { MockAFBase.create } let(:descMetadata) { test_object.descMetadata } describe "#content" do subject { descMetadata.content } it { should_not be_nil } end describe "#described_by" do subject { descMetadata.described_by } it { should eq descMetadata.uri + '/fcr:metadata' } end context "an XML file" do let(:xml_content) { Nokogiri::XML::Document.parse(descMetadata.content) } let(:title) { Nokogiri::XML::Element.new "title", xml_content } before do title.content = "Test Title" xml_content.root.add_child title allow(descMetadata).to receive(:before_save) descMetadata.content = xml_content.to_s descMetadata.save end let(:found) { Nokogiri::XML::Document.parse(test_object.reload.descMetadata.content) } subject { found.xpath('//dc/title/text()').first.inner_text } it { should eq title.content } end end context "with a sub-resource" do before do class MockAFBase < ActiveFedora::Base has_subresource "descMetadata", class_name: 'ActiveFedora::QualifiedDublinCoreDatastream' end end after do Object.send(:remove_const, :MockAFBase) end let(:test_object) { MockAFBase.create } let(:descMetadata) { test_object.descMetadata } describe "the metadata file" do subject { descMetadata } it { should be_a_kind_of(described_class) } end context "a binary file" do let(:path) { "ds#{Time.now.to_i}" } let(:content) { fixture('dino.jpg') } let(:file) { described_class.new.tap { |ds| ds.content = content } } before do test_object.attach_file(file, path) test_object.save end it "is not changed" do expect(test_object.attached_files[path]).to_not be_content_changed end it "is able to read the content from fedora" do content.rewind expect(test_object.attached_files[path].content).to eq content.read end describe "streaming the response" do let(:stream_reader) { double } it "streams the response" do expect(stream_reader).to receive(:read).at_least(:once) test_object.attached_files[path].stream.each { |buff| stream_reader.read(buff) } end context "with a range request" do before do test_object.add_file('one1two2threfour', path: 'webm', mime_type: 'video/webm') test_object.save! end subject { str = ''; test_object.webm.stream(range).each { |chunk| str << chunk }; str } context "whole thing" do let(:range) { 'bytes=0-15' } it { should eq 'one1two2threfour' } end context "open ended" do let(:range) { 'bytes=0-' } it { should eq 'one1two2threfour' } end context "not starting at the beginning" do let(:range) { 'bytes=3-15' } it { should eq '1two2threfour' } end context "not ending at the end" do let(:range) { 'bytes=4-11' } it { should eq 'two2thre' } end end context "when the request results in a redirect" do before do test_object.add_file('one1two2threfour', path: 'webm', mime_type: 'video/webm') test_object.add_file('', path: 'redirector', mime_type: "message/external-body; access-type=URL; url=\"#{test_object.webm.uri}\"") test_object.save! end subject { str = ''; test_object.redirector.stream.each { |chunk| str << chunk }; str } it { should eq 'one1two2threfour' } end context "when there are more than 3 requests because of redirects" do before do test_object.add_file('', path: 'one', mime_type: "message/external-body; access-type=URL; url=\"#{test_object.attached_files[path].uri}\"") test_object.add_file('', path: 'two', mime_type: "message/external-body; access-type=URL; url=\"#{test_object.one.uri}\"") test_object.add_file('', path: 'three', mime_type: "message/external-body; access-type=URL; url=\"#{test_object.two.uri}\"") test_object.save! end it "raises a HTTP redirect too deep Error" do expect { test_object.three.stream.each { |chunk| chunk } }.to raise_error('HTTP redirect too deep') end end end end end end