resync-client 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.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +42 -0
  3. data/.rubocop.yml +23 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +2 -0
  6. data/Gemfile +3 -0
  7. data/LICENSE.md +22 -0
  8. data/README.md +59 -0
  9. data/Rakefile +56 -0
  10. data/example.rb +49 -0
  11. data/lib/resync/client/bitstream.rb +79 -0
  12. data/lib/resync/client/client.rb +58 -0
  13. data/lib/resync/client/downloadable.rb +35 -0
  14. data/lib/resync/client/dump.rb +25 -0
  15. data/lib/resync/client/http_helper.rb +111 -0
  16. data/lib/resync/client/resync_extensions.rb +85 -0
  17. data/lib/resync/client/version.rb +6 -0
  18. data/lib/resync/client/zip_package.rb +66 -0
  19. data/lib/resync/client.rb +3 -0
  20. data/resync-client.gemspec +35 -0
  21. data/spec/data/examples/capability-list.xml +25 -0
  22. data/spec/data/examples/change-dump-manifest.xml +41 -0
  23. data/spec/data/examples/change-dump.xml +41 -0
  24. data/spec/data/examples/change-list-index.xml +22 -0
  25. data/spec/data/examples/change-list.xml +36 -0
  26. data/spec/data/examples/resource-dump-manifest.xml +25 -0
  27. data/spec/data/examples/resource-dump.xml +39 -0
  28. data/spec/data/examples/resource-list-index.xml +21 -0
  29. data/spec/data/examples/resource-list.xml +24 -0
  30. data/spec/data/examples/source-description.xml +25 -0
  31. data/spec/data/resourcedump/manifest.xml +18 -0
  32. data/spec/data/resourcedump/resourcedump.xml +16 -0
  33. data/spec/data/resourcedump/resourcedump.zip +0 -0
  34. data/spec/data/resourcedump/resources/res1 +7 -0
  35. data/spec/data/resourcedump/resources/res2 +7 -0
  36. data/spec/rspec_custom_matchers.rb +11 -0
  37. data/spec/spec_helper.rb +31 -0
  38. data/spec/todo.rb +65 -0
  39. data/spec/unit/resync/client/bitstream_spec.rb +90 -0
  40. data/spec/unit/resync/client/client_spec.rb +130 -0
  41. data/spec/unit/resync/client/dump_spec.rb +26 -0
  42. data/spec/unit/resync/client/http_helper_spec.rb +235 -0
  43. data/spec/unit/resync/client/resync_extensions_spec.rb +148 -0
  44. data/spec/unit/resync/client/zip_package_spec.rb +44 -0
  45. metadata +238 -0
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+ require 'mime/type'
3
+ require 'zip'
4
+
5
+ module Resync
6
+ describe Bitstream do
7
+
8
+ # ------------------------------------------------------------
9
+ # Fixture
10
+
11
+ before(:each) do
12
+ @zipfile = instance_double(Zip::File)
13
+
14
+ @metadata = instance_double(Metadata)
15
+ @path = 'path/to/resource'
16
+ allow(@metadata).to receive(:path).and_return(@path)
17
+
18
+ @zip_entry = instance_double(Zip::Entry)
19
+ allow(@zipfile).to receive(:find_entry).with(@path).and_return(@zip_entry)
20
+
21
+ @resource = instance_double(Resource)
22
+ allow(@resource).to receive(:metadata).and_return(@metadata)
23
+
24
+ @bitstream = Bitstream.new(zipfile: @zipfile, resource: @resource)
25
+ end
26
+
27
+ # ------------------------------------------------------------
28
+ # Tests
29
+
30
+ describe '#new' do
31
+ it 'requires a zipfile' do
32
+ expect { Bitstream.new(resource: @resource) }.to raise_error
33
+ end
34
+
35
+ it 'requires a resource' do
36
+ expect { Bitstream.new(zipfile: @zipfile) }.to raise_error
37
+ end
38
+ end
39
+
40
+ describe '#size' do
41
+ it 'returns the size of the zip entry' do
42
+ expect(@zip_entry).to receive(:size).and_return(123)
43
+ expect(@bitstream.size).to eq(123)
44
+ end
45
+ end
46
+
47
+ describe '#stream' do
48
+ it 'returns the input stream from the zip entry' do
49
+ stream = instance_double(Zip::InputStream)
50
+ expect(@zip_entry).to receive(:get_input_stream).and_return(stream)
51
+ expect(@bitstream.stream).to be(stream)
52
+ end
53
+
54
+ it 'returns the same stream each time' do
55
+ stream = instance_double(Zip::InputStream)
56
+ expect(@zip_entry).to receive(:get_input_stream).and_return(stream)
57
+ expect(@bitstream.stream).to be(stream)
58
+ expect(@bitstream.stream).to be(stream)
59
+ end
60
+ end
61
+
62
+ describe '#content' do
63
+ it 'gets the content of the stream' do
64
+ stream = instance_double(Zip::InputStream)
65
+ content = 'I am the content of the zip stream'
66
+ allow(stream).to receive(:read).and_return(content)
67
+ expect(@zip_entry).to receive(:get_input_stream).and_return(stream)
68
+ expect(@bitstream.content).to eq(content)
69
+ end
70
+
71
+ it 'gets the content of the stream only once' do
72
+ stream = instance_double(Zip::InputStream)
73
+ content = 'I am the content of the zip stream'
74
+ allow(stream).to receive(:read).and_return(content)
75
+ expect(@zip_entry).to receive(:get_input_stream).and_return(stream)
76
+ expect(@bitstream.content).to eq(content)
77
+ expect(@bitstream.content).to eq(content)
78
+ end
79
+ end
80
+
81
+ describe '#mime_type' do
82
+ it 'returns the MIME type of the metadata' do
83
+ mime_type = instance_double(MIME::Type)
84
+ allow(@metadata).to receive(:mime_type).and_return(mime_type)
85
+ expect(@bitstream.mime_type).to be(mime_type)
86
+ end
87
+ end
88
+
89
+ end
90
+ end
@@ -0,0 +1,130 @@
1
+ require 'spec_helper'
2
+
3
+ module Resync
4
+ describe Client do
5
+ before(:each) do
6
+ @helper = instance_double(HTTPHelper)
7
+ @client = Client.new(helper: @helper)
8
+ end
9
+
10
+ describe '#get' do
11
+ it 'retrieves a CapabilityList' do
12
+ uri = URI('http://example.org/capability-list.xml')
13
+ data = File.read('spec/data/examples/capability-list.xml')
14
+ expect(@helper).to receive(:fetch).with(uri: uri).and_return(data)
15
+ doc = @client.get_and_parse(uri)
16
+ expect(doc).to be_a(Resync::CapabilityList)
17
+ end
18
+
19
+ it 'retrieves a ChangeDump' do
20
+ uri = URI('http://example.org/change-dump.xml')
21
+ data = File.read('spec/data/examples/change-dump.xml')
22
+ expect(@helper).to receive(:fetch).with(uri: uri).and_return(data)
23
+ doc = @client.get_and_parse(uri)
24
+ expect(doc).to be_a(Resync::ChangeDump)
25
+ end
26
+
27
+ it 'retrieves a ChangeDumpManifest' do
28
+ uri = URI('http://example.org/change-dump-manifest.xml')
29
+ data = File.read('spec/data/examples/change-dump-manifest.xml')
30
+ expect(@helper).to receive(:fetch).with(uri: uri).and_return(data)
31
+ doc = @client.get_and_parse(uri)
32
+ expect(doc).to be_a(Resync::ChangeDumpManifest)
33
+ end
34
+
35
+ it 'retrieves a ChangeList' do
36
+ uri = URI('http://example.org/change-list.xml')
37
+ data = File.read('spec/data/examples/change-list.xml')
38
+ expect(@helper).to receive(:fetch).with(uri: uri).and_return(data)
39
+ doc = @client.get_and_parse(uri)
40
+ expect(doc).to be_a(Resync::ChangeList)
41
+ end
42
+
43
+ it 'retrieves a ResourceDump' do
44
+ uri = URI('http://example.org/resource-dump.xml')
45
+ data = File.read('spec/data/examples/resource-dump.xml')
46
+ expect(@helper).to receive(:fetch).with(uri: uri).and_return(data)
47
+ doc = @client.get_and_parse(uri)
48
+ expect(doc).to be_a(Resync::ResourceDump)
49
+ end
50
+
51
+ it 'retrieves a ResourceDumpManifest' do
52
+ uri = URI('http://example.org/resource-dump-manifest.xml')
53
+ data = File.read('spec/data/examples/resource-dump-manifest.xml')
54
+ expect(@helper).to receive(:fetch).with(uri: uri).and_return(data)
55
+ doc = @client.get_and_parse(uri)
56
+ expect(doc).to be_a(Resync::ResourceDumpManifest)
57
+ end
58
+
59
+ it 'retrieves a ResourceList' do
60
+ uri = URI('http://example.org/resource-list.xml')
61
+ data = File.read('spec/data/examples/resource-list.xml')
62
+ expect(@helper).to receive(:fetch).with(uri: uri).and_return(data)
63
+ doc = @client.get_and_parse(uri)
64
+ expect(doc).to be_a(Resync::ResourceList)
65
+ end
66
+
67
+ it 'retrieves a SourceDescription' do
68
+ uri = URI('http://example.org/source-description.xml')
69
+ data = File.read('spec/data/examples/source-description.xml')
70
+ expect(@helper).to receive(:fetch).with(uri: uri).and_return(data)
71
+ doc = @client.get_and_parse(uri)
72
+ expect(doc).to be_a(Resync::SourceDescription)
73
+ end
74
+
75
+ it 'retrieves a ChangeListIndex' do
76
+ uri = URI('http://example.org/change-list-index.xml')
77
+ data = File.read('spec/data/examples/change-list-index.xml')
78
+ expect(@helper).to receive(:fetch).with(uri: uri).and_return(data)
79
+ doc = @client.get_and_parse(uri)
80
+ expect(doc).to be_a(Resync::ChangeListIndex)
81
+ end
82
+
83
+ it 'retrieves a ResourceListIndex' do
84
+ uri = URI('http://example.org/resource-list-index.xml')
85
+ data = File.read('spec/data/examples/resource-list-index.xml')
86
+ expect(@helper).to receive(:fetch).with(uri: uri).and_return(data)
87
+ doc = @client.get_and_parse(uri)
88
+ expect(doc).to be_a(Resync::ResourceListIndex)
89
+ end
90
+
91
+ it 'injects the client into the returned document' do
92
+ uri = URI('http://example.org/resource-list-index.xml')
93
+ data = File.read('spec/data/examples/resource-list-index.xml')
94
+ expect(@helper).to receive(:fetch).with(uri: uri).and_return(data)
95
+ doc = @client.get_and_parse(uri)
96
+ expect(doc.client).to be(@client)
97
+ end
98
+ end
99
+
100
+ describe '#new' do
101
+ it 'creates its own connection if none is provided' do
102
+ uri = URI('http://example.org/capability-list.xml')
103
+ data = File.read('spec/data/examples/capability-list.xml')
104
+ expect(HTTPHelper).to receive(:new).and_return(@helper)
105
+ expect(@helper).to receive(:fetch).with(uri: uri).and_return(data)
106
+ client = Client.new
107
+ client.get_and_parse(uri)
108
+ end
109
+ end
110
+
111
+ describe '#download_to_temp_file' do
112
+ it 'delegates to the helper' do
113
+ uri = 'http://example.org/capability-list.xml'
114
+ path = '/tmp/whatever.zip'
115
+ expect(@helper).to receive(:fetch_to_file).with(uri: URI(uri)).and_return(path)
116
+ expect(@client.download_to_temp_file(uri)).to eq(path)
117
+ end
118
+ end
119
+
120
+ describe '#download_to_file' do
121
+ it 'delegates to the helper' do
122
+ uri = 'http://example.org/capability-list.xml'
123
+ path = '/tmp/whatever.zip'
124
+ expect(@helper).to receive(:fetch_to_file).with(uri: URI(uri), path: path).and_return(path)
125
+ expect(@client.download_to_file(uri: uri, path: path)).to eq(path)
126
+ end
127
+ end
128
+
129
+ end
130
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ module Resync
4
+ describe Dump do
5
+ it 'transparently extracts bitstreams' do
6
+ package_uri = URI('http://example.com/resourcedump.zip')
7
+ client = instance_double(Client)
8
+ expect(client).to receive(:download_to_temp_file).once.with(package_uri).and_return('spec/data/resourcedump/resourcedump.zip')
9
+
10
+ resource_dump = XMLParser.parse(File.read('spec/data/resourcedump/resourcedump.xml'))
11
+ resource_dump.client = client
12
+
13
+ zip_packages = resource_dump.zip_packages
14
+ expect(zip_packages.size).to eq(1)
15
+
16
+ zip_package = zip_packages[0]
17
+ expect(zip_package).to be_a(ZipPackage)
18
+
19
+ bitstreams = zip_package.bitstreams
20
+ expect(bitstreams.size).to eq(2)
21
+
22
+ stream1 = bitstreams[0]
23
+ expect(stream1.content).to eq(File.read('spec/data/resourcedump/resources/res1'))
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,235 @@
1
+ require 'spec_helper'
2
+
3
+ module Resync
4
+ describe HTTPHelper do
5
+
6
+ # ------------------------------------------------------------
7
+ # Fixture
8
+
9
+ attr_writer :user_agent
10
+
11
+ def user_agent
12
+ @user_agent ||= 'elvis'
13
+ end
14
+
15
+ attr_writer :helper
16
+
17
+ def helper
18
+ @helper ||= HTTPHelper.new(user_agent: user_agent)
19
+ end
20
+
21
+ # ------------------------------------------------------------
22
+ # Tests
23
+
24
+ describe '#fetch' do
25
+
26
+ # ------------------------------
27
+ # Fixture
28
+
29
+ before(:each) do
30
+ @http = instance_double(Net::HTTP)
31
+ allow(Net::HTTP).to receive(:new).and_return(@http)
32
+ allow(@http).to receive(:start).and_yield(@http)
33
+ @success = Net::HTTPOK.allocate
34
+ @body = 'I am the body of the response'
35
+ allow(@success).to receive(:body).and_return(@body)
36
+ end
37
+
38
+ # ------------------------------
39
+ # Tests
40
+
41
+ it 'requests the specified URI' do
42
+ uri = URI('http://example.org/')
43
+ expect(@http).to receive(:request).with(request_for(uri: uri)).and_yield(@success)
44
+ helper.fetch(uri: uri)
45
+ end
46
+
47
+ it 'gets a response' do
48
+ expect(@http).to receive(:request).and_yield(@success)
49
+ expect(helper.fetch(uri: URI('http://example.org/'))).to be(@body)
50
+ end
51
+
52
+ it 'sets the User-Agent header' do
53
+ agent = 'Not Elvis'
54
+ helper = HTTPHelper.new(user_agent: agent)
55
+ expect(@http).to receive(:request).with(request_for(headers: { 'User-Agent' => agent })).and_yield(@success)
56
+ helper.fetch(uri: URI('http://example.org/'))
57
+ end
58
+
59
+ it 'uses SSL for https requests' do
60
+ uri = URI('https://example.org/')
61
+ expect(Net::HTTP).to receive(:start).with(uri.hostname, uri.port, use_ssl: true).and_call_original
62
+ expect(@http).to receive(:request).and_yield(@success)
63
+ helper.fetch(uri: uri)
64
+ end
65
+
66
+ it 're-requests on receiving a 1xx' do
67
+ uri = URI('http://example.org/')
68
+ @info = Net::HTTPContinue.allocate
69
+
70
+ expected = [@info, @success]
71
+ expect(@http).to receive(:request).twice.with(request_for(uri: uri, headers: { 'User-Agent' => user_agent })) do |&block|
72
+ block.call(expected.shift)
73
+ end
74
+
75
+ expect(helper.fetch(uri: uri)).to be(@body)
76
+ end
77
+
78
+ it 'redirects on receiving a 3xx' do
79
+ uri = URI('http://example.org/')
80
+ uri2 = URI('http://example.org/new')
81
+ @redirect = Net::HTTPMovedPermanently.allocate
82
+ allow(@redirect).to receive(:[]).with('location').and_return(uri2.to_s)
83
+ expect(@http).to receive(:request).with(request_for(uri: uri, headers: { 'User-Agent' => user_agent })).and_yield(@redirect)
84
+ expect(@http).to receive(:request).with(request_for(uri: uri2, headers: { 'User-Agent' => user_agent })).and_yield(@success)
85
+ expect(helper.fetch(uri: uri)).to be(@body)
86
+ end
87
+
88
+ it 'only redirects a limited number of times' do
89
+ uri = URI('http://example.org/')
90
+ @redirect = Net::HTTPMovedPermanently.allocate
91
+ allow(@redirect).to receive(:[]).with('location').and_return(uri.to_s)
92
+ expect(@http).to receive(:request).with(request_for(uri: uri, headers: { 'User-Agent' => user_agent })).exactly(HTTPHelper::DEFAULT_MAX_REDIRECTS).times.and_yield(@redirect)
93
+ expect { helper.fetch(uri: uri) }.to raise_error
94
+ end
95
+
96
+ it 'fails on a 4xx' do
97
+ @error = Net::HTTPForbidden
98
+ allow(@error).to receive(:code).and_return(403)
99
+ allow(@error).to receive(:message).and_return('Forbidden')
100
+ expect(@http).to receive(:request).and_yield(@error)
101
+ uri = URI('http://example.org/')
102
+ expect { helper.fetch(uri: uri) }.to raise_error
103
+ end
104
+
105
+ it 'fails on a 5xx' do
106
+ @error = Net::HTTPServerError
107
+ allow(@error).to receive(:code).and_return(500)
108
+ allow(@error).to receive(:message).and_return('Internal Server Error')
109
+ expect(@http).to receive(:request).and_yield(@error)
110
+ uri = URI('http://example.org/')
111
+ expect { helper.fetch(uri: uri) }.to raise_error
112
+ end
113
+ end
114
+
115
+ describe '#fetch_to_file' do
116
+
117
+ # ------------------------------
118
+ # Fixture
119
+
120
+ before(:each) do
121
+ @path = nil
122
+ @http = instance_double(Net::HTTP)
123
+ allow(Net::HTTP).to receive(:new).and_return(@http)
124
+ allow(@http).to receive(:start).and_yield(@http)
125
+
126
+ @data = (0...100).map { ('a'..'z').to_a[rand(26)] }.join
127
+ @success = Net::HTTPOK.allocate
128
+ allow(@success).to receive(:[]).with('Content-Type').and_return('text/plain')
129
+ stub = allow(@success).to receive(:read_body)
130
+ (0...10).each do |i|
131
+ chunk = @data[10 * i, 10]
132
+ stub = stub.and_yield(chunk)
133
+ end
134
+ end
135
+
136
+ after(:each) do
137
+ File.delete(@path) if @path
138
+ end
139
+
140
+ # ------------------------------
141
+ # Tests
142
+
143
+ it 'requests the specified URI' do
144
+ uri = URI('http://example.org/')
145
+ expect(@http).to receive(:request).with(request_for(uri: uri)).and_yield(@success)
146
+ @path = helper.fetch_to_file(uri: uri)
147
+ end
148
+
149
+ it 'returns the path to a file containing the response' do
150
+ uri = URI('http://example.org/')
151
+ expect(@http).to receive(:request).with(request_for(uri: uri)).and_yield(@success)
152
+ @path = helper.fetch_to_file(uri: uri)
153
+ expect(File.read(@path)).to eq(@data)
154
+ end
155
+
156
+ it 'sets the User-Agent header' do
157
+ agent = 'Not Elvis'
158
+ helper = HTTPHelper.new(user_agent: agent)
159
+ expect(@http).to receive(:request).with(request_for(headers: { 'User-Agent' => agent })).and_yield(@success)
160
+ @path = helper.fetch_to_file(uri: URI('http://example.org/'))
161
+ end
162
+
163
+ it 'uses SSL for https requests' do
164
+ uri = URI('https://example.org/')
165
+ expect(Net::HTTP).to receive(:start).with(uri.hostname, uri.port, use_ssl: true).and_call_original
166
+ expect(@http).to receive(:request).and_yield(@success)
167
+ @path = helper.fetch_to_file(uri: uri)
168
+ end
169
+
170
+ it 're-requests on receiving a 1xx' do
171
+ uri = URI('http://example.org/')
172
+ @info = Net::HTTPContinue.allocate
173
+
174
+ expected = [@info, @success]
175
+ expect(@http).to receive(:request).twice.with(request_for(uri: uri, headers: { 'User-Agent' => user_agent })) do |&block|
176
+ block.call(expected.shift)
177
+ end
178
+
179
+ @path = helper.fetch_to_file(uri: uri)
180
+ expect(File.read(@path)).to eq(@data)
181
+ end
182
+
183
+ it 'redirects on receiving a 3xx' do
184
+ uri = URI('http://example.org/')
185
+ uri2 = URI('http://example.org/new')
186
+ @redirect = Net::HTTPMovedPermanently.allocate
187
+ allow(@redirect).to receive(:[]).with('location').and_return(uri2.to_s)
188
+ expect(@http).to receive(:request).with(request_for(uri: uri, headers: { 'User-Agent' => user_agent })).and_yield(@redirect)
189
+ expect(@http).to receive(:request).with(request_for(uri: uri2, headers: { 'User-Agent' => user_agent })).and_yield(@success)
190
+ @path = helper.fetch_to_file(uri: uri)
191
+ expect(File.read(@path)).to eq(@data)
192
+ end
193
+
194
+ it 'only redirects a limited number of times' do
195
+ uri = URI('http://example.org/')
196
+ @redirect = Net::HTTPMovedPermanently.allocate
197
+ allow(@redirect).to receive(:[]).with('location').and_return(uri.to_s)
198
+ expect(@http).to receive(:request).with(request_for(uri: uri, headers: { 'User-Agent' => user_agent })).exactly(HTTPHelper::DEFAULT_MAX_REDIRECTS).times.and_yield(@redirect)
199
+ expect { @path = helper.fetch_to_file(uri: uri) }.to raise_error
200
+ expect(@path).to be_nil
201
+ end
202
+
203
+ it 'fails on a 4xx' do
204
+ @error = Net::HTTPForbidden
205
+ allow(@error).to receive(:code).and_return(403)
206
+ allow(@error).to receive(:message).and_return('Forbidden')
207
+ expect(@http).to receive(:request).and_yield(@error)
208
+ uri = URI('http://example.org/')
209
+ expect { @path = helper.fetch_to_file(uri: uri) }.to raise_error
210
+ expect(@path).to be_nil
211
+ end
212
+
213
+ it 'fails on a 5xx' do
214
+ @error = Net::HTTPServerError
215
+ allow(@error).to receive(:code).and_return(500)
216
+ allow(@error).to receive(:message).and_return('Internal Server Error')
217
+ expect(@http).to receive(:request).and_yield(@error)
218
+ uri = URI('http://example.org/')
219
+ expect { helper.fetch_to_file(uri: uri) }.to raise_error
220
+ end
221
+
222
+ it 'accepts a file path argument' do
223
+ Dir.mktmpdir do |dir|
224
+ expect(Dir.exist?(dir)).to be(true)
225
+ path = "#{dir}/http_helper_spec.out"
226
+ uri = URI('http://example.org/')
227
+ expect(@http).to receive(:request).with(request_for(uri: uri)).and_yield(@success)
228
+ helper.fetch_to_file(uri: uri, path: path)
229
+ expect(File.read(path)).to eq(@data)
230
+ end
231
+ end
232
+ end
233
+
234
+ end
235
+ end
@@ -0,0 +1,148 @@
1
+ require 'spec_helper'
2
+
3
+ module Resync
4
+ describe 'extensions' do
5
+
6
+ # ------------------------------------------------------------
7
+ # Fixture
8
+
9
+ before(:each) do
10
+ @resources = [
11
+ Resource.new(uri: 'http://example.com/dataset1/resourcelist.xml', metadata: Metadata.new(capability: 'resourcelist')),
12
+ Resource.new(uri: 'http://example.com/dataset1/resourcedump.xml', metadata: Metadata.new(capability: 'resourcedump')),
13
+ Resource.new(uri: 'http://example.com/dataset1/changelist.xml', metadata: Metadata.new(capability: 'changelist')),
14
+ Resource.new(uri: 'http://example.com/dataset1/changedump.xml', metadata: Metadata.new(capability: 'changedump'))
15
+ ]
16
+ @links = [
17
+ Link.new(rel: 'describedby', uri: 'http://example.org/desc1'),
18
+ Link.new(rel: 'duplicate', uri: 'http://example.com/dup1'),
19
+ Link.new(rel: 'describedby', uri: 'http://example.org/desc2'),
20
+ Link.new(rel: 'duplicate', uri: 'http://example.com/dup2')
21
+ ]
22
+ @list = ResourceList.new(resources: @resources, links: @links)
23
+ end
24
+
25
+ # ------------------------------------------------------------
26
+ # Tests
27
+
28
+ describe BaseResourceList do
29
+ it 'proxies all resource client requests to its own client' do
30
+ client = instance_double(Resync::Client)
31
+ @list.client = client
32
+ @resources.each do |r|
33
+ expect(r.client).to be(client)
34
+ end
35
+ client2 = instance_double(Resync::Client)
36
+ @list.client = client2
37
+ @resources.each do |r|
38
+ expect(r.client).to be(client2)
39
+ end
40
+ end
41
+ end
42
+
43
+ describe Augmented do
44
+ it 'proxies all link client requests to its own client' do
45
+ client = instance_double(Resync::Client)
46
+ @list.client = client
47
+ @links.each do |l|
48
+ expect(l.client).to be(client)
49
+ end
50
+ client2 = instance_double(Resync::Client)
51
+ @list.client = client2
52
+ @links.each do |l|
53
+ expect(l.client).to be(client2)
54
+ end
55
+ end
56
+
57
+ it 'defaults to a new client' do
58
+ client = instance_double(Resync::Client)
59
+ expect(Resync::Client).to receive(:new) { client }
60
+ expect(@list.client).to be(client)
61
+ end
62
+ end
63
+
64
+ describe Resource do
65
+ describe '#get_and_parse' do
66
+ it 'gets the resource using the injected client' do
67
+ client = instance_double(Resync::Client)
68
+ resource = instance_double(Resync::ResourceList)
69
+ @list.client = client
70
+ expect(client).to receive(:get_and_parse).with(@resources[0].uri) { resource }
71
+ expect(@resources[0].get_and_parse).to be(resource)
72
+ end
73
+ end
74
+
75
+ describe '#get' do
76
+ it 'gets the resource contents using the injected client' do
77
+ data = 'I am the contents of a resource'
78
+ client = instance_double(Resync::Client)
79
+ @list.client = client
80
+ expect(client).to receive(:get).with(@resources[0].uri) { data }
81
+ expect(@resources[0].get).to be(data)
82
+ end
83
+ end
84
+
85
+ describe '#download_to_temp_file' do
86
+ it 'downloads the resource contents to a file using the injected client' do
87
+ path = '/tmp/whatever.zip'
88
+ client = instance_double(Resync::Client)
89
+ @list.client = client
90
+ expect(client).to receive(:download_to_temp_file).with(@resources[0].uri) { path }
91
+ expect(@resources[0].download_to_temp_file).to be(path)
92
+ end
93
+ end
94
+
95
+ describe '#download_to_file' do
96
+ it 'delegates to the injected client' do
97
+ path = '/tmp/whatever.zip'
98
+ client = instance_double(Resync::Client)
99
+ @list.client = client
100
+ expect(client).to receive(:download_to_file).with(uri: @resources[0].uri, path: path) { path }
101
+ expect(@resources[0].download_to_file(path)).to be(path)
102
+ end
103
+ end
104
+ end
105
+
106
+ describe Link do
107
+ describe '#get_and_parse' do
108
+ it 'gets the link using the injected client' do
109
+ client = instance_double(Resync::Client)
110
+ resource = instance_double(Resync::ResourceList)
111
+ @list.client = client
112
+ expect(client).to receive(:get_and_parse).with(@links[0].uri) { resource }
113
+ expect(@links[0].get_and_parse).to be(resource)
114
+ end
115
+ end
116
+
117
+ describe '#get' do
118
+ it 'gets the link contents using the injected client' do
119
+ data = 'I am the contents of a link'
120
+ client = instance_double(Resync::Client)
121
+ @list.client = client
122
+ expect(client).to receive(:get).with(@links[0].uri) { data }
123
+ expect(@links[0].get).to be(data)
124
+ end
125
+ end
126
+
127
+ describe '#download_to_temp_file' do
128
+ it 'downloads the link contents to a file using the injected client' do
129
+ path = '/tmp/whatever.zip'
130
+ client = instance_double(Resync::Client)
131
+ @list.client = client
132
+ expect(client).to receive(:download_to_temp_file).with(@links[0].uri) { path }
133
+ expect(@links[0].download_to_temp_file).to be(path)
134
+ end
135
+ end
136
+
137
+ describe '#download_to_file' do
138
+ it 'delegates to the injected client' do
139
+ path = '/tmp/whatever.zip'
140
+ client = instance_double(Resync::Client)
141
+ @list.client = client
142
+ expect(client).to receive(:download_to_file).with(uri: @links[0].uri, path: path) { path }
143
+ expect(@links[0].download_to_file(path)).to be(path)
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+ require 'resync/client/zip_package'
3
+
4
+ module Resync
5
+ describe ZipPackage do
6
+ describe '#new' do
7
+ it 'accepts a path to a ZIP file' do
8
+ path = 'spec/data/resourcedump/resourcedump.zip'
9
+ pkg = ZipPackage.new(path)
10
+ zipfile = pkg.zipfile
11
+ expect(zipfile).to be_a(Zip::File)
12
+ expect(zipfile.name).to eq(path)
13
+ end
14
+
15
+ it 'accepts a Zip::File object' do
16
+ zipfile = Zip::File.open('spec/data/resourcedump/resourcedump.zip')
17
+ pkg = ZipPackage.new(zipfile)
18
+ expect(pkg.zipfile).to eq(zipfile)
19
+ end
20
+
21
+ it 'extracts a manifest' do
22
+ pkg = ZipPackage.new('spec/data/resourcedump/resourcedump.zip')
23
+ manifest = pkg.manifest
24
+ expect(manifest).to be_a(Resync::ResourceDumpManifest)
25
+ end
26
+
27
+ it 'extracts entries' do
28
+ pkg = ZipPackage.new('spec/data/resourcedump/resourcedump.zip')
29
+ bitstreams = pkg.bitstreams
30
+ expect(bitstreams.size).to eq(2)
31
+
32
+ bs0 = bitstreams[0]
33
+ expect(bs0.path).to eq('resources/res1')
34
+ expect(bs0.size).to eq(446)
35
+ expect(bs0.content).to eq(File.read('spec/data/resourcedump/resources/res1'))
36
+
37
+ bs1 = bitstreams[1]
38
+ expect(bs1.path).to eq('resources/res2')
39
+ expect(bs1.size).to eq(447)
40
+ expect(bs1.content).to eq(File.read('spec/data/resourcedump/resources/res2'))
41
+ end
42
+ end
43
+ end
44
+ end