describe "computations from /originInfo field" do let(:smods_rec) { Stanford::Mods::Record.new } # used for single examples let(:mods_origin_info_start_str) { "" } let(:mods_origin_info_end_str) { '' } # used for hashes/arrays of examples let(:mods_origin_info) do <<-EOF #{mods_origin_info_start_str} #{example} #{mods_origin_info_end_str} EOF end RSpec.shared_examples "single pub date value" do |method_sym, exp_val_position| it 'prefers dateIssued to dateCreated' do mods_str = mods_origin_info_start_str + '2005' + '' + ' 1999' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(smods_rec.send(method_sym)).to eq method_sym.to_s.match(/int/) ? 2005 : '2005' end it 'respects ignore_approximate param' do mods_str = mods_origin_info_start_str + '1000' + '1599' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(smods_rec.send(method_sym, true)).to eq method_sym.to_s.match(/int/) ? 1599 : '1599' expect(smods_rec.send(method_sym, false)).to eq method_sym.to_s.match(/int/) ? 1000 : '1000' end it 'nil if ignore_approximate and all dates are approximate' do mods_str = mods_origin_info_start_str + '1000' + '1599' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(smods_rec.send(method_sym, true)).to eq nil expect(smods_rec.send(method_sym, false)).to eq method_sym.to_s.match(/int/) ? 1000 : '1000' end it 'respects ignore_approximate even for keyDate' do mods_str = mods_origin_info_start_str + '1000' + '1599' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(smods_rec.send(method_sym, true)).to eq method_sym.to_s.match(/int/) ? 1599 : '1599' expect(smods_rec.send(method_sym, false)).to eq method_sym.to_s.match(/int/) ? 1000 : '1000' end it 'uses dateCaptured if no dateIssued or dateCreated' do # for web archive seed files mods_str = mods_origin_info_start_str + '20151215121212' + '20151218111111' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(smods_rec.send(method_sym)).to eq method_sym.to_s.match(/int/) ? 2015 : '2015' end context 'spotlight actual data' do require 'fixtures/spotlight_pub_date_data' SPOTLIGHT_PUB_DATE_DATA.each_pair.each do |coll_name, coll_data| # papyri - the only Spotlight data with BC dates unless coll_name == 'papyri' && method_sym == :pub_year_int coll_data.each_pair do |mods_str, exp_vals| expected = exp_vals[exp_val_position] it "#{expected} for rec in #{coll_name}" do smods_rec.from_str(mods_str) expect(smods_rec.send(method_sym)).to eq((method_sym.to_s.match(/int/) ? expected.to_i : expected)) if expected end end end end end end context '#pub_year_display_str' do it_behaves_like "single pub date value", :pub_year_display_str, 1 end context '#pub_year_sort_str' do it_behaves_like "single pub date value", :pub_year_sort_str, 0 end context '#pub_year_int' do it_behaves_like "single pub date value", :pub_year_int, 0 # papyri - the only Spotlight data with BC dates it '-200 for 200 B.C.' do # hd778hw9236 mods_str = mods_origin_info_start_str + '200 B.C.' + '180 B.C.' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(smods_rec.pub_year_int).to eq(-200) end it '-211 for 211 B.C.' do # ww728rz0477 mods_str = mods_origin_info_start_str + '211 B.C.' + '150 B.C.' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(smods_rec.pub_year_int).to eq(-211) end end context '*earliest_year_str' do it 'selects earliest (valid) parseable date from multiple options' do mods_str = mods_origin_info_start_str + '1758' + 'uuuu' + '1753]' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(Stanford::Mods::Record.earliest_year_str(smods_rec.date_issued_elements)).to eq ['1753', '1753]'] end it 'ignores encoding' do # encoding matters for choosing display, not for parsing year mods_str = mods_origin_info_start_str + '1100' + '1200' + '1300' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(Stanford::Mods::Record.earliest_year_str(smods_rec.date_issued_elements)).to eq ['1100', '1100'] mods_str = mods_origin_info_start_str + '1200' + '1300' + '1100' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(Stanford::Mods::Record.earliest_year_str(smods_rec.date_issued_elements)).to eq ['1100', '1100'] mods_str = mods_origin_info_start_str + '1300' + '1100' + '1200' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(Stanford::Mods::Record.earliest_year_str(smods_rec.date_issued_elements)).to eq ['1100', '1100'] end it 'calls DateParsing.sortable_year_string_from_date_str for each element value' do mods_str = mods_origin_info_start_str + '1100' + '1200' + '1300' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(Stanford::Mods::DateParsing).to receive(:sortable_year_string_from_date_str).exactly(3).times Stanford::Mods::Record.earliest_year_str(smods_rec.date_issued_elements) end end RSpec.shared_examples "pub date best single value" do |method_sym| it 'uses keyDate value if specified' do mods_str = mods_origin_info_start_str + '1666' + '2014' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(smods_rec.send(method_sym, smods_rec.date_issued_elements)).to eq method_sym.to_s.match(/int/) ? 2014 : '2014' end it 'ignores invalid keyDate value' do mods_str = mods_origin_info_start_str + '1500' + '1499' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(smods_rec.send(method_sym, smods_rec.date_issued_elements)).to eq method_sym.to_s.match(/int/) ? 1499 : '1499' end it 'calls earliest_year_str if multiple keyDates present' do mods_str = mods_origin_info_start_str + '2003' + '2001' + mods_origin_info_end_str smods_rec.from_str(mods_str) if method_sym.to_s.match(/int/) expect(Stanford::Mods::Record).to receive(:earliest_year_int).with(smods_rec.date_created_elements) else expect(Stanford::Mods::Record).to receive(:earliest_year_str).with(smods_rec.date_created_elements) end expect(smods_rec.send(method_sym, smods_rec.date_created_elements)) end it 'calls earliest_year_str if no keyDate' do mods_str = mods_origin_info_start_str + '1753]' + '1758' + 'uuuu' + mods_origin_info_end_str smods_rec.from_str(mods_str) if method_sym.to_s.match(/int/) expect(Stanford::Mods::Record).to receive(:earliest_year_int).with(smods_rec.date_issued_elements) else expect(Stanford::Mods::Record).to receive(:earliest_year_str).with(smods_rec.date_issued_elements) end smods_rec.send(method_sym, smods_rec.date_issued_elements) end it 'ignores encoding' do # encoding matters for choosing display, not for parsing year mods_str = mods_origin_info_start_str + '1100' + '1200' + '1300' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(smods_rec.send(method_sym, smods_rec.date_issued_elements)).to eq method_sym.to_s.match(/int/) ? 1100 : '1100' mods_str = mods_origin_info_start_str + '1200' + '1300' + '1100' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(smods_rec.send(method_sym, smods_rec.date_issued_elements)).to eq method_sym.to_s.match(/int/) ? 1100 : '1100' mods_str = mods_origin_info_start_str + '1300' + '1100' + '1200' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(smods_rec.send(method_sym, smods_rec.date_issued_elements)).to eq method_sym.to_s.match(/int/) ? 1100 : '1100' end end context '#year_display_str' do it_behaves_like "pub date best single value", :year_display_str it 'uses facet value, not sorting value' do mods_str = mods_origin_info_start_str + '180 B.C.' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(smods_rec.year_display_str(smods_rec.date_created_elements)).to eq '180 B.C.' end end context '#year_sort_str' do it_behaves_like "pub date best single value", :year_sort_str it 'uses string sorting value, not facet value' do mods_str = mods_origin_info_start_str + '180 B.C.' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(smods_rec.year_sort_str(smods_rec.date_created_elements)).to eq '-820' end end context '#year_int' do it_behaves_like "pub date best single value", :year_int it 'uses integer sorting value, not string or facet value' do mods_str = mods_origin_info_start_str + '180 B.C.' + mods_origin_info_end_str smods_rec.from_str(mods_str) expect(smods_rec.year_int(smods_rec.date_created_elements)).to eq(-180) end end context '#date_issued_elements' do # example string as key, expected num of Elements as value { '[1717]1717' => 2, '1552 1575 1544-1628]' => 3, '' => 0 }.each do |example, expected| describe "for example: #{example}" do let(:example) { example } it 'returns Array of Nokogiri Elements matching /originInfo/dateIssued' do smods_rec.from_str(mods_origin_info) result = smods_rec.date_issued_elements expect(result).to be_instance_of(Array) expect(result.size).to eq expected expect(result).to all(be_an(Nokogiri::XML::Element)) end end end context 'ignore_approximate=true' do let(:qual_date_val) { '1666' } let(:mods_rec) do <<-EOF #{mods_origin_info_start_str} 2015 #{qual_date_val} #{mods_origin_info_end_str} EOF end context "removes element when attribute qualifer=" do ['approximate', 'questionable'].each do |attr_val| let(:qual_attr_val) { attr_val } it attr_val do smods_rec.from_str mods_rec result = smods_rec.date_issued_elements(true) expect(result).to be_instance_of(Array) expect(result.size).to eq 1 expect(result[0].content).to eq '2015' end end end context "retains element when attribute qualifer=" do ['inferred', 'invalid_attr_val'].each do |attr_val| let(:qual_attr_val) { attr_val } it attr_val do smods_rec.from_str mods_rec result = smods_rec.date_issued_elements(true) expect(result).to be_instance_of(Array) expect(result.size).to eq 2 expect(result[0].content).to eq '2015' expect(result[1].content).to eq '1666' end end end let(:start_str) {"#{mods_origin_info_start_str}2015"} it 'retains element without qualifier attribute"' do m = start_str + '1666' + mods_origin_info_end_str smods_rec.from_str m result = smods_rec.date_issued_elements(true) expect(result).to be_instance_of(Array) expect(result.size).to eq 2 expect(result[0].content).to eq '2015' expect(result[1].content).to eq '1666' end end end context '#date_created_elements' do # example string as key, expected num of Elements as value { '-0012 -0044' => 2, '' => 0 }.each do |example, expected| describe "for example: '#{example}'" do let(:example) { example } it 'returns Array of Nokogiri Elements matching /originInfo/dateCreated' do smods_rec.from_str(mods_origin_info) result = smods_rec.date_created_elements expect(result).to be_instance_of(Array) expect(result.size).to eq expected expect(result).to all(be_an(Nokogiri::XML::Element)) end end end context 'ignore_approximate=true' do let(:qual_date_val) { '1666' } let(:mods_rec) do <<-EOF #{mods_origin_info_start_str} 2015 #{qual_date_val} #{mods_origin_info_end_str} EOF end context "removes element when attribute qualifer=" do ['approximate', 'questionable'].each do |attr_val| let(:qual_attr_val) { attr_val } it attr_val do smods_rec.from_str mods_rec result = smods_rec.date_created_elements(true) expect(result).to be_instance_of(Array) expect(result.size).to eq 1 expect(result[0].content).to eq '2015' end end end context "retains element when attribute qualifer=" do ['inferred', 'invalid_attr_val'].each do |attr_val| let(:qual_attr_val) { attr_val } it attr_val do smods_rec.from_str mods_rec result = smods_rec.date_created_elements(true) expect(result).to be_instance_of(Array) expect(result.size).to eq 2 expect(result[0].content).to eq '2015' expect(result[1].content).to eq '1666' end end end let(:start_str) {"#{mods_origin_info_start_str}2015"} it 'retains element without qualifier attribute"' do m = start_str + '1666' + mods_origin_info_end_str smods_rec.from_str m result = smods_rec.date_created_elements(true) expect(result).to be_instance_of(Array) expect(result.size).to eq 2 expect(result[0].content).to eq '2015' expect(result[1].content).to eq '1666' end end end context '*keyDate' do it 'returns nil if passed Array is empty' do mods_str = "#{mods_origin_info_start_str}#{mods_origin_info_end_str}" smods_rec.from_str(mods_str) expect(Stanford::Mods::Record.keyDate(smods_rec.date_issued_elements)).to be_nil end it 'returns nil if passed Array has no element with keyDate attribute' do mods_str = "#{mods_origin_info_start_str}[1738]#{mods_origin_info_end_str}" smods_rec.from_str(mods_str) expect(Stanford::Mods::Record.keyDate(smods_rec.date_issued_elements)).to be_nil end it 'returns nil if passed Array has multiple elements with keyDate attribute' do mods_str = "#{mods_origin_info_start_str} [1968?- 1968 9999 #{mods_origin_info_end_str}" smods_rec.from_str(mods_str) expect(Stanford::Mods::Record.keyDate(smods_rec.date_issued_elements)).to be_nil end it 'returns single Nokogiri::XML::Element if Arrays has single element with keyDate attribute' do mods_str = "#{mods_origin_info_start_str}2011#{mods_origin_info_end_str}" smods_rec.from_str(mods_str) expect(Stanford::Mods::Record.keyDate(smods_rec.date_issued_elements)).to be_instance_of(Nokogiri::XML::Element) end end context '*remove_approximate' do it 'removes elements when date_is_approximate? returns true' do mods_str = "#{mods_origin_info_start_str} 1900 1910 1930 #{mods_origin_info_end_str}" smods_rec.from_str(mods_str) elements = smods_rec.date_issued_elements expect(elements.size).to eq 3 result = Stanford::Mods::Record.remove_approximate(elements) expect(result).to be_instance_of(Array) expect(result.size).to eq 2 expect(result.select { |date_el| Stanford::Mods::Record.date_is_approximate?(date_el) }).to eq [] end end context '#date_is_approximate?' do it 'false if bad param passed' do expect(Stanford::Mods::Record.date_is_approximate?(true)).to eq false end it 'false if there is no qualifier attrib' do mods_str = "#{mods_origin_info_start_str}1968#{mods_origin_info_end_str}" smods_rec.from_str(mods_str) date_el = smods_rec.date_issued_elements.first expect(Stanford::Mods::Record.date_is_approximate?(date_el)).to eq false end # value of qualifier attribute as key, expected result as value { 'approximate' => true, 'questionable' => true, 'inferred' => false, 'typo' => false }.each do |attr_value, expected| describe "for qualifier value: '#{attr_value}'" do let(:mods_str) do "#{mods_origin_info_start_str} 1968 #{mods_origin_info_end_str}" end it "#{expected}" do smods_rec.from_str(mods_str) date_el = smods_rec.date_issued_elements.first expect(Stanford::Mods::Record.date_is_approximate?(date_el)).to eq expected end end end end context '#get_u_year' do it "turns ending u to 0" do expect(smods_rec.send(:get_u_year, ["201u"])).to eql "2010" expect(smods_rec.send(:get_u_year, ["198u"])).to eql "1980" expect(smods_rec.send(:get_u_year, ["185u"])).to eql "1850" end it "turns ending uu to --" do expect(smods_rec.send(:get_u_year, ["19uu"])).to eql "19--" expect(smods_rec.send(:get_u_year, ["17uu"])).to eql "17--" end it 'ignores 9999' do expect(smods_rec.send(:get_u_year, ["9999"])).to be_nil end end end