proctorserv-api 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2013 ProctorCam, Inc.
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ ### ProctorservApi Client
2
+
3
+ A ruby wrapper around the Proctorserve scheduling API. Supports listing timeslots that are available to schedule a test session for, scheduling a test session, and canceling a test session.
4
+
5
+ #### Installation
6
+
7
+ $ gem install proctorserv-api
8
+
9
+ #### Configuration
10
+
11
+ The constructor takes two important options: the customer_identifier and shared_secret
12
+
13
+ _What's my customer_identifier?_
14
+
15
+ the Proctorserve service requires that incoming requests identify who is sending them with a `customer_id` parameter. Once your account has been set up, your customer id should be viewable and editable through the web interface.
16
+
17
+ _What's the shared_secret for?_
18
+
19
+ Proctorserve uses a secret key that is shared between customer and service as part of a two-factor authentication scheme. This is also viewable and editable through the web interface. It is important to keep this secure, otherwise a man in the middle can make requests on your behalf.
20
+
21
+ #### Usage
22
+
23
+ ```ruby
24
+ proctorserv_api = Proctorcam::Proctorserv::ProctorservApi.new("our_customer_identifier", "our_shared_secret")
25
+ options = {
26
+ :scheduling_window_start => Time.now,
27
+ :scheduling_window_end => scheduling_window_start + 24 * 60 * 60, # tomorrow at this time
28
+ :test_length => 60 # minutes
29
+ }
30
+ available_timeslots = proctorserv_api.get_available_timeslots_between options
31
+ # returns a list of available timeslots between now and 24 hours from now.
32
+ ```
33
+
34
+ #### Interface
35
+
36
+ The following methods are supported
37
+
38
+ ```ruby
39
+ proctorserv_api = Proctorcam::Proctorserv::ProctorservApi.new("our_customer_identifier", "our_shared_secret")
40
+ proctorserv_api.get_available_timeslots_between
41
+ proctorserv_api.get_available_timeslots_around
42
+ proctorserv_api.make_reservation
43
+ proctorserv_api.make_immediate_reservation
44
+ proctorserv_api.cancel_reservation
45
+ ```
46
+
47
+ Further documentation for these methods can be found in the `doc/` folder
@@ -0,0 +1,27 @@
1
+ #
2
+ # invalid_client_exception.rb
3
+ # ProctorservApi
4
+ #
5
+ # Copyright 2013 ProctorCam, Inc
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ # Created by Max Lahey on 6/6/13.
20
+ #
21
+
22
+ module ProctorCam
23
+ module Proctorserv
24
+ class InvalidClientException < Exception
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ #
2
+ # invalid_ip_exception.rb
3
+ # ProctorservApi
4
+ #
5
+ # Copyright 2013 ProctorCam, Inc
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ # Created by Max Lahey on 6/6/13.
20
+ #
21
+
22
+ module ProctorCam
23
+ module Proctorserv
24
+ class InvalidIpException < Exception
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ #
2
+ # invalid_signature_exception.rb
3
+ # ProctorservApi
4
+ #
5
+ # Copyright 2013 ProctorCam, Inc
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ # Created by Max Lahey on 6/6/13.
20
+ #
21
+
22
+ module ProctorCam
23
+ module Proctorserv
24
+ class InvalidSignatureException < Exception
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ #
2
+ # missing_required_parameter_exception.rb
3
+ # ProctorservApi
4
+ #
5
+ # Copyright 2013 ProctorCam, Inc
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ # Created by Max Lahey on 6/6/13.
20
+ #
21
+
22
+ module ProctorCam
23
+ module Proctorserv
24
+ class MissingRequiredParameterException < Exception
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,39 @@
1
+ require 'digest'
2
+ require 'securerandom'
3
+
4
+ #
5
+ # hashed_authenticator.rb
6
+ # ProctorservApi
7
+ #
8
+ # Copyright 2013 ProctorCam, Inc
9
+ #
10
+ # Licensed under the Apache License, Version 2.0 (the "License");
11
+ # you may not use this file except in compliance with the License.
12
+ # You may obtain a copy of the License at
13
+ #
14
+ # http://www.apache.org/licenses/LICENSE-2.0
15
+ #
16
+ # Unless required by applicable law or agreed to in writing, software
17
+ # distributed under the License is distributed on an "AS IS" BASIS,
18
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
+ # See the License for the specific language governing permissions and
20
+ # limitations under the License.
21
+ #
22
+ # Created by Max Lahey on 6/6/13.
23
+ #
24
+
25
+ module ProctorCam
26
+ module Proctorserv
27
+ class HashedAuthenticator
28
+
29
+ def self.apply_reverse_guid_and_sign(params, customer_identifier, shared_secret)
30
+ params[:guid] = SecureRandom.hex(32)
31
+ params[:customer_id] = customer_identifier
32
+ query_string = params.map{|k,v| "#{k}=#{v}" }.join('&') + shared_secret
33
+ params[:guid].reverse!
34
+ params[:signature] = Digest::SHA256.hexdigest query_string
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,48 @@
1
+ require 'rest-client'
2
+ require 'json'
3
+ require 'proctorserv_api/hashed_authenticator'
4
+
5
+ #
6
+ # rest_request_client.rb
7
+ # ProctorservApi
8
+ #
9
+ # Copyright 2013 ProctorCam, Inc
10
+ #
11
+ # Licensed under the Apache License, Version 2.0 (the "License");
12
+ # you may not use this file except in compliance with the License.
13
+ # You may obtain a copy of the License at
14
+ #
15
+ # http://www.apache.org/licenses/LICENSE-2.0
16
+ #
17
+ # Unless required by applicable law or agreed to in writing, software
18
+ # distributed under the License is distributed on an "AS IS" BASIS,
19
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
+ # See the License for the specific language governing permissions and
21
+ # limitations under the License.
22
+ #
23
+ # Created by Max Lahey on 6/6/13.
24
+ #
25
+
26
+ module ProctorCam
27
+ module Proctorserv
28
+ class RestRequestClient
29
+ attr_accessor :response
30
+
31
+ def make_get_request(url, customer_identifier, shared_secret, params)
32
+ HashedAuthenticator.apply_reverse_guid_and_sign(params, customer_identifier, shared_secret)
33
+ RestClient.get url, :params => params, :accept => :json, :content_type => :json do |response, request, result, &block|
34
+ return response
35
+ end
36
+ end
37
+
38
+ def make_post_request(url, customer_identifier, shared_secret, params)
39
+ HashedAuthenticator.apply_reverse_guid_and_sign(params, customer_identifier, shared_secret)
40
+ RestClient.post url, params.to_json, :accept => :json, :content_type => :json do |response, request, result, &block|
41
+ return response
42
+ end
43
+ end
44
+
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,7 @@
1
+ module ProctorCam
2
+ module Proctorserv
3
+ module ProctorservApi
4
+ VERSION = "1.0.0"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,183 @@
1
+ require 'proctorserv_api/rest_request_client'
2
+ require 'proctorserv_api/exceptions/invalid_client_exception'
3
+ require 'proctorserv_api/exceptions/invalid_ip_exception'
4
+ require 'proctorserv_api/exceptions/invalid_signature_exception'
5
+ require 'proctorserv_api/exceptions/missing_required_parameter_exception'
6
+
7
+ #
8
+ # proctorserv_api.rb
9
+ # ProctorservApi
10
+ #
11
+ # Copyright 2013 ProctorCam, Inc
12
+ #
13
+ # Licensed under the Apache License, Version 2.0 (the "License");
14
+ # you may not use this file except in compliance with the License.
15
+ # You may obtain a copy of the License at
16
+ #
17
+ # http://www.apache.org/licenses/LICENSE-2.0
18
+ #
19
+ # Unless required by applicable law or agreed to in writing, software
20
+ # distributed under the License is distributed on an "AS IS" BASIS,
21
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
+ # See the License for the specific language governing permissions and
23
+ # limitations under the License.
24
+ #
25
+ # Created by Max Lahey on 6/6/13.
26
+ #
27
+
28
+ module ProctorCam
29
+ module Proctorserv
30
+ class ProctorservApi
31
+
32
+ def initialize(api_identifier, shared_secret, service_protocol = "https", service_url = "service.proctorcam.com")
33
+ @service_protocol = service_protocol
34
+ @service_url = service_url
35
+ @api_identifier = api_identifier
36
+ @shared_secret = shared_secret
37
+ end
38
+
39
+ # Get a list of schedulable timeslots (represented as Time objects) between two
40
+ # times for a given test that needs to be scheduled. This API request takes the
41
+ # provided session_duration into account when comparing Proctorserve business hours.
42
+ # The timeslots returned are specific for a test of duration provided.
43
+ #
44
+ # This method will raise exceptions related to authentication (InvalidClientException, InvalidSignatureException, InvalidIpException) or not providing required data (MissingRequiredParameterException)
45
+ #
46
+ # @param [Hash{Symbol => String}] options
47
+ # - :lower_bound (Time or int seconds since epoch) - the earlier of two timestamps to find available timeslots between
48
+ # - :upper_bound (Time or int seconds since epoch) - the later of two timestamps to find available timeslots between
49
+ # - :session_duration (int) - is the length in minutes alloted for this examination
50
+ # @return [Array<Time>] list of Time objects that represent schedulable timeslots in Proctorserve for a test of length session_duration between lower_bound and upper_bound
51
+ def get_available_timeslots_between(options)
52
+ requires_of options, [:lower_bound, :upper_bound, :session_duration]
53
+ url = "#{@service_protocol}://#{@service_url}/#{__method__}"
54
+ convert_times_to_integer options, :lower_bound, :upper_bound
55
+ response = RestRequestClient.new.make_get_request url, @api_identifier, @shared_secret, options
56
+ parsed_response = JSON.parse response
57
+ raise_exception_if_necessary(parsed_response) if response.code != 200
58
+
59
+ parsed_response.map{|timestamp| Time.at(timestamp)}
60
+ end
61
+
62
+ # Get a list of schedulable timeslots (represented as Time objects) around the
63
+ # time for a given test that needs to be scheduled. This API request takes the
64
+ # provided session_duration into account when comparing Proctorserve business hours.
65
+ # The timeslots returned are specific for a test of duration provided. At most
66
+ # 20 slots will be returned
67
+ #
68
+ # This method will raise exceptions related to authentication (InvalidClientException, InvalidSignatureException, InvalidIpException) or not providing required data (MissingRequiredParameterException)
69
+ #
70
+ # @param [Hash{Symbol => String}] options
71
+ # - :time (Time or int seconds since epoch) - time around which to find slots
72
+ # - :num_slots (int) - number of slots to return
73
+ # - :session_duration (int) - length in minutes alloted for this examination
74
+ # @return [Array<Time>] list (length num_slots or 20) of Time objects that represent schedulable timeslots in Proctorserve for a test of length session_duration around time passed in options hash
75
+ def get_available_timeslots_around(options)
76
+ requires_of options, [:time, :num_slots, :session_duration]
77
+ url = "#{@service_protocol}://#{@service_url}/#{__method__}"
78
+ convert_times_to_integer options, :time
79
+ response = RestRequestClient.new.make_get_request url, @api_identifier, @shared_secret, options
80
+ parsed_response = JSON.parse response
81
+ raise_exception_if_necessary(parsed_response) if response.code != 200
82
+
83
+ parsed_response.map{|timestamp| Time.at(timestamp)}
84
+ end
85
+
86
+ # Makes a reservation for a session if the time passed in options is a schedulable time.
87
+ #
88
+ # This method will raise exceptions related to authentication (InvalidClientException, InvalidSignatureException, InvalidIpException) or not providing required data (MissingRequiredParameterException)
89
+ #
90
+ # @param [Hash{Symbol => String}] options
91
+ # - :time (Time or int seconds since epoch) - Scheduable time for examination, as obtained by get_available_timeslots_between or get_available_timeslots_around
92
+ # - :customer_subject_id (String) - Unique identifier in API customer's system for the person taking this test
93
+ # - :customer_client_subject_id (String) - Unique identifier in API customer's client's system for the person taking this test
94
+ # - :client_code (String) - Unique identifier for API customer's client
95
+ # - :reservation_id (String) - Unique identifier representing this test instance in API customer's system
96
+ # - :session_duration (int) - Session length in minutes
97
+ # - :exam_code (String) - Unique identifier representing the group of tests this specific test instance belongs to
98
+ # @return [int] session_id - the Proctorserve id for the created session. Will return nil if the time passed is not scheduable.
99
+ def make_reservation(options)
100
+ requires_of options, [:time, :customer_subject_id, :customer_client_subject_id, :client_code, :reservation_id, :session_duration, :exam_code]
101
+ url = "#{@service_protocol}://#{@service_url}/#{__method__}"
102
+ convert_times_to_integer options, :time
103
+ response = RestRequestClient.new.make_post_request url, @api_identifier, @shared_secret, options
104
+
105
+ parsed_response = JSON.parse response
106
+ raise_exception_if_necessary(parsed_response) if response.code != 200
107
+
108
+ return nil if response.code == 404
109
+
110
+ parsed_response["session_id"]
111
+ end
112
+
113
+ # Makes a reservation for a session if now is a schedulable time.
114
+ #
115
+ # This method will raise exceptions related to authentication (InvalidClientException, InvalidSignatureException, InvalidIpException) or not providing required data (MissingRequiredParameterException)
116
+ #
117
+ # @param [Hash{Symbol => String}] options
118
+ # - :customer_subject_id (String) - Unique identifier in API customer's system for the person taking this test
119
+ # - :customer_client_subject_id (String) - Unique identifier in API customer's client's system for the person taking this test
120
+ # - :client_code (String) - Unique identifier for API customer's client
121
+ # - :reservation_id (String) - Unique identifier representing this test instance in API customer's system
122
+ # - :session_duration (int) - Session length in minutes
123
+ # - :exam_code (String) - Unique identifier representing the group of tests this specific test instance belongs to
124
+ # @return [int] session_id - the Proctorserve id for the created session. Will return nil if the time passed is not scheduable.
125
+ def make_immediate_reservation(options)
126
+ requires_of options, [:customer_subject_id, :customer_client_subject_id, :client_code, :reservation_id, :session_duration, :exam_code]
127
+ url = "#{@service_protocol}://#{@service_url}/#{__method__}"
128
+ convert_times_to_integer options, :time
129
+ response = RestRequestClient.new.make_post_request url, @api_identifier, @shared_secret, options
130
+
131
+ parsed_response = JSON.parse response
132
+ raise_exception_if_necessary(parsed_response) if response.code != 200
133
+
134
+ return nil if response.code == 404
135
+
136
+ parsed_response["session_id"]
137
+ end
138
+
139
+ # Cancels a reservation for a specific session_id. A session is no longer cancelable if it has already begun or the scheduled time has passed.
140
+ #
141
+ # This method will raise exceptions related to authentication (InvalidClientException, InvalidSignatureException, InvalidIpException) or not providing required data (MissingRequiredParameterException)
142
+ #
143
+ # @param [int] session_id Proctorserve id for the session to be canceled
144
+ # @return [Boolean] whether or not the test was successfully canceled.
145
+ def cancel_reservation(options)
146
+ requires_of options, [:session_id]
147
+ url = "#{@service_protocol}://#{@service_url}/#{__method__}"
148
+ response = RestRequestClient.new.make_post_request url, @api_identifier, @shared_secret, options
149
+
150
+ return true if response.code == 204
151
+
152
+ if response.code != 200
153
+ parsed_response = JSON.parse response
154
+ raise_exception_if_necessary(parsed_response)
155
+ end
156
+
157
+ false
158
+ end
159
+
160
+ protected
161
+
162
+ def raise_exception_if_necessary(response)
163
+ case response["message"]
164
+ when "Not a valid client"
165
+ raise InvalidClientException, "The api_identifier for this instance of ProctorservApi does not match up with any for the service."
166
+ when "Signature hash is invalid"
167
+ raise InvalidSignatureException, "Authentication failed for the ProctorservApi request. It is most likely that the shared_secret does not match up with the Proctorserve record for your API client."
168
+ when "Request coming from invalid IP"
169
+ raise InvalidIpException, "Authentication failed for the ProctorservApi request because the IP address of this machine is not whitelisted for this API client in Proctorserve."
170
+ end
171
+ end
172
+
173
+ def requires_of(hash, arguments)
174
+ arguments.each{|argument| raise MissingRequiredParameterException, "#{argument} is a required parameter" unless hash.key? argument}
175
+ end
176
+
177
+ def convert_times_to_integer(hash, *times)
178
+ times.each{|time| hash[time] = hash[time].to_i}
179
+ end
180
+
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,139 @@
1
+ require './lib/proctorserv_api'
2
+ require 'rspec'
3
+
4
+ #
5
+ # proctorserv_api_spec.rb
6
+ # ProctorservApi
7
+ #
8
+ # Copyright 2013 ProctorCam, Inc
9
+ #
10
+ # Licensed under the Apache License, Version 2.0 (the "License");
11
+ # you may not use this file except in compliance with the License.
12
+ # You may obtain a copy of the License at
13
+ #
14
+ # http://www.apache.org/licenses/LICENSE-2.0
15
+ #
16
+ # Unless required by applicable law or agreed to in writing, software
17
+ # distributed under the License is distributed on an "AS IS" BASIS,
18
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
+ # See the License for the specific language governing permissions and
20
+ # limitations under the License.
21
+ #
22
+ # Created by Max Lahey on 6/6/13.
23
+ #
24
+
25
+ describe ProctorCam::Proctorserv::ProctorservApi do
26
+
27
+ before :all do
28
+ @proctorserv_api = ProctorCam::Proctorserv::ProctorservApi.new("api_identifier", "shared_secret", "http", "localhost:3000/api/scheduling")
29
+ end
30
+
31
+ describe "when passed improper credentials" do
32
+
33
+ it "raises an invalid_client_exception when api_identifier is wrong" do
34
+ proctorserv_api = ProctorCam::Proctorserv::ProctorservApi.new("wrong", "shared_secret", "http", "localhost:3000/api/scheduling")
35
+ expect{proctorserv_api.get_available_timeslots_between({:lower_bound => Time.now.to_i, :upper_bound => Time.now.to_i + 24*60*60, :session_duration => 60})}.to raise_error ProctorCam::Proctorserv::InvalidClientException
36
+ end
37
+
38
+ it "raises an invalid_signature_exception when shared_secret is wrong" do
39
+ proctorserv_api = ProctorCam::Proctorserv::ProctorservApi.new("api_identifier", "wrong", "http", "localhost:3000/api/scheduling")
40
+ expect{proctorserv_api.get_available_timeslots_between({:lower_bound => Time.now.to_i, :upper_bound => Time.now.to_i + 24*60*60, :session_duration => 60})}.to raise_error ProctorCam::Proctorserv::InvalidSignatureException
41
+ end
42
+
43
+ end
44
+
45
+ describe "get_available_timeslots_between" do
46
+
47
+ it "raises missing_required_parameter_exception when not passed lower_bound, upper_bound, and session_duration in options hash" do
48
+ expect{@proctorserv_api.get_available_timeslots_between({:lower_bound => Time.now.to_i, :upper_bound => Time.now.to_i + 24*60*60})}.to raise_error ProctorCam::Proctorserv::MissingRequiredParameterException
49
+ expect{@proctorserv_api.get_available_timeslots_between({:lower_bound => Time.now.to_i, :session_duration => 60})}.to raise_error ProctorCam::Proctorserv::MissingRequiredParameterException
50
+ expect{@proctorserv_api.get_available_timeslots_between({:upper_bound => Time.now.to_i + 24*60*60, :session_duration => 60})}.to raise_error ProctorCam::Proctorserv::MissingRequiredParameterException
51
+ end
52
+
53
+ it "returns a list of schedulable timeslots when passed required parameters" do
54
+ response = @proctorserv_api.get_available_timeslots_between({:lower_bound => Time.now.to_i, :upper_bound => Time.now.to_i + 24*60*60, :session_duration => 60})
55
+ response.class.should == Array
56
+ response.length.should > 0
57
+ end
58
+
59
+ end
60
+
61
+ describe "get_available_timeslots_around" do
62
+
63
+ it "raises missing_required_parameter_exception when not passed time, num_slots, and session_duration in options hash" do
64
+ expect{@proctorserv_api.get_available_timeslots_around({:time => Time.now.to_i, :num_slots => 10})}.to raise_error ProctorCam::Proctorserv::MissingRequiredParameterException
65
+ expect{@proctorserv_api.get_available_timeslots_around({:time => Time.now.to_i, :session_duration => 60})}.to raise_error ProctorCam::Proctorserv::MissingRequiredParameterException
66
+ expect{@proctorserv_api.get_available_timeslots_around({:num_slots => 10, :session_duration => 60})}.to raise_error ProctorCam::Proctorserv::MissingRequiredParameterException
67
+ end
68
+
69
+ it "returns a list of schedulable timeslots when passed required parameters" do
70
+ response = @proctorserv_api.get_available_timeslots_around({:time => Time.now.to_i, :num_slots => 10, :session_duration => 60})
71
+ response.class.should == Array
72
+ response.length.should == 10
73
+ end
74
+
75
+ end
76
+
77
+ describe "make_reservation" do
78
+
79
+ it "raises missing_required_parameter_exception when not passed [:time, :customer_subject_id, :customer_client_subject_id, :client_code, :reservation_id, :session_duration, :exam_code] in options hash" do
80
+ options = {:time => Time.now.to_i, :customer_subject_id => 'c_sub_1', :customer_client_subject_id => 'c_c_sub_1', :client_code => 'c_code', :reservation_id => 'res_id', :session_duration => 60, :exam_code => 'e-code-15a'}
81
+ options.each do |k,v|
82
+ expect{@proctorserv_api.make_reservation options.reject{|key,v| key == k} }.to raise_error ProctorCam::Proctorserv::MissingRequiredParameterException
83
+ end
84
+ end
85
+
86
+ it "returns nil when time provided is not schedulable" do
87
+ options = {:time => Time.new(1970, 1, 1, 6, 0, 0), :customer_subject_id => 'c_sub_1', :customer_client_subject_id => 'c_c_sub_1', :client_code => 'c_code', :reservation_id => 'res_id', :session_duration => 60, :exam_code => 'e-code-15a'}
88
+ response = @proctorserv_api.make_reservation options
89
+ response.should == nil
90
+ end
91
+
92
+ it "returns an int value representing session_id when provided a schedulable time and all required parameters" do
93
+ options = {:time => Time.now.to_i, :customer_subject_id => 'c_sub_1', :customer_client_subject_id => 'c_c_sub_1', :client_code => 'c_code', :reservation_id => 'res_id', :session_duration => 60, :exam_code => 'e-code-15a'}
94
+ response = @proctorserv_api.make_reservation options
95
+ response.class.should == Fixnum
96
+ end
97
+
98
+ end
99
+
100
+ describe "make_immediate_reservation" do
101
+
102
+ it "raises missing_required_parameter_exception when not passed [:customer_subject_id, :customer_client_subject_id, :client_code, :reservation_id, :session_duration, :exam_code] in options hash" do
103
+ options = {:customer_subject_id => 'c_sub_1', :customer_client_subject_id => 'c_c_sub_1', :client_code => 'c_code', :reservation_id => 'res_id', :session_duration => 60, :exam_code => 'e-code-15a'}
104
+ options.each do |k,v|
105
+ expect{@proctorserv_api.make_immediate_reservation options.reject{|key,v| key == k} }.to raise_error ProctorCam::Proctorserv::MissingRequiredParameterException
106
+ end
107
+ end
108
+
109
+ it "returns an int value representing session_id when now is a schedulable time and all required parameters" do
110
+ options = {:customer_subject_id => 'c_sub_1', :customer_client_subject_id => 'c_c_sub_1', :client_code => 'c_code', :reservation_id => 'res_id', :session_duration => 60, :exam_code => 'e-code-15a'}
111
+ response = @proctorserv_api.make_immediate_reservation options
112
+ response.class.should == Fixnum
113
+ end
114
+
115
+ end
116
+
117
+ describe "cancel_reservation" do
118
+
119
+ it "raises missing_required_parameter_exception when not passed session_id in options hash" do
120
+ expect{@proctorserv_api.cancel_reservation({})}.to raise_error ProctorCam::Proctorserv::MissingRequiredParameterException
121
+ end
122
+
123
+ it "returns true when passed a session_id that that this client owns that is still cancelable" do
124
+ options = {:time => Time.now.to_i + 24*60*60, :customer_subject_id => 'c_sub_1', :customer_client_subject_id => 'c_c_sub_1', :client_code => 'c_code', :reservation_id => 'res_id', :session_duration => 60, :exam_code => 'e-code-15a'}
125
+ session_id = @proctorserv_api.make_reservation options
126
+ response = @proctorserv_api.cancel_reservation({:session_id => session_id})
127
+ response.should == true
128
+ end
129
+
130
+ it "returns false when passed a session_id that that this client owns that is no longer cancelable" do
131
+ options = {:time => Time.now.to_i - 5, :customer_subject_id => 'c_sub_1', :customer_client_subject_id => 'c_c_sub_1', :client_code => 'c_code', :reservation_id => 'res_id', :session_duration => 60, :exam_code => 'e-code-15a'}
132
+ session_id = @proctorserv_api.make_reservation options
133
+ response = @proctorserv_api.cancel_reservation({:session_id => session_id})
134
+ response.should == false
135
+ end
136
+
137
+ end
138
+
139
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: proctorserv-api
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Max Lahey
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-06-07 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rest-client
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.6.7
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.6.7
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '2.1'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '2.1'
46
+ description: Supports listing timeslots that are available to schedule a test session
47
+ for, scheduling a test session, and canceling a test session.
48
+ email:
49
+ - max@proctorcam.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - lib/proctorserv_api/exceptions/invalid_client_exception.rb
55
+ - lib/proctorserv_api/exceptions/invalid_ip_exception.rb
56
+ - lib/proctorserv_api/exceptions/invalid_signature_exception.rb
57
+ - lib/proctorserv_api/exceptions/missing_required_parameter_exception.rb
58
+ - lib/proctorserv_api/hashed_authenticator.rb
59
+ - lib/proctorserv_api/rest_request_client.rb
60
+ - lib/proctorserv_api/version.rb
61
+ - lib/proctorserv_api.rb
62
+ - LICENSE
63
+ - README.md
64
+ - spec/proctorserv_api_spec.rb
65
+ homepage: http://github.com/proctorcam/proctorserv-api
66
+ licenses: []
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 1.8.23
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: A ruby wrapper around the Proctorserve scheduling API.
89
+ test_files:
90
+ - spec/proctorserv_api_spec.rb
91
+ has_rdoc: