ruby-avm-library 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. data/.autotest +5 -0
  2. data/.gitignore +5 -0
  3. data/.rspec +5 -0
  4. data/Gemfile +14 -0
  5. data/README.md +56 -0
  6. data/Rakefile +2 -0
  7. data/autotest/discover.rb +2 -0
  8. data/bin/avm2avm +7 -0
  9. data/lib/avm/cli.rb +18 -0
  10. data/lib/avm/contact.rb +40 -0
  11. data/lib/avm/controlled_vocabulary.rb +23 -0
  12. data/lib/avm/coordinate_frame.rb +10 -0
  13. data/lib/avm/coordinate_system_projection.rb +10 -0
  14. data/lib/avm/creator.rb +123 -0
  15. data/lib/avm/image.rb +355 -0
  16. data/lib/avm/image_quality.rb +10 -0
  17. data/lib/avm/image_type.rb +10 -0
  18. data/lib/avm/node.rb +28 -0
  19. data/lib/avm/observation.rb +76 -0
  20. data/lib/avm/spatial_quality.rb +10 -0
  21. data/lib/avm/xmp.rb +157 -0
  22. data/lib/ruby-avm-library.rb +7 -0
  23. data/lib/ruby-avm-library/version.rb +7 -0
  24. data/reek.watchr +12 -0
  25. data/ruby-avm-library.gemspec +27 -0
  26. data/spec/avm/cli_spec.rb +0 -0
  27. data/spec/avm/contact_spec.rb +93 -0
  28. data/spec/avm/creator_spec.rb +268 -0
  29. data/spec/avm/image_spec.rb +350 -0
  30. data/spec/avm/observation_spec.rb +191 -0
  31. data/spec/avm/xmp_spec.rb +154 -0
  32. data/spec/quick_fix_formatter.rb +26 -0
  33. data/spec/sample_files/creator/no_creator.xmp +14 -0
  34. data/spec/sample_files/creator/one_creator.xmp +28 -0
  35. data/spec/sample_files/creator/two_creators.xmp +26 -0
  36. data/spec/sample_files/image/both.xmp +101 -0
  37. data/spec/sample_files/image/light_years.xmp +96 -0
  38. data/spec/sample_files/image/nothing.xmp +18 -0
  39. data/spec/sample_files/image/redshift.xmp +101 -0
  40. data/spec/sample_files/image/single_value_light_years.xmp +96 -0
  41. data/spec/sample_files/observation/none.xmp +5 -0
  42. data/spec/sample_files/observation/one.xmp +17 -0
  43. data/spec/sample_files/observation/two.xmp +17 -0
  44. data/spec/spec_helper.rb +3 -0
  45. metadata +184 -0
@@ -0,0 +1,268 @@
1
+ require 'spec_helper'
2
+ require 'avm/image'
3
+ require 'avm/creator'
4
+
5
+ describe AVM::Creator do
6
+ let(:image) { AVM::Image.new }
7
+ let(:creator) { image.creator }
8
+
9
+ let(:name) { 'Space Telescope Science Institute' }
10
+ let(:url) { 'http://www.stsci.edu/' }
11
+ let(:rights) { 'Public Domain' }
12
+
13
+ subject { creator }
14
+
15
+ def self.can_read_properties
16
+ its(:name) { should == name }
17
+ its(:url) { should == url }
18
+ its(:rights) { should == rights }
19
+ end
20
+
21
+ describe '#merge!' do
22
+ before { creator.merge!(:name => name, :url => url, :rights => rights) }
23
+
24
+ can_read_properties
25
+ end
26
+
27
+ describe 'setters' do
28
+ before {
29
+ creator.name = name
30
+ creator.url = url
31
+ creator.rights = rights
32
+ }
33
+
34
+ can_read_properties
35
+ end
36
+
37
+ describe 'primary contact passthrough' do
38
+ context 'no contacts' do
39
+ its(:address) { should be_nil }
40
+ end
41
+
42
+ context 'one contact, must be primary' do
43
+ let(:first_contact) { AVM::Contact.new(
44
+ :name => 'zz bill',
45
+ :address => first_contact_address,
46
+ :city => first_contact_address,
47
+ :state => first_contact_address,
48
+ :postal_code => first_contact_address,
49
+ :country => first_contact_address
50
+ ) }
51
+ let(:first_contact_address) { 'first contact' }
52
+
53
+ before { creator.contacts << first_contact }
54
+
55
+ fields = [ :address, :city, :state, :province, :postal_code, :zip, :country ]
56
+ fields.each { |field| its(field) { should == first_contact_address } }
57
+
58
+ specify { creator.to_a.should == [
59
+ first_contact.to_h
60
+ ] }
61
+
62
+ context 'two contacts' do
63
+ let(:second_contact) { AVM::Contact.new(
64
+ :name => 'aa bill',
65
+ :address => second_contact_address,
66
+ :city => second_contact_address,
67
+ :state => second_contact_address,
68
+ :postal_code => second_contact_address,
69
+ :country => second_contact_address
70
+ ) }
71
+ let(:second_contact_address) { 'second contact' }
72
+
73
+ before { creator.contacts << second_contact }
74
+
75
+ context 'no primary, first alphabetical is primary' do
76
+ subject { second_contact }
77
+
78
+ fields.each { |field| its(field) { should == second_contact_address } }
79
+
80
+ specify { creator.to_a.should == [
81
+ second_contact.to_h, first_contact.to_h
82
+ ] }
83
+ end
84
+
85
+ context 'one is primary, use it' do
86
+ before { first_contact.primary = true }
87
+
88
+ fields.each { |field| its(field) { should == first_contact_address } }
89
+
90
+ specify { creator.to_a.should == [
91
+ first_contact.to_h, second_contact.to_h
92
+ ] }
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ describe '#create_contact' do
99
+ let(:first_name) { 'John' }
100
+ let(:first_contact) { creator.create_contact(:name => first_name) }
101
+
102
+ subject { creator.primary_contact }
103
+ before { first_contact }
104
+
105
+ its(:name) { should == first_name }
106
+ end
107
+
108
+ describe '#from_xml' do
109
+ let(:document) { image.to_xml }
110
+ let(:image) { AVM::Image.from_xml(File.read(file_path)) }
111
+
112
+ subject { image }
113
+
114
+ context 'no creator' do
115
+ let(:file_path) { 'spec/sample_files/creator/no_creator.xmp' }
116
+
117
+ its('creator.length') { should == 0 }
118
+ end
119
+
120
+ context 'one creator' do
121
+ let(:file_path) { 'spec/sample_files/creator/one_creator.xmp' }
122
+
123
+ its('creator.length') { should == 1 }
124
+
125
+ def self.field_checks
126
+ its(:name) { should == name }
127
+ its(:address) { should == address }
128
+ its(:city) { should == city }
129
+ its(:state) { should == state }
130
+ its(:zip) { should == zip }
131
+ its(:country) { should == country }
132
+ its(:email) { should == email }
133
+ its(:telephone) { should == telephone }
134
+ end
135
+
136
+ let(:name) { 'John Bintz' }
137
+ let(:email) { 'bintz@stsci.edu' }
138
+ let(:telephone) { '800-555-1234' }
139
+ let(:address) { '3700 San Martin Drive' }
140
+ let(:city) { 'Baltimore' }
141
+ let(:state) { 'Maryland' }
142
+ let(:zip) { '21218' }
143
+ let(:country) { 'USA' }
144
+
145
+ context 'creator one' do
146
+ subject { image.creator[0] }
147
+
148
+ field_checks
149
+
150
+ it { should be_primary }
151
+ end
152
+
153
+ context 'two creators' do
154
+ let(:file_path) { 'spec/sample_files/creator/two_creators.xmp' }
155
+
156
+ its('creator.length') { should == 2 }
157
+
158
+ context 'first creator' do
159
+ subject { image.creator[0] }
160
+
161
+ field_checks
162
+
163
+ it { should be_primary }
164
+ end
165
+
166
+ context 'second creator' do
167
+ subject { image.creator[1] }
168
+
169
+ field_checks
170
+
171
+ it { should_not be_primary }
172
+
173
+ let(:name) { 'Aohn Bintz' }
174
+ let(:email) { 'aohn@stsci.edu' }
175
+ let(:telephone) { '800-555-2345' }
176
+ let(:address) { '3700 San Martin Drive' }
177
+ let(:city) { 'Baltimore' }
178
+ let(:state) { 'Maryland' }
179
+ let(:zip) { '21218' }
180
+ let(:country) { 'USA' }
181
+ end
182
+ end
183
+ end
184
+ end
185
+
186
+ describe 'contact name node' do
187
+ let(:first_name) { 'John' }
188
+ let(:second_name) { 'Zohn' }
189
+
190
+ let(:first_contact) { creator.create_contact(first_contact_options) }
191
+ let(:second_contact) { creator.create_contact(second_contact_options) }
192
+
193
+ let(:first_contact_options) { { :name => first_name } }
194
+ let(:second_contact_options) { { :name => second_name } }
195
+
196
+ subject { image.to_xml.search('//dc:creator/rdf:Seq/rdf:li').collect { |node| node.text } }
197
+
198
+ context 'no contacts' do
199
+ it { should == [] }
200
+ end
201
+
202
+ context 'one contact' do
203
+ before { first_contact }
204
+
205
+ it { should == [ first_name ] }
206
+ end
207
+
208
+ context 'second contact' do
209
+ before { second_contact ; first_contact }
210
+
211
+ it { should == [ first_name, second_name ] }
212
+ end
213
+
214
+ describe 'everything else uses primary' do
215
+ let(:fields) { [ :address, :city, :state, :zip, :country ] }
216
+
217
+ def other_fields(what)
218
+ Hash[fields.zip(Array.new(fields.length, what))]
219
+ end
220
+
221
+ let(:first_contact_options) { { :name => first_name }.merge(other_fields('one')) }
222
+ let(:second_contact_options) { { :name => second_name }.merge(other_fields('two')) }
223
+
224
+ before { second_contact ; first_contact }
225
+
226
+ specify {
227
+ %w{CiAdrExtadr CiAdrCity CiAdrRegion CiAdrPcode CiAdrCtry}.each do |element_name|
228
+ image.to_xml.at_xpath("//Iptc4xmpCore:#{element_name}").text.should == 'one'
229
+ end
230
+ }
231
+ end
232
+
233
+ describe 'contact emails, telephones' do
234
+ let(:first_email) { 'bintz@stsci.edu' }
235
+ let(:second_email) { 'bintz-2@stsci.edu' }
236
+
237
+ let(:first_phone) { '123-456-7890' }
238
+ let(:second_phone) { '234-567-8901' }
239
+
240
+ let(:first_contact_options) { { :name => first_name, :email => first_email, :telephone => first_phone } }
241
+ let(:second_contact_options) { { :name => second_name, :email => second_email, :telephone => second_phone } }
242
+
243
+ let(:contact_info) { image.to_xml.search('//Iptc4xmpCore:CreatorContactInfo') }
244
+
245
+ let(:telephone_text) { contact_info.at_xpath('./Iptc4xmpCore:CiTelWork').text }
246
+ let(:email_text) { contact_info.at_xpath('./Iptc4xmpCore:CiEmailWork').text }
247
+
248
+ context 'no contacts' do
249
+ specify { expect { telephone_text }.to raise_error }
250
+ specify { expect { email_text }.to raise_error }
251
+ end
252
+
253
+ context 'one contact' do
254
+ before { first_contact }
255
+
256
+ specify { telephone_text.should == first_phone }
257
+ specify { email_text.should == first_email }
258
+ end
259
+
260
+ context 'two contacts' do
261
+ before { first_contact ; second_contact }
262
+
263
+ specify { telephone_text.should == [ first_phone, second_phone ] * ',' }
264
+ specify { email_text.should == [ first_email, second_email ] * ',' }
265
+ end
266
+ end
267
+ end
268
+ end
@@ -0,0 +1,350 @@
1
+ require 'spec_helper'
2
+ require 'avm/image'
3
+
4
+ describe AVM::Image do
5
+ let(:image) { self.class.describes.new(options) }
6
+ let(:options) { {} }
7
+
8
+ subject { image }
9
+
10
+ let(:title) { 'My title' }
11
+ let(:headline) { 'Headline' }
12
+ let(:description) { 'Description' }
13
+ let(:distance_notes) { 'Distance Notes' }
14
+ let(:spectral_notes) { 'Spectral Notes' }
15
+ let(:reference_url) { 'Reference URL' }
16
+ let(:credit) { 'Credit' }
17
+ let(:date) { '2010-01-01' }
18
+ let(:id) { 'ID' }
19
+ let(:type) { 'Observation' }
20
+ let(:image_quality) { 'Good' }
21
+ let(:redshift) { 'Redshift' }
22
+ let(:light_years) { 'Light years' }
23
+
24
+ let(:subject_names) { [ 'Name one', 'Name two' ] }
25
+ let(:categories) { [ 'Category one', 'Category two' ] }
26
+
27
+ let(:coordinate_frame) { 'ICRS' }
28
+ let(:equinox) { '100' }
29
+ let(:reference_value) { [ 100, 50 ] }
30
+ let(:reference_dimension) { [ 200, 150 ] }
31
+ let(:reference_pixel) { [ 25, 15 ] }
32
+ let(:spatial_scale) { [ 40, 35 ] }
33
+ let(:spatial_rotation) { 10.0 }
34
+ let(:coordinate_system_projection) { 'TAN' }
35
+ let(:spatial_quality) { 'Full' }
36
+ let(:spatial_notes) { 'Spatial Notes' }
37
+ let(:fits_header) { 'FITS header' }
38
+ let(:spatial_cd_matrix) { [ 1, 2, 3, 4 ] }
39
+
40
+ let(:publisher) { 'Publisher' }
41
+ let(:publisher_id) { 'Publisher ID' }
42
+ let(:resource_id) { 'Resource ID' }
43
+ let(:resource_url) { 'Resource URL' }
44
+ let(:related_resources) { [ 'Resource 1', 'Resource 2' ] }
45
+ let(:metadata_date) { '2010-01-05' }
46
+ let(:metadata_version) { '1.2' }
47
+
48
+ def self.with_all_options
49
+ let(:options) { {
50
+ :title => title,
51
+ :headline => headline,
52
+ :description => description,
53
+ :distance_notes => distance_notes,
54
+ :spectral_notes => spectral_notes,
55
+ :reference_url => reference_url,
56
+ :credit => credit,
57
+ :date => date,
58
+ :id => id,
59
+ :type => type,
60
+ :quality => image_quality,
61
+ :redshift => redshift,
62
+ :light_years => light_years,
63
+ :coordinate_frame => coordinate_frame,
64
+ :equinox => equinox,
65
+ :reference_value => reference_value,
66
+ :reference_dimension => reference_dimension,
67
+ :reference_pixel => reference_pixel,
68
+ :spatial_scale => spatial_scale,
69
+ :spatial_rotation => spatial_rotation,
70
+ :coordinate_system_projection => coordinate_system_projection,
71
+ :spatial_quality => spatial_quality,
72
+ :spatial_notes => spatial_notes,
73
+ :fits_header => fits_header,
74
+ :spatial_cd_matrix => spatial_cd_matrix,
75
+ :publisher => publisher,
76
+ :publisher_id => publisher_id,
77
+ :resource_id => resource_id,
78
+ :resource_url => resource_url,
79
+ :related_resources => related_resources,
80
+ :metadata_date => metadata_date,
81
+ :metadata_version => metadata_version,
82
+ :subject_names => subject_names,
83
+ :categories => categories
84
+ } }
85
+ end
86
+
87
+ let(:avm_image_type) { eval("AVM::ImageType::#{type}") }
88
+ let(:avm_image_quality) { eval("AVM::ImageQuality::#{image_quality}") }
89
+ let(:avm_coordinate_frame) { eval("AVM::CoordinateFrame::#{coordinate_frame}") }
90
+ let(:avm_coordinate_system_projection) { eval("AVM::CoordinateSystemProjection::#{coordinate_system_projection}") }
91
+ let(:avm_spatial_quality) { eval("AVM::SpatialQuality::#{spatial_quality}") }
92
+
93
+ def self.has_most_options
94
+ its(:creator) { should be_a_kind_of(AVM::Creator) }
95
+ its(:title) { should == title }
96
+ its(:headline) { should == headline }
97
+ its(:description) { should == description }
98
+ its(:distance_notes) { should == distance_notes }
99
+ its(:spectral_notes) { should == spectral_notes }
100
+ its(:reference_url) { should == reference_url }
101
+ its(:credit) { should == credit }
102
+ its(:date) { should == Time.parse(date) }
103
+ its(:id) { should == id }
104
+ its(:image_type) { should be_a_kind_of avm_image_type }
105
+ its(:image_quality) { should be_a_kind_of avm_image_quality }
106
+
107
+ its(:coordinate_frame) { should be_a_kind_of avm_coordinate_frame }
108
+ its(:equinox) { should == equinox }
109
+ its(:reference_value) { should == reference_value }
110
+ its(:reference_dimension) { should == reference_dimension }
111
+ its(:reference_pixel) { should == reference_pixel }
112
+ its(:spatial_scale) { should == spatial_scale }
113
+ its(:spatial_rotation) { should == spatial_rotation }
114
+ its(:coordinate_system_projection) { should be_a_kind_of avm_coordinate_system_projection }
115
+ its(:spatial_quality) { should be_a_kind_of avm_spatial_quality }
116
+ its(:spatial_notes) { should == spatial_notes }
117
+ its(:fits_header) { should == fits_header }
118
+ its(:spatial_cd_matrix) { should == spatial_cd_matrix }
119
+
120
+ its(:publisher) { should == publisher }
121
+ its(:publisher_id) { should == publisher_id }
122
+ its(:resource_id) { should == resource_id }
123
+ its(:resource_url) { should == resource_url }
124
+ its(:related_resources) { should == related_resources }
125
+ its(:metadata_date) { should == Time.parse(metadata_date) }
126
+ its(:metadata_version) { should == metadata_version }
127
+
128
+ its(:subject_names) { should == subject_names }
129
+ its(:categories) { should == categories }
130
+
131
+ it { should be_valid }
132
+ end
133
+
134
+ describe '#initialize' do
135
+ with_all_options
136
+
137
+ it { should be_a_kind_of(AVM::Image) }
138
+
139
+ has_most_options
140
+
141
+ its(:to_h) { should == {
142
+ :title => title,
143
+ :headline => headline,
144
+ :description => description,
145
+ :distance_notes => distance_notes,
146
+ :spectral_notes => spectral_notes,
147
+ :reference_url => reference_url,
148
+ :credit => credit,
149
+ :date => Time.parse(date),
150
+ :id => id,
151
+ :image_type => avm_image_type.new,
152
+ :image_quality => avm_image_quality.new,
153
+ :coordinate_frame => avm_coordinate_frame.new,
154
+ :equinox => equinox,
155
+ :reference_value => reference_value,
156
+ :reference_dimension => reference_dimension,
157
+ :reference_pixel => reference_pixel,
158
+ :spatial_scale => spatial_scale,
159
+ :spatial_rotation => spatial_rotation,
160
+ :coordinate_system_projection => avm_coordinate_system_projection.new,
161
+ :spatial_quality => avm_spatial_quality.new,
162
+ :spatial_notes => spatial_notes,
163
+ :fits_header => fits_header,
164
+ :spatial_cd_matrix => spatial_cd_matrix,
165
+ :distance => [ light_years, redshift ],
166
+ :creator => [],
167
+ :publisher => publisher,
168
+ :publisher_id => publisher_id,
169
+ :resource_id => resource_id,
170
+ :resource_url => resource_url,
171
+ :related_resources => related_resources,
172
+ :metadata_date => Time.parse(metadata_date),
173
+ :metadata_version => metadata_version,
174
+ :subject_names => subject_names,
175
+ :categories => categories,
176
+ :observations => []
177
+ } }
178
+
179
+ its(:distance) { should == [ light_years, redshift ] }
180
+ end
181
+
182
+ describe 'not valid' do
183
+ let(:image) { AVM::Image.new }
184
+
185
+ it { should_not be_valid }
186
+ end
187
+
188
+ describe '.from_xml' do
189
+ let!(:image) { AVM::Image.from_xml(File.read(file_path)) }
190
+
191
+ subject { image }
192
+
193
+ context "nothing in it" do
194
+ let(:file_path) { 'spec/sample_files/image/nothing.xmp' }
195
+
196
+ [ :title, :headline, :description, :distance_notes,
197
+ :spectral_notes, :reference_url, :credit, :date,
198
+ :id, :image_type, :image_quality, :redshift,
199
+ :light_years, :coordinate_frame, :equinox, :reference_value,
200
+ :reference_dimension, :reference_pixel, :spatial_scale,
201
+ :spatial_rotation, :coordinate_system_projection, :spatial_quality, :spatial_notes,
202
+ :fits_header, :spatial_cd_matrix, :subject_names, :categories
203
+ ].each do |field|
204
+ its(field) { should be_nil }
205
+ end
206
+
207
+ it { should_not be_valid }
208
+ end
209
+
210
+ context "image in it" do
211
+ context 'distance as a single value, assume light years' do
212
+ let(:file_path) { 'spec/sample_files/image/single_value_light_years.xmp' }
213
+
214
+ has_most_options
215
+
216
+ its(:redshift) { should be_nil }
217
+ its(:light_years) { should == light_years }
218
+ end
219
+
220
+ context "distance in light years" do
221
+ let(:file_path) { 'spec/sample_files/image/light_years.xmp' }
222
+
223
+ has_most_options
224
+
225
+ its(:redshift) { should be_nil }
226
+ its(:light_years) { should == light_years }
227
+ end
228
+
229
+ context "distaince in redshift" do
230
+ let(:file_path) { 'spec/sample_files/image/redshift.xmp' }
231
+
232
+ has_most_options
233
+
234
+ its(:light_years) { should be_nil }
235
+ its(:redshift) { should == redshift }
236
+ end
237
+
238
+ context "distance in both" do
239
+ let(:file_path) { 'spec/sample_files/image/both.xmp' }
240
+
241
+ has_most_options
242
+
243
+ its(:light_years) { should == light_years }
244
+ its(:redshift) { should == redshift }
245
+ end
246
+ end
247
+ end
248
+
249
+ describe '#to_xml' do
250
+ let(:xml) { image.to_xml }
251
+
252
+ let(:dublin_core) { xml.at_xpath('//rdf:Description[@rdf:about="Dublin Core"]') }
253
+ let(:photoshop) { xml.at_xpath('//rdf:Description[@rdf:about="Photoshop"]') }
254
+ let(:avm) { xml.at_xpath('//rdf:Description[@rdf:about="AVM"]') }
255
+
256
+ context 'nothing in it' do
257
+ it "should have basic tags" do
258
+ xml.at_xpath('//rdf:RDF').should_not be_nil
259
+ xml.search('//rdf:RDF/rdf:Description').should_not be_empty
260
+ photoshop.at_xpath('./photoshop:DateCreated').should_not be_nil
261
+ end
262
+ end
263
+
264
+ context 'with basics' do
265
+ with_all_options
266
+
267
+ def xpath_text(which, xpath)
268
+ which.at_xpath(xpath).text
269
+ end
270
+
271
+ def xpath_list(which, xpath, search = './/rdf:li')
272
+ which.at_xpath(xpath).search(search).collect(&:text)
273
+ end
274
+
275
+ it "should have the image info tags" do
276
+ xpath_text(dublin_core, './dc:title/rdf:Alt/rdf:li').should == title
277
+ xpath_text(photoshop, './photoshop:Headline').should == headline
278
+ xpath_text(dublin_core, './dc:description/rdf:Alt/rdf:li').should == description
279
+
280
+ xpath_text(avm, './avm:Distance.Notes').should == distance_notes
281
+ xpath_text(avm, './avm:Spectral.Notes').should == spectral_notes
282
+ xpath_text(avm, './avm:ReferenceURL').should == reference_url
283
+ xpath_text(photoshop, './photoshop:Credit').should == credit
284
+ xpath_text(photoshop, './photoshop:DateCreated').should == date
285
+ xpath_text(avm, './avm:ID').should == id
286
+ xpath_text(avm, './avm:Type').should == type
287
+ xpath_text(avm, './avm:Image.ProductQuality').should == image_quality
288
+ end
289
+
290
+ it "should have the spatial tags" do
291
+ xpath_text(avm, './avm:Spatial.CoordinateFrame').should == coordinate_frame
292
+ xpath_text(avm, './avm:Spatial.Equinox').should == equinox
293
+ xpath_list(avm, './avm:Spatial.ReferenceValue').should == reference_value.collect { |v| v.to_f.to_s }
294
+ xpath_list(avm, './avm:Spatial.ReferenceDimension').should == reference_dimension.collect { |v| v.to_f.to_s }
295
+ xpath_list(avm, './avm:Spatial.ReferencePixel').should == reference_pixel.collect { |v| v.to_f.to_s }
296
+ xpath_list(avm, './avm:Spatial.Scale').should == spatial_scale.collect { |v| v.to_f.to_s }
297
+ xpath_text(avm, './avm:Spatial.CoordsystemProjection').should == coordinate_system_projection
298
+ xpath_text(avm, './avm:Spatial.Quality').should == spatial_quality
299
+ xpath_text(avm, './avm:Spatial.Notes').should == spatial_notes
300
+ xpath_text(avm, './avm:Spatial.FITSheader').should == fits_header
301
+ xpath_list(avm, './avm:Spatial.CDMatrix').should == spatial_cd_matrix.collect { |v| v.to_f.to_s }
302
+ end
303
+
304
+ it "should have the publisher tags" do
305
+ xpath_text(avm, './avm:Publisher').should == publisher
306
+ xpath_text(avm, './avm:PublisherID').should == publisher_id
307
+ xpath_text(avm, './avm:ResourceID').should == resource_id
308
+ xpath_text(avm, './avm:ResourceURL').should == resource_url
309
+ xpath_list(avm, './avm:RelatedResources', './rdf:Bag/rdf:li').should == related_resources
310
+ xpath_text(avm, './avm:MetadataDate').should == metadata_date
311
+ xpath_text(avm, './avm:MetadataVersion').should == metadata_version
312
+ end
313
+
314
+ context "distance" do
315
+ context "no distances" do
316
+ let(:redshift) { nil }
317
+ let(:light_years) { nil }
318
+
319
+ it("should have no distances") { avm.at_xpath('./avm:Distance').should be_nil }
320
+ end
321
+
322
+ context "redshift only" do
323
+ let(:light_years) { nil }
324
+
325
+ it "should have redshift only" do
326
+ avm.at_xpath('./avm:Distance/rdf:Seq/rdf:li[1]').text.should == '-'
327
+ avm.at_xpath('./avm:Distance/rdf:Seq/rdf:li[2]').text.should == redshift
328
+ end
329
+ end
330
+
331
+ context "light years only" do
332
+ let(:redshift) { nil }
333
+
334
+ it "should should have light years but not redshift" do
335
+ avm.at_xpath('./avm:Distance/rdf:Seq/rdf:li[1]').text.should == light_years
336
+ avm.at_xpath('./avm:Distance/rdf:Seq/rdf:li[2]').should be_nil
337
+ end
338
+ end
339
+
340
+ context "redshift and light years" do
341
+ it "should have both light years and redshift" do
342
+ avm.at_xpath('./avm:Distance/rdf:Seq/rdf:li[1]').text.should == light_years
343
+ avm.at_xpath('./avm:Distance/rdf:Seq/rdf:li[2]').text.should == redshift
344
+ end
345
+ end
346
+ end
347
+ end
348
+ end
349
+ end
350
+