berkeley_library-alma 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/build.yml +18 -0
  3. data/.gitignore +388 -0
  4. data/.idea/.gitignore +8 -0
  5. data/.idea/alma.iml +55 -0
  6. data/.idea/codeStyles/codeStyleConfig.xml +5 -0
  7. data/.idea/inspectionProfiles/Project_Default.xml +26 -0
  8. data/.idea/misc.xml +4 -0
  9. data/.idea/modules.xml +8 -0
  10. data/.idea/vcs.xml +6 -0
  11. data/.rubocop.yml +334 -0
  12. data/.ruby-version +1 -0
  13. data/.simplecov +8 -0
  14. data/.yardopts +2 -0
  15. data/CHANGES.md +3 -0
  16. data/Dockerfile +54 -0
  17. data/Gemfile +3 -0
  18. data/Jenkinsfile +18 -0
  19. data/LICENSE.md +21 -0
  20. data/README.md +210 -0
  21. data/Rakefile +20 -0
  22. data/berkeley_library-alma.gemspec +42 -0
  23. data/bin/alma-mms-lookup +64 -0
  24. data/docker-compose.yml +15 -0
  25. data/lib/berkeley_library/alma/bib_number.rb +90 -0
  26. data/lib/berkeley_library/alma/config.rb +178 -0
  27. data/lib/berkeley_library/alma/constants.rb +16 -0
  28. data/lib/berkeley_library/alma/mms_id.rb +100 -0
  29. data/lib/berkeley_library/alma/module_info.rb +14 -0
  30. data/lib/berkeley_library/alma/record_id.rb +113 -0
  31. data/lib/berkeley_library/alma.rb +1 -0
  32. data/rakelib/bundle.rake +8 -0
  33. data/rakelib/coverage.rake +11 -0
  34. data/rakelib/gem.rake +54 -0
  35. data/rakelib/rubocop.rake +18 -0
  36. data/rakelib/spec.rake +2 -0
  37. data/spec/.rubocop.yml +37 -0
  38. data/spec/data/991054360089706532-sru.xml +186 -0
  39. data/spec/data/b11082434-sru.xml +165 -0
  40. data/spec/data/bibs_with_check_digits.txt +151 -0
  41. data/spec/lib/berkeley_library/alma/bib_number_spec.rb +95 -0
  42. data/spec/lib/berkeley_library/alma/config_spec.rb +94 -0
  43. data/spec/lib/berkeley_library/alma/mms_id_spec.rb +111 -0
  44. data/spec/lib/berkeley_library/alma/record_id_spec.rb +41 -0
  45. data/spec/spec_helper.rb +56 -0
  46. metadata +325 -0
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+
3
+ module BerkeleyLibrary
4
+ module Alma
5
+ describe BibNumber do
6
+ before(:each) do
7
+ BerkeleyLibrary::Alma.configure do
8
+ Config.alma_sru_host = 'berkeley.alma.exlibrisgroup.com'
9
+ Config.alma_institution_code = '01UCS_BER'
10
+ Config.alma_primo_host = 'search.library.berkeley.edu'
11
+ Config.alma_permalink_key = 'iqob43'
12
+ end
13
+ end
14
+
15
+ after(:each) do
16
+ BerkeleyLibrary::Alma::Config.send(:clear!)
17
+ end
18
+
19
+ let(:expected_check_digits_by_bib) do
20
+ infile = 'spec/data/bibs_with_check_digits.txt'
21
+ File.readlines(infile, chomp: true).each_with_object({}) do |bib, x|
22
+ x[bib[0, 9]] = bib[9]
23
+ end
24
+ end
25
+
26
+ describe :new do
27
+ it "raises an error for input that's not a bib number" do
28
+ bad_record_numbers = %w[
29
+ b1234567
30
+ b123456789abcdef
31
+ (coll)12345
32
+ o12345678
33
+ 991054360089706532
34
+ ]
35
+
36
+ aggregate_failures do
37
+ bad_record_numbers.each do |bad_bib|
38
+ expect { BibNumber.new(bad_bib) }.to raise_error(ArgumentError), "#{bad_bib}: No error raised for #{bad_bib}"
39
+ end
40
+ end
41
+ end
42
+
43
+ it 'produces the expected check digit' do
44
+ aggregate_failures do
45
+ expected_check_digits_by_bib.each do |bib_expected, cd_expected|
46
+ bib_with_cd = BibNumber.new(bib_expected).to_s
47
+ expect(bib_with_cd[0, 9]).to eq(bib_expected) # just to be sure
48
+
49
+ cd_actual = bib_with_cd[9]
50
+ expect(cd_actual).to eq(cd_expected), "Wrong check digit for #{bib_expected}; should be #{cd_expected}, was #{cd_actual}"
51
+ end
52
+ end
53
+ end
54
+
55
+ it 'raises an error if passed an invalid check digit' do
56
+ aggregate_failures do
57
+ expected_check_digits_by_bib.each do |bib, cd|
58
+ cd_i = cd == 'x' ? 10 : cd.to_i
59
+ bad_cd = cd_i == 0 ? 'x' : (cd_i - 1).to_s
60
+ bad_bib = "#{bib}#{bad_cd}"
61
+ expect { BibNumber.new(bad_bib).to_s }.to raise_error(ArgumentError), "#{bib}: No error raised for #{bad_cd} (should be #{cd})"
62
+ end
63
+ end
64
+ end
65
+
66
+ it 'ignores a wildcard "a" check digit, but returns the correct digit' do
67
+ aggregate_failures do
68
+ expected_check_digits_by_bib.each do |bib, cd|
69
+ wildcard = "#{bib}a"
70
+ expected = "#{bib}#{cd}"
71
+ begin
72
+ actual = BibNumber.new(wildcard).to_s
73
+ expect(actual).to eq(expected)
74
+ rescue ArgumentError => e
75
+ raise("Expected #{wildcard} not to raise error, got #{e.class}: #{e}")
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ describe :marc_record do
83
+ it 'returns the MARC record' do
84
+ raw_bib_number = 'b11082434'
85
+ stub_sru_request(raw_bib_number)
86
+
87
+ bib_number = BibNumber.new(raw_bib_number)
88
+ marc_record = bib_number.get_marc_record
89
+ expect(marc_record).not_to be_nil
90
+ expect(marc_record.record_id).to eq('991038544199706532')
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+ require 'uri'
3
+ require 'ostruct'
4
+
5
+ module BerkeleyLibrary
6
+ module Alma
7
+ describe Config do
8
+
9
+ after(:each) do
10
+ Config.send(:clear!)
11
+ end
12
+
13
+ describe :alma_sru_host= do
14
+ it 'sets the hostname' do
15
+ expected_host = 'alma.example.org'
16
+ Config.alma_sru_host = expected_host
17
+ expect(Config.alma_sru_host).to eq(expected_host)
18
+ end
19
+ end
20
+
21
+ describe :alma_institution_code= do
22
+ it 'sets the Alma institution code' do
23
+ expected_code = '01UCS_BER'
24
+ Config.alma_institution_code = expected_code
25
+ expect(Config.alma_institution_code).to eq(expected_code)
26
+ end
27
+ end
28
+
29
+ describe :alma_sru_base_uri do
30
+ it 'generates the base URI from the SRU host and institution code' do
31
+ expected_host = 'alma.example.org'
32
+ Config.alma_sru_host = expected_host
33
+
34
+ expected_code = '01UCS_BER'
35
+ Config.alma_institution_code = expected_code
36
+
37
+ base_uri = Config.alma_sru_base_uri
38
+ expect(base_uri.host).to eq(expected_host)
39
+ expect(base_uri.path).to end_with("/#{expected_code}")
40
+ end
41
+
42
+ it 'requires both the SRU host and institution code to be set' do
43
+ expect { Config.alma_sru_base_uri }.to raise_error(ArgumentError)
44
+
45
+ Config.alma_sru_host = 'alma.example.org'
46
+ Config.alma_institution_code = '01UCS_BER'
47
+
48
+ Config.alma_sru_base_uri
49
+ end
50
+ end
51
+
52
+ describe 'with Rails config' do
53
+ attr_reader :rails_config
54
+
55
+ before(:each) do
56
+ @rails_config = OpenStruct.new
57
+
58
+ application = double(Object)
59
+ allow(application).to receive(:config).and_return(rails_config)
60
+
61
+ rails = double(Object)
62
+ allow(rails).to receive(:application).and_return(application)
63
+
64
+ Object.const_set(:Rails, rails)
65
+ end
66
+
67
+ after(:each) do
68
+ Object.send(:remove_const, :Rails)
69
+ end
70
+
71
+ describe :alma_sru_base_uri do
72
+ it 'generates the base URI from the SRU host and institution code' do
73
+ expected_host = 'alma.example.org'
74
+ rails_config.alma_sru_host = expected_host
75
+
76
+ expected_code = '01UCS_BER'
77
+ rails_config.alma_institution_code = expected_code
78
+
79
+ base_uri = Config.alma_sru_base_uri
80
+ expect(base_uri.host).to eq(expected_host)
81
+ expect(base_uri.path).to end_with("/#{expected_code}")
82
+ end
83
+ end
84
+ end
85
+
86
+ describe :default! do
87
+ it 'sets the defaults' do
88
+ Config.default!
89
+ expect(Config.missing).to be_empty
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+
3
+ module BerkeleyLibrary
4
+ module Alma
5
+ describe MMSID do
6
+ before(:each) do
7
+ BerkeleyLibrary::Alma.configure do
8
+ Config.alma_sru_host = 'berkeley.alma.exlibrisgroup.com'
9
+ Config.alma_institution_code = '01UCS_BER'
10
+ Config.alma_primo_host = 'search.library.berkeley.edu'
11
+ Config.alma_permalink_key = 'iqob43'
12
+ end
13
+ end
14
+
15
+ after(:each) do
16
+ BerkeleyLibrary::Alma::Config.send(:clear!)
17
+ end
18
+
19
+ describe :new do
20
+ it "raises an error for input that's not an MMS ID" do
21
+ bad_record_numbers = %w[
22
+ b11082434
23
+ (coll)12345
24
+ 99127506531
25
+ 235607980063450199
26
+ ]
27
+
28
+ aggregate_failures do
29
+ bad_record_numbers.each do |bad_mms_id|
30
+ expect { MMSID.new(bad_mms_id) }.to raise_error(ArgumentError), "#{bad_mms_id}: No error raised for #{bad_mms_id}"
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ describe :to_s do
37
+ it 'returns the MMS ID' do
38
+ raw_mms_id = '991054360089706532'
39
+ mms_id = MMSID.new(raw_mms_id)
40
+ expect(mms_id.to_s).to eq(raw_mms_id)
41
+ end
42
+ end
43
+
44
+ describe :berkeley? do
45
+ it 'returns true for a Berkeley ID' do
46
+ raw_mms_id = '991054360089706532'
47
+ mms_id = MMSID.new(raw_mms_id)
48
+ expect(mms_id).to be_berkeley
49
+ end
50
+
51
+ it 'returns false for a non-Berkeley ID' do
52
+ raw_mms_id = '9912727694506531'
53
+ mms_id = MMSID.new(raw_mms_id)
54
+ expect(mms_id).not_to be_berkeley
55
+ end
56
+ end
57
+
58
+ describe :marc_record do
59
+ it 'returns the MARC record' do
60
+ raw_mms_id = '991054360089706532'
61
+ stub_sru_request(raw_mms_id)
62
+
63
+ mms_id = MMSID.new(raw_mms_id)
64
+ marc_record = mms_id.get_marc_record
65
+ expect(marc_record).not_to be_nil
66
+ expect(marc_record.record_id).to eq(raw_mms_id)
67
+ end
68
+
69
+ it 'returns nil for an empty response' do
70
+ empty_sru_response = <<~XML.strip
71
+ <?xml version="1.0" encoding="UTF-8"?>
72
+ <searchRetrieveResponse>
73
+ <version>1.2</version>
74
+ <numberOfRecords>0</numberOfRecords>
75
+ <records/>
76
+ </searchRetrieveResponse>
77
+ XML
78
+
79
+ raw_mms_id = '991054360089706532'
80
+ sru_url = sru_url_for(raw_mms_id)
81
+ stub_request(:get, sru_url).to_return(status: 200, body: empty_sru_response)
82
+
83
+ mms_id = MMSID.new(raw_mms_id)
84
+ marc_record = mms_id.get_marc_record
85
+ expect(marc_record).to be_nil
86
+ end
87
+
88
+ it 'returns nil for an HTTP error response' do
89
+ raw_mms_id = '991054360089706532'
90
+ sru_url = sru_url_for(raw_mms_id)
91
+ stub_request(:get, sru_url).to_return(status: 404)
92
+
93
+ mms_id = MMSID.new(raw_mms_id)
94
+ marc_record = mms_id.get_marc_record
95
+ expect(marc_record).to be_nil
96
+ end
97
+ end
98
+
99
+ describe :permalink_uri do
100
+ it 'returns the permalink' do
101
+ raw_mms_id = '991054360089706532'
102
+ expected_url = "https://search.library.berkeley.edu/permalink/01UCS_BER/iqob43/alma#{raw_mms_id}"
103
+
104
+ mms_id = MMSID.new(raw_mms_id)
105
+ expected_uri = URI.parse(expected_url)
106
+ expect(mms_id.permalink_uri).to eq(expected_uri)
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ module BerkeleyLibrary
4
+ module Alma
5
+ describe RecordId do
6
+ describe :parse do
7
+ it 'parses a bib number' do
8
+ raw_bib = 'b11082434'
9
+ bib_number = BibNumber.new(raw_bib)
10
+
11
+ expect(RecordId.parse(raw_bib)).to eq(bib_number)
12
+ end
13
+
14
+ it 'parses an MMS ID' do
15
+ raw_mms_id = '991038544199706532'
16
+ mms_id = MMSID.new(raw_mms_id)
17
+
18
+ expect(RecordId.parse(raw_mms_id)).to eq(mms_id)
19
+ end
20
+
21
+ it 'returns nil for things that are not record IDs' do
22
+ bad_ids = %w[
23
+ b1234567
24
+ b123456789abcdef
25
+ (coll)12345
26
+ o12345678
27
+ 99127506531
28
+ 235607980063450199
29
+ ]
30
+
31
+ aggregate_failures do
32
+ bad_ids.each do |bad_id|
33
+ parsed_id = RecordId.parse(bad_id)
34
+ expect(parsed_id).to be_nil, "Expected nil for #{bad_id}, got #{parsed_id}"
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,56 @@
1
+ # ------------------------------------------------------------
2
+ # Simplecov
3
+
4
+ if ENV['COVERAGE']
5
+ require 'colorize'
6
+ require 'simplecov'
7
+ end
8
+
9
+ # ------------------------------------------------------------
10
+ # RSpec
11
+
12
+ require 'webmock/rspec'
13
+
14
+ RSpec.configure do |config|
15
+ config.color = true
16
+ config.tty = true
17
+ config.formatter = :documentation
18
+ config.before(:each) { WebMock.disable_net_connect!(allow_localhost: true) }
19
+ config.after(:each) { WebMock.allow_net_connect! }
20
+ config.mock_with :rspec do |mocks|
21
+ mocks.verify_partial_doubles = true
22
+ end
23
+ config.shared_context_metadata_behavior = :apply_to_host_groups
24
+ end
25
+
26
+ # ------------------------------------------------------------
27
+ # Code under test
28
+
29
+ require 'berkeley_library/alma'
30
+
31
+ # ------------------------------------------------------------
32
+ # Utility methods
33
+
34
+ def sru_url_for(record_id)
35
+ sru_url_base = 'https://berkeley.alma.exlibrisgroup.com/view/sru/01UCS_BER?version=1.2&operation=searchRetrieve&query='
36
+
37
+ if BerkeleyLibrary::Alma::Constants::ALMA_RECORD_RE =~ record_id
38
+ "#{sru_url_base}alma.mms_id%3D#{record_id}"
39
+ elsif BerkeleyLibrary::Alma::Constants::MILLENNIUM_RECORD_RE =~ record_id
40
+ full_bib_number = BerkeleyLibrary::Alma::BibNumber.new(record_id).to_s
41
+ "#{sru_url_base}alma.other_system_number%3DUCB-#{full_bib_number}-01ucs_ber"
42
+ else
43
+ raise ArgumentError, "Unknown record ID type: #{record_id}"
44
+ end
45
+ end
46
+
47
+ def sru_data_path_for(record_id)
48
+ "spec/data/#{record_id}-sru.xml"
49
+ end
50
+
51
+ def stub_sru_request(record_id)
52
+ sru_url = sru_url_for(record_id)
53
+ marc_xml_path = sru_data_path_for(record_id)
54
+
55
+ stub_request(:get, sru_url).to_return(status: 200, body: File.read(marc_xml_path))
56
+ end