require 'spec_helper'
describe Rubydora::Datastream do
before do
@mock_repository = mock(Rubydora::Repository, :config=>{})
@mock_object = mock(Rubydora::DigitalObject)
@mock_object.stub(:repository => @mock_repository, :pid => 'pid')
end
describe "create" do
before(:each) do
@mock_repository.stub(:datastream) { raise(RestClient::ResourceNotFound) }
@datastream = Rubydora::Datastream.new @mock_object, 'dsid'
end
it "should be new" do
@datastream.new?.should == true
end
it "should be dirty" do
@datastream.changed?.should == false
end
it "should have default values" do
@datastream.controlGroup == "M"
@datastream.dsState.should == "A"
@datastream.versionable.should be_true
@datastream.changed.should be_empty
end
it "should allow versionable to be set to false" do
@datastream.versionable = false
@datastream.versionable.should be_false
end
# it "should cast versionable to boolean" do
# @datastream.profile['versionable'] = 'true'
# @datastream.versionable.should be_true
# end
it "should call the appropriate api on save" do
@mock_repository.should_receive(:add_datastream).with(hash_including(:pid => 'pid', :dsid => 'dsid', :controlGroup => 'M', :dsState => 'A'))
@datastream.save
end
it "should be able to override defaults" do
@mock_repository.should_receive(:add_datastream).with(hash_including(:controlGroup => 'E'))
@datastream.controlGroup = 'E'
@datastream.save
end
end
describe 'versionable' do
before(:each) do
@datastream = Rubydora::Datastream.new @mock_object, 'dsid'
end
it "should be true by default" do
@mock_repository.should_receive(:datastream).and_return <<-XML
XML
@datastream.versionable.should be_true
end
it "should be true when it's returned as true" do
@mock_repository.should_receive(:datastream).and_return <<-XML
true
XML
@datastream.versionable.should be_true
end
it "should be false when it's returned as false" do
@mock_repository.should_receive(:datastream).and_return <<-XML
false
XML
@datastream.versionable.should be_false
end
end
describe 'dsChecksumValid' do
before(:each) do
@datastream = Rubydora::Datastream.new @mock_object, 'dsid'
end
it "should be nil when it hasn't been set" do
@mock_repository.should_receive(:datastream).with(hash_including(:validateChecksum => true)).and_return <<-XML
XML
@datastream.dsChecksumValid.should be_nil
end
it "should be true when it's returned as true" do
@mock_repository.should_receive(:datastream).with(hash_including(:validateChecksum => true)).and_return <<-XML
true
XML
@datastream.dsChecksumValid.should be_true
end
it "should be false when it's returned as false" do
@mock_repository.should_receive(:datastream).with(hash_including(:validateChecksum => true)).and_return <<-XML
false
XML
@datastream.dsChecksumValid.should be_false
end
end
describe "retrieve" do
before(:each) do
@datastream = Rubydora::Datastream.new @mock_object, 'dsid'
@mock_repository.should_receive(:datastream).any_number_of_times.and_return <<-XML
some:uri
label
true
XML
end
it "should not be new" do
@datastream.new?.should == false
@datastream.changed?.should == false
end
it "should provide attribute defaults from dsProfile" do
@datastream.dsLocation.should == 'some:uri'
@datastream.dsLabel.should == 'label'
@datastream.dsChecksumValid.should be true
end
it "should mediate access to datastream contents" do
@mock_repository.should_receive(:datastream_dissemination).with(hash_including(:pid => 'pid', :dsid => 'dsid')).and_return('asdf')
@datastream.content.should == "asdf"
end
it "should rewind IO-type contents" do
@mock_io = File.open('rubydora.gemspec')
@mock_io.should_receive(:rewind)
@datastream.content = @mock_io
@datastream.content.should be_a(String)
end
end
describe "update" do
before(:each) do
@datastream = Rubydora::Datastream.new @mock_object, 'dsid'
@mock_repository.should_receive(:datastream).any_number_of_times.and_return <<-XML
some:uri
label
XML
end
it "should not say changed if the value is set the same" do
@datastream.dsLabel = "label"
@datastream.should_not be_changed
end
it "should allow profile attributes to be replaced" do
@datastream.dsLabel = "New Label"
@datastream.dsLabel.should == "New Label"
end
it "should call the appropriate api with any dirty attributes" do
@mock_repository.should_receive(:modify_datastream).with(hash_including(:dsLabel => "New Label"))
@datastream.dsLabel = "New Label"
@datastream.save
end
it "should update the datastream when the content is changed" do
@mock_repository.should_receive(:modify_datastream).with(hash_including(:content => 'test'))
@datastream.content = "test"
@datastream.save
end
it "should be marked as changed when the content is updated" do
@datastream.changed?.should be_false
@datastream.content = "test"
@datastream.changed?.should be_true
end
end
describe "should check if an object is read-only" do
before(:each) do
@datastream = Rubydora::Datastream.new @mock_object, 'dsid'
@mock_repository.should_receive(:datastream).any_number_of_times.and_return <<-XML
some:uri
label
XML
end
it "before updating attributes" do
@datastream.should_receive(:check_if_read_only)
@datastream.dsLabel = 'New Label'
end
it "before saving an object" do
@mock_repository.should_receive(:modify_datastream)
@datastream.should_receive(:check_if_read_only)
@datastream.save
end
it "before deleting an object" do
@mock_repository.should_receive(:purge_datastream)
@mock_object.should_receive(:datastreams).and_return([])
@datastream.should_receive(:check_if_read_only)
@datastream.delete
end
end
describe "versions" do
describe "when versions are in the repo" do
before(:each) do
@datastream = Rubydora::Datastream.new @mock_object, 'dsid'
@mock_repository.should_receive(:datastream_versions).any_number_of_times.and_return <<-XML
dsid.1
2010-01-02T00:00:00.012Z
dsid.0
2008-08-05T01:30:05.012Z
XML
end
it "should have a list of previous versions" do
@datastream.versions.should have(2).items
end
it "should access versions as read-only copies" do
expect { @datastream.versions.first.label = "asdf" }.to raise_error
end
it "should lookup content of datastream using the asOfDateTime parameter" do
@mock_repository.should_receive(:datastream_dissemination).with(hash_including(:asOfDateTime => '2008-08-05T01:30:05.012Z'))
@datastream.versions.last.content
end
end
describe "when no versions are found" do
before(:each) do
@datastream = Rubydora::Datastream.new @mock_object, 'dsid'
@mock_repository.should_receive(:datastream_versions).any_number_of_times.and_return nil
end
it "should have an emptylist of previous versions" do
@datastream.versions.should be_empty
end
end
end
describe "datastream attributes" do
before do
@mock_repository.stub(:datastream => <<-XML
XML
)
end
shared_examples "a datastream attribute" do
subject { Rubydora::Datastream.new @mock_object, 'dsid' }
describe "getter" do
it "should return the value" do
subject.instance_variable_set("@#{method}", 'asdf')
subject.send(method).should == 'asdf'
end
it "should look in the object profile" do
subject.should_receive(:profile) { { Rubydora::Datastream::DS_ATTRIBUTES[method.to_sym].to_s => 'qwerty' } }.twice
subject.send(method).should == 'qwerty'
end
it "should fall-back to the set of default attributes" do
Rubydora::Datastream::DS_DEFAULT_ATTRIBUTES.should_receive(:[]).with(method.to_sym) { 'zxcv'}
subject.send(method).should == 'zxcv'
end
end
describe "setter" do
before do
subject.stub(:datastreams => [])
end
it "should mark the object as changed after setting" do
subject.send("#{method}=", 'new_value')
subject.should be_changed
end
it "should not mark the object as changed if the value does not change" do
subject.should_receive(method) { 'zxcv' }
subject.send("#{method}=", 'zxcv')
end
it "should appear in the save request" do
@mock_repository.should_receive(:modify_datastream).with(hash_including(method.to_sym => 'new_value'))
subject.send("#{method}=", 'new_value')
subject.save
end
end
end
shared_examples "a read-only datastream attribute" do
subject { Rubydora::Datastream.new @mock_object, 'dsid' }
describe "getter" do
it "should return the value" do
subject.instance_variable_set("@#{method}", 'asdf')
subject.send(method).should == 'asdf'
end
it "should look in the object profile" do
subject.should_receive(:profile) { { method => 'qwerty' } }
subject.send(method).should == 'qwerty'
end
it "should fall-back to the set of default attributes" do
Rubydora::Datastream::DS_DEFAULT_ATTRIBUTES.should_receive(:[]).with(method.to_sym) { 'zxcv'}
subject.send(method).should == 'zxcv'
end
end
end
describe "#controlGroup" do
it_behaves_like "a datastream attribute"
let(:method) { 'controlGroup' }
end
describe "#dsLocation" do
it_behaves_like "a datastream attribute"
let(:method) { 'dsLocation' }
end
describe "#altIDs" do
it_behaves_like "a datastream attribute"
let(:method) { 'altIDs' }
end
describe "#dsLabel" do
it_behaves_like "a datastream attribute"
let(:method) { 'dsLabel' }
end
describe "#versionable" do
it_behaves_like "a datastream attribute"
let(:method) { 'versionable' }
end
describe "#dsState" do
it_behaves_like "a datastream attribute"
let(:method) { 'dsState' }
end
describe "#formatURI" do
it_behaves_like "a datastream attribute"
let(:method) { 'formatURI' }
end
describe "#checksumType" do
it_behaves_like "a datastream attribute"
let(:method) { 'checksumType' }
end
describe "#checksum" do
it_behaves_like "a datastream attribute"
let(:method) { 'checksum' }
end
describe "#mimeType" do
it_behaves_like "a datastream attribute"
let(:method) { 'mimeType' }
end
describe "#logMessage" do
it_behaves_like "a datastream attribute"
let(:method) { 'logMessage' }
end
describe "#ignoreContent" do
it_behaves_like "a datastream attribute"
let(:method) { 'ignoreContent' }
end
describe "#lastModifiedDate" do
it_behaves_like "a datastream attribute"
let(:method) { 'lastModifiedDate' }
end
describe "#dsCreateDate" do
it_behaves_like "a read-only datastream attribute"
let(:method) { 'dsCreateDate' }
end
describe "#dsSize" do
it_behaves_like "a read-only datastream attribute"
let(:method) { 'dsSize' }
end
describe "#dsVersionID" do
it_behaves_like "a read-only datastream attribute"
let(:method) { 'dsVersionID' }
end
end
describe "profile=" do
before(:each) do
@datastream = Rubydora::Datastream.new @mock_object, 'dsid'
end
it "should set the profile" do
prof = <<-XML
true
XML
@datastream.profile = prof
@datastream.profile.should == {'dsChecksumValid' =>true}
end
end
describe "profile" do
describe "with a digital_object that doesn't have a repository" do
### see UnsavedDigitalObject in ActiveFedora
before(:each) do
@datastream = Rubydora::Datastream.new stub(:foo), 'dsid'
end
it "should be empty if the digital_object doesn't have a repository" do
@datastream.profile.should == {}
end
end
describe "with a digital_object that has a repository" do
before(:each) do
@datastream = Rubydora::Datastream.new @mock_object, 'dsid'
end
it "should accept a validateChecksum argument" do
@mock_repository.should_receive(:datastream).with(hash_including(:validateChecksum => true)).and_return <<-XML
true
XML
@datastream.profile(:validateChecksum=>true).should == {'dsChecksumValid' =>true}
end
it "should reraise Unauthorized errors" do
@mock_repository.should_receive(:datastream).and_raise(RestClient::Unauthorized)
lambda{@datastream.profile}.should raise_error(RestClient::Unauthorized)
end
describe "once it has a profile" do
it "should use the profile from cache" do
@mock_repository.should_receive(:datastream).once.and_return <<-XML
true
XML
@datastream.profile().should == {'dsChecksumValid' =>true}
#second time should not trigger the mock, which demonstrates that the profile is coming from cache.
@datastream.profile().should == {'dsChecksumValid' =>true}
end
it "should re-fetch and replace the profile when validateChecksum is passed in, and there is no dsChecksumValid in the existing profile" do
@mock_repository.should_receive(:datastream).once.and_return <<-XML
The description of the content
XML
@mock_repository.should_receive(:datastream).with(hash_including(:validateChecksum => true)).once.and_return <<-XML
The description of the content
true
XML
@datastream.profile().should == {"dsLabel"=>"The description of the content"}
@datastream.profile(:validateChecksum=>true).should == {"dsLabel"=>"The description of the content", 'dsChecksumValid' =>true}
## Third time should not trigger a mock, which demonstrates that the profile is coming from cache.
@datastream.profile(:validateChecksum=>true)
end
end
end
end
describe "to_api_params" do
describe "with existing properties" do
before(:each) do
@datastream = Rubydora::Datastream.new @mock_object, 'dsid'
@datastream.stub(:profile) { {'dsMIME' => 'application/rdf+xml', 'dsChecksumType' =>'DISABLED', 'dsVersionable'=>true, 'dsControlGroup'=>'M', 'dsState'=>'A'} }
end
it "should not set unchanged values except for mimeType" do
@datastream.send(:to_api_params).should == {:mimeType=>'application/rdf+xml'}
end
it "should send changed params except those set to nil" do
@datastream.dsLabel = nil
@datastream.mimeType = 'application/json'
@datastream.controlGroup = 'X'
@datastream.send(:to_api_params).should == {:controlGroup=>"X", :mimeType=>"application/json"}
end
end
describe "without existing properties" do
before(:each) do
@datastream = Rubydora::Datastream.new @mock_object, 'dsid'
@datastream.stub(:profile) { {} }
end
it "should compile parameters to hash" do
@datastream.send(:to_api_params).should == {:versionable=>true, :controlGroup=>"M", :dsState=>"A"}
end
it "should not send parameters that are set to nil" do
@datastream.dsLabel = nil
@datastream.send(:to_api_params).should == {:versionable=>true, :controlGroup=>"M", :dsState=>"A"}
end
end
end
end