borrow_direct 1.1.0 → 1.2.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +5 -13
  2. data/.travis.yml +6 -0
  3. data/Gemfile +2 -0
  4. data/README.md +19 -6
  5. data/bd_metrics/finditem_measure.rb +8 -1
  6. data/borrow_direct.gemspec +1 -1
  7. data/lib/borrow_direct/authentication.rb +16 -8
  8. data/lib/borrow_direct/defaults.rb +4 -1
  9. data/lib/borrow_direct/encryption.rb +34 -0
  10. data/lib/borrow_direct/error.rb +17 -0
  11. data/lib/borrow_direct/find_item.rb +32 -18
  12. data/lib/borrow_direct/pickup_location.rb +32 -0
  13. data/lib/borrow_direct/request.rb +30 -8
  14. data/lib/borrow_direct/request_item.rb +15 -7
  15. data/lib/borrow_direct/request_query.rb +18 -4
  16. data/lib/borrow_direct/version.rb +1 -1
  17. data/test/authentication_test.rb +40 -12
  18. data/test/encryption_test.rb +58 -0
  19. data/test/find_item_test.rb +66 -11
  20. data/test/request_item_test.rb +65 -8
  21. data/test/request_query_test.rb +23 -27
  22. data/test/request_test.rb +40 -27
  23. data/test/test_helper.rb +10 -1
  24. data/test/vcr_cassettes/Authentication/Makes_a_request_succesfully.yml +11 -23
  25. data/test/vcr_cassettes/Authentication/Raises_for_bad_library_symbol.yml +12 -23
  26. data/test/vcr_cassettes/Authentication/Raises_for_bad_patron_barcode.yml +12 -24
  27. data/test/vcr_cassettes/Authentication/get_auth_id/Raises_for_bad_api_key.yml +41 -0
  28. data/test/vcr_cassettes/Authentication/get_auth_id/raises_for_a_bad_library_symbol.yml +12 -23
  29. data/test/vcr_cassettes/Authentication/get_auth_id/raises_for_a_bad_patron_barcode.yml +12 -24
  30. data/test/vcr_cassettes/Authentication/get_auth_id/returns_an_auth_id_for_a_good_request.yml +11 -23
  31. data/test/vcr_cassettes/Authentication/get_auth_id/returns_auth_id_with_API_key_from_defaults.yml +40 -0
  32. data/test/vcr_cassettes/Authentication/raw_request_to_verify_HTTP_api/works.yml +11 -23
  33. data/test/vcr_cassettes/FindItem/_find_item_request/Raises_with_bad_api_key.yml +41 -0
  34. data/test/vcr_cassettes/FindItem/_find_item_request/finds_a_locally_available_item.yml +47 -18
  35. data/test/vcr_cassettes/FindItem/_find_item_request/finds_a_requestable_item.yml +66 -18
  36. data/test/vcr_cassettes/FindItem/_find_item_request/finds_an_item_that_does_not_exist_in_BD.yml +66 -19
  37. data/test/vcr_cassettes/FindItem/_find_item_request/raises_proper_error_on_bad_AID.yml +40 -0
  38. data/test/vcr_cassettes/FindItem/_find_item_request/uses_manually_set_auth_id.yml +97 -0
  39. data/test/vcr_cassettes/FindItem/_find_item_request/with_expected_error_PUBFI002/returns_result.yml +46 -9
  40. data/test/vcr_cassettes/FindItem/_find_item_request/works_with_multiple_values.yml +66 -18
  41. data/test/vcr_cassettes/FindItem/find_with_Response/_pickup_location_data/returns_array_of_PickupLocations.yml +97 -0
  42. data/test/vcr_cassettes/FindItem/find_with_Response/has_an_auth_id.yml +66 -18
  43. data/test/vcr_cassettes/FindItem/find_with_Response/has_nil_pickup_locations_when_BD_doesn_t_want_to_give_us_them.yml +46 -9
  44. data/test/vcr_cassettes/FindItem/find_with_Response/has_pickup_locations.yml +66 -18
  45. data/test/vcr_cassettes/FindItem/find_with_Response/knows_locally_available_.yml +47 -18
  46. data/test/vcr_cassettes/FindItem/find_with_Response/not_requestable_for_item_that_BD_returns_PUBFI002.yml +46 -9
  47. data/test/vcr_cassettes/FindItem/find_with_Response/not_requestable_for_item_that_does_not_exist_in_BD.yml +46 -19
  48. data/test/vcr_cassettes/FindItem/find_with_Response/not_requestable_for_item_that_no_libraries_will_lend.yml +275 -18
  49. data/test/vcr_cassettes/FindItem/find_with_Response/not_requestable_for_locally_available_item.yml +47 -18
  50. data/test/vcr_cassettes/FindItem/find_with_Response/requestable_for_requestable_item.yml +66 -18
  51. data/test/vcr_cassettes/FindItem/find_with_Response/requestable_with_multiple_items_if_at_least_one_is_requestable.yml +66 -18
  52. data/test/vcr_cassettes/Request/authentication_id/automatically_fetches_one_when_needed.yml +47 -22
  53. data/test/vcr_cassettes/Request/authentication_id/can_refetch_when_instructed.yml +47 -22
  54. data/test/vcr_cassettes/Request/authentication_id/manually_set_one_will_be_used_without_fetch.yml +40 -0
  55. data/test/vcr_cassettes/Request/authentication_id/starts_out_nil.yml +40 -0
  56. data/test/vcr_cassettes/Request/authentication_id/takes_with_auth_id.yml +40 -0
  57. data/test/vcr_cassettes/Request/can_make_a_succesful_request_with_AID.yml +97 -0
  58. data/test/vcr_cassettes/Request/gets_BD_error_info.yml +49 -12
  59. data/test/vcr_cassettes/Request/gets_BD_error_info_from_a_bad_AID.yml +77 -0
  60. data/test/vcr_cassettes/Request/raises_exception_on_timeout_live.yml +40 -0
  61. data/test/vcr_cassettes/Request/raises_on_bad_path.yml +61 -24
  62. data/test/vcr_cassettes/Request/raises_on_bad_request_hash.yml +50 -35
  63. data/test/vcr_cassettes/Request/uses_timeout_for_HttpClient.yml +40 -0
  64. data/test/vcr_cassettes/Request/with_expected_errors/still_returns_result.yml +47 -10
  65. data/test/vcr_cassettes/RequestItem/make_request/make_request_for_a_locally_available_item.yml +21 -33
  66. data/test/vcr_cassettes/RequestItem/make_request/make_request_for_a_requestable_item.yml +20 -32
  67. data/test/vcr_cassettes/RequestItem/make_request/make_request_for_an_unrequestable_item.yml +21 -33
  68. data/test/vcr_cassettes/RequestItem/make_request/says_no_for_item_that_BD_returns_PUBRI003.yml +77 -0
  69. data/test/vcr_cassettes/RequestItem/make_request/sets_an_auth_id.yml +77 -0
  70. data/test/vcr_cassettes/RequestItem/make_request_/raises_for_unrequestable.yml +21 -33
  71. data/test/vcr_cassettes/RequestItem/make_request_/returns_number_for_succesful_request.yml +20 -32
  72. data/test/vcr_cassettes/RequestItem/raises_proper_error_on_bad_AID.yml +40 -0
  73. data/test/vcr_cassettes/RequestItem/raw_RequestItem_sanity_check.yml +134 -0
  74. data/test/vcr_cassettes/RequestItem/raw_requests_an_unrequestable_item.yml +21 -33
  75. data/test/vcr_cassettes/RequestItem/uses_manually_set_auth_id.yml +20 -32
  76. data/test/vcr_cassettes/RequestItem/with_pickup_location_and_requestable_item/works_with_String_pickup_location.yml +78 -0
  77. data/test/vcr_cassettes/RequestItem/with_pickup_location_and_requestable_item/works_with_structured_PickupLocation.yml +77 -0
  78. data/test/vcr_cassettes/RequestQuery/raises_proper_error_on_bad_AID.yml +40 -0
  79. data/test/vcr_cassettes/RequestQuery/raw_request_query_request/returns_results.yml +117 -325
  80. data/test/vcr_cassettes/RequestQuery/raw_request_to_verify_the_BD_HTTP_API.yml +30 -325
  81. data/test/vcr_cassettes/RequestQuery/requests/fetches_default_records.yml +117 -328
  82. data/test/vcr_cassettes/RequestQuery/requests/fetches_full_records.yml +148 -425
  83. metadata +67 -38
  84. data/test/vcr_cassettes/Authentication/raw_request_to_verify_HTTP_api/.yml +0 -52
  85. data/test/vcr_cassettes/FindItem/find_with_Response/has_nil_auth_id_when_BD_doesn_t_want_to_give_us_one.yml +0 -40
  86. data/test/vcr_cassettes/Request/can_make_a_succesful_request.yml +0 -49
  87. data/test/vcr_cassettes/RequestItem/make_request/raises_for_unrequestable.yml +0 -91
  88. data/test/vcr_cassettes/RequestItem/make_request/returns_number_for_succesful_request.yml +0 -89
  89. data/test/vcr_cassettes/RequestItem/make_request/says_no_for_item_that_BD_returns_PUBRI004.yml +0 -89
  90. data/test/vcr_cassettes/RequestItem/with_pickup_location_and_requestable_item/still_works.yml +0 -90
  91. data/test/vcr_cassettes/top_level_describe/an_inner_describe/.yml +0 -76
@@ -6,14 +6,15 @@ require 'httpclient'
6
6
  describe "Authentication", :vcr => {:tag => :bd_auth} do
7
7
  describe "raw request to verify HTTP api" do
8
8
  it "works" do
9
- uri = BorrowDirect::Defaults.api_base.chomp("/") + "/portal-service/user/authentication/patron"
9
+ uri = BorrowDirect::Defaults.api_base.chomp("/") + "/portal-service/user/authentication"
10
10
 
11
11
 
12
12
  request_hash = {
13
- "AuthenticationInformation" => {
14
- "LibrarySymbol" => VCRFilter[:bd_library_symbol],
15
- "PatronId" => VCRFilter[:bd_patron]
16
- }
13
+ "ApiKey" => VCRFilter[:bd_api_key],
14
+ "PartnershipId" => BorrowDirect::Defaults.partnership_id,
15
+ "UserGroup" => "patron",
16
+ "LibrarySymbol" => VCRFilter[:bd_library_symbol],
17
+ "PatronId" => VCRFilter[:bd_patron]
17
18
  }
18
19
 
19
20
  http = HTTPClient.new
@@ -26,47 +27,74 @@ describe "Authentication", :vcr => {:tag => :bd_auth} do
26
27
 
27
28
  assert_present response_hash
28
29
 
29
- assert_present response_hash["Authentication"]["AuthnUserInfo"]["AId"]
30
+ assert_present response_hash["AuthorizationId"]
30
31
  end
31
32
  end
32
33
 
33
34
  it "Makes a request succesfully" do
34
- bd = BorrowDirect::Authentication.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol])
35
+ bd = BorrowDirect::Authentication.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol], VCRFilter[:bd_api_key])
35
36
  response = bd.authentication_request
36
37
 
37
38
  assert_present response
38
- assert_present response["Authentication"]["AuthnUserInfo"]["AId"]
39
+ assert_present response["AuthorizationId"]
39
40
  end
40
41
 
42
+
43
+
41
44
  it "Raises for bad library symbol" do
42
- bd = BorrowDirect::Authentication.new(VCRFilter[:bd_patron] , "BAD_SYMBOL")
45
+ bd = BorrowDirect::Authentication.new(VCRFilter[:bd_patron] , "BAD_SYMBOL", VCRFilter[:bd_api_key])
43
46
  assert_raises(BorrowDirect::Error) do
44
47
  bd.authentication_request
45
48
  end
46
49
  end
47
50
 
48
51
  it "Raises for bad patron barcode" do
49
- bd = BorrowDirect::Authentication.new("BAD_BARCODE", VCRFilter[:bd_library_symbol])
52
+ bd = BorrowDirect::Authentication.new("BAD_BARCODE", VCRFilter[:bd_library_symbol], VCRFilter[:bd_api_key])
50
53
  assert_raises(BorrowDirect::Error) do
51
54
  bd.authentication_request
52
55
  end
53
56
  end
54
57
 
58
+ it "Raises with no api_key" do
59
+ begin
60
+ orig_api_key = BorrowDirect::Defaults.api_key
61
+ BorrowDirect::Defaults.api_key = nil
62
+
63
+ assert_raises(ArgumentError) do
64
+ bd = BorrowDirect::Authentication.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol])
65
+ end
66
+ ensure
67
+ BorrowDirect::Defaults.api_key = orig_api_key
68
+ end
69
+ end
70
+
71
+
55
72
  describe "get_auth_id" do
56
73
  it "returns an auth_id for a good request" do
74
+ bd = BorrowDirect::Authentication.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol], VCRFilter[:bd_api_key])
75
+ assert_present bd.get_auth_id
76
+ end
77
+
78
+ it "returns auth_id with API key from defaults" do
57
79
  bd = BorrowDirect::Authentication.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol])
58
80
  assert_present bd.get_auth_id
59
81
  end
60
82
 
83
+ it "Raises for bad api_key" do
84
+ assert_raises(BorrowDirect::Error) do
85
+ bd = BorrowDirect::Authentication.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol], "BAD_API_KEY").get_auth_id
86
+ end
87
+ end
88
+
61
89
  it "raises for a bad library symbol" do
62
- bd = BorrowDirect::Authentication.new(VCRFilter[:bd_patron] , "BAD_SYMBOL")
90
+ bd = BorrowDirect::Authentication.new(VCRFilter[:bd_patron] , "BAD_SYMBOL", VCRFilter[:bd_api_key])
63
91
  assert_raises(BorrowDirect::Error) do
64
92
  bd.get_auth_id
65
93
  end
66
94
  end
67
95
 
68
96
  it "raises for a bad patron barcode" do
69
- bd = BorrowDirect::Authentication.new("BAD_BARCODE", VCRFilter[:bd_library_symbol])
97
+ bd = BorrowDirect::Authentication.new("BAD_BARCODE", VCRFilter[:bd_library_symbol], VCRFilter[:bd_api_key])
70
98
  assert_raises(BorrowDirect::Error) do
71
99
  bd.get_auth_id
72
100
  end
@@ -0,0 +1,58 @@
1
+ require 'test_helper'
2
+ require 'borrow_direct/encryption'
3
+
4
+ describe "Relais Encryption" do
5
+ before do
6
+ @sample_private_key = <<-EOS
7
+ -----BEGIN RSA PRIVATE KEY-----
8
+ MIICXAIBAAKBgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4eCZ0FPqri0cb2JZfXJ/DgYSF6vUp
9
+ wmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RKNUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ5
10
+ 1s1SPrCBkedbNf0Tp0GbMJDyR4e9T04ZZwIDAQABAoGAFijko56+qGyN8M0RVyaRAXz++xTqHBLh
11
+ 3tx4VgMtrQ+WEgCjhoTwo23KMBAuJGSYnRmoBZM3lMfTKevIkAidPExvYCdm5dYq3XToLkkLv5L2
12
+ pIIVOFMDG+KESnAFV7l2c+cnzRMW0+b6f8mR1CJzZuxVLL6Q02fvLi55/mbSYxECQQDeAw6fiIQX
13
+ GukBI4eMZZt4nscy2o12KyYner3VpoeE+Np2q+Z3pvAMd/aNzQ/W9WaI+NRfcxUJrmfPwIGm63il
14
+ AkEAxCL5HQb2bQr4ByorcMWm/hEP2MZzROV73yF41hPsRC9m66KrheO9HPTJuo3/9s5p+sqGxOlF
15
+ L0NDt4SkosjgGwJAFklyR1uZ/wPJjj611cdBcztlPdqoxssQGnh85BzCj/u3WqBpE2vjvyyvyI5k
16
+ X6zk7S0ljKtt2jny2+00VsBerQJBAJGC1Mg5Oydo5NwD6BiROrPxGo2bpTbu/fhrT8ebHkTz2epl
17
+ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
18
+ 37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=
19
+ -----END RSA PRIVATE KEY-----
20
+ EOS
21
+
22
+ @sample_public_key = <<-EOS
23
+ -----BEGIN PUBLIC KEY-----
24
+ MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4eCZ0
25
+ FPqri0cb2JZfXJ/DgYSF6vUpwmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RKNUSesmQRMSGkVb1/
26
+ 3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0Tp0GbMJDyR4e9T04ZZwIDAQAB
27
+ -----END PUBLIC KEY-----
28
+ EOS
29
+ end
30
+
31
+ describe "timestamp" do
32
+ it "creates in GMT" do
33
+ timestamp = BorrowDirect::Encryption.new(@sample_public_key).now_timestamp
34
+
35
+ utc_date = Time.now.utc.to_date
36
+
37
+ assert timestamp =~ /(\d{4})(\d{2})(\d{2}) \d{6}/
38
+
39
+ assert_equal utc_date.year.to_s, $1
40
+ assert_equal "%02d" % utc_date.month, $2
41
+ assert_equal "%02d" % utc_date.day, $3
42
+ end
43
+ end
44
+
45
+ describe "encrypted value" do
46
+ it "is encrypted with datestamp properly" do
47
+ original_value = "$$VALUE$$"
48
+ encrypted = BorrowDirect::Encryption.new(@sample_public_key).encode_with_ts(original_value)
49
+ encrypted = Base64.decode64(encrypted)
50
+
51
+ # Let's decrypt it and see
52
+ private_key = OpenSSL::PKey::RSA.new(@sample_private_key)
53
+ payload = private_key.private_decrypt(encrypted)
54
+
55
+ assert payload =~ /#{original_value}|\d{8} \d{6}/
56
+ end
57
+ end
58
+ end
@@ -4,12 +4,13 @@ require 'borrow_direct/find_item'
4
4
 
5
5
 
6
6
 
7
- describe "FindItem", :vcr do
7
+ describe "FindItem", :vcr => {:tag => :bd_finditem }do
8
8
  before do
9
9
  @requestable_item_isbn = "9810743734" # item is in BD, and can be requested
10
10
  @locally_avail_item_isbn = "0745649890" # item is in BD, but is avail locally so not BD-requestable
11
- @not_requestable_item_isbn = "1441190090" # in BD, and we don't have it, but no libraries let us borrow (in this case, it's an ebook)
11
+ @not_requestable_item_isbn = "1444367072" # in BD, and we don't have it, but no libraries let us borrow (in this case, it's an ebook)
12
12
  @returns_PUBFI002_ISBN = "0109836413" # BD returns an error PUBFI002 for this one, which we want to treat as simply not available.
13
+ @not_in_BD_at_all_isbn = "1898989898" # Not in BD at all, made up ISBN, invalid.
13
14
  end
14
15
 
15
16
 
@@ -39,9 +40,12 @@ describe "FindItem", :vcr do
39
40
  finder = BorrowDirect::FindItem.new("barcodeX", "libraryX")
40
41
  hash = finder.send(:exact_search_request_hash, :isbn, "2")
41
42
 
43
+
42
44
  assert_equal BorrowDirect::Defaults.partnership_id, hash["PartnershipId"]
43
- assert_equal "barcodeX", hash["Credentials"]["Barcode"]
44
- assert_equal "libraryX", hash["Credentials"]["LibrarySymbol"]
45
+
46
+ # These aren't there anymore.
47
+ #assert_equal "barcodeX", hash["Credentials"]["Barcode"]
48
+ #assert_equal "libraryX", hash["Credentials"]["LibrarySymbol"]
45
49
 
46
50
  assert_equal "ISBN", hash["ExactSearch"].first["Type"]
47
51
  assert_equal "2", hash["ExactSearch"].first["Value"]
@@ -80,11 +84,42 @@ describe "FindItem", :vcr do
80
84
  end
81
85
  end
82
86
 
87
+ it "raises proper error on bad AID" do
88
+ e = assert_raises(BorrowDirect::InvalidAidError) do
89
+ BorrowDirect::FindItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).with_auth_id("bad_expired_aid").find_item_request(:isbn => @requestable_item_isbn)
90
+ end
91
+ assert_present e.message
92
+ assert_present e.bd_code
93
+ assert_present e.aid
94
+ end
95
+
96
+ it "Raises with bad api_key" do
97
+ begin
98
+ orig_api_key = BorrowDirect::Defaults.api_key
99
+ BorrowDirect::Defaults.api_key = "BADAPIKEY"
100
+
101
+ assert_raises(BorrowDirect::Error) do
102
+ BorrowDirect::FindItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).find_item_request(:isbn => @requestable_item_isbn)
103
+ end
104
+ ensure
105
+ BorrowDirect::Defaults.api_key = orig_api_key
106
+ end
107
+ end
108
+
83
109
 
84
110
  it "finds a requestable item" do
85
111
  assert_present BorrowDirect::FindItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).find_item_request(:isbn => @requestable_item_isbn)
86
112
  end
87
113
 
114
+ it "uses manually set auth_id" do
115
+ auth_id = BorrowDirect::Authentication.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).get_auth_id
116
+ bd = BorrowDirect::FindItem.new("bad_patron" , "bad_symbol").with_auth_id(auth_id)
117
+ resp = bd.find_item_request(:isbn => @requestable_item_isbn)
118
+
119
+ assert_present resp
120
+ assert_equal true, resp["Available"]
121
+ end
122
+
88
123
  it "finds a locally available item" do
89
124
  assert_present BorrowDirect::FindItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).find_item_request(:isbn => @locally_avail_item_isbn)
90
125
  end
@@ -113,8 +148,10 @@ describe "FindItem", :vcr do
113
148
  assert_equal true, @find_item.find(:isbn => @requestable_item_isbn).requestable?
114
149
  end
115
150
 
151
+
152
+
116
153
  it "requestable with multiple items if at least one is requestable" do
117
- assert_equal true, @find_item.find(:isbn => [@requestable_item_isbn, "NO_SUCH_ISBN"]).requestable?
154
+ assert_equal true, @find_item.find(:isbn => [@requestable_item_isbn, @not_in_BD_at_all_isbn]).requestable?
118
155
  end
119
156
 
120
157
  it "not requestable for locally available item" do
@@ -126,7 +163,7 @@ describe "FindItem", :vcr do
126
163
  end
127
164
 
128
165
  it "not requestable for item that does not exist in BD" do
129
- assert_equal false, @find_item.find(:isbn => "NO_SUCH_THING").requestable?
166
+ assert_equal false, @find_item.find(:isbn => @not_in_BD_at_all_isbn).requestable?
130
167
  end
131
168
 
132
169
  it "not requestable for item that no libraries will lend" do
@@ -138,18 +175,36 @@ describe "FindItem", :vcr do
138
175
  end
139
176
 
140
177
  it "has an auth_id" do
178
+ assert @find_item.auth_id.nil?
141
179
  assert_present @find_item.find(:isbn => @requestable_item_isbn).auth_id
142
- end
143
-
144
- it "has nil auth_id when BD doesn't want to give us one" do
145
- assert_nil @find_item.find(:isbn => @returns_PUBFI002_ISBN).auth_id
146
- end
180
+ assert_present @find_item.auth_id
181
+ end
147
182
 
148
183
  it "has pickup locations" do
149
184
  pickup_locations = @find_item.find(:isbn => @requestable_item_isbn).pickup_locations
150
185
 
151
186
  assert_present pickup_locations
152
187
  assert_kind_of Array, pickup_locations
188
+ pickup_locations.each do |location|
189
+ assert_kind_of String, location
190
+ end
191
+ end
192
+
193
+ describe "#pickup_location_data" do
194
+ it "returns array of PickupLocations" do
195
+ pickup_locations = @find_item.find(:isbn => @requestable_item_isbn).pickup_location_data
196
+
197
+ assert_present pickup_locations
198
+ assert_kind_of Array, pickup_locations
199
+ pickup_locations.each do |location|
200
+ assert_kind_of BorrowDirect::PickupLocation, location
201
+ assert_present location.code
202
+ assert_present location.description
203
+
204
+ assert_equal [location.description, location.code], location.to_a
205
+ assert_equal( {"PickupLocationCode" => location.code, "PickupLocationDescription" => location.description}, location.to_h )
206
+ end
207
+ end
153
208
  end
154
209
 
155
210
  it "has nil pickup locations when BD doesn't want to give us them" do
@@ -13,8 +13,38 @@ describe "RequestItem", :vcr => {:tag => :bd_requestitem } do
13
13
  @requestable_item_isbn = "9797994864" # item is in BD, and can be requested
14
14
  @locally_avail_item_isbn = "0745649890" # item is in BD, but is avail locally so not BD-requestable
15
15
  @not_requestable_item_isbn = "1441190090" # in BD, and we don't have it, but no libraries let us borrow (in this case, it's an ebook)
16
- @returns_PUBRI004_ISBN = "0109836413" # BD returns an error PUBRI004 for this one, which we want to treat as simply not available.
16
+ @returns_PUBRI003_ISBN = "0109836413" # BD returns an error PUBRI004 for this one, which we want to treat as simply not available.
17
17
  @pickup_location = "Some location" # BD seems to allow anything, which is disturbing
18
+ @pickup_location_obj = BorrowDirect::PickupLocation.new({"PickupLocationCode" => "a", "PickupLocationDescription" => @pickup_location})
19
+ end
20
+
21
+ it "raw RequestItem sanity check" do
22
+ findable = BorrowDirect::FindItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).find(:isbn => @requestable_item_isbn)
23
+
24
+ assert findable.requestable?
25
+
26
+ pickup = findable.pickup_locations.first
27
+ aid = findable.auth_id
28
+
29
+ uri = BorrowDirect::Defaults.api_base.chomp("/") + "/dws/item/add?aid=#{CGI.escape aid}"
30
+
31
+ request_hash = {
32
+ "PartnershipId" => BorrowDirect::Defaults.partnership_id,
33
+ "PickupLocation" => pickup,
34
+ "ExactSearch" => [
35
+ {"Type" => "ISBN","Value" => @requestable_item_isbn}
36
+ ]
37
+ }
38
+
39
+ http = HTTPClient.new
40
+ response = http.post uri, JSON.generate(request_hash), BorrowDirect::Request.new('').request_headers
41
+
42
+ assert_equal 200, response.code
43
+ assert_present response.body
44
+
45
+ response_hash = JSON.parse response.body
46
+
47
+ assert_present response_hash
18
48
  end
19
49
 
20
50
 
@@ -43,7 +73,8 @@ describe "RequestItem", :vcr => {:tag => :bd_requestitem } do
43
73
  resp = BorrowDirect::RequestItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).request_item_request(nil, :isbn => @not_requestable_item_isbn)
44
74
 
45
75
  assert_present resp
46
- assert_present resp["Request"]
76
+
77
+ assert_present resp["RequestLink"]
47
78
  end
48
79
 
49
80
  it "uses manually set auth_id" do
@@ -52,7 +83,17 @@ describe "RequestItem", :vcr => {:tag => :bd_requestitem } do
52
83
  resp = bd.request_item_request(nil, :isbn => @requestable_item_isbn)
53
84
 
54
85
  assert_present resp
55
- assert_present resp["Request"]
86
+
87
+ assert_present resp["RequestNumber"], "Was not able to succesfully make a request: #{resp}"
88
+ end
89
+
90
+ it "raises proper error on bad AID" do
91
+ e = assert_raises(BorrowDirect::InvalidAidError) do
92
+ BorrowDirect::RequestItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).with_auth_id("bad_expired_aid").make_request(nil, :isbn => @requestable_item_isbn)
93
+ end
94
+ assert_present e.message
95
+ assert_present e.bd_code
96
+ assert_present e.aid
56
97
  end
57
98
 
58
99
  describe "make_request" do
@@ -62,6 +103,15 @@ describe "RequestItem", :vcr => {:tag => :bd_requestitem } do
62
103
  assert_present request_id
63
104
  end
64
105
 
106
+ it "sets an auth_id" do
107
+ requester = BorrowDirect::RequestItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol])
108
+
109
+ assert requester.auth_id.nil?
110
+
111
+ requester.make_request(nil, :isbn => @requestable_item_isbn)
112
+ assert_present requester.auth_id
113
+ end
114
+
65
115
  it "make_request for an unrequestable item" do
66
116
  resp = BorrowDirect::RequestItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).make_request(nil, :isbn => @not_requestable_item_isbn)
67
117
 
@@ -74,18 +124,25 @@ describe "RequestItem", :vcr => {:tag => :bd_requestitem } do
74
124
  assert_nil resp
75
125
  end
76
126
 
77
- it "says no for item that BD returns PUBRI004" do
78
- assert_nil BorrowDirect::RequestItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).make_request(nil, :isbn => @returns_PUBRI004_ISBN)
127
+ it "says no for item that BD returns PUBRI003" do
128
+ assert_nil BorrowDirect::RequestItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).make_request(nil, :isbn => @returns_PUBRI003_ISBN)
79
129
  end
80
130
 
81
131
  end
82
132
 
83
- describe "with pickup location and requestable item" do
84
- it "still works" do
133
+ describe "with pickup location and requestable item" do
134
+ it "works with String pickup_location" do
85
135
  request_id = BorrowDirect::RequestItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).make_request(@pickup_location, :isbn => @requestable_item_isbn)
86
136
 
87
- assert_present request_id
137
+ assert_present request_id, "Was not able to succesfully make a request"
138
+ end
139
+
140
+ it "works with structured PickupLocation" do
141
+ request_id = BorrowDirect::RequestItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).make_request(@pickup_location_obj, :isbn => @requestable_item_isbn)
142
+
143
+ assert_present request_id, "Was not able to succesfully make a request"
88
144
  end
145
+
89
146
  end
90
147
 
91
148
  describe "make_request!" do
@@ -12,35 +12,22 @@ describe "RequestQuery", :vcr => {:tag => :bd_request_query} do
12
12
  it "raw request to verify the BD HTTP API" do
13
13
 
14
14
  # Get the auth code
15
-
16
- auth_uri = BorrowDirect::Defaults.api_base.chomp("/") + "/portal-service/user/authentication/patron"
17
- auth_hash = {
18
- "AuthenticationInformation" => {
19
- "LibrarySymbol" => VCRFilter[:bd_library_symbol],
20
- "PatronId" => VCRFilter[:bd_patron]
21
- }
22
- }
23
-
24
- headers = { "Content-Type" => "application/json",
25
- "User-Agent" => "ruby borrow_direct gem #{BorrowDirect::VERSION} (HTTPClient #{HTTPClient::VERSION}) https://github.com/jrochkind/borrow_direct",
26
- "Accept-Language" => "en"
27
- }
28
- http = HTTPClient.new
29
- response = http.post auth_uri, JSON.generate(auth_hash), headers
30
- response_hash = JSON.parse response.body
31
- auth_id = response_hash["Authentication"]["AuthnUserInfo"]["AId"]
32
-
15
+ auth_id = BorrowDirect::Authentication.new(VCRFilter[:bd_patron], VCRFilter[:bd_library_symbol]).get_auth_id
33
16
 
34
17
  # Now use it to make a RequestQuery request. Note, BD API requires
35
18
  # you to use the same User-Agent you used to receive the auth id.
36
19
 
37
-
38
20
  query = {
39
21
  "aid" => auth_id,
40
22
  "type" => "open",
41
23
  "fullRecord" => "0"
42
24
  }
43
25
 
26
+ headers = { "Content-Type" => "application/json",
27
+ "User-Agent" => "ruby borrow_direct gem #{BorrowDirect::VERSION} (HTTPClient #{HTTPClient::VERSION}) https://github.com/jrochkind/borrow_direct",
28
+ "Accept-Language" => "en"
29
+ }
30
+
44
31
  uri = BorrowDirect::Defaults.api_base.chomp("/") + "/portal-service/request/query/my"
45
32
 
46
33
  http = HTTPClient.new
@@ -52,8 +39,15 @@ describe "RequestQuery", :vcr => {:tag => :bd_request_query} do
52
39
  response_hash = JSON.parse http_response.body
53
40
 
54
41
  assert_present response_hash
55
- assert_present response_hash["QueryResult"]
56
- assert_kind_of Array, response_hash["QueryResult"]["MyRequestRecords"]
42
+ assert_kind_of Array, response_hash["MyRequestRecords"]
43
+ end
44
+
45
+ it "raises proper error on bad AID" do
46
+ e = assert_raises(BorrowDirect::InvalidAidError) do
47
+ BorrowDirect::RequestQuery.new(VCRFilter[:bd_patron]).with_auth_id("bad_expired_id").request_query_request
48
+ end
49
+ assert_present e.message
50
+ assert_present e.aid
57
51
  end
58
52
 
59
53
  describe "raw request_query_request" do
@@ -63,8 +57,8 @@ describe "RequestQuery", :vcr => {:tag => :bd_request_query} do
63
57
 
64
58
  assert_present response
65
59
  assert_kind_of Hash, response
66
- assert_present response["QueryResult"]["MyRequestRecords"]
67
- assert_kind_of Array, response["QueryResult"]["MyRequestRecords"]
60
+ assert_present response["MyRequestRecords"]
61
+ assert_kind_of Array, response["MyRequestRecords"]
68
62
  end
69
63
  end
70
64
 
@@ -85,10 +79,12 @@ describe "RequestQuery", :vcr => {:tag => :bd_request_query} do
85
79
  assert_includes [true, false], item.send(key)
86
80
  end
87
81
 
88
- [:request_status_date, :date_submitted].each do |key|
89
- assert_present item.send(key)
90
- assert_kind_of DateTime, item.send(key)
91
- end
82
+ # Huh, records don't seem to reliably have these, so we
83
+ # can't test for them, bah.
84
+ #[:request_status_date, :date_submitted].each do |key|
85
+ # assert_present item.send(key)
86
+ # assert_kind_of DateTime, item.send(key)
87
+ #end
92
88
  end
93
89
 
94
90
  it "fetches full records" do
data/test/request_test.rb CHANGED
@@ -4,9 +4,11 @@ require 'borrow_direct/request'
4
4
 
5
5
 
6
6
 
7
- describe "Request", :vcr => {:tag => :bd_request} do
7
+ describe "Request", :vcr => {:tag => :bd_request } do
8
8
  before do
9
9
  @successful_item_isbn = "9810743734"
10
+
11
+ @aid = BorrowDirect::Authentication.new(VCRFilter[:bd_patron], VCRFilter[:bd_library_symbol]).get_auth_id
10
12
  end
11
13
 
12
14
 
@@ -17,8 +19,8 @@ describe "Request", :vcr => {:tag => :bd_request} do
17
19
  end
18
20
 
19
21
  it "raises on bad request hash" do
20
- assert_raises(BorrowDirect::HttpError) do
21
- response = BorrowDirect::Request.new("/dws/item/available").request( "foo" => "bar" )
22
+ assert_raises(BorrowDirect::Error) do
23
+ response = BorrowDirect::Request.new("/dws/item/available").request( {"foo" => "bar"}, @aid )
22
24
  end
23
25
  end
24
26
 
@@ -46,13 +48,28 @@ describe "Request", :vcr => {:tag => :bd_request} do
46
48
  refute_nil e.bd_code
47
49
  end
48
50
 
49
- it "can make a succesful request" do
51
+ it "gets BD error info from a bad AID" do
52
+ request = {
53
+ "PartnershipId" => "BD",
54
+ "ExactSearch" => [
55
+ {
56
+ "Type" => "ISBN",
57
+ "Value" => @successful_item_isbn
58
+ }
59
+ ]
60
+ }
61
+
62
+ e = assert_raises(BorrowDirect::InvalidAidError) do
63
+ response = BorrowDirect::Request.new("/dws/item/available").request( request, "bad_aid" )
64
+ end
65
+
66
+ refute_nil e
67
+ assert_equal "PUBFI003", e.bd_code
68
+ end
69
+
70
+ it "can make a succesful request with AID" do
50
71
  request = {
51
72
  "PartnershipId" => "BD",
52
- "Credentials" => {
53
- "LibrarySymbol" => VCRFilter[:bd_library_symbol],
54
- "Barcode" => VCRFilter[:bd_patron]
55
- },
56
73
  "ExactSearch" => [
57
74
  {
58
75
  "Type" => "ISBN",
@@ -62,7 +79,7 @@ describe "Request", :vcr => {:tag => :bd_request} do
62
79
  }
63
80
 
64
81
 
65
- response = BorrowDirect::Request.new("/dws/item/available").request( request )
82
+ response = BorrowDirect::Request.new("/dws/item/available").request( request, @aid )
66
83
  end
67
84
 
68
85
  it "uses timeout for HttpClient" do
@@ -76,13 +93,12 @@ describe "Request", :vcr => {:tag => :bd_request} do
76
93
  assert_equal 5, http_client.connect_timeout
77
94
  end
78
95
 
96
+
79
97
  it "raises exception on timeout, live" do
98
+ skip "Can't get this to work with VCR and new API"
99
+
80
100
  request = {
81
101
  "PartnershipId" => "BD",
82
- "Credentials" => {
83
- "LibrarySymbol" => VCRFilter[:bd_library_symbol],
84
- "Barcode" => VCRFilter[:bd_patron]
85
- },
86
102
  "ExactSearch" => [
87
103
  {
88
104
  "Type" => "ISBN",
@@ -90,19 +106,20 @@ describe "Request", :vcr => {:tag => :bd_request} do
90
106
  }
91
107
  ]
92
108
  }
93
- bd = BorrowDirect::Request.new("/dws/item/available")
109
+ # Using a Bad URI here keeps VCR from interfering with us too much.
110
+ bd = BorrowDirect::Request.new("/dws/item/available_bad_uri")
94
111
  # tiny timeout, it'll def timeout, and on connect no less
95
- bd.timeout = 0.00001
112
+ bd.timeout = 0.00000001
96
113
  timeout_error = assert_raises(BorrowDirect::HttpTimeoutError) do
97
- response = bd.request( request )
114
+ response = bd.request( request, @aid )
98
115
  end
99
116
  assert_equal bd.timeout, timeout_error.timeout
100
117
 
101
118
  # little bit longer to get maybe a receive timeout instead
102
- bd = BorrowDirect::Request.new("/dws/item/available")
119
+ bd = BorrowDirect::Request.new("/dws/item/available_bad_uri")
103
120
  bd.timeout = 0.10
104
121
  timeout_error = assert_raises(BorrowDirect::HttpTimeoutError) do
105
- response = bd.request( request )
122
+ response = bd.request( request, @aid )
106
123
  end
107
124
  assert_equal bd.timeout, timeout_error.timeout
108
125
  end
@@ -110,22 +127,18 @@ describe "Request", :vcr => {:tag => :bd_request} do
110
127
  describe "with expected errors" do
111
128
  it "still returns result" do
112
129
  request = {
113
- "PartnershipId" => "BAD_ID",
114
- "Credentials" => {
115
- "LibrarySymbol" => "librarySymbol",
116
- "Barcode" => "barcode/patronId"
117
- },
130
+ "PartnershipId" => "BD",
118
131
  "ExactSearch" => [
119
132
  {
120
- "Type" => "type",
121
- "Value" => "value"
133
+ "Type" => "BADBAD",
134
+ "Value" => "2292389283928392382938"
122
135
  }
123
136
  ]
124
137
  }
125
138
 
126
139
  bd = BorrowDirect::Request.new("/dws/item/available")
127
- bd.expected_error_codes << "PUBFI003"
128
- response = bd.request( request )
140
+ bd.expected_error_codes << "PRIFI001"
141
+ response = bd.request( request, @aid )
129
142
 
130
143
  assert_present response
131
144
 
data/test/test_helper.rb CHANGED
@@ -9,6 +9,12 @@ require 'minitest-vcr'
9
9
 
10
10
  require 'borrow_direct'
11
11
 
12
+ # Want to run tests against PRODUCTION BD? It WILL result in real requests being
13
+ # made to BD production system, so you probably don't -- but if you're not sure
14
+ # if production API is really behaving like test, you might want to anyway.
15
+ if ENV["RAILS_ENV"] == "production"
16
+ BorrowDirect::Defaults.api_base = BorrowDirect::Defaults::PRODUCTION_API_BASE
17
+ end
12
18
 
13
19
  # Load support files
14
20
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
@@ -19,13 +25,16 @@ VCR.configure do |c|
19
25
 
20
26
  # BD API requests tend to have their distinguishing
21
27
  # features in a POSTed JSON request body
22
- c.default_cassette_options = { :match_requests_on => [:method, :uri, :body] }
28
+ c.default_cassette_options = { :match_requests_on => [:method, VCR.request_matchers.uri_without_param(:aid), :body] }
23
29
  end
24
30
 
25
31
  MinitestVcr::Spec.configure!
26
32
 
27
33
  VCRFilter.sensitive_data! :bd_library_symbol
28
34
  VCRFilter.sensitive_data! :bd_patron
35
+ VCRFilter.sensitive_data! :bd_api_key
36
+
37
+ BorrowDirect::Defaults.api_key = VCRFilter[:bd_api_key]
29
38
 
30
39
  # Silly way to not have to rewrite all our tests if we
31
40
  # temporarily disable VCR, make VCR.use_cassette a no-op