datacite-mapping 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +42 -0
  3. data/.rubocop.yml +28 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +2 -0
  6. data/.yardopts +2 -0
  7. data/CHANGES.md +3 -0
  8. data/Gemfile +3 -0
  9. data/LICENSE.md +22 -0
  10. data/README.md +168 -0
  11. data/Rakefile +49 -0
  12. data/datacite-mapping.gemspec +37 -0
  13. data/examples/reading.rb +75 -0
  14. data/examples/writing.rb +49 -0
  15. data/lib/datacite/mapping.rb +36 -0
  16. data/lib/datacite/mapping/alternate_identifier.rb +45 -0
  17. data/lib/datacite/mapping/contributor.rb +125 -0
  18. data/lib/datacite/mapping/creator.rb +48 -0
  19. data/lib/datacite/mapping/date.rb +153 -0
  20. data/lib/datacite/mapping/description.rb +121 -0
  21. data/lib/datacite/mapping/geo_location.rb +49 -0
  22. data/lib/datacite/mapping/geo_location_box.rb +137 -0
  23. data/lib/datacite/mapping/geo_location_point.rb +102 -0
  24. data/lib/datacite/mapping/identifier.rb +45 -0
  25. data/lib/datacite/mapping/module_info.rb +12 -0
  26. data/lib/datacite/mapping/name_identifier.rb +48 -0
  27. data/lib/datacite/mapping/related_identifier.rb +209 -0
  28. data/lib/datacite/mapping/resource.rb +201 -0
  29. data/lib/datacite/mapping/resource_type.rb +83 -0
  30. data/lib/datacite/mapping/rights.rb +36 -0
  31. data/lib/datacite/mapping/subject.rb +55 -0
  32. data/lib/datacite/mapping/title.rb +69 -0
  33. data/spec/.rubocop.yml +7 -0
  34. data/spec/data/resource.xml +61 -0
  35. data/spec/rspec_custom_matchers.rb +69 -0
  36. data/spec/spec_helper.rb +31 -0
  37. data/spec/unit/datacite/mapping/alternate_identifier_spec.rb +60 -0
  38. data/spec/unit/datacite/mapping/contributor_spec.rb +129 -0
  39. data/spec/unit/datacite/mapping/creator_spec.rb +125 -0
  40. data/spec/unit/datacite/mapping/date_spec.rb +246 -0
  41. data/spec/unit/datacite/mapping/description_spec.rb +89 -0
  42. data/spec/unit/datacite/mapping/geo_location_box_spec.rb +241 -0
  43. data/spec/unit/datacite/mapping/geo_location_point_spec.rb +148 -0
  44. data/spec/unit/datacite/mapping/geo_location_spec.rb +116 -0
  45. data/spec/unit/datacite/mapping/identifier_spec.rb +75 -0
  46. data/spec/unit/datacite/mapping/name_identifier_spec.rb +89 -0
  47. data/spec/unit/datacite/mapping/related_identifier_spec.rb +157 -0
  48. data/spec/unit/datacite/mapping/resource_spec.rb +727 -0
  49. data/spec/unit/datacite/mapping/resource_type_spec.rb +69 -0
  50. data/spec/unit/datacite/mapping/rights_spec.rb +78 -0
  51. data/spec/unit/datacite/mapping/subject_spec.rb +108 -0
  52. data/spec/unit/datacite/mapping/title_spec.rb +113 -0
  53. metadata +262 -0
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+
3
+ module Datacite
4
+ module Mapping
5
+
6
+ describe GeoLocation do
7
+ describe '#initialize' do
8
+ it 'accepts a point' do
9
+ point = GeoLocationPoint.new(47.61, -122.33)
10
+ loc = GeoLocation.new(point: point)
11
+ expect(loc.point).to eq(point)
12
+ end
13
+ it 'accepts a box' do
14
+ box = GeoLocationBox.new(-33.45, -122.33, 47.61, -70.67)
15
+ loc = GeoLocation.new(box: box)
16
+ expect(loc.box).to eq(box)
17
+ end
18
+ it 'accepts a place' do
19
+ place = 'Ouagadougou'
20
+ loc = GeoLocation.new(place: place)
21
+ expect(loc.place).to eq(place)
22
+ end
23
+ it 'allows an empty location' do
24
+ loc = GeoLocation.new
25
+ expect(loc.point).to be_nil
26
+ expect(loc.box).to be_nil
27
+ expect(loc.place).to be_nil
28
+ end
29
+ end
30
+
31
+ describe '#point=' do
32
+ it 'sets the point' do
33
+ point = GeoLocationPoint.new(47.61, -122.33)
34
+ loc = GeoLocation.new
35
+ loc.point = point
36
+ expect(loc.point).to eq(point)
37
+ end
38
+ it 'accepts nil' do
39
+ loc = GeoLocation.new(point: GeoLocationPoint.new(47.61, -122.33))
40
+ loc.point = nil
41
+ expect(loc.point).to be_nil
42
+ end
43
+ end
44
+
45
+ describe '#box=' do
46
+ it 'sets the box' do
47
+ box = GeoLocationBox.new(-33.45, -122.33, 47.61, -70.67)
48
+ loc = GeoLocation.new
49
+ loc.box = box
50
+ expect(loc.box).to eq(box)
51
+ end
52
+ it 'accepts nil' do
53
+ loc = GeoLocation.new(box: GeoLocationBox.new(-33.45, -122.33, 47.61, -70.67))
54
+ loc.box = nil
55
+ expect(loc.box).to be_nil
56
+ end
57
+ end
58
+
59
+ describe '#place=' do
60
+ it 'sets the place' do
61
+ place = 'Ouagadougou'
62
+ loc = GeoLocation.new
63
+ loc.place = place
64
+ expect(loc.place).to eq(place)
65
+ end
66
+ it 'accepts nil' do
67
+ loc = GeoLocation.new(place: 'Ouagadougou')
68
+ loc.place = nil
69
+ expect(loc.place).to be_nil
70
+ end
71
+ end
72
+
73
+ describe '#load_from_xml' do
74
+ it 'parses XML' do
75
+ xml_text = '<geoLocation>
76
+ <geoLocationPoint>31.233 -67.302</geoLocationPoint>
77
+ <geoLocationBox>41.090 -71.032 42.893 -68.211</geoLocationBox>
78
+ <geoLocationPlace>Atlantic Ocean</geoLocationPlace>
79
+ </geoLocation>'
80
+ xml = REXML::Document.new(xml_text).root
81
+ loc = GeoLocation.load_from_xml(xml)
82
+ expect(loc.point).to eq(GeoLocationPoint.new(31.233, -67.302))
83
+ expect(loc.box).to eq(GeoLocationBox.new(41.09, -71.032, 42.893, -68.211))
84
+ expect(loc.place).to eq('Atlantic Ocean')
85
+ end
86
+
87
+ it 'trims place-name whitespace' do
88
+ xml_text = '<geoLocation>
89
+ <geoLocationPlace>
90
+ Atlantic Ocean
91
+ </geoLocationPlace>
92
+ </geoLocation>'
93
+ xml = REXML::Document.new(xml_text).root
94
+ loc = GeoLocation.load_from_xml(xml)
95
+ expect(loc.place).to eq('Atlantic Ocean')
96
+ end
97
+ end
98
+
99
+ describe '#save_to_xml' do
100
+ it 'writes XML' do
101
+ loc = GeoLocation.new(
102
+ point: GeoLocationPoint.new(31.233, -67.302),
103
+ box: GeoLocationBox.new(41.09, -71.032, 42.893, -68.211),
104
+ place: 'Atlantic Ocean'
105
+ )
106
+ expected_xml = '<geoLocation>
107
+ <geoLocationPoint>31.233 -67.302</geoLocationPoint>
108
+ <geoLocationBox>41.09 -71.032 42.893 -68.211</geoLocationBox>
109
+ <geoLocationPlace>Atlantic Ocean</geoLocationPlace>
110
+ </geoLocation>'
111
+ expect(loc.save_to_xml).to be_xml(expected_xml)
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ module Datacite
4
+ module Mapping
5
+ describe Identifier do
6
+
7
+ describe '#initialize' do
8
+ it 'sets the value' do
9
+ value = '10.14749/1407399495'
10
+ id = Identifier.new(value: value)
11
+ expect(id.value).to eq(value)
12
+ end
13
+
14
+ it 'sets the type' do
15
+ id = Identifier.new(value: '10.14749/1407399495')
16
+ expect(id.identifier_type).to eq('DOI')
17
+ end
18
+
19
+ it 'disallows bad DOIs' do
20
+ bad_dois = %w(
21
+ 20.14749/1407399495
22
+ 11.14749/1407399495
23
+ 10./1407399495
24
+ 10.14749\1407399495
25
+ 10.14749/
26
+ )
27
+ bad_dois.each do |doi|
28
+ expect { Identifier.new(value: doi) }.to raise_error(ArgumentError)
29
+ end
30
+ end
31
+ end
32
+
33
+ describe '#value=' do
34
+ it 'sets the value' do
35
+ id = Identifier.allocate
36
+ id.value = '10.14749/1407399495'
37
+ expect(id.value).to eq('10.14749/1407399495')
38
+ end
39
+ it 'disallows bad DOIs' do
40
+ id = Identifier.allocate
41
+ bad_dois = %w(
42
+ 20.14749/1407399495
43
+ 11.14749/1407399495
44
+ 10./1407399495
45
+ 10.14749\1407399495
46
+ 10.14749/
47
+ )
48
+ bad_dois.each do |doi|
49
+ expect { id.value = doi }.to raise_error(ArgumentError)
50
+ expect(id.value).to be_nil
51
+ end
52
+ end
53
+ end
54
+
55
+ describe '#load_from_xml' do
56
+ it 'parses XML' do
57
+ xml_text = "<identifier identifierType='DOI'>10.14749/1407399498</identifier>"
58
+ xml = REXML::Document.new(xml_text).root
59
+ id = Identifier.load_from_xml(xml)
60
+ expect(id.identifier_type).to eq('DOI')
61
+ expect(id.value).to eq('10.14749/1407399498')
62
+ end
63
+ end
64
+
65
+ describe '#save_to_xml' do
66
+ it 'writes XML' do
67
+ id = Identifier.new(value: '10.14749/1407399498')
68
+ xml = id.save_to_xml
69
+ expect(xml).to be_xml("<identifier identifierType='DOI'>10.14749/1407399498</identifier>")
70
+ end
71
+ end
72
+
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ module Datacite
4
+ module Mapping
5
+ describe NameIdentifier do
6
+
7
+ describe '#initialize' do
8
+ it 'sets the identifier scheme and value' do
9
+ id = NameIdentifier.new(scheme: 'ORCID', value: '0000-0003-1632-8708')
10
+ expect(id.scheme).to eq('ORCID')
11
+ expect(id.value).to eq('0000-0003-1632-8708')
12
+ end
13
+
14
+ it 'accepts a scheme URI' do
15
+ id = NameIdentifier.new(scheme: 'ORCID', scheme_uri: URI('http://orcid.org/'), value: '0000-0003-1632-8708')
16
+ expect(id.scheme_uri).to eq(URI('http://orcid.org/'))
17
+ end
18
+
19
+ it 'defaults to a nil scheme URI' do
20
+ id = NameIdentifier.new(scheme: 'ORCID', value: '0000-0003-1632-8708')
21
+ expect(id.scheme_uri).to be_nil
22
+ end
23
+
24
+ it 'requires a scheme' do
25
+ expect { NameIdentifier.new(value: '0000-0003-1632-8708') }.to raise_error(ArgumentError)
26
+ end
27
+
28
+ it 'requires a non-empty scheme' do
29
+ expect { NameIdentifier.new(scheme: '', value: '0000-0003-1632-8708') }.to raise_error(ArgumentError)
30
+ end
31
+
32
+ it 'requires a value' do
33
+ expect { NameIdentifier.new(scheme: 'ORCID') }.to raise_error(ArgumentError)
34
+ end
35
+
36
+ it 'requires a non-empty value' do
37
+ expect { NameIdentifier.new(scheme: '', scheme: 'ORCID') }.to raise_error(ArgumentError)
38
+ end
39
+ end
40
+
41
+ describe '#scheme=' do
42
+ it 'requires a scheme' do
43
+ id = NameIdentifier.new(scheme: 'ORCID', value: '0000-0003-1632-8708')
44
+ expect { id.scheme = nil }.to raise_error(ArgumentError)
45
+ expect(id.scheme).to eq('ORCID')
46
+ end
47
+
48
+ it 'requires a non-empty scheme' do
49
+ id = NameIdentifier.new(scheme: 'ORCID', value: '0000-0003-1632-8708')
50
+ expect { id.scheme = '' }.to raise_error(ArgumentError)
51
+ expect(id.scheme).to eq('ORCID')
52
+ end
53
+ end
54
+
55
+ describe '#value=' do
56
+ it 'requires a value' do
57
+ id = NameIdentifier.new(scheme: 'ORCID', value: '0000-0003-1632-8708')
58
+ expect { id.value = nil }.to raise_error(ArgumentError)
59
+ expect(id.value).to eq('0000-0003-1632-8708')
60
+ end
61
+
62
+ it 'requires a non-empty value' do
63
+ id = NameIdentifier.new(scheme: 'ORCID', value: '0000-0003-1632-8708')
64
+ expect { id.value = '' }.to raise_error(ArgumentError)
65
+ expect(id.value).to eq('0000-0003-1632-8708')
66
+ end
67
+ end
68
+
69
+ describe '#load_from_xml' do
70
+ it 'parses XML' do
71
+ xml_text = '<nameIdentifier schemeURI="http://orcid.org/" nameIdentifierScheme="ORCID">0000-0003-1632-8708</nameIdentifier>'
72
+ xml = REXML::Document.new(xml_text).root
73
+ id = NameIdentifier.load_from_xml(xml)
74
+ expect(id.scheme).to eq('ORCID')
75
+ expect(id.scheme_uri).to eq(URI('http://orcid.org/'))
76
+ expect(id.value).to eq('0000-0003-1632-8708')
77
+ end
78
+ end
79
+
80
+ describe '#save_to_xml' do
81
+ it 'writes XML' do
82
+ id = NameIdentifier.new(scheme: 'ORCID', scheme_uri: URI('http://orcid.org/'), value: '0000-0003-1632-8708')
83
+ xml = id.save_to_xml
84
+ expect(xml).to be_xml('<nameIdentifier schemeURI="http://orcid.org/" nameIdentifierScheme="ORCID">0000-0003-1632-8708</nameIdentifier>')
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,157 @@
1
+ require 'spec_helper'
2
+
3
+ module Datacite
4
+ module Mapping
5
+ describe RelatedIdentifier do
6
+ describe '#initialize' do
7
+ it 'sets the relatedIdentifierType' do
8
+ ri = RelatedIdentifier.new(identifier_type: RelatedIdentifierType::ARXIV, relation_type: RelationType::IS_REVIEWED_BY, value: 'arXiv:0706.0001')
9
+ expect(ri.identifier_type).to eq(RelatedIdentifierType::ARXIV)
10
+ end
11
+ it 'sets the relationType' do
12
+ ri = RelatedIdentifier.new(identifier_type: RelatedIdentifierType::ARXIV, relation_type: RelationType::IS_REVIEWED_BY, value: 'arXiv:0706.0001')
13
+ expect(ri.relation_type).to eq(RelationType::IS_REVIEWED_BY)
14
+ end
15
+ it 'sets the relatedMetadataScheme' do
16
+ ri = RelatedIdentifier.new(related_metadata_scheme: 'citeproc+json', identifier_type: 'URL', relation_type: RelationType::HAS_METADATA, value: 'http://data.datacite.org/application/citeproc+json/10.5072/example-full')
17
+ expect(ri.related_metadata_scheme).to eq('citeproc+json')
18
+ end
19
+ it 'sets the schemeURI' do
20
+ ri = RelatedIdentifier.new(scheme_uri: URI('https://github.com/citation-style-language/schema/raw/master/csl-data.json'), identifier_type: 'URL', relation_type: RelationType::HAS_METADATA, value: 'http://data.datacite.org/application/citeproc+json/10.5072/example-full')
21
+ expect(ri.scheme_uri).to eq(URI('https://github.com/citation-style-language/schema/raw/master/csl-data.json'))
22
+ end
23
+ it 'sets the schemeType' do
24
+ ri = RelatedIdentifier.new(scheme_type: 'Turtle', identifier_type: 'URL', relation_type: RelationType::HAS_METADATA, value: 'http://data.datacite.org/application/citeproc+json/10.5072/example-full')
25
+ expect(ri.scheme_type).to eq('Turtle')
26
+ end
27
+ it 'sets the value' do
28
+ ri = RelatedIdentifier.new(identifier_type: RelatedIdentifierType::ARXIV, relation_type: RelationType::IS_REVIEWED_BY, value: 'arXiv:0706.0001')
29
+ expect(ri.value).to eq('arXiv:0706.0001')
30
+ end
31
+ it 'requires a relatedIdentifierType' do
32
+ expect { RelatedIdentifier.new(relation_type: RelationType::IS_REVIEWED_BY, value: 'arXiv:0706.0001') }.to raise_error(ArgumentError)
33
+ end
34
+ it 'requires a relationType' do
35
+ expect { RelatedIdentifier.new(identifier_type: RelatedIdentifierType::ARXIV, value: 'arXiv:0706.0001') }.to raise_error(ArgumentError)
36
+ end
37
+ it 'requires a value' do
38
+ expect { RelatedIdentifier.new(identifier_type: RelatedIdentifierType::ARXIV, relation_type: RelationType::IS_REVIEWED_BY) }.to raise_error(ArgumentError)
39
+ end
40
+ end
41
+
42
+ describe 'value=' do
43
+ it 'sets the value' do
44
+ ri = RelatedIdentifier.allocate
45
+ ri.value = 'arXiv:0706.0001'
46
+ expect(ri.value).to eq('arXiv:0706.0001')
47
+ end
48
+ it 'requires a value' do
49
+ ri = RelatedIdentifier.new(identifier_type: RelatedIdentifierType::ARXIV, relation_type: RelationType::IS_REVIEWED_BY, value: 'arXiv:0706.0001')
50
+ expect { ri.value = nil }.to raise_error(ArgumentError)
51
+ expect(ri.value).to eq('arXiv:0706.0001')
52
+ end
53
+ it 'requires a non-empty value' do
54
+ ri = RelatedIdentifier.new(identifier_type: RelatedIdentifierType::ARXIV, relation_type: RelationType::IS_REVIEWED_BY, value: 'arXiv:0706.0001')
55
+ expect { ri.value = '' }.to raise_error(ArgumentError)
56
+ expect(ri.value).to eq('arXiv:0706.0001')
57
+ end
58
+ end
59
+ describe 'identifier_type=' do
60
+ it 'sets the relatedIdentifierType' do
61
+ ri = RelatedIdentifier.allocate
62
+ ri.identifier_type = RelatedIdentifierType::ARXIV
63
+ expect(ri.identifier_type).to eq(RelatedIdentifierType::ARXIV)
64
+ end
65
+ it 'requires a relatedIdentifierType' do
66
+ ri = RelatedIdentifier.new(identifier_type: RelatedIdentifierType::ARXIV, relation_type: RelationType::IS_REVIEWED_BY, value: 'arXiv:0706.0001')
67
+ expect { ri.identifier_type = nil }.to raise_error(ArgumentError)
68
+ expect(ri.identifier_type).to eq(RelatedIdentifierType::ARXIV)
69
+ end
70
+ end
71
+ describe 'relation_type=' do
72
+ it 'sets the relationType' do
73
+ ri = RelatedIdentifier.allocate
74
+ ri.relation_type = RelationType::IS_REVIEWED_BY
75
+ expect(ri.relation_type).to eq(RelationType::IS_REVIEWED_BY)
76
+ end
77
+ it 'requires a relationType' do
78
+ ri = RelatedIdentifier.new(identifier_type: RelatedIdentifierType::ARXIV, relation_type: RelationType::IS_REVIEWED_BY, value: 'arXiv:0706.0001')
79
+ expect { ri.relation_type = nil }.to raise_error(ArgumentError)
80
+ expect(ri.relation_type).to eq(RelationType::IS_REVIEWED_BY)
81
+ end
82
+ end
83
+ describe 'related_metadata_scheme=' do
84
+ it 'sets the relatedMetadataScheme' do
85
+ ri = RelatedIdentifier.allocate
86
+ ri.related_metadata_scheme = 'citeproc+json'
87
+ expect(ri.related_metadata_scheme).to eq('citeproc+json')
88
+ end
89
+ it 'allows a nil relatedMetadataScheme' do
90
+ ri = RelatedIdentifier.new(related_metadata_scheme: 'citeproc+json', identifier_type: 'URL', relation_type: RelationType::HAS_METADATA, value: 'http://data.datacite.org/application/citeproc+json/10.5072/example-full')
91
+ ri.related_metadata_scheme = nil
92
+ expect(ri.related_metadata_scheme).to be_nil
93
+ end
94
+ end
95
+ describe 'scheme_uri=' do
96
+ it 'sets the schemeURI' do
97
+ ri = RelatedIdentifier.allocate
98
+ ri.scheme_uri = URI('https://github.com/citation-style-language/schema/raw/master/csl-data.json')
99
+ expect(ri.scheme_uri).to eq(URI('https://github.com/citation-style-language/schema/raw/master/csl-data.json'))
100
+ end
101
+ it 'allows a nil schemeURI' do
102
+ ri = RelatedIdentifier.new(scheme_uri: URI('https://github.com/citation-style-language/schema/raw/master/csl-data.json'), identifier_type: 'URL', relation_type: RelationType::HAS_METADATA, value: 'http://data.datacite.org/application/citeproc+json/10.5072/example-full')
103
+ ri.scheme_uri = nil
104
+ expect(ri.scheme_uri).to be_nil
105
+ end
106
+ end
107
+ describe 'scheme_type=' do
108
+ it 'sets the schemeType' do
109
+ ri = RelatedIdentifier.allocate
110
+ ri.scheme_type = 'Turtle'
111
+ expect(ri.scheme_type).to eq('Turtle')
112
+ end
113
+ it 'allows a nil schemeType' do
114
+ ri = RelatedIdentifier.new(scheme_type: 'Turtle', identifier_type: 'URL', relation_type: RelationType::HAS_METADATA, value: 'http://data.datacite.org/application/citeproc+json/10.5072/example-full')
115
+ ri.scheme_type = nil
116
+ expect(ri.scheme_type).to be_nil
117
+ end
118
+ end
119
+
120
+ describe '#load_from_xml' do
121
+ it 'parses XML' do
122
+ xml_text = '<relatedIdentifier relatedIdentifierType="URL" relationType="HasMetadata" relatedMetadataScheme="citeproc+json" schemeType="Turtle" schemeURI="https://github.com/citation-style-language/schema/raw/master/csl-data.json">http://data.datacite.org/application/citeproc+json/10.5072/example-full</relatedIdentifier>'
123
+ xml = REXML::Document.new(xml_text).root
124
+ id = RelatedIdentifier.load_from_xml(xml)
125
+
126
+ expected_id_type = RelatedIdentifierType::URL
127
+ expected_rel_type = RelationType::HAS_METADATA
128
+ expected_scheme = 'citeproc+json'
129
+ expected_scheme_uri = URI('https://github.com/citation-style-language/schema/raw/master/csl-data.json')
130
+ expected_value = 'http://data.datacite.org/application/citeproc+json/10.5072/example-full'
131
+
132
+ expect(id.identifier_type).to eq(expected_id_type)
133
+ expect(id.relation_type).to eq(expected_rel_type)
134
+ expect(id.related_metadata_scheme).to eq(expected_scheme)
135
+ expect(id.scheme_type).to eq('Turtle')
136
+ expect(id.scheme_uri).to eq(expected_scheme_uri)
137
+ expect(id.value).to eq(expected_value)
138
+ end
139
+ end
140
+
141
+ describe '#save_to_xml' do
142
+ it 'writes XML' do
143
+ id = RelatedIdentifier.new(
144
+ identifier_type: RelatedIdentifierType::URL,
145
+ relation_type: RelationType::HAS_METADATA,
146
+ related_metadata_scheme: 'citeproc+json',
147
+ scheme_type: 'Turtle',
148
+ scheme_uri: URI('https://github.com/citation-style-language/schema/raw/master/csl-data.json'),
149
+ value: 'http://data.datacite.org/application/citeproc+json/10.5072/example-full'
150
+ )
151
+ expected_xml = '<relatedIdentifier relatedIdentifierType="URL" relationType="HasMetadata" relatedMetadataScheme="citeproc+json" schemeType="Turtle" schemeURI="https://github.com/citation-style-language/schema/raw/master/csl-data.json">http://data.datacite.org/application/citeproc+json/10.5072/example-full</relatedIdentifier>'
152
+ expect(id.save_to_xml).to be_xml(expected_xml)
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,727 @@
1
+ # coding: utf-8
2
+ require 'spec_helper'
3
+
4
+ module Datacite
5
+ module Mapping
6
+ describe Resource do
7
+
8
+ before :each do
9
+ @id = Identifier.new(value: '10.14749/1407399495')
10
+ @creators = [
11
+ Creator.new(
12
+ name: 'Hedy Lamarr',
13
+ identifier: NameIdentifier.new(scheme: 'ISNI', scheme_uri: URI('http://isni.org/'), value: '0000-0001-1690-159X'),
14
+ affiliations: ['United Artists', 'Metro-Goldwyn-Mayer']
15
+ ),
16
+ Creator.new(
17
+ name: 'Herschlag, Natalie',
18
+ identifier: NameIdentifier.new(scheme: 'ISNI', scheme_uri: URI('http://isni.org/'), value: '0000-0001-0907-8419'),
19
+ affiliations: ['Gaumont Buena Vista International', '20th Century Fox']
20
+ )
21
+ ]
22
+ @titles = [
23
+ Title.new(value: 'An Account of a Very Odd Monstrous Calf', language: 'en-emodeng'),
24
+ Title.new(type: TitleType::SUBTITLE, value: 'And a Contest between Two Artists about Optick Glasses, &c', language: 'en-emodeng')
25
+ ]
26
+ @publisher = 'California Digital Library'
27
+ @pub_year = 2015
28
+ end
29
+
30
+ # TODO: double-check all required/optional attributes
31
+
32
+ it 'correctly differentiates required and optional attributes'
33
+
34
+ # Required:
35
+ #
36
+ # <xs:element name="resource">
37
+ # <xs:element name="identifier">
38
+ # <xs:element name="creators">
39
+ # <xs:element name="creator" maxOccurs="unbounded">
40
+ # <xs:element name="creatorName">
41
+ # <xs:element name="titles">
42
+ # <xs:element name="title" maxOccurs="unbounded">
43
+ # <xs:element name="publisher">
44
+ # <xs:element name="publicationYear">
45
+ # <xs:element name="contributorName">
46
+
47
+ # Optional:
48
+ #
49
+ # <xs:element name="nameIdentifier" minOccurs="0">
50
+ # <xs:element name="affiliation" minOccurs="0" maxOccurs="unbounded"/>
51
+ # <xs:element name="subjects" minOccurs="0">
52
+ # <xs:element name="subject" minOccurs="0" maxOccurs="unbounded">
53
+ # <xs:element name="contributors" minOccurs="0">
54
+ # <xs:element name="contributor" minOccurs="0" maxOccurs="unbounded">
55
+ # <xs:element name="nameIdentifier" minOccurs="0">
56
+ # <xs:element name="affiliation" minOccurs="0" maxOccurs="unbounded"/>
57
+ # <xs:element name="dates" minOccurs="0">
58
+ # <xs:element name="date" minOccurs="0" maxOccurs="unbounded">
59
+ # <xs:element name="language" type="xs:language" minOccurs="0">
60
+ # <xs:element name="resourceType" minOccurs="0">
61
+ # <xs:element name="alternateIdentifiers" minOccurs="0">
62
+ # <xs:element name="alternateIdentifier" minOccurs="0" maxOccurs="unbounded">
63
+ # <xs:element name="relatedIdentifiers" minOccurs="0">
64
+ # <xs:element name="relatedIdentifier" minOccurs="0" maxOccurs="unbounded">
65
+ # <xs:element name="sizes" minOccurs="0">
66
+ # <xs:element name="size" type="xs:string" minOccurs="0" maxOccurs="unbounded">
67
+ # <xs:element name="formats" minOccurs="0">
68
+ # <xs:element name="format" type="xs:string" minOccurs="0" maxOccurs="unbounded">
69
+ # <xs:element name="version" type="xs:string" minOccurs="0">
70
+ # <xs:element name="rightsList" minOccurs="0">
71
+ # <xs:element name="rights" minOccurs="0" maxOccurs="unbounded">
72
+ # <xs:element name="descriptions" minOccurs="0">
73
+ # <xs:element name="description" minOccurs="0" maxOccurs="unbounded">
74
+ # <xs:element name="br" minOccurs="0" maxOccurs="unbounded">
75
+ # <xs:element name="geoLocations" minOccurs="0">
76
+ # <xs:element name="geoLocation" minOccurs="0" maxOccurs="unbounded">
77
+ # <xs:element name="geoLocationPoint" type="point" minOccurs="0"/>
78
+ # <xs:element name="geoLocationBox" type="box" minOccurs="0"/>
79
+ # <xs:element name="geoLocationPlace" minOccurs="0"/>
80
+
81
+ describe '#initialize' do
82
+ it 'sets the identifier' do
83
+ resource = Resource.new(
84
+ identifier: @id,
85
+ creators: @creators,
86
+ titles: @titles,
87
+ publisher: @publisher,
88
+ publication_year: @pub_year
89
+ )
90
+ expect(resource.identifier).to eq(@id)
91
+ expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
92
+ end
93
+
94
+ it 'sets the creators' do
95
+ resource = Resource.new(
96
+ identifier: @id,
97
+ creators: @creators,
98
+ titles: @titles,
99
+ publisher: @publisher,
100
+ publication_year: @pub_year
101
+ )
102
+ expect(resource.creators).to eq(@creators)
103
+ expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
104
+ end
105
+
106
+ it 'sets the titles' do
107
+ resource = Resource.new(
108
+ identifier: @id,
109
+ creators: @creators,
110
+ titles: @titles,
111
+ publisher: @publisher,
112
+ publication_year: @pub_year
113
+ )
114
+ expect(resource.titles).to eq(@titles)
115
+ expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
116
+ end
117
+
118
+ it 'sets the publisher' do
119
+ resource = Resource.new(
120
+ identifier: @id,
121
+ creators: @creators,
122
+ titles: @titles,
123
+ publisher: @publisher,
124
+ publication_year: @pub_year
125
+ )
126
+ expect(resource.publisher).to eq(@publisher)
127
+ expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
128
+ end
129
+
130
+ it 'sets the publicationYear' do
131
+ resource = Resource.new(
132
+ identifier: @id,
133
+ creators: @creators,
134
+ titles: @titles,
135
+ publisher: @publisher,
136
+ publication_year: @pub_year
137
+ )
138
+ expect(resource.publication_year).to eq(@pub_year)
139
+ expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
140
+ end
141
+
142
+ it 'requires an identifier' do
143
+ expect do
144
+ Resource.new(
145
+ creators: @creators,
146
+ titles: @titles,
147
+ publisher: @publisher,
148
+ publication_year: @pub_year
149
+ )
150
+ end.to raise_error(ArgumentError)
151
+ expect do
152
+ Resource.new(
153
+ creators: @creators,
154
+ titles: @titles,
155
+ publisher: @publisher,
156
+ publication_year: @pub_year,
157
+ identifier: nil
158
+ )
159
+ end.to raise_error(ArgumentError)
160
+ end
161
+
162
+ it 'requires creators' do
163
+ expect do
164
+ Resource.new(
165
+ identifier: @id,
166
+ titles: @titles,
167
+ publisher: @publisher,
168
+ publication_year: @pub_year
169
+ )
170
+ end.to raise_error(ArgumentError)
171
+ expect do
172
+ Resource.new(
173
+ identifier: @id,
174
+ titles: @titles,
175
+ publisher: @publisher,
176
+ publication_year: @pub_year,
177
+ creators: []
178
+ )
179
+ end.to raise_error(ArgumentError)
180
+ expect do
181
+ Resource.new(
182
+ identifier: @id,
183
+ titles: @titles,
184
+ publisher: @publisher,
185
+ publication_year: @pub_year,
186
+ creators: nil
187
+ )
188
+ end.to raise_error(ArgumentError)
189
+ end
190
+
191
+ it 'requires titles' do
192
+ expect do
193
+ Resource.new(
194
+ identifier: @id,
195
+ creators: @creators,
196
+ publisher: @publisher,
197
+ publication_year: @pub_year
198
+ )
199
+ end.to raise_error(ArgumentError)
200
+ expect do
201
+ Resource.new(
202
+ identifier: @id,
203
+ creators: @creators,
204
+ publisher: @publisher,
205
+ publication_year: @pub_year,
206
+ titles: nil
207
+ )
208
+ end.to raise_error(ArgumentError)
209
+ expect do
210
+ Resource.new(
211
+ identifier: @id,
212
+ creators: @creators,
213
+ publisher: @publisher,
214
+ publication_year: @pub_year,
215
+ titles: []
216
+ )
217
+ end.to raise_error(ArgumentError)
218
+ end
219
+
220
+ it 'requires a publisher' do
221
+ expect do
222
+ Resource.new(
223
+ identifier: @id,
224
+ creators: @creators,
225
+ titles: @titles,
226
+ publication_year: @pub_year
227
+ )
228
+ end.to raise_error(ArgumentError)
229
+ expect do
230
+ Resource.new(
231
+ identifier: @id,
232
+ creators: @creators,
233
+ titles: @titles,
234
+ publication_year: @pub_year,
235
+ publisher: nil
236
+ )
237
+ end.to raise_error(ArgumentError)
238
+ expect do
239
+ Resource.new(
240
+ identifier: @id,
241
+ creators: @creators,
242
+ titles: @titles,
243
+ publication_year: @pub_year,
244
+ publisher: []
245
+ )
246
+ end.to raise_error(ArgumentError)
247
+ expect do
248
+ Resource.new(
249
+ identifier: @id,
250
+ creators: @creators,
251
+ titles: @titles,
252
+ publication_year: @pub_year,
253
+ publisher: ''
254
+ )
255
+ end.to raise_error(ArgumentError)
256
+ end
257
+
258
+ it 'requires a publicationYear' do
259
+ expect do
260
+ Resource.new(
261
+ identifier: @id,
262
+ creators: @creators,
263
+ titles: @titles,
264
+ publisher: @publisher
265
+ )
266
+ end.to raise_error(ArgumentError)
267
+ expect do
268
+ Resource.new(
269
+ identifier: @id,
270
+ creators: @creators,
271
+ titles: @titles,
272
+ publisher: @publisher,
273
+ publication_year: nil
274
+ )
275
+ end.to raise_error(ArgumentError)
276
+ expect do
277
+ Resource.new(
278
+ identifier: @id,
279
+ creators: @creators,
280
+ titles: @titles,
281
+ publisher: @publisher,
282
+ publication_year: -1
283
+ )
284
+ end.to raise_error(ArgumentError)
285
+ expect do
286
+ Resource.new(
287
+ identifier: @id,
288
+ creators: @creators,
289
+ titles: @titles,
290
+ publisher: @publisher,
291
+ publication_year: 999
292
+ )
293
+ end.to raise_error(ArgumentError)
294
+ expect do
295
+ Resource.new(
296
+ identifier: @id,
297
+ creators: @creators,
298
+ titles: @titles,
299
+ publisher: @publisher,
300
+ publication_year: 10_000
301
+ )
302
+ end.to raise_error(ArgumentError)
303
+ end
304
+
305
+ it 'allows subjects' do
306
+ subjects = [
307
+ Subject.new(
308
+ language: 'en-us',
309
+ scheme: 'LCSH',
310
+ scheme_uri: URI('http://id.loc.gov/authorities/subjects'),
311
+ value: 'Mammals--Embryology'
312
+ ),
313
+ Subject.new(
314
+ language: 'fr',
315
+ scheme: 'dewey',
316
+ scheme_uri: URI('http://dewey.info/'),
317
+ value: '571.8 Croissance, développement, reproduction biologique (fécondation, sexualité)'
318
+ )
319
+ ]
320
+ resource = Resource.new(
321
+ identifier: @id,
322
+ creators: @creators,
323
+ titles: @titles,
324
+ publisher: @publisher,
325
+ publication_year: @pub_year,
326
+ subjects: subjects
327
+ )
328
+ expect(resource.subjects).to eq(subjects)
329
+ expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
330
+ end
331
+
332
+ it 'allows dates' do
333
+ dates = [
334
+ Date.new(value: DateTime.new(1914, 8, 4, 11, 01, 6.0123, '+1'), type: DateType::AVAILABLE),
335
+ Date.new(value: '1914-08-04T11:01:06.0123+01:00', type: DateType::AVAILABLE)
336
+ ]
337
+ resource = Resource.new(
338
+ identifier: @id,
339
+ creators: @creators,
340
+ titles: @titles,
341
+ publisher: @publisher,
342
+ publication_year: @pub_year,
343
+ dates: dates
344
+ )
345
+ expect(resource.dates).to eq(dates)
346
+ expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
347
+ end
348
+
349
+ it 'allows a language' do
350
+ resource = Resource.new(
351
+ identifier: @id,
352
+ creators: @creators,
353
+ titles: @titles,
354
+ publisher: @publisher,
355
+ publication_year: @pub_year,
356
+ language: 'en-emodeng'
357
+ )
358
+ expect(resource.language).to eq('en-emodeng')
359
+ expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
360
+ end
361
+
362
+ it 'allows alternate identifiers' do
363
+ alternate_identifiers = [
364
+ AlternateIdentifier.new(type: 'URL', value: 'http://example.org'),
365
+ AlternateIdentifier.new(type: 'URL', value: 'http://example.com')
366
+ ]
367
+ resource = Resource.new(
368
+ identifier: @id,
369
+ creators: @creators,
370
+ titles: @titles,
371
+ publisher: @publisher,
372
+ publication_year: @pub_year,
373
+ alternate_identifiers: alternate_identifiers
374
+ )
375
+ expect(resource.alternate_identifiers).to eq(alternate_identifiers)
376
+ expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
377
+ end
378
+
379
+ it 'allows sizes' do
380
+ sizes = ['2 petabytes', '2048 TB']
381
+ resource = Resource.new(
382
+ identifier: @id,
383
+ creators: @creators,
384
+ titles: @titles,
385
+ publisher: @publisher,
386
+ publication_year: @pub_year,
387
+ sizes: sizes
388
+ )
389
+ expect(resource.sizes).to eq(sizes)
390
+ expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
391
+ end
392
+
393
+ it 'allows related identifiers' do
394
+ related_identifiers = [
395
+ RelatedIdentifier.new(
396
+ identifier_type: RelatedIdentifierType::URL,
397
+ relation_type: RelationType::HAS_METADATA,
398
+ related_metadata_scheme: 'citeproc+json',
399
+ scheme_type: 'Turtle',
400
+ scheme_uri: URI('https://github.com/citation-style-language/schema/raw/master/csl-data.json'),
401
+ value: 'http://data.datacite.org/application/citeproc+json/10.5072/example-full'
402
+ ),
403
+ RelatedIdentifier.new(
404
+ identifier_type: RelatedIdentifierType::ARXIV,
405
+ relation_type: RelationType::IS_REVIEWED_BY,
406
+ value: 'arXiv:0706.0001'
407
+ )
408
+ ]
409
+ resource = Resource.new(
410
+ identifier: @id,
411
+ creators: @creators,
412
+ titles: @titles,
413
+ publisher: @publisher,
414
+ publication_year: @pub_year,
415
+ related_identifiers: related_identifiers
416
+ )
417
+ expect(resource.related_identifiers).to eq(related_identifiers)
418
+ expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
419
+ end
420
+
421
+ it 'allows formats' do
422
+ formats = %w(application/xml text/html)
423
+ resource = Resource.new(
424
+ identifier: @id,
425
+ creators: @creators,
426
+ titles: @titles,
427
+ publisher: @publisher,
428
+ publication_year: @pub_year,
429
+ formats: formats
430
+ )
431
+ expect(resource.formats).to eq(formats)
432
+ expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
433
+ end
434
+
435
+ it 'allows a version' do
436
+ version = '3.1'
437
+ resource = Resource.new(
438
+ identifier: @id,
439
+ creators: @creators,
440
+ titles: @titles,
441
+ publisher: @publisher,
442
+ publication_year: @pub_year,
443
+ version: version
444
+ )
445
+ expect(resource.version).to eq(version)
446
+ expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
447
+ end
448
+
449
+ it 'allows rights' do
450
+ rights_list = [
451
+ Rights.new(value: 'CC0 1.0 Universal', uri: URI('http://creativecommons.org/publicdomain/zero/1.0/')),
452
+ Rights.new(value: 'This work is free of known copyright restrictions.', uri: URI('http://creativecommons.org/publicdomain/mark/1.0/'))
453
+ ]
454
+ resource = Resource.new(
455
+ identifier: @id,
456
+ creators: @creators,
457
+ titles: @titles,
458
+ publisher: @publisher,
459
+ publication_year: @pub_year,
460
+ rights_list: rights_list
461
+ )
462
+ expect(resource.rights_list).to eq(rights_list)
463
+ expect(resource.save_to_xml).to be_a(REXML::Element) # sanity check
464
+ end
465
+ end
466
+
467
+ describe '#save_to_xml' do
468
+ it 'sets the namespace to http://datacite.org/schema/kernel-3'
469
+ it "doesn't clobber the namespace on the various xml:lang attributes"
470
+ end
471
+
472
+ describe 'identifier' do
473
+ it 'returns the identifier'
474
+ end
475
+
476
+ describe 'identifier=' do
477
+ it 'sets the identifier'
478
+ it 'rejects nil'
479
+ end
480
+
481
+ describe 'creators' do
482
+ it 'returns the creator list'
483
+ it 'returns an editable list'
484
+ end
485
+
486
+ describe 'creators=' do
487
+ it 'overwrites the creator list'
488
+ it 'requires at least one creator'
489
+ end
490
+
491
+ describe 'titles' do
492
+ it 'returns the title list'
493
+ it 'returns an editable list'
494
+ end
495
+
496
+ describe 'titles=' do
497
+ it 'overwrites the title list'
498
+ it 'requires at least one title'
499
+ end
500
+
501
+ describe 'publisher' do
502
+ it 'returns the publisher'
503
+ end
504
+
505
+ describe 'publisher=' do
506
+ it 'sets the publisher'
507
+ it 'rejects nil'
508
+ it 'rejects the empty string'
509
+ end
510
+
511
+ describe 'publication_year' do
512
+ it 'returns the publication year'
513
+ it 'rejects nil'
514
+ it 'accepts only 4-digit integers'
515
+ end
516
+
517
+ describe 'publication_year=' do
518
+ it 'sets the publication year'
519
+ end
520
+
521
+ describe 'subjects' do
522
+ it 'returns the subject list'
523
+ it 'returns an editable list'
524
+ end
525
+
526
+ describe 'subjects=' do
527
+ it 'overwrites the subject list'
528
+ it 'accepts an empty list'
529
+ end
530
+
531
+ describe 'dates' do
532
+ it 'returns the date list'
533
+ it 'returns an editable list'
534
+ end
535
+
536
+ describe 'dates=' do
537
+ it 'overwrites the date list'
538
+ it 'accepts an empty list'
539
+ end
540
+
541
+ describe 'language' do
542
+ it 'returns the language'
543
+ end
544
+
545
+ describe 'language=' do
546
+ it 'sets the languge'
547
+ it 'requires a language'
548
+ end
549
+
550
+ describe 'resource_type' do
551
+ it 'returns the resource type'
552
+ end
553
+
554
+ describe 'resource_type=' do
555
+ it 'sets the resource type'
556
+ it 'requires a resource type'
557
+ end
558
+
559
+ describe 'alternate_identifiers' do
560
+ it 'returns the alternate identifier list'
561
+ it 'returns an editable list'
562
+ end
563
+
564
+ describe 'alternate_identifiers=' do
565
+ it 'overwrites the alternate identifier list'
566
+ it 'accepts an empty list'
567
+ end
568
+
569
+ describe 'related_identifiers' do
570
+ it 'returns the related identifier list'
571
+ it 'returns an editable list'
572
+ end
573
+
574
+ describe 'related_identifiers=' do
575
+ it 'overwrites the related identifier list'
576
+ it 'accepts an empty list'
577
+ end
578
+
579
+ describe 'sizes' do
580
+ it 'returns the size list'
581
+ it 'returns an editable list'
582
+ end
583
+
584
+ describe 'sizes=' do
585
+ it 'overwrites the size list'
586
+ it 'accepts an empty list'
587
+ end
588
+
589
+ describe 'formats' do
590
+ it 'returns the size list'
591
+ it 'returns an editable list'
592
+ end
593
+
594
+ describe 'formats=' do
595
+ it 'overwrites the size list'
596
+ it 'accepts an empty list'
597
+ end
598
+
599
+ describe 'version' do
600
+ it 'returns the version'
601
+ end
602
+
603
+ describe 'version=' do
604
+ it 'sets the languge'
605
+ it 'accepts nil'
606
+ end
607
+
608
+ describe 'rights' do
609
+ it 'returns the rights list'
610
+ it 'returns an editable list'
611
+ end
612
+
613
+ describe 'rights=' do
614
+ it 'overwrites the rights list'
615
+ it 'accepts an empty list'
616
+ end
617
+
618
+ describe 'descriptions' do
619
+ it 'returns the description list'
620
+ it 'returns an editable list'
621
+ end
622
+
623
+ describe 'descriptions=' do
624
+ it 'overwrites the description list'
625
+ it 'accepts an empty list'
626
+ end
627
+
628
+ describe 'geo_locations' do
629
+ it 'returns the geolocation list'
630
+ it 'returns an editable list'
631
+ end
632
+
633
+ describe 'geo_locations=' do
634
+ it 'overwrites the geolocation list'
635
+ it 'accepts an empty list'
636
+ end
637
+
638
+ describe 'XML mapping' do
639
+
640
+ describe '#save_to_xml' do
641
+ it 'writes XML' do
642
+ resource = Resource.new(
643
+ identifier: Identifier.new(value: '10.5072/D3P26Q35R-Test'),
644
+ creators: [
645
+ Creator.new(name: 'Fosmire, Michael'),
646
+ Creator.new(name: 'Wertz, Ruth'),
647
+ Creator.new(name: 'Purzer, Senay')
648
+ ],
649
+ titles: [
650
+ Title.new(value: 'Critical Engineering Literacy Test (CELT)')
651
+ ],
652
+ publisher: 'Purdue University Research Repository (PURR)',
653
+ publication_year: 2013,
654
+ subjects: [
655
+ Subject.new(value: 'Assessment'),
656
+ Subject.new(value: 'Information Literacy'),
657
+ Subject.new(value: 'Engineering'),
658
+ Subject.new(value: 'Undergraduate Students'),
659
+ Subject.new(value: 'CELT'),
660
+ Subject.new(value: 'Purdue University')
661
+ ],
662
+ language: 'en',
663
+ resource_type: ResourceType.new(resource_type_general: ResourceTypeGeneral::DATASET, value: 'Dataset'),
664
+ version: '1',
665
+ descriptions: [
666
+ Description.new(
667
+ type: DescriptionType::ABSTRACT,
668
+ value: 'We developed an instrument, Critical Engineering Literacy Test (CELT), which is a multiple choice instrument
669
+ designed to measure undergraduate students’ scientific and information literacy skills. It requires students to
670
+ first read a technical memo and, based on the memo’s arguments, answer eight multiple choice and six open-ended
671
+ response questions. We collected data from 143 first-year engineering students and conducted an item analysis. The
672
+ KR-20 reliability of the instrument was .39. Item difficulties ranged between .17 to .83. The results indicate low
673
+ reliability index but acceptable levels of item difficulties and item discrimination indices. Students were most
674
+ challenged when answering items measuring scientific and mathematical literacy (i.e., identifying incorrect
675
+ information).'
676
+ )
677
+ ]
678
+ )
679
+
680
+ expected_xml = '<resource xsi:schemaLocation="http://datacite.org/schema/kernel-3 http://schema.datacite.org/meta/kernel-3/metadata.xsd" xmlns="http://datacite.org/schema/kernel-3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
681
+ <identifier identifierType="DOI">10.5072/D3P26Q35R-Test</identifier>
682
+ <creators>
683
+ <creator>
684
+ <creatorName>Fosmire, Michael</creatorName>
685
+ </creator>
686
+ <creator>
687
+ <creatorName>Wertz, Ruth</creatorName>
688
+ </creator>
689
+ <creator>
690
+ <creatorName>Purzer, Senay</creatorName>
691
+ </creator>
692
+ </creators>
693
+ <titles>
694
+ <title xml:lang="en">Critical Engineering Literacy Test (CELT)</title>
695
+ </titles>
696
+ <publisher>Purdue University Research Repository (PURR)</publisher>
697
+ <publicationYear>2013</publicationYear>
698
+ <subjects>
699
+ <subject xml:lang="en">Assessment</subject>
700
+ <subject xml:lang="en">Information Literacy</subject>
701
+ <subject xml:lang="en">Engineering</subject>
702
+ <subject xml:lang="en">Undergraduate Students</subject>
703
+ <subject xml:lang="en">CELT</subject>
704
+ <subject xml:lang="en">Purdue University</subject>
705
+ </subjects>
706
+ <language>en</language>
707
+ <resourceType resourceTypeGeneral="Dataset">Dataset</resourceType>
708
+ <version>1</version>
709
+ <descriptions>
710
+ <description descriptionType="Abstract" xml:lang="en">We developed an instrument, Critical Engineering Literacy Test (CELT), which is a multiple choice instrument designed to measure undergraduate students’ scientific and information literacy skills. It requires students to first read a technical memo and, based on the memo’s arguments, answer eight multiple choice and six open-ended response questions. We collected data from 143 first-year engineering students and conducted an item analysis. The KR-20 reliability of the instrument was .39. Item difficulties ranged between .17 to .83. The results indicate low reliability index but acceptable levels of item difficulties and item discrimination indices. Students were most challenged when answering items measuring scientific and mathematical literacy (i.e., identifying incorrect information).</description>
711
+ </descriptions>
712
+ </resource>'
713
+
714
+ expect(resource.save_to_xml).to be_xml(expected_xml)
715
+ end
716
+ end
717
+
718
+ it 'round-trips' do
719
+ xml_text = File.read('spec/data/resource.xml')
720
+ xml = REXML::Document.new(xml_text).root
721
+ resource = Resource.load_from_xml(xml)
722
+ expect(resource.save_to_xml).to be_xml(xml_text)
723
+ end
724
+ end
725
+ end
726
+ end
727
+ end