berkeley_library-alma 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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