require File.join( File.dirname(__FILE__), "../spec_helper" )
describe ActiveFedora::NokogiriDatastream do
before(:all) do
@sample_fields = {:publisher => {:values => ["publisher1"], :type => :string},
:coverage => {:values => ["coverage1", "coverage2"], :type => :text},
:creation_date => {:values => "fake-date", :type => :date},
:mydate => {:values => "fake-date", :type => :date},
:empty_field => {:values => {}}
}
@sample_xml = XmlSimple.xml_in("coverage1coverage2fake-datefake-datepublisher1")
end
before(:each) do
@test_ds = ActiveFedora::NokogiriDatastream.new(:blob=>"")
end
after(:each) do
end
describe '#new' do
it 'should provide #new' do
ActiveFedora::NokogiriDatastream.should respond_to(:new)
@test_ds.ng_xml.should be_instance_of(Nokogiri::XML::Document)
end
it 'should load xml from blob if provided' do
test_ds1 = ActiveFedora::NokogiriDatastream.new(:blob=>"")
test_ds1.ng_xml.to_xml.should == "\n\n \n\n"
end
end
describe '#from_xml' do
it "should work when a template datastream is passed in" do
mods_xml = Nokogiri::XML::Document.parse( fixture(File.join("mods_articles", "hydrangea_article1.xml")) )
tmpl = Hydra::ModsArticle.new
Hydra::ModsArticle.from_xml(mods_xml,tmpl).ng_xml.root.to_xml.should == mods_xml.root.to_xml
end
it "should work when foxml datastream xml is passed in" do
pending "at least for now, just updated Base.deserialize to feed in the xml content rather than the foxml datstream xml. Possibly we can update MetadataDatstream to assume the same and leave it at that? -MZ 23-06-2010"
hydrangea_article_foxml = Nokogiri::XML::Document.parse( fixture("hydrangea_fixture_mods_article1.foxml.xml") )
ds_xml = hydrangea_article_foxml.at_xpath("//foxml:datastream[@ID='descMetadata']")
Hydra::ModsArticle.from_xml(ds_xml).ng_xml.to_xml.should == hydrangea_article_foxml.at_xpath("//foxml:datastream[@ID='descMetadata']/foxml:datastreamVersion[last()]/foxml:xmlContent").first_element_child.to_xml
end
end
it 'should provide .fields' do
@test_ds.should respond_to(:fields)
end
describe '.save' do
it "should provide .save" do
@test_ds.should respond_to(:save)
end
it "should persist the product of .to_xml in fedora" do
Fedora::Repository.instance.expects(:save)
@test_ds.expects(:to_xml).returns("fake xml")
@test_ds.expects(:blob=).with("fake xml")
@test_ds.save
end
end
describe '.to_xml' do
it "should provide .to_xml" do
@test_ds.should respond_to(:to_xml)
end
it "should ng_xml.to_xml" do
@test_ds.ng_xml.expects(:to_xml).returns("xml")
@test_ds.to_xml.should == "xml"
end
it 'should accept an optional Nokogiri::XML Document as an argument and insert its fields into that (mocked test)' do
doc = Nokogiri::XML::Document.parse("")
doc.root.expects(:add_child).with(@test_ds.ng_xml.root)
@test_ds.to_xml(doc)
end
it 'should accept an optional Nokogiri::XML Document as an argument and insert its fields into that (functional test)' do
expected_result = XmlSimple.xml_in("")
doc = Nokogiri::XML::Document.parse("")
result = @test_ds.to_xml(doc)
XmlSimple.xml_in(doc.to_s).should == expected_result
XmlSimple.xml_in(result).should == expected_result
end
it 'should add to root of Nokogiri::XML::Documents, but add directly to the elements if a Nokogiri::XML::Node is passed in' do
mock_new_node = mock("new node")
mock_new_node.stubs(:to_xml).returns("foo")
doc = Nokogiri::XML::Document.parse("")
el = Nokogiri::XML::Node.new("test_element", Nokogiri::XML::Document.new)
doc.root.expects(:add_child).with(@test_ds.ng_xml.root).returns(mock_new_node)
el.expects(:add_child).with(@test_ds.ng_xml.root).returns(mock_new_node)
@test_ds.to_xml(doc).should
@test_ds.to_xml(el)
end
end
describe '.set_blob_for_save' do
it "should provide .set_blob_for_save" do
@test_ds.should respond_to(:set_blob_for_save)
end
it "should set the blob to to_xml" do
@test_ds.expects(:blob=).with(@test_ds.to_xml)
@test_ds.set_blob_for_save
end
end
describe ".to_solr" do
after(:all) do
# Revert to default mappings after running tests
ActiveFedora::SolrService.load_mappings
end
it "should iterate through the class accessors, calling .solrize_accessor on each and passing in the solr doc" do
mock_accessors = {:accessor1=>:accessor1_info, :accessor2=>:accessor2_info}
ActiveFedora::NokogiriDatastream.stubs(:accessors).returns(mock_accessors)
doc = Solr::Document.new
mock_accessors.each_pair do |k,v|
@test_ds.expects(:solrize_accessor).with(k, v, :solr_doc=>doc)
end
@test_ds.to_solr(doc)
end
it "should provide .to_solr and return a SolrDocument" do
@test_ds.should respond_to(:to_solr)
@test_ds.to_solr.should be_kind_of(Solr::Document)
end
it "should optionally allow you to provide the Solr::Document to add fields to and return that document when done" do
doc = Solr::Document.new
@test_ds.to_solr(doc).should equal(doc)
end
end
describe ".solrize_accessor" do
before(:all) do
class AccessorizedDs < ActiveFedora::NokogiriDatastream
root_property :mods, "mods", "http://www.loc.gov/mods/v3", :attributes=>["id", "version"], :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd"
accessor :title_info, :relative_xpath=>'oxns:titleInfo', :children=>[
{:main_title=>{:relative_xpath=>'oxns:title'}},
{:language =>{:relative_xpath=>{:attribute=>"lang"} }}
]
accessor :abstract
accessor :topic_tag, :relative_xpath=>'oxns:subject/oxns:topic'
accessor :person, :relative_xpath=>'oxns:name[@type="personal"]', :children=>[
{:last_name=>{:relative_xpath=>'oxns:namePart[@type="family"]'}},
{:first_name=>{:relative_xpath=>'oxns:namePart[@type="given"]'}},
{:institution=>{:relative_xpath=>'oxns:affiliation'}},
{:role=>{:children=>[
{:text=>{:relative_xpath=>'oxns:roleTerm[@type="text"]'}},
{:code=>{:relative_xpath=>'oxns:roleTerm[@type="code"]'}}
]}}
]
end
end
before(:each) do
file = fixture(File.join("mods_articles", "hydrangea_article1.xml"))
@accessorized_ds = AccessorizedDs.new(:blob=>file)
end
it "should perform a lookup and iterate over nodes in the result set calling solrize_node then calling solrize_accessor on any of the children, adding accessor_name & node index to parents array" do
mock_title_info_set = ["TI1", "TI2"]
mock_main_title_set = ["main title"]
mock_language_set = ["language"]
solr_doc = Solr::Document.new
AccessorizedDs.expects(:accessor_xpath).with( :title_info ).returns("title_info_xpath")
@accessorized_ds.expects(:lookup).with( "title_info_xpath" ).returns(mock_title_info_set)
mock_title_info_set.each do |tin|
node_index = mock_title_info_set.index(tin)
@accessorized_ds.expects(:solrize_node).with(tin, [:title_info], solr_doc)
# Couldn't mock the recursive calls to solrize_accessor without preventing the initial one, so was forced to mock out the whole recursive stack.
# @accessorized_ds.expects(:solrize_accessor).with(:main_title, AccessorizedDs.accessors[:title_info][:children][:main_title], :parents=>[{:title_info=>node_index}])
# @accessorized_ds.expects(:solrize_accessor).with(:language, AccessorizedDs.accessors[:title_info][:children][:language], :parents=>[{:title_info=>node_index}])
AccessorizedDs.expects(:accessor_xpath).with( {:title_info=>node_index}, :main_title ).returns("title_info_main_title_xpath")
AccessorizedDs.expects(:accessor_xpath).with( {:title_info=>node_index}, :language ).returns("title_info_language_xpath")
@accessorized_ds.expects(:lookup).with( "title_info_main_title_xpath" ).returns(mock_main_title_set)
@accessorized_ds.expects(:lookup).with( "title_info_language_xpath" ).returns(mock_language_set)
@accessorized_ds.expects(:solrize_node).with("main title", [{:title_info=>node_index}, :main_title], solr_doc)
@accessorized_ds.expects(:solrize_node).with("language", [{:title_info=>node_index}, :language], solr_doc)
end
@accessorized_ds.solrize_accessor(:title_info, AccessorizedDs.accessors[:title_info], :solr_doc=>solr_doc)
end
it "should not call solrize_accessor once it reaches an accessor with no children accessors set" do
pending "not sure how to test for this"
@accessorized_ds.solrize_accessor(:text, AccessorizedDs.accessor_info( [{:person=>1}, :last_name] ), :parents=>[{:person=>1}])
end
it "should use values form parents array when requesting accessor_xpath and when generating solr field names" do
parents_array = [{:person=>0}, {:role=>1}]
AccessorizedDs.accessors[:person][:children][:role][:children][:text]
# This should catch the "submitter" roleTerm from the second role node within the first person node and put it into a solr field called "person_0_role_2_text_0_t" and a solr field called "person_role_text_t"
@accessorized_ds.solrize_accessor(:text, AccessorizedDs.accessor_info( *parents_array + [:text] ), :parents=>parents_array)
end
it "should use Solr mappings to generate field names" do
solr_doc = @accessorized_ds.to_solr
#should have these
solr_doc[:abstract_t].should == "ABSTRACT"
solr_doc[:title_info_1_language_t].should == "finnish"
solr_doc[:person_1_role_0_text_t].should == "teacher"
# solr_doc[:mydate_date].should == "fake-date"
#
# solr_doc[:publisher_t].should be_nil
# solr_doc[:coverage_t].should be_nil
# solr_doc[:creation_date_dt].should be_nil
# solr_doc.should == ""
end
end
describe ".solrize_node" do
it "should create a solr field containing node.text"
it "should create hierarchical field entries if parents is not empty"
it "should only create one node if parents is empty"
end
end