berkeley_library-util 0.1.4 → 0.1.6

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.
@@ -3,6 +3,10 @@ require 'spec_helper'
3
3
  module BerkeleyLibrary::Util
4
4
  describe URIs do
5
5
  describe :append do
6
+ it 'rejects a nil URI' do
7
+ expect { URIs.append(nil, 'foo') }.to raise_error(ArgumentError)
8
+ end
9
+
6
10
  it 'appends paths' do
7
11
  original_uri = URI('https://example.org/foo/bar')
8
12
  new_uri = URIs.append(original_uri, 'qux', 'corge', 'garply')
@@ -16,16 +20,14 @@ module BerkeleyLibrary::Util
16
20
  expect(new_uri).to eq(expected_uri)
17
21
  end
18
22
 
19
- # TODO: make this work
20
- xit "doesn't append to a bare URI when there's nothing to append" do
23
+ it 'returns a bare URI when there\'s nothing to append' do
21
24
  original_url = 'https://example.org'
22
25
  new_uri = URIs.append(original_url)
23
26
  expected_uri = URI(original_url)
24
27
  expect(new_uri).to eq(expected_uri)
25
28
  end
26
29
 
27
- # TODO: make this work
28
- xit "doesn't append to a bare URI when there's only a query string" do
30
+ it 'appends to a bare URI even when there\'s only a query string' do
29
31
  original_url = 'https://example.org'
30
32
  new_uri = URIs.append(original_url, '?foo=bar')
31
33
  expected_uri = URI("#{original_url}?foo=bar")
@@ -94,29 +96,67 @@ module BerkeleyLibrary::Util
94
96
  expect(new_uri).to eq(URI('https://example.org/foo/bar/qux/corge/garply?baz=qux#grault'))
95
97
  end
96
98
 
97
- it 'rejects a query string if the original URI already has one' do
98
- original_uri = URI('https://example.org/foo/bar?baz=qux')
99
- expect { URIs.append(original_uri, '/qux?corge') }.to raise_error(URI::InvalidComponentError)
100
- end
101
-
102
99
  it 'rejects a fragment if the original URI already has one' do
103
100
  original_uri = URI('https://example.org/foo/bar#baz')
104
101
  expect { URIs.append(original_uri, '/qux#corge') }.to raise_error(URI::InvalidComponentError)
105
102
  end
106
103
 
107
- it 'rejects appending multiple queries' do
104
+ # Per RFC3986, "3.4. Query"
105
+ it 'allows queries containing ?' do
108
106
  original_uri = URI('https://example.org/foo/bar')
109
- expect { URIs.append(original_uri, 'baz?qux=corge', 'grault?plugh=xyzzy') }.to raise_error(URI::InvalidComponentError)
107
+ expected_url = "#{original_uri}/baz?qux=corge?grault?plugh=xyzzy"
108
+ expected_uri = URI.parse(expected_url)
109
+
110
+ uri1 = URIs.append(original_uri, 'baz?qux=corge', '?grault?plugh=xyzzy')
111
+ expect(uri1).to eq(expected_uri)
112
+
113
+ uri2 = URIs.append(original_uri, 'baz?qux=corge?grault?plugh=xyzzy')
114
+ expect(uri2).to eq(expected_uri)
110
115
  end
111
116
 
112
- it 'rejects appending multiple fragments' do
117
+ # Per RFC3986, "3.4. Query"
118
+ it 'allows queries containing /' do
119
+ original_uri = URI('https://example.org/foo/bar')
120
+ expected_url = "#{original_uri}/baz?qux=corge/grault/plugh=xyzzy"
121
+ expected_uri = URI.parse(expected_url)
122
+
123
+ uri1 = URIs.append(original_uri, 'baz?qux=corge', '/grault/plugh=xyzzy')
124
+ expect(uri1).to eq(expected_uri)
125
+
126
+ uri2 = URIs.append(original_uri, 'baz?qux=corge/grault/plugh=xyzzy')
127
+ expect(uri2).to eq(expected_uri)
128
+ end
129
+
130
+ it 'rejects fragments containing #' do
113
131
  original_uri = URI('https://example.org/foo/bar')
114
132
  expect { URIs.append(original_uri, 'baz#qux', 'grault#plugh') }.to raise_error(URI::InvalidComponentError)
133
+ expect { URIs.append(original_uri, 'baz#qux#plugh') }.to raise_error(URI::InvalidComponentError)
115
134
  end
116
135
 
117
- it 'rejects queries after fragments' do
136
+ # Per RFC3986, "3.5. Fragment"
137
+ it 'allows fragments containing ?' do
118
138
  original_uri = URI('https://example.org/foo/bar')
119
- expect { URIs.append(original_uri, 'baz#qux', '?grault=plugh') }.to raise_error(URI::InvalidComponentError)
139
+ expected_url = "#{original_uri}/baz#qux?grault=plugh"
140
+ expected_uri = URI.parse(expected_url)
141
+
142
+ uri1 = URIs.append(original_uri, 'baz#qux', '?grault=plugh')
143
+ expect(uri1).to eq(expected_uri)
144
+
145
+ uri2 = URIs.append(original_uri, 'baz#qux?grault=plugh')
146
+ expect(uri2).to eq(expected_uri)
147
+ end
148
+
149
+ # Per RFC3986, "3.5. Fragment"
150
+ it 'allows fragments containing /' do
151
+ original_uri = URI('https://example.org/foo/bar')
152
+ expected_url = "#{original_uri}/baz#qux/grault=plugh"
153
+ expected_uri = URI.parse(expected_url)
154
+
155
+ uri1 = URIs.append(original_uri, 'baz#qux', '/grault=plugh')
156
+ expect(uri1).to eq(expected_uri)
157
+
158
+ uri2 = URIs.append(original_uri, 'baz#qux/grault=plugh')
159
+ expect(uri2).to eq(expected_uri)
120
160
  end
121
161
 
122
162
  it 'correctly handles fragments in mid-path-segment' do
@@ -136,6 +176,28 @@ module BerkeleyLibrary::Util
136
176
  new_uri = URIs.append(original_uri, '?qux=corge', '&grault=plugh#xyzzy')
137
177
  expect(new_uri).to eq(URI('https://example.org/foo/bar?qux=corge&grault=plugh#xyzzy'))
138
178
  end
179
+
180
+ it 'rejects invalid characters' do
181
+ original_uri = URI('https://example.org/')
182
+ expect { URIs.append(original_uri, '精力善用') }.to raise_error(URI::InvalidComponentError)
183
+ end
184
+
185
+ it 'accepts percent-encoded path segments' do
186
+ original_uri = URI('https://example.org/')
187
+ encoded_segment = URIs.path_escape('精力善用')
188
+ new_uri = URIs.append(original_uri, encoded_segment, 'foo.html')
189
+ expected_url = "https://example.org/#{encoded_segment}/foo.html"
190
+ expect(new_uri).to eq(URI(expected_url))
191
+ end
192
+
193
+ it 'accepts path segments with allowed punctuation' do
194
+ original_uri = URI('https://example.org/')
195
+ path = 'foo/bar/baz@qux&corge=garply+grault$waldo/fred'
196
+ new_uri = URIs.append(original_uri, path, 'plugh')
197
+ expected_url = "#{original_uri}#{path}/plugh"
198
+ expect(new_uri).to eq(URI(expected_url))
199
+ end
200
+
139
201
  end
140
202
 
141
203
  describe 'requests' do
@@ -177,6 +239,42 @@ module BerkeleyLibrary::Util
177
239
  expect(response.code).to eq(404)
178
240
  end
179
241
  end
242
+
243
+ describe :head do
244
+ it 'makes a HEAD request' do
245
+ expected_status = 200
246
+ stub_request(:head, url_with_query).with(headers: headers).to_return(status: expected_status)
247
+
248
+ result = URIs.head(url, params: params, headers: headers)
249
+ expect(result).to eq(expected_status)
250
+ end
251
+
252
+ it 'returns the status even for unsuccessful requests' do
253
+ expected_status = 404
254
+ stub_request(:head, url_with_query).with(headers: headers).to_return(status: expected_status)
255
+
256
+ result = URIs.head(url, params: params, headers: headers)
257
+ expect(result).to eq(expected_status)
258
+ end
259
+ end
260
+
261
+ describe :head_response do
262
+ it 'makes a HEAD request' do
263
+ stub_request(:head, url_with_query).with(headers: headers).to_return(body: expected_body)
264
+
265
+ response = URIs.head_response(url, params: params, headers: headers)
266
+ expect(response.body).to eq(expected_body)
267
+ expect(response.code).to eq(200)
268
+ end
269
+
270
+ it 'returns the response even for errors' do
271
+ stub_request(:head, url_with_query).with(headers: headers).to_return(status: 404, body: expected_body)
272
+
273
+ response = URIs.head_response(url, params: params, headers: headers)
274
+ expect(response.body).to eq(expected_body)
275
+ expect(response.code).to eq(404)
276
+ end
277
+ end
180
278
  end
181
279
 
182
280
  describe :safe_parse_uri do
@@ -210,5 +308,50 @@ module BerkeleyLibrary::Util
210
308
  end
211
309
  end
212
310
  end
311
+
312
+ describe :path_escape do
313
+ let(:in_out) do
314
+ {
315
+ '' => '',
316
+ 'corge' => 'corge',
317
+ 'foo+bar' => 'foo+bar',
318
+ 'qux/quux' => 'qux%2Fquux',
319
+ 'foo bar baz' => 'foo%20bar%20baz',
320
+ 'Corge-Grault.Fred_Waldo~Plugh' => 'Corge-Grault.Fred_Waldo~Plugh',
321
+ '25%' => '25%25',
322
+ "\t !\"#$%&'()*+,/:;<=>?@[\\]^`{|}☺" => '%09%20%21%22%23$%25&%27%28%29%2A+%2C%2F:%3B%3C=%3E%3F@%5B%5C%5D%5E%60%7B%7C%7D%E2%98%BA',
323
+ '精力善用' => '%E7%B2%BE%E5%8A%9B%E5%96%84%E7%94%A8'
324
+ }
325
+ end
326
+
327
+ it 'escapes a path segment' do
328
+ aggregate_failures do
329
+ in_out.each do |in_str, out_str|
330
+ expect(URIs.path_escape(in_str)).to eq(out_str)
331
+ end
332
+ end
333
+ end
334
+
335
+ it 'rejects non-strings' do
336
+ str = in_out.keys.last
337
+ expect { URIs.path_escape(str.bytes) }.to raise_error(ArgumentError)
338
+ end
339
+
340
+ it 'rejects non-UTF-8 strings' do
341
+ str = in_out.keys.last
342
+ expect { URIs.path_escape(str.encode(Encoding::Shift_JIS)) }.to raise_error(ArgumentError)
343
+ end
344
+
345
+ it 'accepts non-UTF-8 strings converted to UTF-8' do
346
+ in_str = in_out.keys.last
347
+ out_str = in_out[in_str]
348
+
349
+ # OK, we're really just testing String#encode here, but
350
+ # it's useful for documentation
351
+ in_str_sjis = in_str.encode(Encoding::Shift_JIS)
352
+ in_str_utf8 = in_str_sjis.encode(Encoding::UTF_8)
353
+ expect(URIs.path_escape(in_str_utf8)).to eq(out_str)
354
+ end
355
+ end
213
356
  end
214
357
  end
data/spec/spec_helper.rb CHANGED
@@ -13,8 +13,8 @@ RSpec.configure do |config|
13
13
  config.color = true
14
14
  config.tty = true
15
15
  config.formatter = :documentation
16
- config.before(:each) { WebMock.disable_net_connect!(allow_localhost: true) }
17
- config.after(:each) { WebMock.allow_net_connect! }
16
+ config.before { WebMock.disable_net_connect!(allow_localhost: true) }
17
+ config.after { WebMock.allow_net_connect! }
18
18
  config.mock_with :rspec do |mocks|
19
19
  mocks.verify_partial_doubles = true
20
20
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: berkeley_library-util
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Moles
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-20 00:00:00.000000000 Z
11
+ date: 2023-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: berkeley_library-logging
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0.3'
55
- - !ruby/object:Gem::Dependency
56
- name: bundle-audit
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '0.1'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '0.1'
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: ci_reporter_rspec
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -142,42 +128,42 @@ dependencies:
142
128
  requirements:
143
129
  - - '='
144
130
  - !ruby/object:Gem::Version
145
- version: '1.11'
131
+ version: '1.39'
146
132
  type: :development
147
133
  prerelease: false
148
134
  version_requirements: !ruby/object:Gem::Requirement
149
135
  requirements:
150
136
  - - '='
151
137
  - !ruby/object:Gem::Version
152
- version: '1.11'
138
+ version: '1.39'
153
139
  - !ruby/object:Gem::Dependency
154
140
  name: rubocop-rake
155
141
  requirement: !ruby/object:Gem::Requirement
156
142
  requirements:
157
- - - "~>"
143
+ - - '='
158
144
  - !ruby/object:Gem::Version
159
- version: '0.5'
145
+ version: 0.6.0
160
146
  type: :development
161
147
  prerelease: false
162
148
  version_requirements: !ruby/object:Gem::Requirement
163
149
  requirements:
164
- - - "~>"
150
+ - - '='
165
151
  - !ruby/object:Gem::Version
166
- version: '0.5'
152
+ version: 0.6.0
167
153
  - !ruby/object:Gem::Dependency
168
154
  name: rubocop-rspec
169
155
  requirement: !ruby/object:Gem::Requirement
170
156
  requirements:
171
- - - "~>"
157
+ - - '='
172
158
  - !ruby/object:Gem::Version
173
- version: '2.2'
159
+ version: 2.4.0
174
160
  type: :development
175
161
  prerelease: false
176
162
  version_requirements: !ruby/object:Gem::Requirement
177
163
  requirements:
178
- - - "~>"
164
+ - - '='
179
165
  - !ruby/object:Gem::Version
180
- version: '2.2'
166
+ version: 2.4.0
181
167
  - !ruby/object:Gem::Dependency
182
168
  name: ruby-prof
183
169
  requirement: !ruby/object:Gem::Requirement
@@ -206,20 +192,6 @@ dependencies:
206
192
  - - "~>"
207
193
  - !ruby/object:Gem::Version
208
194
  version: '0.21'
209
- - !ruby/object:Gem::Dependency
210
- name: simplecov-rcov
211
- requirement: !ruby/object:Gem::Requirement
212
- requirements:
213
- - - "~>"
214
- - !ruby/object:Gem::Version
215
- version: '0.2'
216
- type: :development
217
- prerelease: false
218
- version_requirements: !ruby/object:Gem::Requirement
219
- requirements:
220
- - - "~>"
221
- - !ruby/object:Gem::Version
222
- version: '0.2'
223
195
  - !ruby/object:Gem::Dependency
224
196
  name: webmock
225
197
  requirement: !ruby/object:Gem::Requirement
@@ -271,7 +243,7 @@ files:
271
243
  - lib/berkeley_library/util/uris/appender.rb
272
244
  - lib/berkeley_library/util/uris/requester.rb
273
245
  - lib/berkeley_library/util/uris/validator.rb
274
- - rakelib/bundle.rake
246
+ - rakelib/.rubocop.yml
275
247
  - rakelib/coverage.rake
276
248
  - rakelib/gem.rake
277
249
  - rakelib/rubocop.rake
@@ -290,7 +262,8 @@ files:
290
262
  homepage: https://github.com/BerkeleyLibrary/util
291
263
  licenses:
292
264
  - MIT
293
- metadata: {}
265
+ metadata:
266
+ rubygems_mfa_required: 'true'
294
267
  post_install_message:
295
268
  rdoc_options: []
296
269
  require_paths:
@@ -310,15 +283,4 @@ rubygems_version: 3.1.6
310
283
  signing_key:
311
284
  specification_version: 4
312
285
  summary: Miscellaneous Ruby utilities for the UC Berkeley Library
313
- test_files:
314
- - spec/.rubocop.yml
315
- - spec/berkeley_library/util/arrays_spec.rb
316
- - spec/berkeley_library/util/files_spec.rb
317
- - spec/berkeley_library/util/paths_spec.rb
318
- - spec/berkeley_library/util/stringios_spec.rb
319
- - spec/berkeley_library/util/strings_spec.rb
320
- - spec/berkeley_library/util/times_spec.rb
321
- - spec/berkeley_library/util/uris/requester_spec.rb
322
- - spec/berkeley_library/util/uris/validator_spec.rb
323
- - spec/berkeley_library/util/uris_spec.rb
324
- - spec/spec_helper.rb
286
+ test_files: []
data/rakelib/bundle.rake DELETED
@@ -1,8 +0,0 @@
1
- namespace :bundle do
2
- desc 'Updates the ruby-advisory-db then runs bundle-audit'
3
- task :audit do
4
- require 'bundler/audit/cli'
5
- Bundler::Audit::CLI.start ['update']
6
- Bundler::Audit::CLI.start %w[check --ignore CVE-2015-9284]
7
- end
8
- end