borrow_direct 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +14 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +183 -0
  6. data/Rakefile +11 -0
  7. data/bd_metrics/finditem_measure.rb +61 -0
  8. data/bd_metrics/isbn.txt +1088 -0
  9. data/bd_metrics/lccn.txt +1668 -0
  10. data/bd_metrics/oclc.txt +167 -0
  11. data/borrow_direct.gemspec +30 -0
  12. data/lib/borrow_direct/authentication.rb +55 -0
  13. data/lib/borrow_direct/defaults.rb +38 -0
  14. data/lib/borrow_direct/error.rb +17 -0
  15. data/lib/borrow_direct/find_item.rb +149 -0
  16. data/lib/borrow_direct/generate_query.rb +78 -0
  17. data/lib/borrow_direct/request.rb +185 -0
  18. data/lib/borrow_direct/request_item.rb +119 -0
  19. data/lib/borrow_direct/request_query.rb +124 -0
  20. data/lib/borrow_direct/util.rb +18 -0
  21. data/lib/borrow_direct/version.rb +3 -0
  22. data/lib/borrow_direct.rb +19 -0
  23. data/test/authentication_test.rb +79 -0
  24. data/test/find_item_test.rb +159 -0
  25. data/test/generate_query_test.rb +91 -0
  26. data/test/request_item_test.rb +109 -0
  27. data/test/request_query_test.rb +113 -0
  28. data/test/request_test.rb +141 -0
  29. data/test/support/assertions.rb +23 -0
  30. data/test/support/vcr_filter.rb +45 -0
  31. data/test/test_helper.rb +39 -0
  32. data/test/util_test.rb +32 -0
  33. data/test/vcr_cassettes/Authentication/Makes_a_request_succesfully.yml +52 -0
  34. data/test/vcr_cassettes/Authentication/Raises_for_bad_library_symbol.yml +52 -0
  35. data/test/vcr_cassettes/Authentication/Raises_for_bad_patron_barcode.yml +53 -0
  36. data/test/vcr_cassettes/Authentication/get_auth_id/raises_for_a_bad_library_symbol.yml +52 -0
  37. data/test/vcr_cassettes/Authentication/get_auth_id/raises_for_a_bad_patron_barcode.yml +53 -0
  38. data/test/vcr_cassettes/Authentication/get_auth_id/returns_an_auth_id_for_a_good_request.yml +52 -0
  39. data/test/vcr_cassettes/Authentication/raw_request_to_verify_HTTP_api/.yml +52 -0
  40. data/test/vcr_cassettes/FindItem/_find_item_request/finds_a_locally_available_item.yml +49 -0
  41. data/test/vcr_cassettes/FindItem/_find_item_request/finds_a_requestable_item.yml +49 -0
  42. data/test/vcr_cassettes/FindItem/_find_item_request/finds_an_item_that_does_not_exist_in_BD.yml +50 -0
  43. data/test/vcr_cassettes/FindItem/_find_item_request/with_expected_error_PUBFI002/returns_result.yml +40 -0
  44. data/test/vcr_cassettes/FindItem/_find_item_request/works_with_multiple_values.yml +49 -0
  45. data/test/vcr_cassettes/FindItem/find_with_Response/has_an_auth_id.yml +49 -0
  46. data/test/vcr_cassettes/FindItem/find_with_Response/has_nil_auth_id_when_BD_doesn_t_want_to_give_us_one.yml +40 -0
  47. data/test/vcr_cassettes/FindItem/find_with_Response/has_nil_pickup_locations_when_BD_doesn_t_want_to_give_us_them.yml +40 -0
  48. data/test/vcr_cassettes/FindItem/find_with_Response/has_pickup_locations.yml +49 -0
  49. data/test/vcr_cassettes/FindItem/find_with_Response/not_requestable_for_item_that_BD_returns_PUBFI002.yml +40 -0
  50. data/test/vcr_cassettes/FindItem/find_with_Response/not_requestable_for_item_that_does_not_exist_in_BD.yml +50 -0
  51. data/test/vcr_cassettes/FindItem/find_with_Response/not_requestable_for_item_that_no_libraries_will_lend.yml +50 -0
  52. data/test/vcr_cassettes/FindItem/find_with_Response/not_requestable_for_locally_available_item.yml +49 -0
  53. data/test/vcr_cassettes/FindItem/find_with_Response/requestable_for_requestable_item.yml +49 -0
  54. data/test/vcr_cassettes/FindItem/find_with_Response/requestable_with_multiple_items_if_at_least_one_is_requestable.yml +49 -0
  55. data/test/vcr_cassettes/Request/authentication_id/automatically_fetches_one_when_needed.yml +52 -0
  56. data/test/vcr_cassettes/Request/authentication_id/can_refetch_when_instructed.yml +52 -0
  57. data/test/vcr_cassettes/Request/can_make_a_succesful_request.yml +49 -0
  58. data/test/vcr_cassettes/Request/gets_BD_error_info.yml +41 -0
  59. data/test/vcr_cassettes/Request/raises_on_bad_path.yml +53 -0
  60. data/test/vcr_cassettes/Request/raises_on_bad_request_hash.yml +63 -0
  61. data/test/vcr_cassettes/Request/with_expected_errors/still_returns_result.yml +41 -0
  62. data/test/vcr_cassettes/RequestItem/make_request/make_request_for_a_locally_available_item.yml +90 -0
  63. data/test/vcr_cassettes/RequestItem/make_request/make_request_for_a_requestable_item.yml +89 -0
  64. data/test/vcr_cassettes/RequestItem/make_request/make_request_for_an_unrequestable_item.yml +91 -0
  65. data/test/vcr_cassettes/RequestItem/make_request/raises_for_unrequestable.yml +91 -0
  66. data/test/vcr_cassettes/RequestItem/make_request/returns_number_for_succesful_request.yml +89 -0
  67. data/test/vcr_cassettes/RequestItem/make_request/says_no_for_item_that_BD_returns_PUBRI004.yml +89 -0
  68. data/test/vcr_cassettes/RequestItem/raw_requests_an_unrequestable_item.yml +91 -0
  69. data/test/vcr_cassettes/RequestItem/uses_manually_set_auth_id.yml +89 -0
  70. data/test/vcr_cassettes/RequestItem/with_pickup_location_and_requestable_item/still_works.yml +90 -0
  71. data/test/vcr_cassettes/RequestQuery/raw_request_query_request/returns_results.yml +381 -0
  72. data/test/vcr_cassettes/RequestQuery/raw_request_to_verify_the_BD_HTTP_API.yml +381 -0
  73. data/test/vcr_cassettes/RequestQuery/requests/fetches_default_records.yml +384 -0
  74. data/test/vcr_cassettes/RequestQuery/requests/fetches_full_records.yml +481 -0
  75. data/test/vcr_cassettes/top_level_describe/an_inner_describe/.yml +76 -0
  76. metadata +262 -0
@@ -0,0 +1,185 @@
1
+ require 'json'
2
+ require 'httpclient'
3
+ require 'ostruct'
4
+
5
+ require 'borrow_direct'
6
+
7
+ module BorrowDirect
8
+ # Generic abstract BD request, put in a Hash request body, get
9
+ # back a Hash answer.
10
+ #
11
+ # response_hash = Request.new("/path/to/endpoint").request(request_hash)
12
+ #
13
+ # Typically, clients will use various sub-classes of Request implementing
14
+ # calling of individual BD API's
15
+ #
16
+ # ## AuthenticationID's
17
+ #
18
+ # Some API endpoints require an "AId"/"AuthencationID". BorrowDirect::Request
19
+ # provides some facilities for managing obtaining such (using Authentication API),
20
+ # usually will be used under the hood by Request subclasses.
21
+ #
22
+ # # fetch new auth ID using Authentication API, store it
23
+ # # in self.auth_id
24
+ # request.fetch_auth_id!(barcode, library_symbol)
25
+ #
26
+ # # return the existing value in self.auth_id, or if
27
+ # # nil run fetch_auth_id! to fill it out.
28
+ # request.need_auth_id(barcode, library_symbol)
29
+ #
30
+ # request.auth_id # cached or nil
31
+ class Request
32
+ attr_writer :http_client
33
+ attr_accessor :timeout
34
+ attr_accessor :auth_id
35
+ # default :post, but can be set to :get, usually by a subclass
36
+ attr_accessor :http_method
37
+ attr_reader :last_request_uri, :last_request_json, :last_request_response, :last_request_time
38
+
39
+ # Usually an error code from the server will be turned into an exception.
40
+ # But if there are error codes you expect (usually fixed in a subclass of Request),
41
+ # fill them in this array, and the responses will be returned anyway -- warning,
42
+ # REGARDLESS of HTTP response status code, as these are often non-200 but we want
43
+ # to catch em anyway.
44
+ attr_accessor :expected_error_codes
45
+
46
+ def initialize(path)
47
+ @api_base = Defaults.api_base
48
+ @api_path = path
49
+
50
+ @api_uri = @api_base.chomp("/") + @api_path
51
+
52
+ @expected_error_codes = []
53
+
54
+ @timeout = Defaults.timeout
55
+ @http_method = :post
56
+ end
57
+
58
+ def request(hash)
59
+ http = http_client
60
+
61
+
62
+ # Mostly for debugging, store these
63
+ @last_request_uri = @api_uri
64
+
65
+
66
+ start_time = Time.now
67
+
68
+ if self.http_method == :post
69
+ @last_request_json = json_request = JSON.generate(hash)
70
+ http_response = http.post @api_uri, json_request, self.request_headers
71
+ elsif self.http_method == :get
72
+ @last_request_query_params = hash
73
+ http_response = http.get @api_uri, hash, self.request_headers
74
+ else
75
+ raise ArgumentError.new("BorrowDirect::Request only understands http_method :get and :post, not `#{self.http_method}`")
76
+ end
77
+
78
+ @last_request_response = http_response
79
+ @last_request_time = Time.now - start_time
80
+
81
+ response_hash = begin
82
+ JSON.parse(http_response.body)
83
+ rescue JSON::ParserError => json_parse_exception
84
+ nil
85
+ end
86
+
87
+ # will be nil if we have none
88
+ einfo = error_info(response_hash)
89
+ expected_error = (einfo && self.expected_error_codes.include?(einfo.number))
90
+
91
+
92
+ if einfo && (! expected_error)
93
+ raise BorrowDirect::Error.new(einfo.message, einfo.number)
94
+ elsif http_response.code != 200 && (! expected_error)
95
+ raise BorrowDirect::HttpError.new("HTTP Error: #{http_response.code}: #{http_response.body}")
96
+ elsif response_hash.nil?
97
+ raise BorrowDirect::Error.new("Could not parse expected JSON response: #{http_response.code} #{json_parse_exception}: #{http_response.body}")
98
+ end
99
+
100
+
101
+
102
+ return response_hash
103
+ rescue HTTPClient::ReceiveTimeoutError => e
104
+ elapsed = Time.now - start_time
105
+ raise BorrowDirect::HttpTimeoutError.new("Timeout after #{elapsed}s connecting to BorrowDirect server at #{@api_base}")
106
+ end
107
+
108
+ def http_client
109
+ @http_client ||= make_http_client!
110
+ end
111
+
112
+ # For now, we can send same request headers for all requests. May have to
113
+ # make parameterized later.
114
+ # Note SOME but not all BD API endpoints REQUIRE User-Agent and
115
+ # Accept-Language (for no discernable reason)
116
+ #
117
+ # NOTE WELL: API sometimes requires User-Agent _not to change_ when using
118
+ # an AuthorizationID, or it will revoke your authorization. Need to use the
119
+ # same User-Agent when using an auth_id as you used when receiving it.
120
+ def request_headers
121
+ { "Content-Type" => "application/json",
122
+ "User-Agent" => "ruby borrow_direct gem #{BorrowDirect::VERSION} (HTTPClient #{HTTPClient::VERSION}) https://github.com/jrochkind/borrow_direct",
123
+ "Accept-Language" => "en"
124
+ }
125
+ end
126
+
127
+ # Fetches new authID, stores it in self.auth_id, overwriting
128
+ # any previous value there. Will raise BorrowDirect::Error if no auth
129
+ # could be fetched.
130
+ #
131
+ # returns auth_id too.
132
+ def fetch_auth_id!(barcode, library_symbol)
133
+ auth = Authentication.new(barcode, library_symbol)
134
+ # use the same HTTPClient so we use the same HTTP connection, perhaps
135
+ # slightly more performance worth a shot.
136
+ auth.http_client = http_client
137
+ self.auth_id = auth.get_auth_id
138
+ end
139
+
140
+ # Will use value in self.auth_id, or if nil will
141
+ # fetch a value with fetch_auth_id! and return that.
142
+ def need_auth_id(barcode, library_symbol)
143
+ self.auth_id || fetch_auth_id!(barcode, library_symbol)
144
+ end
145
+
146
+ # Can be used to set an already existing AuthID to be used.
147
+ # Beware, we have no facility for rescuing from escpired auth ids
148
+ # at the moment.
149
+ def with_auth_id(aid)
150
+ self.auth_id = aid
151
+ return self
152
+ end
153
+
154
+
155
+
156
+
157
+ protected
158
+
159
+ def make_http_client!
160
+ http = HTTPClient.new
161
+ if self.timeout
162
+ http.send_timeout = self.timeout
163
+ http.connect_timeout = self.timeout
164
+ http.receive_timeout = self.timeout
165
+ end
166
+
167
+ return http
168
+ end
169
+
170
+ # returns an OpenStruct with #message and #number,
171
+ # or nil if error info can not be extracted
172
+ def error_info(hash)
173
+ if hash && (e = hash["Error"]) && (e["ErrorNumber"] || e["ErrorMessage"])
174
+ return OpenStruct.new(:number => e["ErrorNumber"], :message => e["ErrorMessage"])
175
+ end
176
+
177
+ # Or wait! Some API's have a totally different way of reporting errors, great!
178
+ if hash && (e = hash["Authentication"]) && e["Problem"]
179
+ return OpenStruct.new(:number => e["Problem"]["Code"], :message => e["Problem"]["Message"])
180
+ end
181
+
182
+ return nil
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,119 @@
1
+ require 'borrow_direct'
2
+ require 'borrow_direct/request'
3
+
4
+ module BorrowDirect
5
+ # The BorrowDirect RequestItem service, for placing a request
6
+ # http://borrowdirect.pbworks.com/w/file/86126056/RequestItem.docx
7
+ #
8
+ # You can also use #find_item_request to get the raw BD response as a ruby hash
9
+ class RequestItem < Request
10
+ attr_reader :patron_barcode, :patron_library_symbol
11
+ attr_reader :authorization_id
12
+
13
+ @@api_path = "/dws/item/add"
14
+ @@valid_search_types = %w{ISBN ISSN LCCN OCLC Control }
15
+
16
+
17
+
18
+ def initialize(patron_barcode,
19
+ patron_library_symbol = Defaults.library_symbol)
20
+ super(@@api_path)
21
+
22
+ @patron_barcode = patron_barcode
23
+ @patron_library_symbol = patron_library_symbol
24
+
25
+ # BD sometimes unpredictably returns this error when it means
26
+ # "no results", other times it doens't. We don't want to raise on it.
27
+ self.expected_error_codes << "PUBRI004"
28
+ end
29
+
30
+ # need to send a key and value for a valid exact_search type
31
+ # type can be string or symbol, lowercase or uppercase.
32
+ #
33
+ # Also a pickup_location -- can pass in nil, and we'll send no
34
+ # PickupLocation to BD, which it seems to accept, not sure what it
35
+ # does with it.
36
+ #
37
+ # Returns the actual complete BD response hash. You may want
38
+ # #make_request instead
39
+ #
40
+ # finder.request_item_request(pickup_location, :isbn => "12345545456")
41
+ # finder.request_item_request(pickup_location, :lccn => "12345545456")
42
+ # finder.request_item_request(pickup_location, :oclc => "12345545456")
43
+ def request_item_request(pickup_location, options)
44
+ search_type, search_value = nil, nil
45
+ options.each_pair do |key, value|
46
+ if @@valid_search_types.include? key.to_s.upcase
47
+ if search_type || search_value
48
+ raise ArgumentError.new("Only one search criteria at a time is allowed: '#{options}'")
49
+ end
50
+
51
+ search_type, search_value = key, value
52
+ end
53
+ end
54
+ unless search_type && search_value
55
+ raise ArgumentError.new("Missing valid search type and value: '#{options}'")
56
+ end
57
+
58
+ request exact_search_request_hash(pickup_location, search_type, search_value)
59
+ end
60
+
61
+ # Pass in a BD exact search and pickup location eg
62
+ # make_request(pickup_location, :isbn => isbn)
63
+ #
64
+ # Pass in nil for pickup_location if... not sure exactly what
65
+ # BD will do, but it does allow it.
66
+ #
67
+ # Returns the BD RequestNumber, or nil if a request could
68
+ # not be made
69
+ #
70
+ # See also make_request! to raise if request can not be made
71
+ def make_request(pickup_location, options)
72
+ resp = request_item_request(pickup_location, options)
73
+
74
+ return extract_request_number(resp)
75
+ end
76
+
77
+ # Like make_request, but will raise a BorrowDirect::Error if
78
+ # item can't be requested.
79
+ def make_request!(pickup_location, options)
80
+ resp = request_item_request(pickup_location, options)
81
+
82
+ number = extract_request_number(resp)
83
+
84
+ if number.nil?
85
+ raise BorrowDirect::Error.new("Can not request for: #{options.inspect}: #{resp.inspect}")
86
+ end
87
+
88
+ return number
89
+ end
90
+
91
+ protected
92
+
93
+ def extract_request_number(resp)
94
+ return (resp["Request"] && resp["Request"]["RequestNumber"])
95
+ end
96
+
97
+ def exact_search_request_hash(pickup_location, type, value)
98
+ hash = {
99
+ "PartnershipId" => Defaults.partnership_id,
100
+ "AuthorizationId" => need_auth_id(self.patron_barcode, self.patron_library_symbol),
101
+ "PickupLocation" => pickup_location,
102
+ "ExactSearch" => [
103
+ {
104
+ "Type" => type.to_s.upcase,
105
+ "Value" => value
106
+ }
107
+ ]
108
+ }
109
+
110
+ if pickup_location
111
+ hash["PickupLocation"] = pickup_location
112
+ end
113
+
114
+ return hash
115
+ end
116
+
117
+
118
+ end
119
+ end
@@ -0,0 +1,124 @@
1
+ require 'borrow_direct'
2
+ require 'date'
3
+
4
+ module BorrowDirect
5
+ # Info from Relais/BD on type and status:
6
+ #
7
+ # valid 'type' values for requests:
8
+ #
9
+ # xdays: Retrieve requests submitted within the last xdays (for example, one would include two parameters: type=xdays&xdays=7 to retrieve requests submitted within the last 7 days)
10
+ # all: Retrieve all request submitted by the user
11
+ # open: Retrieve all open requests i.e. requests which haven't been fulfilled yet.
12
+ # allposttoweb: BD doesn't use the post-to-web application; you can ignore this.
13
+ # unopenedposttoweb: You can safely ignore this.
14
+ # onloan: Retrieve requests which are on loan
15
+ #
16
+ # possible RequestStatus values in results:
17
+ #
18
+ # ENTERED: Request has been entered and yet to be processed.
19
+ # IN_PROCESS: Request is being processed.
20
+ # CANCELLED: Request has been cancelled.
21
+ # UNFILLED: Request can't be filled.
22
+ # SHIPPED: Item has been shipped.
23
+ # ARTICLE_SENT: A scanned document or an electronic document has been sent (It doesn't apply to BD)
24
+ # ON_LOAN: Request is on loan.
25
+ # OVERDUE: Item is over due.
26
+ # COMPLETE: Item has been returned and request is completed.
27
+ # UNKNOWN: You should never see this; this indicates there is probably an inconsistency with the record somewhere. You probably want to flag and report this.
28
+ class RequestQuery < Request
29
+ attr_reader :patron_barcode, :patron_library_symbol
30
+
31
+ @@api_path = "/portal-service/request/query/my"
32
+
33
+ # I'm not exactly sure what these mean either.
34
+ @@query_types = %w{xdays all open allposttoweb unopenedposttoweb onloan}
35
+
36
+
37
+ def initialize(patron_barcode,
38
+ patron_library_symbol = Defaults.library_symbol)
39
+ super(@@api_path)
40
+
41
+ @patron_barcode = patron_barcode
42
+ @patron_library_symbol = patron_library_symbol
43
+ self.http_method = :get
44
+ end
45
+
46
+ # Returns raw BD response as a hash.
47
+ # * type defaults to 'all', but can be BD values of xdays, all
48
+ # open, allposttoweb, unopenedposttoweb, onloan.
49
+ # xdays not really supported yet, cause no way to pass an xdays param yet
50
+ # * full_record can be true or false, defaults to false.
51
+ def request_query_request(type = "all", full_record = false)
52
+ query_params = {
53
+ "aid" => need_auth_id(patron_barcode, patron_library_symbol),
54
+ "type" => type.to_s,
55
+ "fullRecord" => (full_record ? "1" : "0")
56
+ }
57
+
58
+ request query_params
59
+ end
60
+
61
+ # Returns an array of BorrowDirect::RequestQuery::Item
62
+ # * type defaults to 'all', but can be BD values of xdays, all
63
+ # open, allposttoweb, unopenedposttoweb, onloan.
64
+ # xdays not really supported yet, cause no way to pass an xdays param yet
65
+ # * full_record can be true or false, defaults to false.
66
+ def requests(*args)
67
+ response = request_query_request(*args)
68
+
69
+ results = []
70
+
71
+ response["QueryResult"]["MyRequestRecords"].each do |item_hash|
72
+ results << BorrowDirect::RequestQuery::Item.new(item_hash)
73
+ end
74
+
75
+ return results
76
+ end
77
+
78
+ class Item
79
+ # fullRecord == 0 values
80
+ attr_reader :request_number, :title, :date_submitted, :allow_renew,
81
+ :allow_cancel, :request_status, :request_status_date
82
+ # fullRecord == 1 values, not all are applicable for BorrowDirect,
83
+ # and many may be nil.
84
+ attr_reader :publication_type, :publication_date, :publication_place,
85
+ :volume, :issue, :edition, :issn, :issn2, :isbn, :isbn2,
86
+ :ismn, :pages_requested, :delivery_date
87
+
88
+ def initialize(hash)
89
+ # basic record values
90
+ @request_number = hash["RequestNumber"]
91
+ @title = hash["Title"]
92
+ @date_submitted = DateTime.iso8601 hash["ISO8601DateSubmitted"]
93
+ @allow_renew = hash["AllowRenew"]
94
+ @allow_cancel = hash["AllowCancel"]
95
+ @request_status = hash["RequestStatus"]
96
+ @request_status_date = DateTime.iso8601 hash["ISO8601RequestStatusDate"]
97
+
98
+ # full record values
99
+ @publicaition_type = hash["PublicationType"]
100
+ @publication_date = hash["PublicationDate"] # BD just gives us a string
101
+ @publication_place = hash["PublicationPlace"]
102
+ @volume = hash["Volume"]
103
+ @issue = hash["Issue"]
104
+ @edition = hash["Edition"]
105
+ @issn = hash["Issn"]
106
+ @issn2 = hash["Issn2"]
107
+ @isbn = hash["Isbn"]
108
+ @isbn2 = hash["Isbn2"]
109
+ @ismn = hash["Ismn"]
110
+ @pages_requested = hash["PagesRequested"]
111
+ if hash["ISO8601DeliveryDate"]
112
+ @delivery_date = DateTime.iso8601 hash["ISO8601DeliveryDate"]
113
+ end
114
+ end
115
+ end
116
+
117
+ end
118
+
119
+
120
+
121
+
122
+
123
+
124
+ end
@@ -0,0 +1,18 @@
1
+ module BorrowDirect
2
+ module Util
3
+ # A utility method that lets you access a nested hash,
4
+ # returning nil if any intermediate hashes are unavailable.
5
+ def hash_key_path(hash, *path)
6
+ result = nil
7
+
8
+ path.each do |key|
9
+ return nil unless hash.respond_to? :"[]"
10
+ result = hash = hash[key]
11
+ end
12
+
13
+ return result
14
+ end
15
+ module_function :hash_key_path
16
+
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module BorrowDirect
2
+ VERSION = "0.9.0"
3
+ end
@@ -0,0 +1,19 @@
1
+ require "borrow_direct/version"
2
+
3
+ require 'borrow_direct/defaults'
4
+ require 'borrow_direct/error'
5
+ require 'borrow_direct/util'
6
+
7
+ require 'borrow_direct/authentication'
8
+
9
+ require 'borrow_direct/request'
10
+ require 'borrow_direct/find_item'
11
+ require 'borrow_direct/request_item'
12
+ require 'borrow_direct/request_query'
13
+
14
+ require 'borrow_direct/generate_query'
15
+
16
+
17
+ module BorrowDirect
18
+
19
+ end
@@ -0,0 +1,79 @@
1
+ require 'test_helper'
2
+ require 'json'
3
+ require 'httpclient'
4
+
5
+
6
+ describe "Authentication", :vcr => {:tag => :bd_auth} do
7
+ describe "raw request to verify HTTP api" do
8
+ it "works" do
9
+ uri = BorrowDirect::Defaults.api_base.chomp("/") + "/portal-service/user/authentication/patron"
10
+
11
+
12
+ request_hash = {
13
+ "AuthenticationInformation" => {
14
+ "LibrarySymbol" => VCRFilter[:bd_library_symbol],
15
+ "PatronId" => VCRFilter[:bd_patron]
16
+ }
17
+ }
18
+
19
+ http = HTTPClient.new
20
+ response = http.post uri, JSON.generate(request_hash), {"Content-Type" => "application/json", "User-Agent" => "ruby borrow_direct gem (#{BorrowDirect::VERSION}) https://github.com/jrochkind/borrow_direct", "Accept-Language" => "en"}
21
+
22
+ assert_equal 200, response.code
23
+ assert_present response.body
24
+
25
+ response_hash = JSON.parse response.body
26
+
27
+ assert_present response_hash
28
+
29
+ assert_present response_hash["Authentication"]["AuthnUserInfo"]["AId"]
30
+ end
31
+ end
32
+
33
+ it "Makes a request succesfully" do
34
+ bd = BorrowDirect::Authentication.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol])
35
+ response = bd.authentication_request
36
+
37
+ assert_present response
38
+ assert_present response["Authentication"]["AuthnUserInfo"]["AId"]
39
+ end
40
+
41
+ it "Raises for bad library symbol" do
42
+ bd = BorrowDirect::Authentication.new(VCRFilter[:bd_patron] , "BAD_SYMBOL")
43
+ assert_raises(BorrowDirect::Error) do
44
+ bd.authentication_request
45
+ end
46
+ end
47
+
48
+ it "Raises for bad patron barcode" do
49
+ bd = BorrowDirect::Authentication.new("BAD_BARCODE", VCRFilter[:bd_library_symbol])
50
+ assert_raises(BorrowDirect::Error) do
51
+ bd.authentication_request
52
+ end
53
+ end
54
+
55
+ describe "get_auth_id" do
56
+ it "returns an auth_id for a good request" do
57
+ bd = BorrowDirect::Authentication.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol])
58
+ assert_present bd.get_auth_id
59
+ end
60
+
61
+ it "raises for a bad library symbol" do
62
+ bd = BorrowDirect::Authentication.new(VCRFilter[:bd_patron] , "BAD_SYMBOL")
63
+ assert_raises(BorrowDirect::Error) do
64
+ bd.get_auth_id
65
+ end
66
+ end
67
+
68
+ it "raises for a bad patron barcode" do
69
+ bd = BorrowDirect::Authentication.new("BAD_BARCODE", VCRFilter[:bd_library_symbol])
70
+ assert_raises(BorrowDirect::Error) do
71
+ bd.get_auth_id
72
+ end
73
+ end
74
+
75
+ end
76
+
77
+
78
+
79
+ end