quiz_api_client 4.24.0 → 4.25.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e7e14132240ede40616dabc2feac9400fe84262ba29cf2d2aacbdedddcded259
4
- data.tar.gz: 745e10dfc3a5e4917ad9e0000a66022c31cd16fc4f8dfb7c386eb9a09846267d
3
+ metadata.gz: 271c4523cdeb2e7861c0292366ce7db0e6f87ab37a1406d5a9bc5fb001ad935e
4
+ data.tar.gz: 3e290ab1b995fbd19c9b00e0b73a8cea69974a15f77859900a4a8d66f1876c85
5
5
  SHA512:
6
- metadata.gz: 2d62d169bf07dad6adfcf0fbc43d850ebaf705cccd9db6bc848d74268501769b98a983fed9028e12d0dbffb67d9e0bcfa73d1f721c5a4f83220c4ee1d1323589
7
- data.tar.gz: 2a4b338ae4b34b16fcfbe36b2e99ed13fec4b8ea9e08e636b830dec0215e9d01300973ded39e25907dcc7457c1961b33b265eb60f2b8adbb55aa000d32156791
6
+ metadata.gz: 2f125d17891e1fddacaaab43282ac302e88668277e00df91cd184358cca2ee5c0303cf97345eb2a592e53d8237d126e13319b6169db5e091548f3434153624e0
7
+ data.tar.gz: 904d69175eee4889c4c12f17ca57d1306f909fe585171b1d100229e0036c57b9e70686e05a602fb782258dac16d2f1ff8fd041fb8f6f8c8ec8361f0415c1877d
data/README.md CHANGED
@@ -187,3 +187,37 @@ Then, run `bundle exec rake spec` to run the tests.
187
187
  You can also run `bundle exec rake console` for an interactive prompt that will allow you to experiment.
188
188
 
189
189
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
190
+
191
+ ## Development with Quiz LTI
192
+
193
+ Copy this repo inside the Quiz LTI docker container:
194
+
195
+ ```shell
196
+ docker cp . quiz-lti-web:/quiz_api_client_ruby
197
+ ```
198
+
199
+ Tell Quiz LTI to use the gem, find the line containing `gem 'quiz_api_client'` in `app.rb`, update it to:
200
+
201
+ ```shell
202
+ gem 'quiz_api_client', path: '/quiz_api_client_ruby'
203
+ ```
204
+
205
+ Run bundle install the container:
206
+
207
+ ```shell
208
+ docker exec quiz-lti-web bundle install
209
+ ```
210
+
211
+ Restart the container:
212
+
213
+ ```shell
214
+ docker restart quiz-lti-web
215
+ ```
216
+
217
+ Your changes should be reflected in the container!
218
+
219
+ If you update the code afterwards you'll need to copy and restart the container:
220
+
221
+ ```shell
222
+ docker cp . quiz-lti-web:gems/quiz_api_client_ruby && docker restart quiz-lti-web
223
+ ```
@@ -2,7 +2,7 @@ module QuizApiClient
2
2
  class Config
3
3
  DEFAULT_ALLOWABLE_RESPONSE_CODES = [401, 422].freeze
4
4
  DEFAULT_PROTOCOL = 'https'.freeze
5
- ERROR_HANDLERS = %i[sentry_raven].freeze
5
+ ERROR_HANDLERS = %i[sentry_raven sentry_rails].freeze
6
6
  METRICS_HANDLERS = %i[inststatsd].freeze
7
7
 
8
8
  class InvalidErrorHandler < StandardError; end
@@ -48,6 +48,10 @@ module QuizApiClient
48
48
  when :sentry_raven
49
49
  require 'sentry-raven'
50
50
  Raven.extra_context(context)
51
+ when :sentry_rails
52
+ require 'sentry-ruby'
53
+ require 'sentry-rails'
54
+ Sentry.set_extras(context)
51
55
  end
52
56
  end
53
57
 
@@ -1,3 +1,3 @@
1
1
  module QuizApiClient
2
- VERSION = '4.24.0'.freeze
2
+ VERSION = '4.25.0'.freeze
3
3
  end
@@ -360,6 +360,162 @@ describe QuizApiClient::HttpClient do
360
360
  expect { client.get('/') }.to raise_error(QuizApiClient::HttpClient::RequestFailed)
361
361
  end
362
362
 
363
+ it 'handles an Net::ReadTimeout error' do
364
+ stub_request(:get, url).to_raise(Net::ReadTimeout)
365
+ expect_metrics_calls(client.config, :get, 0)
366
+ expect_raise_error_call(client.config, :get, url_for_path(path), nil, kind_of(Net::ReadTimeout))
367
+ expect { client.get('/') }.to raise_error(QuizApiClient::HttpClient::RequestFailed)
368
+ end
369
+ end
370
+ context 'with :sentry_rails error handler' do
371
+ let(:error_handler) { :sentry_rails }
372
+ let(:path) { '/' }
373
+ let(:url) { "http://api.quiz.docker#{path}" }
374
+ let(:error_context) do
375
+ {
376
+ quiz_api_client: {
377
+ request: {
378
+ method: :get,
379
+ url: url
380
+ }
381
+ }
382
+ }
383
+ end
384
+
385
+ before do
386
+ client.config.error_handler = error_handler
387
+ end
388
+
389
+ context 'with non-success responses' do
390
+ let(:body) { '[2]' }
391
+ let(:code) { 404 }
392
+ let(:path) { '/api/quizzes' }
393
+ let(:context_url) { url }
394
+ let(:method) { :get }
395
+ let(:error_context) do
396
+ {
397
+ quiz_api_client: {
398
+ request: {
399
+ method: method,
400
+ url: context_url
401
+ },
402
+ response: {
403
+ body: body,
404
+ code: code
405
+ }
406
+ }
407
+ }
408
+ end
409
+ let(:mock_response) do
410
+ instance_double(
411
+ 'HTTParty::Response',
412
+ success?: false,
413
+ body: body,
414
+ code: code
415
+ )
416
+ end
417
+ let(:success_response) do
418
+ # rubocop:disable Metrics/LineLength
419
+ instance_double(
420
+ 'HTTParty::Response',
421
+ body: body,
422
+ code: 200,
423
+ parsed_response: [1],
424
+ headers: {
425
+ 'link' => '<http://api.quiz.docker/api/quizzes?page=2>; rel="last", <http://api.quiz.docker/api/quizzes?page=2>; rel="next"',
426
+ 'content-type' => ['application/json']
427
+ }
428
+ )
429
+ # rubocop:enable Metrics/LineLength
430
+ end
431
+
432
+ context ':get request' do
433
+ it 'raises error' do
434
+ expect(client).to receive(:successful_response?).with(mock_response).and_return(false)
435
+ expect(client.class).to receive(:get).and_return(mock_response)
436
+ expect_metrics_calls(client.config, method, code)
437
+ expect_raise_error_call(client.config, method, url_for_path(path), mock_response, nil)
438
+ expect { client.get(path, all: false, query: { sort: 'alpha' }) }
439
+ .to raise_error(QuizApiClient::HttpClient::RequestFailed)
440
+ end
441
+ end
442
+
443
+ context ':post request' do
444
+ let(:method) { :post }
445
+
446
+ it 'raises error' do
447
+ expect(client).to receive(:successful_response?).with(mock_response).and_return(false)
448
+ expect(client.class).to receive(:post).and_return(mock_response)
449
+ expect_metrics_calls(client.config, method, code)
450
+ expect_raise_error_call(client.config, method, url_for_path(path), mock_response, nil)
451
+ expect { client.post(path) }.to raise_error(QuizApiClient::HttpClient::RequestFailed)
452
+ end
453
+ end
454
+
455
+ context ':put request' do
456
+ let(:method) { :put }
457
+
458
+ it 'raises error' do
459
+ expect(client).to receive(:successful_response?).with(mock_response).and_return(false)
460
+ expect(client.class).to receive(:put).and_return(mock_response)
461
+ expect_metrics_calls(client.config, method, code)
462
+ expect_raise_error_call(client.config, method, url_for_path(path), mock_response, nil)
463
+ expect { client.put(path) }.to raise_error(QuizApiClient::HttpClient::RequestFailed)
464
+ end
465
+ end
466
+
467
+ context ':patch request' do
468
+ let(:method) { :patch }
469
+
470
+ it 'raises error' do
471
+ expect(client).to receive(:successful_response?).with(mock_response).and_return(false)
472
+ expect(client.class).to receive(:patch).and_return(mock_response)
473
+ expect_metrics_calls(client.config, method, code)
474
+ expect_raise_error_call(client.config, method, url_for_path(path), mock_response, nil)
475
+ expect { client.patch(path) }.to raise_error(QuizApiClient::HttpClient::RequestFailed)
476
+ end
477
+ end
478
+
479
+ context ':delete request' do
480
+ let(:method) { :delete }
481
+
482
+ it 'raises error' do
483
+ expect(client).to receive(:successful_response?).with(mock_response).and_return(false)
484
+ expect(client.class).to receive(:delete).and_return(mock_response)
485
+ expect_metrics_calls(client.config, method, code)
486
+ expect_raise_error_call(client.config, method, url_for_path(path), mock_response, nil)
487
+ expect { client.delete(path) }.to raise_error(QuizApiClient::HttpClient::RequestFailed)
488
+ end
489
+ end
490
+
491
+ context 'with pagination' do
492
+ let(:context_url) { "#{url}?page=2" }
493
+
494
+ it 'raises error if one of the linked pages does not return 200 response' do
495
+ stub_quiz_api path, headers: { link: link_header(path, 1, 2) }
496
+ stub_quiz_api path, item: 2, query: { page: 2 }, headers: { link: link_header(path, 2, 2) }, status: code
497
+ allow(HTTParty::Response).to receive(:new).and_return(success_response, mock_response)
498
+ expect(client).to receive(:successful_response?).and_return(true, false).twice
499
+ expect_raise_error_call(client.config, method, context_url, mock_response, nil)
500
+ expect { client.get('/api/quizzes', all: true) }.to raise_error(QuizApiClient::HttpClient::RequestFailed)
501
+ end
502
+ end
503
+ end
504
+
505
+ it 'handles an HTTParty::Error error' do
506
+ stub_request(:get, url).to_raise(HTTParty::Error)
507
+ expect_metrics_calls(client.config, :get, 0)
508
+ expect_raise_error_call(client.config, :get, url_for_path(path), nil, kind_of(HTTParty::Error))
509
+ expect { client.get('/') }.to raise_error(QuizApiClient::HttpClient::RequestFailed)
510
+ end
511
+
512
+ it 'handles an Errno::ECONNREFUSED error' do
513
+ stub_request(:get, url).to_raise(Errno::ECONNREFUSED)
514
+ expect_metrics_calls(client.config, :get, 0)
515
+ expect_raise_error_call(client.config, :get, url_for_path(path), nil, kind_of(Errno::ECONNREFUSED))
516
+ expect { client.get('/') }.to raise_error(QuizApiClient::HttpClient::RequestFailed)
517
+ end
518
+
363
519
  it 'handles an Net::ReadTimeout error' do
364
520
  stub_request(:get, url).to_raise(Net::ReadTimeout)
365
521
  expect_metrics_calls(client.config, :get, 0)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quiz_api_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.24.0
4
+ version: 4.25.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Slaughter
@@ -15,7 +15,7 @@ authors:
15
15
  autorequire:
16
16
  bindir: exe
17
17
  cert_chain: []
18
- date: 2025-12-02 00:00:00.000000000 Z
18
+ date: 2026-04-29 00:00:00.000000000 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: httparty
@@ -115,6 +115,20 @@ dependencies:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
117
  version: 0.74.0
118
+ - !ruby/object:Gem::Dependency
119
+ name: sentry-rails
120
+ requirement: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '6.5'
125
+ type: :development
126
+ prerelease: false
127
+ version_requirements: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '6.5'
118
132
  - !ruby/object:Gem::Dependency
119
133
  name: sentry-raven
120
134
  requirement: !ruby/object:Gem::Requirement
@@ -129,6 +143,20 @@ dependencies:
129
143
  - - "~>"
130
144
  - !ruby/object:Gem::Version
131
145
  version: '3.1'
146
+ - !ruby/object:Gem::Dependency
147
+ name: sentry-ruby
148
+ requirement: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '6.5'
153
+ type: :development
154
+ prerelease: false
155
+ version_requirements: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '6.5'
132
160
  - !ruby/object:Gem::Dependency
133
161
  name: simplecov
134
162
  requirement: !ruby/object:Gem::Requirement