quiz_api_client 4.2.0 → 4.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/quiz_api_client/services/courses_service.rb +26 -0
  4. data/lib/quiz_api_client/services/items_service.rb +11 -0
  5. data/lib/quiz_api_client/services/quiz_clone_jobs_service.rb +11 -0
  6. data/lib/quiz_api_client/services/quiz_sync_job_service.rb +17 -0
  7. data/lib/quiz_api_client/services/quiz_sync_jobs_service.rb +16 -0
  8. data/lib/quiz_api_client/version.rb +1 -1
  9. data/lib/quiz_api_client.rb +15 -0
  10. data/spec/config_spec.rb +66 -0
  11. data/spec/contracts/interaction_types_service_spec.rb +22 -0
  12. data/spec/contracts/item_analyses_service_spec.rb +59 -0
  13. data/spec/contracts/items_service_spec.rb +59 -0
  14. data/spec/contracts/qti_imports_service_spec.rb +34 -0
  15. data/spec/contracts/quiz_clone_job_service_spec.rb +20 -0
  16. data/spec/contracts/quiz_clone_jobs_service_spec.rb +21 -0
  17. data/spec/contracts/quiz_entries_service_spec.rb +125 -0
  18. data/spec/contracts/quiz_service_spec.rb +68 -0
  19. data/spec/contracts/quiz_session_events_service_spec.rb +30 -0
  20. data/spec/contracts/quiz_session_result_service_spec.rb +42 -0
  21. data/spec/contracts/quiz_session_service_spec.rb +56 -0
  22. data/spec/contracts/quiz_sessions_service_spec.rb +28 -0
  23. data/spec/contracts/quiz_sync_job_service_spec.rb +21 -0
  24. data/spec/contracts/quiz_sync_jobs_service_spec.rb +21 -0
  25. data/spec/contracts/quizzes_service_spec.rb +80 -0
  26. data/spec/contracts/session_item_results_service_spec.rb +60 -0
  27. data/spec/contracts/session_items_service_spec.rb +21 -0
  28. data/spec/contracts/shared_banks_spec.rb +366 -0
  29. data/spec/contracts/shared_examples/http_delete_example.rb +56 -0
  30. data/spec/contracts/shared_examples/http_get_example.rb +139 -0
  31. data/spec/contracts/shared_examples/http_patch_example.rb +60 -0
  32. data/spec/contracts/shared_examples/http_post_example.rb +68 -0
  33. data/spec/contracts/shared_examples/http_put_example.rb +60 -0
  34. data/spec/http_client_spec.rb +347 -0
  35. data/spec/json_formatter_spec.rb +32 -0
  36. data/spec/quiz_api_client/http_request/failure_spec.rb +100 -0
  37. data/spec/quiz_api_client/http_request/metrics_spec.rb +75 -0
  38. data/spec/quiz_api_client_spec.rb +124 -0
  39. data/spec/services/base_api_service_spec.rb +50 -0
  40. data/spec/services/courses_service_spec.rb +59 -0
  41. data/spec/services/interaction_types_service_spec.rb +25 -0
  42. data/spec/services/item_analyses_service_spec.rb +76 -0
  43. data/spec/services/items_service_spec.rb +56 -0
  44. data/spec/services/jwt_service_spec.rb +66 -0
  45. data/spec/services/qti_imports_service_spec.rb +114 -0
  46. data/spec/services/quiz_analyses_service_spec.rb +44 -0
  47. data/spec/services/quiz_clone_job_service_spec.rb +41 -0
  48. data/spec/services/quiz_clone_jobs_service_spec.rb +77 -0
  49. data/spec/services/quiz_entries_service_spec.rb +71 -0
  50. data/spec/services/quiz_service_spec.rb +49 -0
  51. data/spec/services/quiz_session_events_service_spec.rb +42 -0
  52. data/spec/services/quiz_session_result_service_spec.rb +26 -0
  53. data/spec/services/quiz_session_service_spec.rb +49 -0
  54. data/spec/services/quiz_sessions_service_spec.rb +42 -0
  55. data/spec/services/quiz_sync_job_service_spec.rb +41 -0
  56. data/spec/services/quiz_sync_jobs_service_spec.rb +77 -0
  57. data/spec/services/quizzes_service_spec.rb +71 -0
  58. data/spec/services/session_item_results_service_spec.rb +33 -0
  59. data/spec/services/session_items_service_spec.rb +26 -0
  60. data/spec/spec_helper.rb +42 -0
  61. data/spec/support/pact_config.rb +64 -0
  62. data/spec/support/pact_helper.rb +19 -0
  63. metadata +121 -39
  64. data/.dockerignore +0 -7
  65. data/.editorconfig +0 -16
  66. data/.gitignore +0 -13
  67. data/.rspec +0 -3
  68. data/.rubocop.yml +0 -72
  69. data/CHANGELOG.md +0 -35
  70. data/Dockerfile +0 -12
  71. data/Gemfile +0 -5
  72. data/Jenkinsfile +0 -86
  73. data/bin/console +0 -7
  74. data/bin/contracts-generate +0 -26
  75. data/bin/setup +0 -65
  76. data/docker-compose.dev.override.yml +0 -11
  77. data/docker-compose.yml +0 -10
  78. data/quiz_api_client.gemspec +0 -60
@@ -0,0 +1,124 @@
1
+ describe QuizApiClient do
2
+ it 'has a version number' do
3
+ expect(QuizApiClient::VERSION).not_to be nil
4
+ end
5
+
6
+ context 'service helper methods' do
7
+ let(:host) { 'api.host' }
8
+ let(:shared_secret) { 'secret' }
9
+ let(:protocol) { 'http' }
10
+ let(:consumer_key) { 'some consumer_key' }
11
+ let(:consumer_request_id) { 'guid_value' }
12
+ let(:subject) do
13
+ QuizApiClient::Client.new(
14
+ consumer_key: consumer_key,
15
+ consumer_request_id: consumer_request_id,
16
+ host: host,
17
+ shared_secret: shared_secret,
18
+ protocol: protocol
19
+ )
20
+ end
21
+
22
+ describe '#config' do
23
+ it 'should populate the values' do
24
+ config = subject.config
25
+ expect(config.consumer_key).to eq consumer_key
26
+ expect(config.consumer_request_id).to eq consumer_request_id
27
+ expect(config.host).to eq host
28
+ expect(config.shared_secret).to eq shared_secret
29
+ expect(config.protocol).to eq protocol
30
+ end
31
+
32
+ it 'should yield the config on instantiation' do
33
+ client = QuizApiClient::Client.new(
34
+ consumer_key: consumer_key,
35
+ consumer_request_id: consumer_request_id,
36
+ host: host,
37
+ shared_secret: shared_secret,
38
+ protocol: protocol
39
+ ) do |config|
40
+ config.host = 'my.hosting'
41
+ end
42
+
43
+ expect(client.config.host).to eq 'my.hosting'
44
+ end
45
+ end
46
+
47
+ describe '#jwt_service' do
48
+ it 'should create the service' do
49
+ expect(QuizApiClient::Services::JwtService).to receive(:new).with(subject.config)
50
+ subject.jwt_service
51
+ end
52
+ end
53
+
54
+ describe '#courses_service' do
55
+ it 'creates the service' do
56
+ expect(QuizApiClient::Services::CoursesService).to receive(:new).with(subject.config)
57
+ subject.courses_service
58
+ end
59
+ end
60
+
61
+ describe '#quizzes_service' do
62
+ it 'should create the service' do
63
+ expect(QuizApiClient::Services::QuizzesService).to receive(:new).with(subject.config)
64
+ subject.quizzes_service
65
+ end
66
+ end
67
+
68
+ describe '#quiz_session_service' do
69
+ it 'should create the service' do
70
+ expect(QuizApiClient::Services::QuizSessionService).to receive(:new).with(subject.config)
71
+ subject.quiz_session_service
72
+ end
73
+ end
74
+
75
+ describe '#quiz_sessions_service' do
76
+ it 'should create the service' do
77
+ expect(QuizApiClient::Services::QuizSessionsService).to receive(:new).with(subject.config)
78
+ subject.quiz_sessions_service
79
+ end
80
+ end
81
+
82
+ describe '#qti_imports_service' do
83
+ it 'should create the service' do
84
+ expect(QuizApiClient::Services::QtiImportsService).to receive(:new).with(subject.config)
85
+ subject.qti_imports_service
86
+ end
87
+ end
88
+
89
+ describe '#item_analyses_service' do
90
+ it 'should create the service' do
91
+ expect(QuizApiClient::Services::ItemAnalysesService).to receive(:new).with(subject.config)
92
+ subject.item_analyses_service
93
+ end
94
+ end
95
+
96
+ describe '#quiz_analyses_service' do
97
+ it 'should create the service' do
98
+ expect(QuizApiClient::Services::QuizAnalysesService).to receive(:new).with(subject.config)
99
+ subject.quiz_analyses_service
100
+ end
101
+ end
102
+
103
+ describe '#quiz_session_events_service' do
104
+ it 'should create the service' do
105
+ expect(QuizApiClient::Services::QuizSessionEventsService).to receive(:new).with(subject.config)
106
+ subject.quiz_session_events_service
107
+ end
108
+ end
109
+
110
+ describe '#items_service' do
111
+ it 'should create the service' do
112
+ expect(QuizApiClient::Services::ItemsService).to receive(:new).with(subject.config)
113
+ subject.items_service
114
+ end
115
+ end
116
+
117
+ describe '#interaction_types_service' do
118
+ it 'should create the service' do
119
+ expect(QuizApiClient::Services::InteractionTypesService).to receive(:new).with(subject.config)
120
+ subject.interaction_types_service
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,50 @@
1
+ describe QuizApiClient::Services::BaseApiService do
2
+ let(:consumer_key) { 'consumer key' }
3
+ let(:host) { 'api.host' }
4
+ let(:shared_secret) { 'secret' }
5
+ let(:protocol) { 'http' }
6
+ let(:service_class) do
7
+ Class.new(QuizApiClient::Services::BaseApiService) do
8
+ def test_uri
9
+ uri
10
+ end
11
+ end
12
+ end
13
+ let(:service) do
14
+ service_class.new(QuizApiClient::Config.new do |c|
15
+ c.consumer_key = consumer_key
16
+ c.host = host
17
+ c.shared_secret = shared_secret
18
+ c.protocol = protocol
19
+ end)
20
+ end
21
+
22
+ def decode_token(token, secret)
23
+ JWT.decode(
24
+ token, secret, true,
25
+ algorithm: QuizApiClient::Services::JwtService::HASHING_ALGORITHM
26
+ )
27
+ end
28
+
29
+ describe '#uri' do
30
+ it 'returns full URI' do
31
+ expect(service.test_uri).to eq 'http://api.host'
32
+ end
33
+
34
+ context 'with https protocol' do
35
+ let(:protocol) { 'https' }
36
+
37
+ it 'uses specified protocol' do
38
+ expect(service.test_uri).to eq 'https://api.host'
39
+ end
40
+ end
41
+
42
+ context 'with port specified in host' do
43
+ let(:host) { 'api.host:8443' }
44
+
45
+ it 'includes port in URI' do
46
+ expect(service.test_uri).to eq 'http://api.host:8443'
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,59 @@
1
+ describe QuizApiClient::Services::CoursesService do
2
+ let(:host) { 'api.host' }
3
+ let(:config) { QuizApiClient::Config.new { |c| c.host = host } }
4
+ let(:subject) { described_class.new(config) }
5
+
6
+ describe '#create' do
7
+ let(:params) do
8
+ {
9
+ title: 'foo',
10
+ canvas_id: 2,
11
+ is_blueprint: true
12
+ }
13
+ end
14
+
15
+ let(:response) do
16
+ {
17
+ 'id' => '4',
18
+ 'title' => 'foo',
19
+ 'canvas_id' => '2',
20
+ 'is_blueprint' => true,
21
+ 'created_at' => '2022-06-22T18:59:27.577Z',
22
+ 'updated_at' => '2022-06-22T18:59:27.577Z'
23
+ }
24
+ end
25
+
26
+ let(:expected_url) { "https://#{host}/api/courses" }
27
+
28
+ before do
29
+ stub_request(:post, expected_url)
30
+ .with(body: { course: params }.to_json)
31
+ .to_return(
32
+ status: 201,
33
+ body: response.to_json,
34
+ headers: { 'Content-Type' => 'application/json' }
35
+ )
36
+ end
37
+
38
+ it 'posts to the correct endpoint and returns the response' do
39
+ expect(
40
+ subject.create(params: params, token: 'token').parsed_response
41
+ ).to eq(response)
42
+ end
43
+ end
44
+
45
+ describe '#destroy' do
46
+ let(:params) { { canvas_id: 1 } }
47
+ let(:expected_url) { "https://#{host}/api/courses/1" }
48
+
49
+ before do
50
+ stub_request(:delete, expected_url).to_return(status: 204)
51
+ end
52
+
53
+ it 'deletes to the correct endpoint and returns the response' do
54
+ response = subject.destroy(params: params, token: 'token')
55
+ expect(response.code).to eq 204
56
+ expect(response.body).to be_nil
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,25 @@
1
+ describe QuizApiClient::Services::InteractionTypesService do
2
+ let(:host) { 'api.host' }
3
+ let(:config) { QuizApiClient::Config.new { |c| c.host = host } }
4
+ let(:subject) { described_class.new(config) }
5
+
6
+ describe '#list' do
7
+ let(:status_code) { 200 }
8
+ let(:expected_url) { "https://#{host}/api/interaction_types" }
9
+ let(:stubbed_response) { [{ 'name' => 'Type One', 'id' => 1 }] }
10
+
11
+ before do
12
+ stub_request(:get, expected_url)
13
+ .to_return(
14
+ status: status_code,
15
+ body: stubbed_response.to_json,
16
+ headers: { 'Content-Type' => 'application/json' }
17
+ )
18
+ end
19
+
20
+ it 'gets from quiz_api/api/interaction_types and returns the response' do
21
+ result = subject.list(token: 'token')
22
+ expect(result.parsed_response).to eql(stubbed_response)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,76 @@
1
+ describe QuizApiClient::Services::ItemAnalysesService do
2
+ let(:host) { 'api.host' }
3
+ let(:config) { QuizApiClient::Config.new { |c| c.host = host } }
4
+ let(:subject) { described_class.new(config) }
5
+
6
+ describe '#list' do
7
+ let(:params) { { quiz_id: 1, id: 7 } }
8
+ let(:stubbed_response) { { 'id' => '1' } }
9
+ let(:expected_url) do
10
+ "https://#{host}/api/quizzes/#{params[:quiz_id]}/stats/item_analyses"
11
+ end
12
+ let(:expected_body) { '' }
13
+ let(:status_code) { 200 }
14
+
15
+ before do
16
+ stub_request(:get, expected_url)
17
+ .with(body: expected_body)
18
+ .to_return(
19
+ status: status_code,
20
+ body: stubbed_response.to_json,
21
+ headers: { 'Content-Type' => 'application/json' }
22
+ )
23
+ end
24
+
25
+ it 'posts to /api/quizzes/1/stats/item_analyses and returns the response' do
26
+ result = subject.list(params: params, token: 'token')
27
+ expect(result.parsed_response).to eql(stubbed_response)
28
+ end
29
+
30
+ it 'raises an error when no quiz_id is specified' do
31
+ params = {}
32
+ expect do
33
+ subject.list(params: params, token: 'token')
34
+ end.to raise_error 'Quiz Id Required'
35
+ end
36
+ end
37
+
38
+ describe '#get' do
39
+ let(:params) { { quiz_id: 1, id: 7 } }
40
+ let(:stubbed_response) { { 'id' => '1' } }
41
+ let(:expected_url) do
42
+ "https://#{host}/api/quizzes/#{params[:quiz_id]}/stats/item_analyses/#{params[:id]}"
43
+ end
44
+ let(:expected_body) { '' }
45
+ let(:status_code) { 200 }
46
+
47
+ before do
48
+ stub_request(:get, expected_url)
49
+ .with(body: expected_body)
50
+ .to_return(
51
+ status: status_code,
52
+ body: stubbed_response.to_json,
53
+ headers: { 'Content-Type' => 'application/json' }
54
+ )
55
+ end
56
+
57
+ it 'posts to /api/quizzes/1/stats/item_analyses/7 and returns the response' do
58
+ result = subject.get(params: params, token: 'token')
59
+ expect(result.parsed_response).to eql(stubbed_response)
60
+ end
61
+
62
+ it 'raises an error when no quiz_id is specified' do
63
+ params = {}
64
+ expect do
65
+ subject.list(params: params, token: 'token')
66
+ end.to raise_error 'Quiz Id Required'
67
+ end
68
+
69
+ context 'response' do
70
+ it 'returns the response with the correct status code' do
71
+ response = subject.get(params: params, token: 'token')
72
+ expect(response.code).to eq(status_code)
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,56 @@
1
+ describe QuizApiClient::Services::ItemsService do
2
+ let(:host) { 'api.host' }
3
+ let(:config) { QuizApiClient::Config.new { |c| c.host = host } }
4
+ let(:subject) { described_class.new(config) }
5
+
6
+ describe '#list' do
7
+ let(:params) { { quiz_id: 1 } }
8
+ let(:stubbed_response) { { 'id' => 1, 'item' => { 'id' => 1 } } }
9
+ let(:expected_url) { "https://#{host}/api/quizzes/#{params[:quiz_id]}/items" }
10
+ let(:status_code) { 200 }
11
+
12
+ before do
13
+ stub_request(:get, expected_url)
14
+ .to_return(
15
+ status: status_code,
16
+ body: stubbed_response.to_json,
17
+ headers: { 'Content-Type' => 'application/json' }
18
+ )
19
+ end
20
+
21
+ it 'list from quiz_api/api/quizzes/{id}/items and returns the response' do
22
+ result = subject.list(params: params, token: 'token')
23
+ expect(result.parsed_response).to eql(stubbed_response)
24
+ end
25
+ end
26
+
27
+ describe '#create' do
28
+ let(:params) do
29
+ {
30
+ quiz_id: 1,
31
+ item_body: 'item body',
32
+ scoring_data: { value: 'value' },
33
+ scoring_algorithm: 'Equivalence',
34
+ interaction_type_id: 'choice',
35
+ user_response_type: 'response type'
36
+ }
37
+ end
38
+ let(:stubbed_response) { { 'id' => 1, 'item' => { 'id' => 1 } } }
39
+ let(:expected_url) { "https://#{host}/api/quizzes/#{params[:quiz_id]}/items" }
40
+ let(:status_code) { 201 }
41
+
42
+ before do
43
+ stub_request(:post, expected_url)
44
+ .to_return(
45
+ status: status_code,
46
+ body: stubbed_response.to_json,
47
+ headers: { 'Content-Type' => 'application/json' }
48
+ )
49
+ end
50
+
51
+ it 'posts to quiz_api/api/quizzes/{id}/items and returns the response' do
52
+ result = subject.create(params: params, token: 'token')
53
+ expect(result.parsed_response).to eql(stubbed_response)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,66 @@
1
+ describe QuizApiClient::Services::JwtService do
2
+ let(:host) { 'test.host' }
3
+ let(:shared_secret) { 'secret' }
4
+ let(:consumer_key) { 'some consumer_key' }
5
+
6
+ let(:config) do
7
+ QuizApiClient::Config.new do |c|
8
+ c.shared_secret = shared_secret
9
+ c.host = host
10
+ c.consumer_key = consumer_key
11
+ end
12
+ end
13
+
14
+ subject do
15
+ QuizApiClient::Services::JwtService.new(config)
16
+ end
17
+
18
+ describe 'grant_permission' do
19
+ it 'generates a JWT using the shared_secret' do
20
+ jwt = subject.grant_permission(scope: 'quiz.create')
21
+
22
+ payload, header = JWT.decode(jwt, shared_secret, true, algorithm: 'HS512')
23
+
24
+ expect(payload['host']).to eq(host)
25
+ expect(payload['scope']).to eq('quiz.create')
26
+ expect(payload['consumer_key']).to eq(consumer_key)
27
+ expect(payload).not_to have_key('resource_id')
28
+ expect(payload).not_to have_key('user')
29
+ expect(payload).to have_key('exp')
30
+ expect(header['alg']).to eq('HS512')
31
+ end
32
+
33
+ it 'includes user uuid in payload when provided' do
34
+ jwt = subject.grant_permission(scope: 'quiz.create', uuid: '123')
35
+
36
+ payload = JWT.decode(jwt, shared_secret, true, algorithm: 'HS512').first
37
+
38
+ expect(payload['user']).to eq('uuid' => '123')
39
+ end
40
+
41
+ it 'merges in other provided user context' do
42
+ jwt = subject.grant_permission(scope: 'quiz.create', uuid: '123', user: { email: 'test@example.com' })
43
+
44
+ payload = JWT.decode(jwt, shared_secret, true, algorithm: 'HS512').first
45
+
46
+ expect(payload['user']).to eq('uuid' => '123', 'email' => 'test@example.com')
47
+ end
48
+
49
+ it 'allows arbitrary additional params' do
50
+ jwt = subject.grant_permission(scope: 'quiz.create', foo: 'bar', monkey: 'do')
51
+ payload = JWT.decode(jwt, shared_secret, true, algorithm: 'HS512').first
52
+ expect(payload['foo']).to eq 'bar'
53
+ expect(payload['monkey']).to eq 'do'
54
+ end
55
+
56
+ context 'with port in host' do
57
+ let(:host) { 'test.host:8443' }
58
+
59
+ it 'leaves port out of payload host' do
60
+ jwt = subject.grant_permission scope: 'quiz.build'
61
+ payload, _header = JWT.decode(jwt, shared_secret, true, algorithm: 'HS512')
62
+ expect(payload['host']).to eq 'test.host'
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,114 @@
1
+ describe QuizApiClient::Services::QtiImportsService do
2
+ let(:host) { 'api.host' }
3
+ let(:config) { QuizApiClient::Config.new { |c| c.host = host } }
4
+ let(:subject) { described_class.new(config) }
5
+
6
+ describe '#create' do
7
+ let(:params) { { url: 'https://fake-s3-url.com', quiz_id: 1 } }
8
+ let(:stubbed_response) { { 'id' => '1', 'status' => 'created' } }
9
+ let(:expected_url) { "https://#{host}/api/quizzes/1/qti_imports" }
10
+ let(:expected_body) { {} }
11
+ let(:status_code) { 200 }
12
+
13
+ before do
14
+ stub_request(:post, expected_url)
15
+ .with(body: expected_body)
16
+ .to_return(
17
+ status: 200,
18
+ body: stubbed_response.to_json,
19
+ headers: { 'Content-Type' => 'application/json' }
20
+ )
21
+ end
22
+
23
+ it 'posts to quiz_api/api/qti_imports and returns the response' do
24
+ result = subject.create(params: params, token: 'token')
25
+ expect(result.parsed_response).to eql(stubbed_response)
26
+ end
27
+
28
+ context 'response' do
29
+ it 'returns the response with the correct code' do
30
+ response = subject.create(params: params, token: 'token')
31
+ expect(response.code).to eq(status_code)
32
+ end
33
+ end
34
+
35
+ context 'no quiz id provided' do
36
+ let(:params) {}
37
+ it 'raises Quiz Id Required' do
38
+ expect do
39
+ subject.create(params: params, token: 'token')
40
+ end.to raise_error('Quiz Id Required')
41
+ end
42
+ end
43
+ end
44
+
45
+ describe '#banks' do
46
+ let(:params) { { everything: false, overwrite: false, assessment_question_banks: ['abc123'] } }
47
+ let(:stubbed_response) { { 'id' => '1', 'status' => 'created' } }
48
+ let(:expected_url) { "https://#{host}/api/qti_imports/banks" }
49
+ let(:expected_body) { {} }
50
+ let(:status_code) { 200 }
51
+
52
+ before do
53
+ stub_request(:post, expected_url)
54
+ .with(body: expected_body)
55
+ .to_return(
56
+ status: 200,
57
+ body: stubbed_response.to_json,
58
+ headers: { 'Content-Type' => 'application/json' }
59
+ )
60
+ end
61
+
62
+ it 'posts to quiz_api/api/qti_imports and returns the response' do
63
+ result = subject.banks(params: params, token: 'token')
64
+ expect(result.parsed_response).to eql(stubbed_response)
65
+ end
66
+
67
+ context 'response' do
68
+ it 'returns the response with the correct code' do
69
+ response = subject.banks(params: params, token: 'token')
70
+ expect(response.code).to eq(status_code)
71
+ end
72
+ end
73
+ end
74
+
75
+ describe '#get_imported_consumer_settings' do
76
+ let(:params) { { quiz_id: 1 } }
77
+ let(:stubbed_response) { { 'score_to_keep' => 'highest', 'max_attempts' => '10' } }
78
+ let(:expected_url) { "https://#{host}/api/quizzes/1/qti_imports/imported_consumer_settings" }
79
+
80
+ let(:expected_body) { {} }
81
+ let(:status_code) { 200 }
82
+
83
+ before do
84
+ stub_request(:get, expected_url)
85
+ .with(body: expected_body)
86
+ .to_return(
87
+ status: 200,
88
+ body: stubbed_response.to_json,
89
+ headers: { 'Content-Type' => 'application/json' }
90
+ )
91
+ end
92
+
93
+ it 'posts to quiz_api/api/qti_imports and returns the response' do
94
+ result = subject.get_imported_consumer_settings(params: params, token: 'token')
95
+ expect(result.parsed_response).to eql(stubbed_response)
96
+ end
97
+
98
+ context 'response' do
99
+ it 'returns the response with the correct code' do
100
+ response = subject.get_imported_consumer_settings(params: params, token: 'token')
101
+ expect(response.code).to eq(status_code)
102
+ end
103
+ end
104
+
105
+ context 'no quiz id provided' do
106
+ let(:params) {}
107
+ it 'raises Quiz Id Required' do
108
+ expect do
109
+ subject.create(params: params, token: 'token')
110
+ end.to raise_error('Quiz Id Required')
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,44 @@
1
+ describe QuizApiClient::Services::QuizAnalysesService do
2
+ let(:host) { 'api.host' }
3
+ let(:config) { QuizApiClient::Config.new { |c| c.host = host } }
4
+ let(:subject) { described_class.new(config) }
5
+
6
+ describe '#list' do
7
+ let(:params) { { quiz_id: 1 } }
8
+ let(:stubbed_response) { { 'id' => '1' } }
9
+ let(:expected_url) do
10
+ "https://#{host}/api/quizzes/#{params[:quiz_id]}/stats/quiz_analysis"
11
+ end
12
+ let(:expected_body) { '' }
13
+ let(:status_code) { 200 }
14
+
15
+ before do
16
+ stub_request(:get, expected_url)
17
+ .with(body: expected_body)
18
+ .to_return(
19
+ status: status_code,
20
+ body: stubbed_response.to_json,
21
+ headers: { 'Content-Type' => 'application/json' }
22
+ )
23
+ end
24
+
25
+ it 'posts to quiz_api/api/quizzes and returns the response' do
26
+ result = subject.get(params: params, token: 'token')
27
+ expect(result.parsed_response).to eql(stubbed_response)
28
+ end
29
+
30
+ it 'raises an error when no quiz_id is specified' do
31
+ params = {}
32
+ expect do
33
+ subject.get(params: params, token: 'token')
34
+ end.to raise_error 'Quiz Id Required'
35
+ end
36
+
37
+ context 'response' do
38
+ it 'returns the response with the correct status code' do
39
+ response = subject.get(params: params, token: 'token')
40
+ expect(response.code).to eq(status_code)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,41 @@
1
+ describe QuizApiClient::Services::QuizCloneJobService do
2
+ let(:host) { 'api.host' }
3
+ let(:config) { QuizApiClient::Config.new { |c| c.host = host } }
4
+ let(:subject) { described_class.new(config) }
5
+
6
+ describe '#show' do
7
+ let(:expected_url) { "https://#{host}/api/quiz_clone_jobs/#{params[:id]}" }
8
+ let(:params) { { id: 1 } }
9
+ let(:stubbed_response) { { 'id' => 1, 'original_quiz_id' => 666, 'status' => 'completed' } }
10
+
11
+ context 'on success' do
12
+ before do
13
+ stub_request(:get, expected_url)
14
+ .to_return(
15
+ status: 200,
16
+ body: stubbed_response.to_json,
17
+ headers: { 'Content-Type' => 'application/json' }
18
+ )
19
+ end
20
+
21
+ it 'gets from /api/quiz_clone_jobs/:id' do
22
+ result = subject.show(params: params, token: 'token')
23
+ expect(result.parsed_response).to eql(stubbed_response)
24
+ end
25
+ end
26
+
27
+ context 'on failure' do
28
+ let(:status_code) { 401 }
29
+
30
+ before do
31
+ stub_request(:get, expected_url)
32
+ .to_return(status: status_code)
33
+ end
34
+
35
+ it 'returns a response with the correct code' do
36
+ response = subject.show(params: params, token: 'token')
37
+ expect(response.code).to eq(status_code)
38
+ end
39
+ end
40
+ end
41
+ end