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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/quiz_api_client/services/courses_service.rb +26 -0
- data/lib/quiz_api_client/services/items_service.rb +11 -0
- data/lib/quiz_api_client/services/quiz_clone_jobs_service.rb +11 -0
- data/lib/quiz_api_client/services/quiz_sync_job_service.rb +17 -0
- data/lib/quiz_api_client/services/quiz_sync_jobs_service.rb +16 -0
- data/lib/quiz_api_client/version.rb +1 -1
- data/lib/quiz_api_client.rb +15 -0
- data/spec/config_spec.rb +66 -0
- data/spec/contracts/interaction_types_service_spec.rb +22 -0
- data/spec/contracts/item_analyses_service_spec.rb +59 -0
- data/spec/contracts/items_service_spec.rb +59 -0
- data/spec/contracts/qti_imports_service_spec.rb +34 -0
- data/spec/contracts/quiz_clone_job_service_spec.rb +20 -0
- data/spec/contracts/quiz_clone_jobs_service_spec.rb +21 -0
- data/spec/contracts/quiz_entries_service_spec.rb +125 -0
- data/spec/contracts/quiz_service_spec.rb +68 -0
- data/spec/contracts/quiz_session_events_service_spec.rb +30 -0
- data/spec/contracts/quiz_session_result_service_spec.rb +42 -0
- data/spec/contracts/quiz_session_service_spec.rb +56 -0
- data/spec/contracts/quiz_sessions_service_spec.rb +28 -0
- data/spec/contracts/quiz_sync_job_service_spec.rb +21 -0
- data/spec/contracts/quiz_sync_jobs_service_spec.rb +21 -0
- data/spec/contracts/quizzes_service_spec.rb +80 -0
- data/spec/contracts/session_item_results_service_spec.rb +60 -0
- data/spec/contracts/session_items_service_spec.rb +21 -0
- data/spec/contracts/shared_banks_spec.rb +366 -0
- data/spec/contracts/shared_examples/http_delete_example.rb +56 -0
- data/spec/contracts/shared_examples/http_get_example.rb +139 -0
- data/spec/contracts/shared_examples/http_patch_example.rb +60 -0
- data/spec/contracts/shared_examples/http_post_example.rb +68 -0
- data/spec/contracts/shared_examples/http_put_example.rb +60 -0
- data/spec/http_client_spec.rb +347 -0
- data/spec/json_formatter_spec.rb +32 -0
- data/spec/quiz_api_client/http_request/failure_spec.rb +100 -0
- data/spec/quiz_api_client/http_request/metrics_spec.rb +75 -0
- data/spec/quiz_api_client_spec.rb +124 -0
- data/spec/services/base_api_service_spec.rb +50 -0
- data/spec/services/courses_service_spec.rb +59 -0
- data/spec/services/interaction_types_service_spec.rb +25 -0
- data/spec/services/item_analyses_service_spec.rb +76 -0
- data/spec/services/items_service_spec.rb +56 -0
- data/spec/services/jwt_service_spec.rb +66 -0
- data/spec/services/qti_imports_service_spec.rb +114 -0
- data/spec/services/quiz_analyses_service_spec.rb +44 -0
- data/spec/services/quiz_clone_job_service_spec.rb +41 -0
- data/spec/services/quiz_clone_jobs_service_spec.rb +77 -0
- data/spec/services/quiz_entries_service_spec.rb +71 -0
- data/spec/services/quiz_service_spec.rb +49 -0
- data/spec/services/quiz_session_events_service_spec.rb +42 -0
- data/spec/services/quiz_session_result_service_spec.rb +26 -0
- data/spec/services/quiz_session_service_spec.rb +49 -0
- data/spec/services/quiz_sessions_service_spec.rb +42 -0
- data/spec/services/quiz_sync_job_service_spec.rb +41 -0
- data/spec/services/quiz_sync_jobs_service_spec.rb +77 -0
- data/spec/services/quizzes_service_spec.rb +71 -0
- data/spec/services/session_item_results_service_spec.rb +33 -0
- data/spec/services/session_items_service_spec.rb +26 -0
- data/spec/spec_helper.rb +42 -0
- data/spec/support/pact_config.rb +64 -0
- data/spec/support/pact_helper.rb +19 -0
- metadata +121 -39
- data/.dockerignore +0 -7
- data/.editorconfig +0 -16
- data/.gitignore +0 -13
- data/.rspec +0 -3
- data/.rubocop.yml +0 -72
- data/CHANGELOG.md +0 -35
- data/Dockerfile +0 -12
- data/Gemfile +0 -5
- data/Jenkinsfile +0 -86
- data/bin/console +0 -7
- data/bin/contracts-generate +0 -26
- data/bin/setup +0 -65
- data/docker-compose.dev.override.yml +0 -11
- data/docker-compose.yml +0 -10
- 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
|