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,159 @@
1
+ require 'test_helper'
2
+
3
+ require 'borrow_direct/find_item'
4
+
5
+
6
+
7
+ describe "FindItem", :vcr do
8
+ before do
9
+ @requestable_item_isbn = "9810743734" # item is in BD, and can be requested
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)
12
+ @returns_PUBFI002_ISBN = "0109836413" # BD returns an error PUBFI002 for this one, which we want to treat as simply not available.
13
+ end
14
+
15
+
16
+
17
+ describe "with defaults" do
18
+ before do
19
+ @original_symbol = BorrowDirect::Defaults.library_symbol
20
+ @original_bar = BorrowDirect::Defaults.find_item_patron_barcode
21
+ BorrowDirect::Defaults.library_symbol = "OUR_SYMBOL"
22
+ BorrowDirect::Defaults.find_item_patron_barcode = "OUR_BARCODE"
23
+ end
24
+ after do
25
+ BorrowDirect::Defaults.library_symbol = @original_symbol
26
+ BorrowDirect::Defaults.find_item_patron_barcode = @original_bar
27
+ end
28
+
29
+ it "uses defaults" do
30
+ finder = BorrowDirect::FindItem.new
31
+
32
+ assert_equal "OUR_SYMBOL", finder.patron_library_symbol
33
+ assert_equal "OUR_BARCODE", finder.patron_barcode
34
+ end
35
+ end
36
+
37
+ describe "query production" do
38
+ it "exact search works" do
39
+ finder = BorrowDirect::FindItem.new("barcodeX", "libraryX")
40
+ hash = finder.send(:exact_search_request_hash, :isbn, "2")
41
+
42
+ assert_equal BorrowDirect::Defaults.partnership_id, hash["PartnershipId"]
43
+ assert_equal "barcodeX", hash["Credentials"]["Barcode"]
44
+ assert_equal "libraryX", hash["Credentials"]["LibrarySymbol"]
45
+
46
+ assert_equal "ISBN", hash["ExactSearch"].first["Type"]
47
+ assert_equal "2", hash["ExactSearch"].first["Value"]
48
+ end
49
+
50
+ it "works with multiple values" do
51
+ finder = BorrowDirect::FindItem.new("barcodeX", "libraryX")
52
+ hash = finder.send(:exact_search_request_hash, :isbn, ["2", "3"])
53
+
54
+ exact_searches = hash["ExactSearch"]
55
+
56
+ assert_length 2, exact_searches
57
+
58
+ assert_include exact_searches, {"Type"=>"ISBN", "Value"=>"2"}
59
+ assert_include exact_searches, {"Type"=>"ISBN", "Value"=>"3"}
60
+ end
61
+ end
62
+
63
+ describe "#find_item_request" do
64
+
65
+ it "raises on no search critera" do
66
+ assert_raises(ArgumentError) do
67
+ BorrowDirect::FindItem.new("whatever", "whatever").find_item_request
68
+ end
69
+ end
70
+
71
+ it "raises on multiple search critera" do
72
+ assert_raises(ArgumentError) do
73
+ BorrowDirect::FindItem.new("whatever", "whatever").find_item_request(:isbn => "1", :issn => "1")
74
+ end
75
+ end
76
+
77
+ it "raises on unrecognized search criteria" do
78
+ assert_raises(ArgumentError) do
79
+ BorrowDirect::FindItem.new("whatever", "whatever").find_item_request(:whoknows => "1")
80
+ end
81
+ end
82
+
83
+
84
+ it "finds a requestable item" do
85
+ assert_present BorrowDirect::FindItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).find_item_request(:isbn => @requestable_item_isbn)
86
+ end
87
+
88
+ it "finds a locally available item" do
89
+ assert_present BorrowDirect::FindItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).find_item_request(:isbn => @locally_avail_item_isbn)
90
+ end
91
+
92
+ it "finds an item that does not exist in BD" do
93
+ assert_present BorrowDirect::FindItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).find_item_request(:isbn => "NO_SUCH_THING")
94
+ end
95
+
96
+ it "works with multiple values" do
97
+ assert_present BorrowDirect::FindItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).find_item_request(:isbn => [@requestable_item_isbn, @locally_avail_item_isbn])
98
+ end
99
+
100
+ describe "with expected error PUBFI002" do
101
+ it "returns result" do
102
+ assert_present BorrowDirect::FindItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).find_item_request(:isbn => @returns_PUBFI002_ISBN )
103
+ end
104
+ end
105
+ end
106
+
107
+ describe "find with Response" do
108
+ before do
109
+ @find_item = BorrowDirect::FindItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol])
110
+ end
111
+
112
+ it "requestable for requestable item" do
113
+ assert_equal true, @find_item.find(:isbn => @requestable_item_isbn).requestable?
114
+ end
115
+
116
+ 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?
118
+ end
119
+
120
+ it "not requestable for locally available item" do
121
+ assert_equal false, @find_item.find(:isbn => @locally_avail_item_isbn).requestable?
122
+ end
123
+
124
+ it "not requestable for item that does not exist in BD" do
125
+ assert_equal false, @find_item.find(:isbn => "NO_SUCH_THING").requestable?
126
+ end
127
+
128
+ it "not requestable for item that no libraries will lend" do
129
+ assert_equal false, @find_item.find(:isbn => @not_requestable_item_isbn).requestable?
130
+ end
131
+
132
+ it "not requestable for item that BD returns PUBFI002" do
133
+ assert_equal false, @find_item.find(:isbn => @returns_PUBFI002_ISBN).requestable?
134
+ end
135
+
136
+ it "has an auth_id" do
137
+ assert_present @find_item.find(:isbn => @requestable_item_isbn).auth_id
138
+ end
139
+
140
+ it "has nil auth_id when BD doesn't want to give us one" do
141
+ assert_nil @find_item.find(:isbn => @returns_PUBFI002_ISBN).auth_id
142
+ end
143
+
144
+ it "has pickup locations" do
145
+ pickup_locations = @find_item.find(:isbn => @requestable_item_isbn).pickup_locations
146
+
147
+ assert_present pickup_locations
148
+ assert_kind_of Array, pickup_locations
149
+ end
150
+
151
+ it "has nil pickup locations when BD doesn't want to give us them" do
152
+ assert_nil @find_item.find(:isbn => @returns_PUBFI002_ISBN).pickup_locations
153
+ end
154
+
155
+ end
156
+
157
+
158
+
159
+ end
@@ -0,0 +1,91 @@
1
+ require 'uri'
2
+ require 'cgi'
3
+
4
+ describe "GenerateQuery" do
5
+ before do
6
+ @test_base = "http://example.org"
7
+ end
8
+
9
+ describe "query_url_with" do
10
+
11
+ it "raises on unknown field" do
12
+ assert_raises(ArgumentError) do
13
+ BorrowDirect::GenerateQuery.new(@test_base).query_url_with(:invalid_thing => "foo")
14
+ end
15
+ end
16
+
17
+ it "generates query" do
18
+ generate_query = BorrowDirect::GenerateQuery.new(@test_base)
19
+
20
+ url = generate_query.query_url_with(:title => "This is a title", :author => "This is an author")
21
+
22
+ assert url.start_with? @test_base
23
+
24
+ parsed_url = URI.parse(url)
25
+ url_query = CGI.parse( parsed_url.query )
26
+
27
+ assert_present url_query
28
+
29
+ assert_length 1, url_query["query"]
30
+
31
+ query_text = url_query["query"].first
32
+
33
+ parts = query_text.split(" and ")
34
+
35
+ assert_length 2, parts
36
+
37
+ assert_include parts, 'ti="This is a title"'
38
+ assert_include parts, 'au="This is an author"'
39
+ end
40
+ end
41
+
42
+ describe "best_known_item_query_url_with" do
43
+ it "uses only isbn when available" do
44
+ generate_query = BorrowDirect::GenerateQuery.new(@test_base)
45
+
46
+ url = generate_query.best_known_item_query_url_with(:isbn => "OUR_ISBN", :title => "This is a title", :author => "This is an author")
47
+
48
+ assert url.start_with? @test_base
49
+
50
+ parsed_url = URI.parse(url)
51
+ url_query = CGI.parse( parsed_url.query )
52
+
53
+ assert_present url_query
54
+
55
+ assert_length 1, url_query["query"]
56
+
57
+ query_text = url_query["query"].first
58
+
59
+ parts = query_text.split(" and ")
60
+
61
+ assert_length 1, parts
62
+
63
+ assert_include parts, 'isbn="OUR_ISBN"'
64
+ end
65
+
66
+ it "uses author and title when it has to" do
67
+ generate_query = BorrowDirect::GenerateQuery.new(@test_base)
68
+
69
+ url = generate_query.best_known_item_query_url_with(:title => "This is a title", :author => "This is an author")
70
+
71
+ assert url.start_with? @test_base
72
+
73
+ parsed_url = URI.parse(url)
74
+ url_query = CGI.parse( parsed_url.query )
75
+
76
+ assert_present url_query
77
+
78
+ assert_length 1, url_query["query"]
79
+
80
+ query_text = url_query["query"].first
81
+
82
+ parts = query_text.split(" and ")
83
+
84
+ assert_length 2, parts
85
+
86
+ assert_include parts, 'ti="This is a title"'
87
+ assert_include parts, 'au="This is an author"'
88
+ end
89
+
90
+ end
91
+ end
@@ -0,0 +1,109 @@
1
+ require 'test_helper'
2
+ require 'vcr'
3
+
4
+ require 'borrow_direct/authentication'
5
+ require 'borrow_direct/request_item'
6
+
7
+
8
+
9
+
10
+
11
+ describe "RequestItem", :vcr => {:tag => :bd_requestitem } do
12
+ before do
13
+ @requestable_item_isbn = "9797994864" # item is in BD, and can be requested
14
+ @locally_avail_item_isbn = "0745649890" # item is in BD, but is avail locally so not BD-requestable
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.
17
+ @pickup_location = "Some location" # BD seems to allow anything, which is disturbing
18
+ end
19
+
20
+
21
+
22
+ it "raises on no search critera" do
23
+ assert_raises(ArgumentError) do
24
+ BorrowDirect::RequestItem.new("whatever").request_item_request
25
+ end
26
+ end
27
+
28
+ it "raises on multiple search critera" do
29
+ assert_raises(ArgumentError) do
30
+ BorrowDirect::RequestItem.new("whatever").request_item_request(nil, :isbn => "1", :issn => "1")
31
+ end
32
+ end
33
+
34
+ it "raises on unrecognized search criteria" do
35
+ assert_raises(ArgumentError) do
36
+ BorrowDirect::RequestItem.new("whatever").request_item_request(nil, :whoknows => "1")
37
+ end
38
+ end
39
+
40
+
41
+ it "raw requests an unrequestable item" do
42
+
43
+ resp = BorrowDirect::RequestItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).request_item_request(nil, :isbn => @not_requestable_item_isbn)
44
+
45
+ assert_present resp
46
+ assert_present resp["Request"]
47
+ end
48
+
49
+ it "uses manually set auth_id" do
50
+ bd = BorrowDirect::RequestItem.new("bad_patron" , "bad_symbol")
51
+ bd.auth_id = BorrowDirect::Authentication.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).get_auth_id
52
+ resp = bd.request_item_request(nil, :isbn => @requestable_item_isbn)
53
+
54
+ assert_present resp
55
+ assert_present resp["Request"]
56
+ end
57
+
58
+ describe "make_request" do
59
+ it "make_request for a requestable item" do
60
+ request_id = BorrowDirect::RequestItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).make_request(nil, :isbn => @requestable_item_isbn)
61
+
62
+ assert_present request_id
63
+ end
64
+
65
+ it "make_request for an unrequestable item" do
66
+ resp = BorrowDirect::RequestItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).make_request(nil, :isbn => @not_requestable_item_isbn)
67
+
68
+ assert_nil resp
69
+ end
70
+
71
+ it "make_request for a locally available item" do
72
+ resp = BorrowDirect::RequestItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).make_request(nil, :isbn => @locally_avail_item_isbn)
73
+
74
+ assert_nil resp
75
+ end
76
+
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)
79
+ end
80
+
81
+ end
82
+
83
+ describe "with pickup location and requestable item" do
84
+ it "still works" do
85
+ request_id = BorrowDirect::RequestItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).make_request(@pickup_location, :isbn => @requestable_item_isbn)
86
+
87
+ assert_present request_id
88
+ end
89
+ end
90
+
91
+ describe "make_request!" do
92
+ it "returns number for succesful request" do
93
+ request_id = BorrowDirect::RequestItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).make_request!(nil, :isbn => @requestable_item_isbn)
94
+
95
+ assert_present request_id
96
+ end
97
+
98
+ it "raises for unrequestable" do
99
+ error = assert_raises(BorrowDirect::Error) do
100
+ request_id = BorrowDirect::RequestItem.new(VCRFilter[:bd_patron] , VCRFilter[:bd_library_symbol]).make_request!(nil, :isbn => @not_requestable_item_isbn)
101
+ end
102
+ end
103
+
104
+ end
105
+
106
+
107
+
108
+
109
+ end
@@ -0,0 +1,113 @@
1
+ require 'test_helper'
2
+ require 'httpclient'
3
+
4
+
5
+
6
+
7
+ describe "RequestQuery", :vcr => {:tag => :bd_request_query} do
8
+ before do
9
+ @requestable_item_isbn = "9797994864" # item is in BD, and can be requested
10
+ end
11
+
12
+ it "raw request to verify the BD HTTP API" do
13
+
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
+
33
+
34
+ # Now use it to make a RequestQuery request. Note, BD API requires
35
+ # you to use the same User-Agent you used to receive the auth id.
36
+
37
+
38
+ query = {
39
+ "aid" => auth_id,
40
+ "type" => "open",
41
+ "fullRecord" => "0"
42
+ }
43
+
44
+ uri = BorrowDirect::Defaults.api_base.chomp("/") + "/portal-service/request/query/my"
45
+
46
+ http = HTTPClient.new
47
+ http_response = http.get uri, query, headers
48
+
49
+ assert_equal 200, http_response.code
50
+ assert_present http_response.body
51
+
52
+ response_hash = JSON.parse http_response.body
53
+
54
+ assert_present response_hash
55
+ assert_present response_hash["QueryResult"]
56
+ assert_kind_of Array, response_hash["QueryResult"]["MyRequestRecords"]
57
+ end
58
+
59
+ describe "raw request_query_request" do
60
+ it "returns results" do
61
+ request_query = BorrowDirect::RequestQuery.new(VCRFilter[:bd_patron], VCRFilter[:bd_library_symbol])
62
+ response = request_query.request_query_request
63
+
64
+ assert_present response
65
+ assert_kind_of Hash, response
66
+ assert_present response["QueryResult"]["MyRequestRecords"]
67
+ assert_kind_of Array, response["QueryResult"]["MyRequestRecords"]
68
+ end
69
+ end
70
+
71
+ describe "requests" do
72
+ it "fetches default records" do
73
+ request_query = BorrowDirect::RequestQuery.new(VCRFilter[:bd_patron], VCRFilter[:bd_library_symbol])
74
+ results = request_query.requests
75
+
76
+ assert_kind_of Array, results
77
+
78
+ item = results.sample
79
+
80
+ [ :request_number, :title, :request_status].each do |key|
81
+ assert_present item.send key
82
+ end
83
+
84
+ [:allow_renew, :allow_cancel].each do |key|
85
+ assert_includes [true, false], item.send(key)
86
+ end
87
+
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
92
+ end
93
+
94
+ it "fetches full records" do
95
+ request_query = BorrowDirect::RequestQuery.new(VCRFilter[:bd_patron], VCRFilter[:bd_library_symbol])
96
+ results = request_query.requests("all", true)
97
+
98
+ assert_kind_of Array, results
99
+ # too hard to test presence of each attributes, as not every item has every
100
+ # attribute and too hard to find examples to test.
101
+ end
102
+
103
+ end
104
+
105
+
106
+
107
+
108
+
109
+
110
+ end
111
+
112
+
113
+
@@ -0,0 +1,141 @@
1
+ require 'test_helper'
2
+ require 'borrow_direct/request'
3
+
4
+
5
+
6
+
7
+ describe "Request", :vcr => {:tag => :bd_request} do
8
+ before do
9
+ @successful_item_isbn = "9810743734"
10
+ end
11
+
12
+
13
+ it "raises on bad path" do
14
+ assert_raises(BorrowDirect::HttpError) do
15
+ response = BorrowDirect::Request.new("/no/such/path").request( "foo" => "bar" )
16
+ end
17
+ end
18
+
19
+ 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
+ end
23
+ end
24
+
25
+ it "gets BD error info" do
26
+ request = {
27
+ "PartnershipId" => "BAD_ID",
28
+ "Credentials" => {
29
+ "LibrarySymbol" => "librarySymbol",
30
+ "Barcode" => "barcode/patronId"
31
+ },
32
+ "ExactSearch" => [
33
+ {
34
+ "Type" => "type",
35
+ "Value" => "value"
36
+ }
37
+ ]
38
+ }
39
+
40
+ e = assert_raises(BorrowDirect::Error) do
41
+ response = BorrowDirect::Request.new("/dws/item/available").request( request )
42
+ end
43
+
44
+ refute_nil e
45
+ refute_nil e.message
46
+ refute_nil e.bd_code
47
+ end
48
+
49
+ it "can make a succesful request" do
50
+ request = {
51
+ "PartnershipId" => "BD",
52
+ "Credentials" => {
53
+ "LibrarySymbol" => VCRFilter[:bd_library_symbol],
54
+ "Barcode" => VCRFilter[:bd_patron]
55
+ },
56
+ "ExactSearch" => [
57
+ {
58
+ "Type" => "ISBN",
59
+ "Value" => @successful_item_isbn
60
+ }
61
+ ]
62
+ }
63
+
64
+
65
+ response = BorrowDirect::Request.new("/dws/item/available").request( request )
66
+ end
67
+
68
+ it "uses timeout for HttpClient" do
69
+ request = BorrowDirect::Request.new("/some/path")
70
+ request.timeout = 5
71
+
72
+ http_client = request.http_client
73
+
74
+ assert_equal 5, http_client.send_timeout
75
+ assert_equal 5, http_client.receive_timeout
76
+ assert_equal 5, http_client.connect_timeout
77
+ end
78
+
79
+ describe "with expected errors" do
80
+ it "still returns result" do
81
+ request = {
82
+ "PartnershipId" => "BAD_ID",
83
+ "Credentials" => {
84
+ "LibrarySymbol" => "librarySymbol",
85
+ "Barcode" => "barcode/patronId"
86
+ },
87
+ "ExactSearch" => [
88
+ {
89
+ "Type" => "type",
90
+ "Value" => "value"
91
+ }
92
+ ]
93
+ }
94
+
95
+ bd = BorrowDirect::Request.new("/dws/item/available")
96
+ bd.expected_error_codes << "PUBFI003"
97
+ response = bd.request( request )
98
+
99
+ assert_present response
100
+
101
+ end
102
+ end
103
+
104
+ describe "authentication id" do
105
+ it "starts out nil" do
106
+ assert_nil BorrowDirect::Request.new("/").auth_id
107
+ end
108
+
109
+ it "manually set one will be used without fetch" do
110
+ r = BorrowDirect::Request.new("/")
111
+ r.auth_id = "OUR_AUTH_ID"
112
+
113
+ assert_equal "OUR_AUTH_ID", r.need_auth_id("wont_use_this", "or_this")
114
+ end
115
+
116
+ it "automatically fetches one when needed" do
117
+ r = BorrowDirect::Request.new("/")
118
+ auth_id = r.need_auth_id(VCRFilter[:bd_patron], VCRFilter[:bd_library_symbol])
119
+
120
+ assert_present auth_id
121
+ assert_equal auth_id, r.auth_id
122
+ end
123
+
124
+ it "can refetch when instructed" do
125
+ r = BorrowDirect::Request.new("/")
126
+
127
+ r.auth_id = "OLD_BAD_AUTH_ID"
128
+ fetched = r.fetch_auth_id!(VCRFilter[:bd_patron], VCRFilter[:bd_library_symbol])
129
+
130
+ assert_present r.auth_id
131
+ assert_equal fetched, r.auth_id
132
+ refute_equal "OLD_BAD_AUTH_ID", r.auth_id
133
+ end
134
+
135
+ it "takes with_auth_id" do
136
+ r = BorrowDirect::Request.new("/").with_auth_id("OUR_AUTH_ID")
137
+ assert_equal "OUR_AUTH_ID", r.auth_id
138
+ end
139
+ end
140
+
141
+ end
@@ -0,0 +1,23 @@
1
+ # Useful assertions not provided by minitest-spec
2
+
3
+ def assert_present(arg, msg = nil)
4
+ msg ||= "#{arg.inspect} is empty or not present"
5
+
6
+ is_present = arg.respond_to?(:empty?) ? !arg.empty? : !!arg
7
+
8
+ assert is_present, msg
9
+ end
10
+
11
+ def assert_length(length, array, msg = nil)
12
+ msg ||= "Expected #{array.inspect} to be length #{length}"
13
+
14
+ assert (array.respond_to?(:length) && array.length == length), msg
15
+ end
16
+
17
+ def assert_include(collection, item, msg = nil)
18
+ assert_respond_to(collection, :include?, "The collection must respond to :include?.")
19
+
20
+ msg ||= "#{collection.inspect.slice(0,10)} expected to include\#{item}"
21
+
22
+ assert collection.include?(item), msg
23
+ end
@@ -0,0 +1,45 @@
1
+ require 'vcr'
2
+
3
+ # Convenience for using VCR's filter_sensitive_data according to our common
4
+ # pattern.
5
+ #
6
+ # For a sensitive piece of information, set in your shell environment variable eg:
7
+ #
8
+ # BD_FINDITEM_PATRON="patron_barcode"
9
+ #
10
+ # Then call in a test:
11
+ # VCRFilter.sensitive_data! :bd_finditem_patron
12
+ #
13
+ # In the tests, when you need to use the piece of data somewhere, use
14
+ # VCRFilter[:bd_library_symbol]
15
+ #
16
+ # eg
17
+ # BorrowDirect::FindItem.new(VCRFilter[:bd_finditem_patron])
18
+ #
19
+ # Optional but recommended, use VCR cassette tags...
20
+ # VCRFilter.sensitive_data!, :bd_finditem_patron, :bd_finditem_tests
21
+ # #...
22
+ # describe "BD finditem items", :vcr => {:tag => :bd_finditem_tests}
23
+ #
24
+ # When recording a new cassette, the value from ENV will be used in interactions
25
+ # with remote service, but won't be saved in your on disk cassettes -- it will
26
+ # be saved as eg DUMMY_BD_FINDITEM_PATRON instead.
27
+ #
28
+ # When running from recorded cassettes, you don't need to have the ENV defined, but
29
+ # when (re-)recording a cassette, you of course do.
30
+ module VCRFilter
31
+ @@data = {}
32
+ def self.[](key) ; @@data[key.to_s.downcase] ; end
33
+ def self.[]=(key, value) ; @@data[key.to_s.downcase] = value ; end
34
+
35
+ def self.sensitive_data!(key, vcr_tag = nil)
36
+ env_key = key.to_s.upcase
37
+ dummy_value = "DUMMY_#{env_key}"
38
+
39
+ self[key] = (ENV[env_key] || dummy_value)
40
+
41
+ VCR.configure do |c|
42
+ c.filter_sensitive_data( dummy_value, vcr_tag ) { self[key] }
43
+ end
44
+ end
45
+ end