berkeley_library-util 0.1.4 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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