require 'spec_helper'
describe ActiveFedora::OmDatastream do
subject { described_class.new }
it { should be_metadata }
it "includes the Solrizer::XML::TerminologyBasedSolrizer for .to_solr support" do
expect(described_class.included_modules).to include(OM::XML::TerminologyBasedSolrizer)
end
describe '#new' do
it 'loads xml from blob if provided' do
test_ds1 = described_class.new
test_ds1.content = ""
expect(test_ds1.ng_xml.to_xml).to be_equivalent_to("\n\n \n\n")
end
it "initializes from #xml_template if no xml is provided" do
expect(described_class).to receive(:xml_template).and_return("")
n = described_class.new
expect(n.ng_xml).to be_equivalent_to("")
end
end
describe "#prefix" do
subject { described_class.new }
it "reflects the dsid" do
expect(subject.send(:prefix, 'descMetadata')).to eq "desc_metadata__"
end
end
describe '#xml_template' do
subject { described_class.xml_template.to_xml }
it "returns an empty xml document" do
expect(subject).to be_equivalent_to("\n\n")
end
end
describe "to_solr" do
describe "with a dsid" do
subject { described_class.new.to_solr }
it { should be_empty }
end
describe "when prefix is set" do
before do
class MyDatastream < ActiveFedora::OmDatastream
set_terminology do |t|
t.root(path: "mods")
t.title(index_as: [:stored_searchable])
end
def prefix(_)
"foo__"
end
end
subject.title = 'Science'
end
after do
Object.send(:remove_const, :MyDatastream)
end
subject { MyDatastream.new }
it "uses the prefix" do
expect(subject.to_solr).to have_key('foo__title_tesim')
end
it "does not prefix fields that aren't defined by this datastream" do
expect(subject.to_solr('id' => 'test:123')).to have_key('id')
end
end
end
describe ".update_indexed_attributes" do
before(:each) do
@mods_ds = Hydra::ModsArticleDatastream.new
@mods_ds.content = fixture(File.join("mods_articles", "mods_article1.xml")).read
end
it "applies submitted hash to corresponding datastream field values" do
result = @mods_ds.update_indexed_attributes([{ ":person" => "0" }, "role"] => { "0" => "role1", "1" => "role2", "2" => "role3" })
expect(result).to eq("person_0_role" => ["role1", "role2", "role3"])
expect(@mods_ds.property_values('//oxns:name[@type="personal"][1]/oxns:role')).to eq ["role1", "role2", "role3"]
end
it "supports single-value arguments (as opposed to a hash of values with array indexes as keys)" do
# In other words, { "fubar"=>"dork" } should have the same effect as { "fubar"=>{"0"=>"dork"} }
result = @mods_ds.update_indexed_attributes([{ ":person" => "0" }, "role"] => "the role")
expect(result).to eq("person_0_role" => ["the role"])
expect(@mods_ds.term_values('//oxns:name[@type="personal"][1]/oxns:role').first).to eq "the role"
end
it "does nothing if field key is a string (must be an array or symbol). Will not accept xpath queries!" do
xml_before = @mods_ds.to_xml
expect(ActiveFedora::Base.logger).to receive(:warn).with "WARNING: Hydra::ModsArticleDatastream ignoring {\"fubar\" => \"the role\"} because \"fubar\" is a String (only valid OM Term Pointers will be used). Make sure your html has the correct field_selector tags in it."
expect(@mods_ds.update_indexed_attributes("fubar" => "the role")).to eq({})
expect(@mods_ds.to_xml).to eq xml_before
end
it "does nothing if there is no accessor corresponding to the given field key" do
xml_before = @mods_ds.to_xml
expect(@mods_ds.update_indexed_attributes([{ "fubar" => "0" }] => "the role")).to eq({})
expect(@mods_ds.to_xml).to eq xml_before
end
### Examples copied over form metadata_datastream_spec
it "works for text fields" do
att = { [{ "person" => "0" }, "description"] => { "-1" => "mork", "1" => "york" } }
result = @mods_ds.update_indexed_attributes(att)
expect(result).to eq("person_0_description" => ["mork", "york"])
expect(@mods_ds.get_values([{ person: 0 }, :description])).to eq ['mork', 'york']
att = { [{ "person" => "0" }, "description"] => { "-1" => "dork" } }
result2 = @mods_ds.update_indexed_attributes(att)
expect(result2).to eq("person_0_description" => ["dork"])
expect(@mods_ds.get_values([{ person: 0 }, :description])).to eq ['dork']
end
it "allows deleting of values and should delete values so that to_xml does not return emtpy nodes" do
att = { [{ "person" => "0" }, "description"] => { "0" => "york", "1" => "mangle", "2" => "mork" } }
@mods_ds.update_indexed_attributes(att)
expect(@mods_ds.get_values([{ "person" => "0" }, "description"])).to eq ['york', 'mangle', 'mork']
@mods_ds.update_indexed_attributes([{ "person" => "0" }, { "description" => '1' }] => nil)
expect(@mods_ds.get_values([{ "person" => "0" }, "description"])).to eq ['york', 'mork']
@mods_ds.update_indexed_attributes([{ "person" => "0" }, { "description" => '0' }] => :delete)
expect(@mods_ds.get_values([{ "person" => "0" }, "description"])).to eq ['mork']
end
it "sets changed to true" do
expect(@mods_ds.get_values([{ title_info: 0 }, :main_title])).to eq ["ARTICLE TITLE", "TITLE OF HOST JOURNAL"]
@mods_ds.update_indexed_attributes [{ "title_info" => "0" }, "main_title"] => { "-1" => "mork" }
expect(@mods_ds).to be_changed
end
end
describe ".get_values" do
before(:each) do
@mods_ds = Hydra::ModsArticleDatastream.new
@mods_ds.content = fixture(File.join("mods_articles", "mods_article1.xml")).read
end
it "calls lookup with field_name and return the text values from each resulting node" do
expect(@mods_ds).to receive(:term_values).with("--my xpath--").and_return(["value1", "value2"])
expect(@mods_ds.get_values("--my xpath--")).to eq ["value1", "value2"]
end
it "assumes that field_names that are strings are xpath queries" do
expect(described_class).to receive(:accessor_xpath).never
expect(@mods_ds).to receive(:term_values).with("--my xpath--").and_return(["abstract1", "abstract2"])
expect(@mods_ds.get_values("--my xpath--")).to eq ["abstract1", "abstract2"]
end
end
describe '.save' do
let(:base_path) { '/foo' }
let(:ldp_source) { Ldp::Resource.new(mock_client, nil, nil, base_path) }
let(:conn_stubs) do
Faraday::Adapter::Test::Stubs.new do |stub|
stub.post(base_path) { [200, { 'Last-Modified' => 'Tue, 22 Jul 2014 02:23:32 GMT' }] }
end
end
let(:mock_conn) do
Faraday.new do |builder|
builder.adapter :test, conn_stubs do |_stub|
end
end
end
let :mock_client do
Ldp::Client.new mock_conn
end
before do
allow(subject).to receive(:ldp_source).and_return(ldp_source)
end
it "persists the product of .to_xml in fedora" do
subject.serialize!
subject.save
expect(subject.mime_type).to eq 'text/xml'
end
end
describe 'setting content' do
subject { described_class.new }
before { subject.content = "" }
it "updates the content" do
expect(subject.content).to eq "\n"
end
it "marks the object as changed" do
expect(subject).to be_changed
end
it "update ngxml and mark the xml as loaded" do
expect(subject.ng_xml.to_xml).to match(//)
expect(subject.xml_loaded).to be true
end
end
describe 'ng_xml=' do
let(:sample_raw_xml) { "" }
subject { described_class.new }
it "parses raw xml for you" do
subject.ng_xml = sample_raw_xml
expect(subject.ng_xml).to be_kind_of Nokogiri::XML::Document
expect(subject.ng_xml.to_xml).to be_equivalent_to(sample_raw_xml)
end
it "alwayses set a document when an Element is passed" do
subject.ng_xml = Nokogiri::XML(sample_raw_xml).xpath('//xmlelement').first
expect(subject.ng_xml).to be_kind_of Nokogiri::XML::Document
expect(subject.ng_xml.to_xml).to be_equivalent_to("")
end
it "marks the datastream as changed" do
expect {
subject.ng_xml = sample_raw_xml
}.to change { subject.changed? }.from(false).to(true)
end
end
describe '.to_xml' do
let(:doc) { Nokogiri::XML::Document.parse("") }
it "ng_xml.to_xmls" do
allow(subject).to receive(:ng_xml).and_return(doc)
expect(subject.to_xml).to eq "\n"
end
it 'accepts an optional Nokogiri::XML Document as an argument and insert its fields into that (mocked test)' do
expect(doc.root).to receive(:add_child) # .with(test_ds.ng_xml.root)
subject.to_xml(doc)
end
context "with some existing content" do
before do
subject.content = ""
end
it 'accepts an optional Nokogiri::XML Document as an argument and insert its fields into that (functional test)' do
expected_result = ""
doc = Nokogiri::XML::Document.parse("")
result = subject.to_xml(doc)
expect(doc).to be_equivalent_to expected_result
expect(result).to be_equivalent_to expected_result
end
it 'adds to root of Nokogiri::XML::Documents, but add directly to the elements if a Nokogiri::XML::Node is passed in' do
doc = Nokogiri::XML::Document.parse("")
el = Nokogiri::XML::Node.new("test_element", Nokogiri::XML::Document.new)
expect(subject.to_xml(doc)).to be_equivalent_to ""
expect(subject.to_xml(el)).to be_equivalent_to ""
end
end
end
describe '.has_solr_name?' do
let(:name0_role0) { ActiveFedora.index_field_mapper.solr_name("desc_metadata__name_0_role_0_roleTerm", type: :string) }
let(:name1_role1) { ActiveFedora.index_field_mapper.solr_name("desc_metadata__name_1_role_1_roleTerm", type: :string) }
let(:solr_doc) do
{ "id" => "mods_article1",
ActiveFedora.index_field_mapper.solr_name("desc_metadata__name_role_roleTerm", type: :string) => ["creator", "submitter", "teacher"],
ActiveFedora.index_field_mapper.solr_name("desc_metadata__name_0_role", type: :string) => "\r\ncreator\r\nsubmitter\r\n",
ActiveFedora.index_field_mapper.solr_name("desc_metadata__name_1_role", type: :string) => "\r\n teacher \r\n",
name0_role0 => "creator",
ActiveFedora.index_field_mapper.solr_name("desc_metadata__name_0_role_1_roleTerm", type: :string) => "submitter",
ActiveFedora.index_field_mapper.solr_name("desc_metadata__name_1_role_0_roleTerm", type: :string) => ["teacher"] }
end
it "returns true if the given key exists in the solr document passed in" do
expect(subject).to have_solr_name(name0_role0, solr_doc)
expect(subject).to have_solr_name(name0_role0.to_sym, solr_doc)
expect(subject).to_not have_solr_name(name1_role1, solr_doc)
# if not doc passed in should be new empty solr doc and always return false
expect(subject).to_not have_solr_name(name0_role0)
end
end
describe '.is_hierarchical_term_pointer?' do
it "returns true only if the pointer passed in is an array that contains a hash" do
expect(subject.is_hierarchical_term_pointer?(*[:image, { tag1: 1 }, :tag2])).to be true
expect(subject.is_hierarchical_term_pointer?(*[:image, :tag1, { tag2: 1 }])).to be true
expect(subject.is_hierarchical_term_pointer?(*[:image, :tag1, :tag2])).to be false
expect(subject.is_hierarchical_term_pointer?(nil)).to be false
end
end
describe '.update_values' do
subject { described_class.new }
before { subject.content = fixture(File.join("mods_articles", "mods_article1.xml")).read }
it "updates a value internally call OM::XML::TermValueOperators::update_values if internal_solr_doc is not set" do
expect(subject).to receive(:om_update_values)
subject.update_values([{ ":person" => "0" }, "role", "text"] => { "0" => "role1", "1" => "role2", "2" => "role3" })
end
it "sets changed to true" do
subject.update_values([{ ":person" => "0" }, "role", "text"] => { "0" => "role1", "1" => "role2", "2" => "role3" })
expect(subject).to be_changed
end
end
describe "an instance that exists in the datastore, but hasn't been loaded" do
before do
class MyObj < ActiveFedora::Base
has_metadata 'descMetadata', type: Hydra::ModsArticleDatastream
end
@obj = MyObj.new
@obj.descMetadata.title = 'Foobar'
@obj.save
end
after do
@obj.destroy
Object.send(:remove_const, :MyObj)
end
subject { @obj.reload.descMetadata }
it "does not load the descMetadata datastream when calling content_changed?" do
expect(@obj).to_not receive(:content)
expect(subject).to_not be_content_changed
end
end
end