proctorserv-api 1.0.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.
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: