opinionated-xml 0.0.1 → 0.1.0

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.
@@ -0,0 +1,60 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require "nokogiri"
3
+ require "om"
4
+
5
+ describe "OM::XML::Container" do
6
+
7
+ before(:all) do
8
+ class ContainerTest
9
+ include OM::XML::Container
10
+ end
11
+ end
12
+
13
+ before(:each) do
14
+ @container = ContainerTest.from_xml("<foo><bar>1</bar></foo>")
15
+ end
16
+
17
+ it "should automatically include the other modules" do
18
+ pending
19
+ ContainerTest.included_modules.should include(OM::XML::Accessor)
20
+ ContainerTest.included_modules.should include(OM::XML::Schema)
21
+ end
22
+
23
+ it "should add .ng_xml accessor" do
24
+ @container.should respond_to(:ng_xml)
25
+ @container.should respond_to(:ng_xml=)
26
+ end
27
+
28
+ describe "new" do
29
+ it "should populate ng_xml with an instance of Nokogiri::XML::Document" do
30
+ @container.ng_xml.class.should == Nokogiri::XML::Document
31
+ end
32
+ end
33
+
34
+ describe "#from_xml" do
35
+ it "should accept a String, parse it and store it in .ng_xml" do
36
+ Nokogiri::XML::Document.expects(:parse).returns("parsed xml")
37
+ container1 = ContainerTest.from_xml("<foo><bar>1</bar></foo>")
38
+ container1.ng_xml.should == "parsed xml"
39
+ end
40
+ it "should accept a File, parse it and store it in .ng_xml" do
41
+ file = fixture(File.join("mods_articles", "hydrangea_article1.xml"))
42
+ Nokogiri::XML::Document.expects(:parse).returns("parsed xml")
43
+ container1 = ContainerTest.from_xml(file)
44
+ container1.ng_xml.should == "parsed xml"
45
+ end
46
+ it "should accept Nokogiri nodes as input and leave them as-is" do
47
+ parsed_xml = Nokogiri::XML::Document.parse("<foo><bar>1</bar></foo>")
48
+ container1 = ContainerTest.from_xml(parsed_xml)
49
+ container1.ng_xml.should == parsed_xml
50
+ end
51
+ end
52
+
53
+ describe ".to_xml" do
54
+ it "should call .ng_xml.to_xml" do
55
+ @container.ng_xml.expects(:to_xml).returns("ng xml")
56
+ @container.to_xml.should == "ng xml"
57
+ end
58
+ end
59
+
60
+ end
@@ -1,12 +1,14 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require "om"
2
3
 
3
- describe "OpinionatedXml" do
4
+ describe "OM::XML::Properties" do
4
5
 
5
6
  before(:all) do
6
7
  #ModsHelpers.name_("Beethoven, Ludwig van", :date=>"1770-1827", :role=>"creator")
7
- class FakeOxMods < Nokogiri::XML::Document
8
-
9
- include OX
8
+ class FakeOxMods
9
+
10
+ include OM::XML::Container
11
+ include OM::XML::Properties
10
12
 
11
13
  # Could add support for multiple root declarations.
12
14
  # For now, assume that any modsCollections have already been broken up and fed in as individual mods documents
@@ -40,8 +42,8 @@ describe "OpinionatedXml" do
40
42
 
41
43
  class FakeOtherOx < Nokogiri::XML::Document
42
44
 
43
- include OX
44
- extend OX::ClassMethods
45
+ include OM::XML::Properties
46
+ # extend OX::ClassMethods
45
47
 
46
48
  root_property :other, "other", "http://www.foo.com"
47
49
 
@@ -50,7 +52,7 @@ describe "OpinionatedXml" do
50
52
  end
51
53
 
52
54
  before(:each) do
53
- @fixturemods = FakeOxMods.parse( fixture( File.join("CBF_MODS", "ARS0025_016.xml") ) )
55
+ @fixturemods = FakeOxMods.from_xml( fixture( File.join("CBF_MODS", "ARS0025_016.xml") ) )
54
56
  end
55
57
 
56
58
  after(:all) do
@@ -68,7 +70,6 @@ describe "OpinionatedXml" do
68
70
  FakeOxMods.root_property_ref.should == :mods
69
71
  FakeOxMods.root_config.should == {:ref=>:mods, :path=>"mods", :namespace=>"http://www.loc.gov/mods/v3", :attributes=>["id", "version"], :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd"}
70
72
  FakeOxMods.ox_namespaces.should == {"oxns"=>"http://www.loc.gov/mods/v3"}
71
- FakeOxMods.schema_url.should == "http://www.loc.gov/standards/mods/v3/mods-3-2.xsd"
72
73
 
73
74
  FakeOtherOx.root_property_ref.should == :other
74
75
  FakeOtherOx.root_config.should == {:namespace=>"http://www.foo.com", :path=>"other", :ref=>:other}
@@ -135,16 +136,16 @@ describe "OpinionatedXml" do
135
136
  describe ".lookup" do
136
137
 
137
138
  it "uses the generated xpath queries" do
138
- @fixturemods.expects(:xpath).with('//oxns:name[@type="personal"]', @fixturemods.ox_namespaces)
139
+ @fixturemods.ng_xml.expects(:xpath).with('//oxns:name[@type="personal"]', @fixturemods.ox_namespaces)
139
140
  @fixturemods.lookup(:person)
140
141
 
141
- @fixturemods.expects(:xpath).with('//oxns:name[@type="personal" and contains(oxns:namePart, "Beethoven, Ludwig van")]', @fixturemods.ox_namespaces)
142
+ @fixturemods.ng_xml.expects(:xpath).with('//oxns:name[@type="personal" and contains(oxns:namePart, "Beethoven, Ludwig van")]', @fixturemods.ox_namespaces)
142
143
  @fixturemods.lookup(:person, "Beethoven, Ludwig van")
143
144
 
144
- @fixturemods.expects(:xpath).with('//oxns:name[@type="personal" and contains(oxns:namePart[@type="date"], "2010")]', @fixturemods.ox_namespaces)
145
+ @fixturemods.ng_xml.expects(:xpath).with('//oxns:name[@type="personal" and contains(oxns:namePart[@type="date"], "2010")]', @fixturemods.ox_namespaces)
145
146
  @fixturemods.lookup(:person, :date=>"2010")
146
147
 
147
- @fixturemods.expects(:xpath).with('//oxns:name[@type="personal" and contains(oxns:role/oxns:roleTerm, "donor")]', @fixturemods.ox_namespaces)
148
+ @fixturemods.ng_xml.expects(:xpath).with('//oxns:name[@type="personal" and contains(oxns:role/oxns:roleTerm, "donor")]', @fixturemods.ox_namespaces)
148
149
  @fixturemods.lookup(:person, :role=>"donor")
149
150
 
150
151
  # @fixturemods.expects(:xpath).with('//oxns:name[@type="personal"]/oxns:namePart[@type="date"]', @fixturemods.ox_namespaces)
@@ -242,59 +243,5 @@ describe "OpinionatedXml" do
242
243
  FakeOxMods.send(:applicable_attributes, ["authority", {:type=>["text","code"]}] ).should == {:type=>"text"}
243
244
  end
244
245
  end
245
-
246
- ## Validation Support
247
- # Some of these tests fail when you don't have an internet connection because the mods schema includes other xsd schemas by URL reference.
248
-
249
- describe "#schema" do
250
- it "should return an instance of Nokogiri::XML::Schema loaded from the schema url -- fails if no internet connection" do
251
- FakeOxMods.schema.should be_kind_of Nokogiri::XML::Schema
252
- end
253
- end
254
-
255
- describe "#validate" do
256
- it "should validate the provided document against the schema provided in class definition -- fails if no internet connection" do
257
- FakeOxMods.schema.expects(:validate).with(@fixturemods).returns([])
258
- FakeOxMods.validate(@fixturemods)
259
- end
260
- end
261
-
262
- describe ".validate" do
263
- it "should rely on class validate method" do
264
- FakeOxMods.expects(:validate).with(@fixturemods)
265
- @fixturemods.validate
266
- end
267
- end
268
-
269
- describe "#schema_file" do
270
- before(:all) do
271
- FakeOxMods.schema_file = nil
272
- end
273
-
274
- after(:all) do
275
- FakeOxMods.schema_file = fixture("mods-3-2.xsd")
276
- end
277
-
278
- it "should lazy load the schema file from the @schema_url" do
279
- FakeOxMods.instance_variable_get(:@schema_file).should be_nil
280
- FakeOxMods.expects(:file_from_url).with(FakeOxMods.schema_url).returns("fake file").once
281
- FakeOxMods.schema_file
282
- FakeOxMods.instance_variable_get(:@schema_file).should == "fake file"
283
- FakeOxMods.schema_file.should == "fake file"
284
- end
285
- end
286
-
287
- describe "#file_from_url" do
288
- it "should retrieve a file from the provided url over HTTP" do
289
- FakeOxMods.send(:file_from_url, "http://google.com")
290
- end
291
- it "should raise an error if the url is invalid" do
292
- lambda {FakeOxMods.send(:file_from_url, "")}.should raise_error(RuntimeError, "Could not retrieve file from . Error: No such file or directory - ")
293
- lambda {FakeOxMods.send(:file_from_url, "foo")}.should raise_error(RuntimeError, "Could not retrieve file from foo. Error: No such file or directory - foo")
294
- end
295
- it "should raise an error if file retrieval fails" do
296
- lambda {FakeOxMods.send(:file_from_url, "http://fedora-commons.org/nonexistent_file")}.should raise_error(RuntimeError, "Could not retrieve file from http://fedora-commons.org/nonexistent_file. Error: 404 Not Found")
297
- end
298
- end
299
246
 
300
247
  end
@@ -0,0 +1,245 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require "om"
3
+
4
+ describe "OM::XML::PropertyValueOperators" do
5
+
6
+ before(:all) do
7
+ #ModsHelpers.name_("Beethoven, Ludwig van", :date=>"1770-1827", :role=>"creator")
8
+ class PropertiesValueOperatorsTest
9
+
10
+ include OM::XML::Container
11
+ include OM::XML::Properties
12
+ include OM::XML::PropertyValueOperators
13
+
14
+ # Could add support for multiple root declarations.
15
+ # For now, assume that any modsCollections have already been broken up and fed in as individual mods documents
16
+ # root :mods_collection, :path=>"modsCollection",
17
+ # :attributes=>[],
18
+ # :subelements => :mods
19
+
20
+ 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"
21
+
22
+
23
+ property :name_, :path=>"name",
24
+ :attributes=>[:xlink, :lang, "xml:lang", :script, :transliteration, {:type=>["personal", "enumerated", "corporate"]} ],
25
+ :subelements=>["namePart", "displayForm", "affiliation", :role, "description"],
26
+ :default_content_path => "namePart",
27
+ :convenience_methods => {
28
+ :date => {:path=>"namePart", :attributes=>{:type=>"date"}},
29
+ :family_name => {:path=>"namePart", :attributes=>{:type=>"family"}},
30
+ :given_name => {:path=>"namePart", :attributes=>{:type=>"given"}},
31
+ :terms_of_address => {:path=>"namePart", :attributes=>{:type=>"termsOfAddress"}}
32
+ }
33
+
34
+ property :person, :variant_of=>:name_, :attributes=>{:type=>"personal"}
35
+
36
+ property :role, :path=>"role",
37
+ :parents=>[:name_],
38
+ :attributes=>[ { "type"=>["text", "code"] } , "authority"],
39
+ :default_content_path => "roleTerm"
40
+
41
+
42
+ end
43
+
44
+ end
45
+
46
+ before(:each) do
47
+ @sample = PropertiesValueOperatorsTest.from_xml( fixture( File.join("test_dummy_mods.xml") ) )
48
+ end
49
+
50
+ after(:all) do
51
+ Object.send(:remove_const, :PropertiesValueOperatorsTest)
52
+ end
53
+
54
+ describe ".property_values" do
55
+
56
+ it "should call .lookup and then build an array of values from the returned nodeset (using default_node, etc as nessesary)" do
57
+ lookup_opts = "insert args here"
58
+ mock_node = mock("node")
59
+ mock_node.expects(:text).returns("sample value").times(3)
60
+ mock_nodeset = [mock_node, mock_node, mock_node]
61
+ @sample.expects(:lookup).with(lookup_opts).returns(mock_nodeset)
62
+
63
+ @sample.property_values(lookup_opts).should == ["sample value","sample value","sample value"]
64
+ end
65
+
66
+ end
67
+
68
+ describe ".property_values_append" do
69
+
70
+ it "looks up the parent using :parent_select, uses :child_index to choose the parent node from the result set, uses :template to build the node(s) to be inserted, inserts the :values(s) into the node(s) and adds the node(s) to the parent" do
71
+ @sample.property_values_append(
72
+ :parent_select => [:person, {:given_name=>"Tim", :family_name=>"Berners-Lee"}] ,
73
+ :child_index => :first,
74
+ :template => [:person, :affiliation],
75
+ :values => ["my new value", "another new value"]
76
+ )
77
+ end
78
+
79
+ it "should accept parent_select and template [property_reference, lookup_opts] as argument arrays for generators/lookups" do
80
+ # this appends two affiliation nodes into the first person node whose name is Tim Berners-Lee
81
+ expected_result = '<ns3:name type="personal">
82
+ <ns3:namePart type="family">Berners-Lee</ns3:namePart>
83
+ <ns3:namePart type="given">Tim</ns3:namePart>
84
+ <ns3:role>
85
+ <ns3:roleTerm type="text" authority="marcrelator">creator</ns3:roleTerm>
86
+ <ns3:roleTerm type="code" authority="marcrelator">cre</ns3:roleTerm>
87
+ </ns3:role>
88
+ <ns3:affiliation>my new value</ns3:affiliation><ns3:affiliation>another new value</ns3:affiliation></ns3:name>'
89
+
90
+ @sample.property_values_append(
91
+ :parent_select => [:person, {:given_name=>"Tim", :family_name=>"Berners-Lee"}] ,
92
+ :child_index => :first,
93
+ :template => [:person, :affiliation],
94
+ :values => ["my new value", "another new value"]
95
+ ).to_xml.should == expected_result
96
+
97
+ @sample.lookup(:person, {:given_name=>"Tim", :family_name=>"Berners-Lee"}).first.to_xml.should == expected_result
98
+ end
99
+
100
+ it "should accept symbols as arguments for generators/lookups" do
101
+ # this appends a role of "my role" into the third "person" node in the document
102
+ expected_result = "<ns3:name type=\"personal\">\n <ns3:namePart type=\"family\">Klimt</ns3:namePart>\n <ns3:namePart type=\"given\">Gustav</ns3:namePart>\n <ns3:role>\n <ns3:roleTerm type=\"text\" authority=\"marcrelator\">creator</ns3:roleTerm>\n <ns3:roleTerm type=\"code\" authority=\"marcrelator\">cre</ns3:roleTerm>\n </ns3:role>\n <ns3:role>\n <ns3:roleTerm type=\"text\" authority=\"marcrelator\">visionary</ns3:roleTerm>\n <ns3:roleTerm type=\"code\" authority=\"marcrelator\">vry</ns3:roleTerm>\n </ns3:role>\n <ns3:role type=\"text\"><ns3:roleTerm>my role</ns3:roleTerm></ns3:role></ns3:name>"
103
+
104
+ @sample.property_values_append(
105
+ :parent_select => :person ,
106
+ :child_index => 3,
107
+ :template => :role,
108
+ :values => "my role"
109
+ ).to_xml.should == expected_result
110
+
111
+ @sample.lookup(:person)[3].to_xml.should == expected_result
112
+ end
113
+
114
+ it "should accept parent_select as an (xpath) string and template as a (template) string" do
115
+ # this uses the provided template to add a node into the first node resulting from the xpath '//oxns:name[@type="personal"]'
116
+ expected_result = "<ns3:name type=\"personal\">\n <ns3:namePart type=\"family\">Berners-Lee</ns3:namePart>\n <ns3:namePart type=\"given\">Tim</ns3:namePart>\n <ns3:role>\n <ns3:roleTerm type=\"text\" authority=\"marcrelator\">creator</ns3:roleTerm>\n <ns3:roleTerm type=\"code\" authority=\"marcrelator\">cre</ns3:roleTerm>\n </ns3:role>\n <ns3:role type=\"code\" authority=\"marcrelator\"><ns3:roleTerm>creator</ns3:roleTerm></ns3:role></ns3:name>"
117
+
118
+ @sample.ng_xml.xpath('//oxns:name[@type="personal" and position()=1]/oxns:role', @sample.ox_namespaces).length.should == 1
119
+
120
+ @sample.property_values_append(
121
+ :parent_select =>'//oxns:name[@type="personal"]',
122
+ :child_index => 0,
123
+ :template => 'xml.role { xml.roleTerm( \'#{builder_new_value}\', :type=>\'code\', :authority=>\'marcrelator\') }',
124
+ :values => "founder"
125
+ )
126
+
127
+ @sample.ng_xml.xpath('//oxns:name[@type="personal" and position()=1]/oxns:role', @sample.ox_namespaces).length.should == 2
128
+ @sample.ng_xml.xpath('//oxns:name[@type="personal" and position()=1]/oxns:role[last()]/oxns:roleTerm', @sample.ox_namespaces).first.text.should == "founder"
129
+
130
+ # @sample.lookup(:person).first.to_xml.should == expected_result
131
+ end
132
+
133
+ it "should support more complex mixing & matching" do
134
+ expected_result = "<ns3:name type=\"personal\">\n <ns3:namePart type=\"family\">Jobs</ns3:namePart>\n <ns3:namePart type=\"given\">Steve</ns3:namePart>\n <ns3:namePart type=\"date\">2004</ns3:namePart>\n <ns3:role>\n <ns3:roleTerm type=\"text\" authority=\"marcrelator\">creator</ns3:roleTerm>\n <ns3:roleTerm type=\"code\" authority=\"marcrelator\">cre</ns3:roleTerm>\n </ns3:role>\n <ns3:role type=\"code\" authority=\"marcrelator\"><ns3:roleTerm>foo</ns3:roleTerm></ns3:role></ns3:name>"
135
+
136
+ @sample.ng_xml.xpath('//oxns:name[@type="personal" and position()=2]/oxns:role', @sample.ox_namespaces).length.should == 1
137
+
138
+ @sample.property_values_append(
139
+ :parent_select =>'//oxns:name[@type="personal"]',
140
+ :child_index => 1,
141
+ :template => [ :person, :role, {:attributes=>{"type"=>"code", "authority"=>"marcrelator"}} ],
142
+ :values => "foo"
143
+ )
144
+
145
+ @sample.ng_xml.xpath('//oxns:name[@type="personal" and position()=2]/oxns:role', @sample.ox_namespaces).length.should == 2
146
+ @sample.lookup(:person)[1].search("./oxns:role[last()]/oxns:roleTerm", @sample.ox_namespaces).first.text.should == "foo"
147
+ end
148
+
149
+ it "should raise exception if no node corresponds to the provided :parent_select and :child_index"
150
+
151
+ end
152
+
153
+ describe ".property_value_update" do
154
+
155
+ it "should accept an xpath as :parent_select" do
156
+ sample_xpath = '//oxns:name[@type="personal"]/oxns:role/oxns:roleTerm[@type="text"]'
157
+ @sample.property_value_update(
158
+ :parent_select =>sample_xpath,
159
+ :child_index => 1,
160
+ :value => "donor"
161
+ )
162
+ @sample.ng_xml.xpath(sample_xpath, @sample.ox_namespaces)[1].text.should == "donor"
163
+ end
164
+
165
+ it "if :select is provided, should update the first node provided by that xpath statement" do
166
+ sample_xpath = '//oxns:name[@type="personal" and position()=1]/oxns:namePart[@type="given"]'
167
+ @sample.property_value_update(
168
+ :select =>sample_xpath,
169
+ :value => "Timmeh"
170
+ )
171
+ @sample.ng_xml.xpath(sample_xpath, @sample.ox_namespaces).first.text.should == "Timmeh"
172
+ end
173
+
174
+ it "should replace the existing node if you pass a template and values" do
175
+ pending
176
+ @sample.property_value_update(
177
+ :parent_select =>'//oxns:name[@type="personal"]',
178
+ :child_index => 1,
179
+ :template => [ :person, :role, {:attributes=>{"type"=>"code", "authority"=>"marcrelator"}} ],
180
+ :value => "foo"
181
+ )
182
+ 1.should == 2
183
+ end
184
+ end
185
+
186
+ describe ".property_value_delete" do
187
+ it "should accept an xpath query as :select option" do
188
+ generic_xpath = '//oxns:name[@type="personal" and position()=4]/oxns:role'
189
+ specific_xpath = '//oxns:name[@type="personal" and position()=4]/oxns:role[oxns:roleTerm="visionary"]'
190
+ select_xpath = '//oxns:name[@type="personal" and position()=4]/oxns:role[last()]'
191
+
192
+ # Check that we're starting with 2 roles
193
+ # Check that the specific node we want to delete exists
194
+ @sample.lookup(generic_xpath).length.should == 2
195
+ @sample.lookup(specific_xpath).length.should == 1
196
+
197
+ @sample.property_value_delete(
198
+ :select =>select_xpath
199
+ )
200
+ # Check that we're finishing with 1 role
201
+ @sample.lookup(generic_xpath).length.should == 1
202
+ # Check that the specific node we want to delete no longer exists
203
+ @sample.lookup(specific_xpath).length.should == 0
204
+ end
205
+ it "should accept :parent_select, :parent_index and :child_index options instead of a :select" do
206
+
207
+ generic_xpath = '//oxns:name[@type="personal" and position()=4]/oxns:role/oxns:roleTerm'
208
+ specific_xpath = '//oxns:name[@type="personal" and position()=4]/oxns:role[oxns:roleTerm="visionary"]'
209
+
210
+ # Check that we're starting with 2 roles
211
+ # Check that the specific node we want to delete exists
212
+ @sample.lookup(generic_xpath).length.should == 4
213
+ @sample.lookup(specific_xpath).length.should == 1
214
+
215
+ # this is attempting to delete the last child (in this case roleTerm) from the 3rd role in the document.
216
+ @sample.property_value_delete(
217
+ :parent_select => [:person, :role],
218
+ :parent_index => 3,
219
+ :child_index => :last
220
+ )
221
+
222
+ # Check that we're finishing with 1 role
223
+ @sample.lookup(generic_xpath).length.should == 3
224
+ # Check that the specific node we want to delete no longer exists
225
+ @sample.lookup(specific_xpath).length.should == 1
226
+ end
227
+ it "should work if only :parent_select and :child_index are provided" do
228
+ generic_xpath = '//oxns:name[@type="personal"]/oxns:role'
229
+ # specific_xpath = '//oxns:name[@type="personal"]/oxns:role'
230
+
231
+ # Check that we're starting with 2 roles
232
+ # Check that the specific node we want to delete exists
233
+ @sample.lookup(generic_xpath).length.should == 4
234
+ # @sample.lookup(specific_xpath).length.should == 1
235
+
236
+ @sample.property_value_delete(
237
+ :parent_select => [:person, :role],
238
+ :child_index => 3
239
+ )
240
+ # Check that we're finishing with 1 role
241
+ @sample.lookup(generic_xpath).length.should == 3
242
+ end
243
+ end
244
+
245
+ end
@@ -0,0 +1,78 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require "nokogiri"
3
+ require "om"
4
+
5
+ describe "OM::XML::Validation" do
6
+
7
+ before(:all) do
8
+ class ValidationTest
9
+ include OM::XML::Container
10
+ include OM::XML::Validation
11
+ self.schema_url = "http://www.loc.gov/standards/mods/v3/mods-3-2.xsd"
12
+ end
13
+ end
14
+
15
+ before(:each) do
16
+ @sample = ValidationTest.from_xml("<foo><bar>1</bar></foo>")
17
+ end
18
+
19
+ ## Validation Support
20
+ # Some of these tests fail when you don't have an internet connection because the mods schema includes other xsd schemas by URL reference.
21
+
22
+ describe '#schema_url' do
23
+ it "should allow you to set the schema url" do
24
+ ValidationTest.schema_url.should == "http://www.loc.gov/standards/mods/v3/mods-3-2.xsd"
25
+ end
26
+ end
27
+
28
+ describe "#schema" do
29
+ it "should return an instance of Nokogiri::XML::Schema loaded from the schema url -- fails if no internet connection" do
30
+ ValidationTest.schema.should be_kind_of Nokogiri::XML::Schema
31
+ end
32
+ end
33
+
34
+ describe "#validate" do
35
+ it "should validate the provided document against the schema provided in class definition -- fails if no internet connection" do
36
+ ValidationTest.schema.expects(:validate).with(@sample).returns([])
37
+ ValidationTest.validate(@sample)
38
+ end
39
+ end
40
+
41
+ describe ".validate" do
42
+ it "should rely on class validate method" do
43
+ ValidationTest.expects(:validate).with(@sample)
44
+ @sample.validate
45
+ end
46
+ end
47
+
48
+ describe "#schema_file" do
49
+ before(:all) do
50
+ ValidationTest.schema_file = nil
51
+ end
52
+
53
+ after(:all) do
54
+ ValidationTest.schema_file = fixture("mods-3-2.xsd")
55
+ end
56
+
57
+ it "should lazy load the schema file from the @schema_url" do
58
+ ValidationTest.instance_variable_get(:@schema_file).should be_nil
59
+ ValidationTest.expects(:file_from_url).with(ValidationTest.schema_url).returns("fake file").once
60
+ ValidationTest.schema_file
61
+ ValidationTest.instance_variable_get(:@schema_file).should == "fake file"
62
+ ValidationTest.schema_file.should == "fake file"
63
+ end
64
+ end
65
+
66
+ describe "#file_from_url" do
67
+ it "should retrieve a file from the provided url over HTTP" do
68
+ ValidationTest.send(:file_from_url, "http://google.com")
69
+ end
70
+ it "should raise an error if the url is invalid" do
71
+ lambda {ValidationTest.send(:file_from_url, "")}.should raise_error(RuntimeError, "Could not retrieve file from . Error: No such file or directory - ")
72
+ lambda {ValidationTest.send(:file_from_url, "foo")}.should raise_error(RuntimeError, "Could not retrieve file from foo. Error: No such file or directory - foo")
73
+ end
74
+ it "should raise an error if file retrieval fails" do
75
+ lambda {ValidationTest.send(:file_from_url, "http://fedora-commons.org/nonexistent_file")}.should raise_error(RuntimeError, "Could not retrieve file from http://fedora-commons.org/nonexistent_file. Error: 404 Not Found")
76
+ end
77
+ end
78
+ end