# frozen_string_literal: true require 'spec_helper' module Datacite module Mapping describe GeoLocation do attr_reader :warnings def warnings_including(substring) warnings.select { |w| w.include?(substring) } end def expect_warning(substring, count, include_matches = false) matches = warnings_including(substring) found_count = matches.size msg = "expected #{count} warnings including '#{substring}', found #{found_count}" msg << ": #{matches}" if include_matches expect(found_count).to eq(count), msg end before(:each) do @warnings = [] allow(ReadOnlyNodes).to receive(:warn) do |w| warnings << w Kernel.warn(w) # for debugging end end describe '#initialize' do it 'accepts a point' do point = GeoLocationPoint.new(47.61, -122.33) loc = GeoLocation.new(point: point) expect(loc.point).to eq(point) end it 'accepts a box' do box = GeoLocationBox.new(-33.45, -122.33, 47.61, -70.67) loc = GeoLocation.new(box: box) expect(loc.box).to eq(box) end it 'accepts a place' do place = 'Ouagadougou' loc = GeoLocation.new(place: place) expect(loc.place).to eq(place) end it 'accepts a polygon' do polygon = GeoLocationPolygon.new(points: [ GeoLocationPoint.new(47.61, -122.33), GeoLocationPoint.new(-33.45, -122.33), GeoLocationPoint.new(47.61, -70.67), GeoLocationPoint.new(47.61, -122.33) ]) loc = GeoLocation.new(polygon: polygon) expect(loc.polygon).to eq(polygon) end it 'allows an empty location' do loc = GeoLocation.new expect(loc.point).to be_nil expect(loc.box).to be_nil expect(loc.place).to be_nil end end describe '#point=' do it 'sets the point' do point = GeoLocationPoint.new(47.61, -122.33) loc = GeoLocation.new loc.point = point expect(loc.point).to eq(point) end it 'accepts nil' do loc = GeoLocation.new(point: GeoLocationPoint.new(47.61, -122.33)) loc.point = nil expect(loc.point).to be_nil end end describe '#box=' do it 'sets the box' do box = GeoLocationBox.new(-33.45, -122.33, 47.61, -70.67) loc = GeoLocation.new loc.box = box expect(loc.box).to eq(box) end it 'accepts nil' do loc = GeoLocation.new(box: GeoLocationBox.new(-33.45, -122.33, 47.61, -70.67)) loc.box = nil expect(loc.box).to be_nil end end describe '#place=' do it 'sets the place' do place = 'Ouagadougou' loc = GeoLocation.new loc.place = place expect(loc.place).to eq(place) end it 'accepts nil' do loc = GeoLocation.new(place: 'Ouagadougou') loc.place = nil expect(loc.place).to be_nil end end describe '#polygon=' do it 'sets the polygon' do polygon = GeoLocationPolygon.new(points: [ GeoLocationPoint.new(47.61, -122.33), GeoLocationPoint.new(-33.45, -122.33), GeoLocationPoint.new(47.61, -70.67), GeoLocationPoint.new(47.61, -122.33) ]) loc = GeoLocation.new loc.polygon = polygon expect(loc.polygon).to eq(polygon) end end describe '#load_from_xml' do it 'parses DC3' do xml_text = ' Atlantic Ocean 31.233 -67.302 41.090 -71.032 42.893 -68.211 ' loc = GeoLocation.parse_xml(xml_text) expect(loc.point).to eq(GeoLocationPoint.new(31.233, -67.302)) expect(loc.box).to eq(GeoLocationBox.new(41.09, -71.032, 42.893, -68.211)) expect(loc.place).to eq('Atlantic Ocean') end it 'parses DC4' do xml_text = ' Atlantic Ocean 31.233 -67.302 41.090 -71.032 42.893 -68.211 -67.302 31.233 -71.032 -68.211 41.09 42.893 -67.302 31.233 ' loc = GeoLocation.parse_xml(xml_text) expect(loc.point).to eq(GeoLocationPoint.new(31.233, -67.302)) expect(loc.box).to eq(GeoLocationBox.new(41.09, -71.032, 42.893, -68.211)) expect(loc.place).to eq('Atlantic Ocean') actual_polygon = loc.polygon expected_polygon = GeoLocationPolygon.new(points: [ GeoLocationPoint.new(31.233, -67.302), GeoLocationPoint.new(-68.211, -71.032), GeoLocationPoint.new(42.893, 41.09), GeoLocationPoint.new(31.233, -67.302) ]) expect(actual_polygon).to eq(expected_polygon) end it 'trims place-name whitespace' do xml_text = ' Atlantic Ocean ' loc = GeoLocation.parse_xml(xml_text) expect(loc.place).to eq('Atlantic Ocean') end end describe '#save_to_xml' do attr_reader :loc before(:each) do @loc = GeoLocation.new( point: GeoLocationPoint.new(31.233, -67.302), box: GeoLocationBox.new(41.09, -71.032, 42.893, -68.211), place: 'Atlantic Ocean', polygon: GeoLocationPolygon.new(points: [ GeoLocationPoint.new(-67.302, 31.233), GeoLocationPoint.new(-71.032, -68.211), GeoLocationPoint.new(41.09, 42.893), GeoLocationPoint.new(-67.302, 31.233) ]) ) end describe 'DC4 mode' do it 'writes DC4' do expected_xml = ' Atlantic Ocean 31.233 -67.302 -71.032 -68.211 41.09 42.893 31.233 -67.302 -68.211 -71.032 42.893 41.09 31.233 -67.302 ' actual_xml = loc.save_to_xml expect(actual_xml).to be_xml(expected_xml) end end describe 'DC3 mapping' do it 'writes DC3 points and boxes' do expected_xml = ' 31.233 -67.302 41.09 -71.032 42.893 -68.211 Atlantic Ocean ' actual_xml = loc.save_to_xml(mapping: :datacite_3) expect(actual_xml).to be_xml(expected_xml) expect_warning(loc.polygon.to_s, 1) end it 'writes DC3 in XSD-defined order: point, box, place' do actual_xml = loc.save_to_xml(mapping: :datacite_3) expected_order = %w[geoLocationPoint geoLocationBox geoLocationPlace] actual_order = actual_xml.children.map(&:name) expect(actual_order).to eq(expected_order) end end end end end end