borrow_direct 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +183 -0
- data/Rakefile +11 -0
- data/bd_metrics/finditem_measure.rb +61 -0
- data/bd_metrics/isbn.txt +1088 -0
- data/bd_metrics/lccn.txt +1668 -0
- data/bd_metrics/oclc.txt +167 -0
- data/borrow_direct.gemspec +30 -0
- data/lib/borrow_direct/authentication.rb +55 -0
- data/lib/borrow_direct/defaults.rb +38 -0
- data/lib/borrow_direct/error.rb +17 -0
- data/lib/borrow_direct/find_item.rb +149 -0
- data/lib/borrow_direct/generate_query.rb +78 -0
- data/lib/borrow_direct/request.rb +185 -0
- data/lib/borrow_direct/request_item.rb +119 -0
- data/lib/borrow_direct/request_query.rb +124 -0
- data/lib/borrow_direct/util.rb +18 -0
- data/lib/borrow_direct/version.rb +3 -0
- data/lib/borrow_direct.rb +19 -0
- data/test/authentication_test.rb +79 -0
- data/test/find_item_test.rb +159 -0
- data/test/generate_query_test.rb +91 -0
- data/test/request_item_test.rb +109 -0
- data/test/request_query_test.rb +113 -0
- data/test/request_test.rb +141 -0
- data/test/support/assertions.rb +23 -0
- data/test/support/vcr_filter.rb +45 -0
- data/test/test_helper.rb +39 -0
- data/test/util_test.rb +32 -0
- data/test/vcr_cassettes/Authentication/Makes_a_request_succesfully.yml +52 -0
- data/test/vcr_cassettes/Authentication/Raises_for_bad_library_symbol.yml +52 -0
- data/test/vcr_cassettes/Authentication/Raises_for_bad_patron_barcode.yml +53 -0
- data/test/vcr_cassettes/Authentication/get_auth_id/raises_for_a_bad_library_symbol.yml +52 -0
- data/test/vcr_cassettes/Authentication/get_auth_id/raises_for_a_bad_patron_barcode.yml +53 -0
- data/test/vcr_cassettes/Authentication/get_auth_id/returns_an_auth_id_for_a_good_request.yml +52 -0
- data/test/vcr_cassettes/Authentication/raw_request_to_verify_HTTP_api/.yml +52 -0
- data/test/vcr_cassettes/FindItem/_find_item_request/finds_a_locally_available_item.yml +49 -0
- data/test/vcr_cassettes/FindItem/_find_item_request/finds_a_requestable_item.yml +49 -0
- data/test/vcr_cassettes/FindItem/_find_item_request/finds_an_item_that_does_not_exist_in_BD.yml +50 -0
- data/test/vcr_cassettes/FindItem/_find_item_request/with_expected_error_PUBFI002/returns_result.yml +40 -0
- data/test/vcr_cassettes/FindItem/_find_item_request/works_with_multiple_values.yml +49 -0
- data/test/vcr_cassettes/FindItem/find_with_Response/has_an_auth_id.yml +49 -0
- data/test/vcr_cassettes/FindItem/find_with_Response/has_nil_auth_id_when_BD_doesn_t_want_to_give_us_one.yml +40 -0
- data/test/vcr_cassettes/FindItem/find_with_Response/has_nil_pickup_locations_when_BD_doesn_t_want_to_give_us_them.yml +40 -0
- data/test/vcr_cassettes/FindItem/find_with_Response/has_pickup_locations.yml +49 -0
- data/test/vcr_cassettes/FindItem/find_with_Response/not_requestable_for_item_that_BD_returns_PUBFI002.yml +40 -0
- data/test/vcr_cassettes/FindItem/find_with_Response/not_requestable_for_item_that_does_not_exist_in_BD.yml +50 -0
- data/test/vcr_cassettes/FindItem/find_with_Response/not_requestable_for_item_that_no_libraries_will_lend.yml +50 -0
- data/test/vcr_cassettes/FindItem/find_with_Response/not_requestable_for_locally_available_item.yml +49 -0
- data/test/vcr_cassettes/FindItem/find_with_Response/requestable_for_requestable_item.yml +49 -0
- data/test/vcr_cassettes/FindItem/find_with_Response/requestable_with_multiple_items_if_at_least_one_is_requestable.yml +49 -0
- data/test/vcr_cassettes/Request/authentication_id/automatically_fetches_one_when_needed.yml +52 -0
- data/test/vcr_cassettes/Request/authentication_id/can_refetch_when_instructed.yml +52 -0
- data/test/vcr_cassettes/Request/can_make_a_succesful_request.yml +49 -0
- data/test/vcr_cassettes/Request/gets_BD_error_info.yml +41 -0
- data/test/vcr_cassettes/Request/raises_on_bad_path.yml +53 -0
- data/test/vcr_cassettes/Request/raises_on_bad_request_hash.yml +63 -0
- data/test/vcr_cassettes/Request/with_expected_errors/still_returns_result.yml +41 -0
- data/test/vcr_cassettes/RequestItem/make_request/make_request_for_a_locally_available_item.yml +90 -0
- data/test/vcr_cassettes/RequestItem/make_request/make_request_for_a_requestable_item.yml +89 -0
- data/test/vcr_cassettes/RequestItem/make_request/make_request_for_an_unrequestable_item.yml +91 -0
- data/test/vcr_cassettes/RequestItem/make_request/raises_for_unrequestable.yml +91 -0
- data/test/vcr_cassettes/RequestItem/make_request/returns_number_for_succesful_request.yml +89 -0
- data/test/vcr_cassettes/RequestItem/make_request/says_no_for_item_that_BD_returns_PUBRI004.yml +89 -0
- data/test/vcr_cassettes/RequestItem/raw_requests_an_unrequestable_item.yml +91 -0
- data/test/vcr_cassettes/RequestItem/uses_manually_set_auth_id.yml +89 -0
- data/test/vcr_cassettes/RequestItem/with_pickup_location_and_requestable_item/still_works.yml +90 -0
- data/test/vcr_cassettes/RequestQuery/raw_request_query_request/returns_results.yml +381 -0
- data/test/vcr_cassettes/RequestQuery/raw_request_to_verify_the_BD_HTTP_API.yml +381 -0
- data/test/vcr_cassettes/RequestQuery/requests/fetches_default_records.yml +384 -0
- data/test/vcr_cassettes/RequestQuery/requests/fetches_full_records.yml +481 -0
- data/test/vcr_cassettes/top_level_describe/an_inner_describe/.yml +76 -0
- 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
|