alexandria-book-collection-manager 0.7.9 → 0.7.11

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 (129) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +5 -1
  3. data/.github/workflows/ruby.yml +36 -22
  4. data/.rubocop.yml +12 -3
  5. data/.rubocop_todo.yml +35 -47
  6. data/.simplecov +2 -2
  7. data/CHANGELOG.md +71 -24
  8. data/Gemfile +0 -6
  9. data/Rakefile +5 -5
  10. data/alexandria-book-collection-manager.gemspec +24 -21
  11. data/bin/rake +28 -0
  12. data/bin/rspec +28 -0
  13. data/doc/dependency_decisions.yml +32 -26
  14. data/{bin → exe}/alexandria +1 -3
  15. data/lib/alexandria/about.rb +1 -0
  16. data/lib/alexandria/book_providers/bl_provider.rb +4 -6
  17. data/lib/alexandria/book_providers/{douban.rb → douban_provider.rb} +1 -1
  18. data/lib/alexandria/book_providers/loc_provider.rb +2 -6
  19. data/lib/alexandria/book_providers/sbn_provider.rb +2 -12
  20. data/lib/alexandria/book_providers/thalia_provider.rb +5 -6
  21. data/lib/alexandria/book_providers/{web.rb → website_based_provider.rb} +20 -1
  22. data/lib/alexandria/book_providers/{worldcat.rb → world_cat_provider.rb} +3 -4
  23. data/lib/alexandria/book_providers/z3950_provider.rb +25 -27
  24. data/lib/alexandria/book_providers.rb +14 -10
  25. data/lib/alexandria/config.rb +2 -2
  26. data/lib/alexandria/console.rb +12 -10
  27. data/lib/alexandria/export_format.rb +3 -2
  28. data/lib/alexandria/export_library.rb +35 -40
  29. data/lib/alexandria/import_library.rb +3 -4
  30. data/lib/alexandria/import_library_csv.rb +2 -2
  31. data/lib/alexandria/library_collection.rb +1 -1
  32. data/lib/alexandria/library_store.rb +20 -15
  33. data/lib/alexandria/logging.rb +22 -21
  34. data/lib/alexandria/models/book.rb +1 -2
  35. data/lib/alexandria/models/library.rb +7 -8
  36. data/lib/alexandria/preferences.rb +7 -19
  37. data/lib/alexandria/{book_providers/pseudomarc.rb → pseudo_marc_parser.rb} +2 -2
  38. data/lib/alexandria/scanners/cue_cat.rb +5 -9
  39. data/lib/alexandria/scanners/{keyboard.rb → keyboard_wedge.rb} +3 -3
  40. data/lib/alexandria/scanners.rb +2 -2
  41. data/lib/alexandria/smart_library.rb +9 -5
  42. data/lib/alexandria/ui/acquire_dialog.rb +42 -45
  43. data/lib/alexandria/ui/alert_dialog.rb +3 -3
  44. data/lib/alexandria/ui/barcode_animation.rb +3 -3
  45. data/lib/alexandria/ui/book_properties_dialog.rb +9 -9
  46. data/lib/alexandria/ui/book_properties_dialog_base.rb +13 -14
  47. data/lib/alexandria/ui/builder_base.rb +1 -1
  48. data/lib/alexandria/ui/callbacks.rb +8 -7
  49. data/lib/alexandria/ui/confirm_erase_dialog.rb +1 -0
  50. data/lib/alexandria/ui/conflict_while_copying_dialog.rb +1 -0
  51. data/lib/alexandria/ui/export_dialog.rb +1 -0
  52. data/lib/alexandria/ui/{iconview.rb → icon_view_manager.rb} +1 -0
  53. data/lib/alexandria/ui/icons.rb +2 -2
  54. data/lib/alexandria/ui/iconview_tooltips.rb +1 -1
  55. data/lib/alexandria/ui/init.rb +10 -4
  56. data/lib/alexandria/ui/keep_bad_isbn_dialog.rb +1 -0
  57. data/lib/alexandria/ui/libraries_combo.rb +1 -0
  58. data/lib/alexandria/ui/listview.rb +2 -0
  59. data/lib/alexandria/ui/main_app.rb +3 -1
  60. data/lib/alexandria/ui/multi_drag_treeview.rb +0 -2
  61. data/lib/alexandria/ui/new_book_dialog.rb +15 -20
  62. data/lib/alexandria/ui/new_book_dialog_manual.rb +7 -7
  63. data/lib/alexandria/ui/new_provider_dialog.rb +1 -0
  64. data/lib/alexandria/ui/new_smart_library_dialog.rb +2 -1
  65. data/lib/alexandria/ui/preferences_dialog.rb +4 -4
  66. data/lib/alexandria/ui/provider_preferences_dialog.rb +1 -0
  67. data/lib/alexandria/ui/really_delete_dialog.rb +1 -0
  68. data/lib/alexandria/ui/sidepane_manager.rb +49 -48
  69. data/lib/alexandria/ui/skip_entry_dialog.rb +1 -0
  70. data/lib/alexandria/ui/smart_library_properties_dialog.rb +1 -0
  71. data/lib/alexandria/ui/smart_library_properties_dialog_base.rb +2 -1
  72. data/lib/alexandria/ui/{sound.rb → sound_effects_player.rb} +3 -0
  73. data/lib/alexandria/ui/ui_manager.rb +194 -143
  74. data/lib/alexandria/ui.rb +1 -0
  75. data/lib/alexandria/version.rb +1 -1
  76. data/lib/alexandria/web_themes.rb +1 -1
  77. data/lib/alexandria.rb +6 -5
  78. data/po/Makefile +1 -1
  79. data/po/it.po +64 -82
  80. data/spec/alexandria/book_providers/bl_provider_spec.rb +11 -2
  81. data/spec/alexandria/book_providers/douban_provider_spec.rb +17 -0
  82. data/spec/alexandria/book_providers/loc_provider_spec.rb +10 -2
  83. data/spec/alexandria/book_providers/sbn_provider_spec.rb +10 -2
  84. data/spec/alexandria/book_providers/thalia_provider_spec.rb +9 -1
  85. data/spec/alexandria/book_providers/world_cat_provider_spec.rb +30 -10
  86. data/spec/alexandria/book_providers/z3950_provider_spec.rb +22 -0
  87. data/spec/alexandria/book_spec.rb +5 -3
  88. data/spec/alexandria/console_spec.rb +1 -1
  89. data/spec/alexandria/export_library_spec.rb +65 -19
  90. data/spec/alexandria/library_collection_spec.rb +24 -0
  91. data/spec/alexandria/library_spec.rb +68 -53
  92. data/spec/alexandria/library_store_spec.rb +33 -1
  93. data/spec/alexandria/preferences_spec.rb +7 -7
  94. data/spec/alexandria/pseudo_marc_parser_spec.rb +71 -0
  95. data/spec/alexandria/scanners/cue_cat_spec.rb +11 -4
  96. data/spec/alexandria/scanners/keyboard_wedge_spec.rb +47 -0
  97. data/spec/alexandria/smart_library_spec.rb +7 -5
  98. data/spec/alexandria/ui/about_dialog_spec.rb +2 -2
  99. data/spec/alexandria/ui/acquire_dialog_spec.rb +8 -3
  100. data/spec/alexandria/ui/alert_dialog_spec.rb +6 -4
  101. data/spec/alexandria/ui/bad_isbns_dialog_spec.rb +2 -2
  102. data/spec/alexandria/ui/book_properties_dialog_spec.rb +5 -5
  103. data/spec/alexandria/ui/confirm_erase_dialog_spec.rb +19 -3
  104. data/spec/alexandria/ui/conflict_while_copying_dialog_spec.rb +2 -2
  105. data/spec/alexandria/ui/error_dialog_spec.rb +14 -3
  106. data/spec/alexandria/ui/export_dialog_spec.rb +6 -6
  107. data/spec/alexandria/ui/{iconview_spec.rb → icon_view_manager_spec.rb} +2 -2
  108. data/spec/alexandria/ui/import_dialog_spec.rb +3 -3
  109. data/spec/alexandria/ui/keep_bad_isbn_dialog_spec.rb +2 -2
  110. data/spec/alexandria/ui/main_app_spec.rb +0 -2
  111. data/spec/alexandria/ui/new_book_dialog_manual_spec.rb +5 -5
  112. data/spec/alexandria/ui/new_book_dialog_spec.rb +7 -4
  113. data/spec/alexandria/ui/new_provider_dialog_spec.rb +3 -3
  114. data/spec/alexandria/ui/new_smart_library_dialog_spec.rb +9 -7
  115. data/spec/alexandria/ui/preferences_dialog_spec.rb +2 -2
  116. data/spec/alexandria/ui/provider_preferences_dialog_spec.rb +22 -7
  117. data/spec/alexandria/ui/really_delete_dialog_spec.rb +2 -2
  118. data/spec/alexandria/ui/sidepane_manager_spec.rb +2 -2
  119. data/spec/alexandria/ui/skip_entry_dialog_spec.rb +19 -3
  120. data/spec/alexandria/ui/smart_library_properties_dialog_spec.rb +2 -2
  121. data/spec/alexandria/ui/ui_manager_spec.rb +7 -5
  122. data/spec/end_to_end/basic_run_spec.rb +2 -1
  123. data/spec/spec_helper.rb +26 -33
  124. data/tasks/setup.rb +1 -1
  125. data/util/rake/fileinstall.rb +12 -13
  126. data/util/rake/gettextgenerate.rb +1 -1
  127. data/util/rake/omfgenerate.rb +1 -1
  128. metadata +97 -64
  129. /data/spec/alexandria/ui/{sound_spec.rb → sound_effects_player_spec.rb} +0 -0
@@ -11,12 +11,11 @@ RSpec.describe Alexandria::ExportLibrary do
11
11
  loader = Alexandria::LibraryStore.new(TESTDIR)
12
12
  loader.load_library("My Library")
13
13
  end
14
- let(:format) { Alexandria::ExportFormat.all.find { |it| it.message == message } }
14
+ let(:format) { Alexandria::ExportFormat.all.find { _1.message == message } }
15
15
  let(:outfile) do
16
16
  outfile_base = format.ext ? "my-library.#{format.ext}" : "my-library"
17
- File.join(Dir.tmpdir, outfile_base)
17
+ File.join(Dir.mktmpdir, outfile_base)
18
18
  end
19
- let(:unsorted) { Alexandria::LibrarySortOrder::Unsorted.new }
20
19
 
21
20
  before do
22
21
  test_library = File.join(LIBDIR, "0.6.2")
@@ -24,7 +23,7 @@ RSpec.describe Alexandria::ExportLibrary do
24
23
  end
25
24
 
26
25
  after do
27
- FileUtils.rm_rf(outfile) if File.exist? outfile
26
+ FileUtils.rm_rf(outfile)
28
27
  end
29
28
 
30
29
  describe "#export_as_csv_list" do
@@ -38,7 +37,7 @@ RSpec.describe Alexandria::ExportLibrary do
38
37
  sort_by_title = Alexandria::LibrarySortOrder.new(:title)
39
38
  format.invoke(my_library, sort_by_title, outfile)
40
39
  rows = load_rows_from_csv
41
- titles = rows.map { |it| it["Title"] }
40
+ titles = rows.map { _1["Title"] }
42
41
  expect(titles).to eq titles.sort
43
42
  end
44
43
 
@@ -46,7 +45,7 @@ RSpec.describe Alexandria::ExportLibrary do
46
45
  sort_by_date_desc = Alexandria::LibrarySortOrder.new(:publishing_year, false)
47
46
  format.invoke(my_library, sort_by_date_desc, outfile)
48
47
  rows = load_rows_from_csv
49
- dates = rows.map { |it| it["Year Published"] }
48
+ dates = rows.map { _1["Year Published"] }
50
49
  expect(dates).to eq dates.sort.reverse
51
50
  end
52
51
  end
@@ -55,12 +54,13 @@ RSpec.describe Alexandria::ExportLibrary do
55
54
  let(:message) { :export_as_html }
56
55
 
57
56
  it "can export unsorted" do
58
- format.invoke(my_library, unsorted, outfile, Alexandria::WebTheme.all.first)
57
+ format.invoke(my_library, Alexandria::LibrarySortOrder::Unsorted.new,
58
+ outfile, Alexandria::WebTheme.all.first)
59
59
  index = File.join(outfile, "index.html")
60
60
 
61
61
  aggregate_failures do
62
- expect(File.exist?(outfile)).to be_truthy
63
- expect(File.exist?(index)).to be_truthy
62
+ expect(outfile).to be_an_existing_file
63
+ expect(index).to be_an_existing_file
64
64
  expect(File.size(index)).to be_nonzero
65
65
  end
66
66
  end
@@ -70,9 +70,9 @@ RSpec.describe Alexandria::ExportLibrary do
70
70
  let(:message) { :export_as_onix_xml_archive }
71
71
 
72
72
  it "can export unsorted" do
73
- format.invoke(my_library, unsorted, outfile)
73
+ format.invoke(my_library, Alexandria::LibrarySortOrder::Unsorted.new, outfile)
74
74
  aggregate_failures do
75
- expect(File.exist?(outfile)).to be_truthy
75
+ expect(outfile).to be_an_existing_file
76
76
  expect(File.size(outfile)).to be_nonzero
77
77
  end
78
78
  end
@@ -82,9 +82,9 @@ RSpec.describe Alexandria::ExportLibrary do
82
82
  let(:message) { :export_as_tellico_xml_archive }
83
83
 
84
84
  it "can export unsorted" do
85
- format.invoke(my_library, unsorted, outfile)
85
+ format.invoke(my_library, Alexandria::LibrarySortOrder::Unsorted.new, outfile)
86
86
  aggregate_failures do
87
- expect(File.exist?(outfile)).to be_truthy
87
+ expect(outfile).to be_an_existing_file
88
88
  expect(File.size(outfile)).to be_nonzero
89
89
  end
90
90
  end
@@ -92,12 +92,58 @@ RSpec.describe Alexandria::ExportLibrary do
92
92
 
93
93
  describe "#export_as_bibtex" do
94
94
  let(:message) { :export_as_bibtex }
95
+ let(:expected_content) do
96
+ <<~BIBTEX
97
+ %Generated on #{Date.today} by: Alexandria #{Alexandria::DISPLAY_VERSION}
98
+ %
99
+
100
+ @BOOK{William1,
101
+ author = "William Gibson",
102
+ title = "Pattern Recognition",
103
+ publisher = "Penguin Books Ltd",
104
+ year = 2004
105
+ }
106
+
107
+ @BOOK{Francoise1,
108
+ author = "Francoise Sagan and Irene Ash",
109
+ title = "Bonjour Tristesse",
110
+ publisher = "Penguin Books Ltd",
111
+ OPTnote = "Essential penguin",
112
+ year = 1998
113
+ }
114
+
115
+ @BOOK{Kazuo1,
116
+ author = "Kazuo Ishiguro",
117
+ title = "An Artist of the Floating World",
118
+ publisher = "Faber and Faber",
119
+ year = 1999
120
+ }
121
+
122
+ @BOOK{Ursula1,
123
+ author = "Ursula Le Guin",
124
+ title = "The Dispossessed",
125
+ publisher = "Gollancz",
126
+ OPTnote = "Gollancz S.F.",
127
+ year = 2006
128
+ }
129
+
130
+ @BOOK{Neil1,
131
+ author = "Neil Gaiman",
132
+ title = "Neverwhere",
133
+ publisher = "Headline Review",
134
+ OPTnote = "The Author's Preferred Text",
135
+ year = 2005
136
+ }
137
+
138
+ BIBTEX
139
+ end
95
140
 
96
141
  it "can export unsorted" do
97
- format.invoke(my_library, unsorted, outfile)
142
+ format.invoke(my_library, Alexandria::LibrarySortOrder::Unsorted.new, outfile)
98
143
  aggregate_failures do
99
- expect(File.exist?(outfile)).to be_truthy
144
+ expect(outfile).to be_an_existing_file
100
145
  expect(File.size(outfile)).to be_nonzero
146
+ expect(File.read(outfile)).to eq expected_content
101
147
  end
102
148
  end
103
149
  end
@@ -106,9 +152,9 @@ RSpec.describe Alexandria::ExportLibrary do
106
152
  let(:message) { :export_as_isbn_list }
107
153
 
108
154
  it "can export unsorted" do
109
- format.invoke(my_library, unsorted, outfile)
155
+ format.invoke(my_library, Alexandria::LibrarySortOrder::Unsorted.new, outfile)
110
156
  aggregate_failures do
111
- expect(File.exist?(outfile)).to be_truthy
157
+ expect(outfile).to be_an_existing_file
112
158
  expect(File.size(outfile)).to be_nonzero
113
159
  end
114
160
  end
@@ -118,11 +164,11 @@ RSpec.describe Alexandria::ExportLibrary do
118
164
  let(:message) { :export_as_ipod_notes }
119
165
 
120
166
  it "can export unsorted" do
121
- format.invoke(my_library, unsorted, outfile, nil)
167
+ format.invoke(my_library, Alexandria::LibrarySortOrder::Unsorted.new, outfile, nil)
122
168
  index = File.join(outfile, "index.linx")
123
169
 
124
170
  aggregate_failures do
125
- expect(File.exist?(outfile)).to be_truthy
171
+ expect(outfile).to be_an_existing_file
126
172
  expect(File.size(index)).to be_nonzero
127
173
  end
128
174
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is part of Alexandria.
4
+ #
5
+ # See the file README.md for authorship and licensing information.
6
+
7
+ require "spec_helper"
8
+
9
+ RSpec.describe Alexandria::LibraryCollection do
10
+ describe "#ruined_books" do
11
+ before do
12
+ test_library = File.join(LIBDIR, "0.6.2")
13
+ FileUtils.cp_r(test_library, TESTDIR)
14
+ end
15
+
16
+ it "lists ISBNs of empty files with their libraries" do
17
+ FileUtils.touch File.join(TESTDIR, "My Library", "0740704923.yaml")
18
+ collection = described_class.instance
19
+ collection.reload
20
+ library = collection.all_libraries.first
21
+ expect(collection.ruined_books).to eq [[nil, "0740704923", library]]
22
+ end
23
+ end
24
+ end
@@ -12,62 +12,71 @@ describe Alexandria::Library do
12
12
  describe "::EXT" do
13
13
  it "has symbolic references to file extensions" do
14
14
  extensions = Alexandria::Library::EXT
15
- expect(extensions[:book]).not_to be_nil
16
- expect(extensions[:cover]).not_to be_nil
15
+ aggregate_failures do
16
+ expect(extensions[:book]).not_to be_nil
17
+ expect(extensions[:cover]).not_to be_nil
18
+ end
17
19
  end
18
20
  end
19
21
 
20
22
  describe "#valid_isbn?" do
21
23
  it "returns a true value for valid isbns" do
22
24
  ["014143984X", "0-345-43192-8"].each do |x|
23
- expect(described_class.valid_isbn?(x)).to be_truthy
25
+ expect(described_class.valid_isbn?(x)).to be true
24
26
  end
25
27
  end
26
28
  end
27
29
 
28
30
  describe "#valid_ean?" do
29
31
  it "returns a true value for valid EANs" do
30
- expect(described_class.valid_ean?("9780345431929")).to be_truthy
31
- expect(described_class.valid_ean?("978034543192912345")).to be_truthy
32
+ aggregate_failures do
33
+ expect(described_class.valid_ean?("9780345431929")).to be true
34
+ expect(described_class.valid_ean?("978034543192912345")).to be true
32
35
 
33
- # Regression test: this EAN has a checksum of 10, which should be
34
- # treated like a checksum of 0.
35
- expect(described_class.valid_ean?("9784047041790")).to be_truthy
36
+ # Regression test: this EAN has a checksum of 10, which should be
37
+ # treated like a checksum of 0.
38
+ expect(described_class.valid_ean?("9784047041790")).to be true
39
+ end
36
40
  end
37
41
 
38
42
  it "returns a false value for invalid EANs" do
39
- expect(described_class.valid_ean?("780345431929")).to be_falsey
40
- expect(described_class.valid_ean?("97803454319290")).to be_falsey
41
- expect(described_class.valid_ean?("97803454319291234")).to be_falsey
42
- expect(described_class.valid_ean?("9780345431929123456")).to be_falsey
43
- expect(described_class.valid_ean?("9780345431928")).to be_falsey
44
- expect(described_class.valid_ean?("9780345431929A")).to be_falsey
43
+ invalid_eans = ["780345431929", "97803454319290", "97803454319291234",
44
+ "9780345431929123456", "9780345431928", "9780345431929A",
45
+ "9784047041791"]
45
46
 
46
- expect(described_class.valid_ean?("9784047041791")).to be_falsey
47
+ aggregate_failures do
48
+ invalid_eans.each do |ean|
49
+ expect(described_class.valid_ean?(ean)).to be false
50
+ end
51
+ end
47
52
  end
48
53
  end
49
54
 
50
55
  describe "#valid_upc?" do
51
56
  it "returns a true value for valid UPCs" do
52
- expect(described_class.valid_upc?("97803454319312356")).to be_truthy
57
+ expect(described_class.valid_upc?("97803454319312356")).to be true
53
58
  end
54
59
 
55
60
  it "returns a false value for invalid UPCs" do
56
- expect(described_class.valid_upc?("978034543193123567")).to be_falsey
57
- expect(described_class.valid_upc?("9780345431931235")).to be_falsey
61
+ aggregate_failures do
62
+ expect(described_class.valid_upc?("978034543193123567")).to be false
63
+ expect(described_class.valid_upc?("9780345431931235")).to be false
58
64
 
59
- expect(described_class.valid_upc?("97803454319412356")).to be_falsey
60
- expect(described_class.valid_upc?("97803454319212356")).to be_falsey
65
+ expect(described_class.valid_upc?("97803454319412356")).to be false
66
+ expect(described_class.valid_upc?("97803454319212356")).to be false
67
+ end
61
68
  end
62
69
  end
63
70
 
64
71
  describe "#canonicalise_isbn" do
65
72
  it "returns the correct value for several examples" do
66
- expect(described_class.canonicalise_isbn("014143984X")).to eq "014143984X"
67
- expect(described_class.canonicalise_isbn("0-345-43192-8")).to eq "0345431928"
68
- expect(described_class.canonicalise_isbn("3522105907")).to eq "3522105907"
69
- # EAN number
70
- expect(described_class.canonicalise_isbn("9780345431929")).to eq "0345431928"
73
+ aggregate_failures do
74
+ expect(described_class.canonicalise_isbn("014143984X")).to eq "014143984X"
75
+ expect(described_class.canonicalise_isbn("0-345-43192-8")).to eq "0345431928"
76
+ expect(described_class.canonicalise_isbn("3522105907")).to eq "3522105907"
77
+ # EAN number
78
+ expect(described_class.canonicalise_isbn("9780345431929")).to eq "0345431928"
79
+ end
71
80
  end
72
81
  end
73
82
 
@@ -75,7 +84,7 @@ describe Alexandria::Library do
75
84
  let(:my_library) { loader.load_library("Empty") }
76
85
 
77
86
  before do
78
- FileUtils.mkdir(TESTDIR) unless File.exist? TESTDIR
87
+ FileUtils.mkdir_p(TESTDIR)
79
88
  end
80
89
 
81
90
  it "disallows multiple deletion of the same copy of a book" do
@@ -136,21 +145,27 @@ describe Alexandria::Library do
136
145
  end
137
146
 
138
147
  it "can be loaded" do
139
- expect(libs.size).to eq(1)
140
- expect(my_library.size).to eq(3)
148
+ aggregate_failures do
149
+ expect(libs.size).to eq(1)
150
+ expect(my_library.size).to eq(3)
151
+ end
141
152
  end
142
153
 
143
- it "imports cleanly from version 0.6.1 data format" do
144
- # Malory
154
+ it "imports Malory book cleanly from version 0.6.1 data format" do
145
155
  malory_book = my_library.find { |b| b.isbn == "9780192812179" }
146
- expect(malory_book.publisher).to eq("Oxford University Press")
147
- expect(malory_book.authors.include?("Vinaver")).to be_truthy
148
- expect(malory_book.version).to eq(Alexandria::DATA_VERSION)
156
+ aggregate_failures do
157
+ expect(malory_book.publisher).to eq("Oxford University Press")
158
+ expect(malory_book.authors).to include "Vinaver"
159
+ expect(malory_book.version).to eq(Alexandria::DATA_VERSION)
160
+ end
161
+ end
149
162
 
150
- # Guide to LaTeX
163
+ it "imports Guide to LaTeX cleanly from version 0.6.1 data format" do
151
164
  latex_book = my_library.find { |b| b.title.include? "Latex" }
152
- expect(latex_book.isbn).to eq("9780201398250")
153
- expect(latex_book.publisher).to eq("Addison Wesley")
165
+ aggregate_failures do
166
+ expect(latex_book.isbn).to eq("9780201398250")
167
+ expect(latex_book.publisher).to eq("Addison Wesley")
168
+ end
154
169
  end
155
170
  end
156
171
 
@@ -168,16 +183,20 @@ describe Alexandria::Library do
168
183
  end
169
184
 
170
185
  it "can be loaded" do
171
- expect(libs.size).to eq(1)
172
- expect(my_library.size).to eq(2)
186
+ aggregate_failures do
187
+ expect(libs.size).to eq(1)
188
+ expect(my_library.size).to eq(2)
189
+ end
173
190
  end
174
191
 
175
192
  it "loads a book with ISBN" do
176
193
  # Guide to LaTeX
177
194
  latex_book = my_library.find { |b| b.title.include? "Latex" }
178
- expect(latex_book.isbn).to eq("9780201398250")
179
- expect(latex_book.publisher).to eq("Addison Wesley")
180
- expect(latex_book.version).to eq(Alexandria::DATA_VERSION)
195
+ aggregate_failures do
196
+ expect(latex_book.isbn).to eq("9780201398250")
197
+ expect(latex_book.publisher).to eq("Addison Wesley")
198
+ expect(latex_book.version).to eq(Alexandria::DATA_VERSION)
199
+ end
181
200
  end
182
201
 
183
202
  it "loads a book without ISBN" do
@@ -189,13 +208,9 @@ describe Alexandria::Library do
189
208
  it "saves loaded books properly" do
190
209
  my_library.each { |book| my_library.save(book, true) }
191
210
  my_library_reloaded = loader.load_all_libraries[0]
192
- expect(my_library_reloaded.size).to eq(2)
193
-
194
- latex_book = my_library_reloaded.find { |b| b.title.include? "Latex" }
195
- expect(latex_book.publisher).to eq("Addison Wesley")
196
211
 
197
- lex_and_yacc_book = my_library_reloaded.find { |b| b.title.include? "Lex" }
198
- expect(lex_and_yacc_book.publisher).to eq("O'Reilley")
212
+ expect(my_library_reloaded.map(&:publisher))
213
+ .to contain_exactly("O'Reilley", "Addison Wesley")
199
214
  end
200
215
  end
201
216
 
@@ -224,10 +239,10 @@ describe Alexandria::Library do
224
239
  described_class.move(source, target, book)
225
240
 
226
241
  aggregate_failures do
227
- expect(File.exist?(source.yaml(book))).to be_falsey
228
- expect(File.exist?(source.cover(book))).to be_falsey
229
- expect(File.exist?(target.yaml(book))).to be_truthy
230
- expect(File.exist?(target.cover(book))).to be_truthy
242
+ expect(source.yaml(book)).not_to be_an_existing_file
243
+ expect(source.cover(book)).not_to be_an_existing_file
244
+ expect(target.yaml(book)).to be_an_existing_file
245
+ expect(target.cover(book)).to be_an_existing_file
231
246
  end
232
247
  end
233
248
  end
@@ -236,7 +251,7 @@ describe Alexandria::Library do
236
251
  let(:my_library) { loader.load_library("Empty") }
237
252
 
238
253
  before do
239
- FileUtils.mkdir(TESTDIR) unless File.exist? TESTDIR
254
+ FileUtils.mkdir_p(TESTDIR)
240
255
  end
241
256
 
242
257
  it "changes the library's name" do
@@ -246,7 +261,7 @@ describe Alexandria::Library do
246
261
 
247
262
  it "moves the library's directory" do
248
263
  my_library.name = "Really Empty"
249
- expect(File.exist?(File.join(TESTDIR, "Really Empty"))).to be_truthy
264
+ expect(File.join(TESTDIR, "Really Empty")).to be_an_existing_file
250
265
  end
251
266
  end
252
267
  end
@@ -16,7 +16,7 @@ RSpec.describe Alexandria::LibraryStore do
16
16
  aggregate_failures do
17
17
  expect(smart_libs.size).to eq 5
18
18
  smart_libs.each do |lib|
19
- expect(File.exist?(lib.yaml)).to be_truthy
19
+ expect(lib.yaml).to be_an_existing_file
20
20
  end
21
21
  end
22
22
  end
@@ -34,4 +34,36 @@ RSpec.describe Alexandria::LibraryStore do
34
34
  end
35
35
  end
36
36
  end
37
+
38
+ describe "#load_all_libraries" do
39
+ before do
40
+ test_library = File.join(LIBDIR, "0.6.2")
41
+ FileUtils.cp_r(test_library, TESTDIR)
42
+ end
43
+
44
+ it "loads the libraries in the target directory" do
45
+ result = loader.load_all_libraries
46
+ aggregate_failures do
47
+ expect(result.count).to eq 1
48
+ expect(result.first.map(&:title))
49
+ .to contain_exactly("Pattern Recognition", "Bonjour Tristesse",
50
+ "An Artist of the Floating World", "The Dispossessed",
51
+ "Neverwhere")
52
+ end
53
+ end
54
+
55
+ it "lists ISBNs of empty files in ruined books" do
56
+ FileUtils.touch File.join(TESTDIR, "My Library", "0740704923.yaml")
57
+ result = loader.load_all_libraries
58
+ library = result.first
59
+ expect(library.ruined_books).to eq ["0740704923"]
60
+ end
61
+
62
+ it "skips empty files with names that are not valid ISBNs" do
63
+ FileUtils.touch File.join(TESTDIR, "My Library", "12345.yaml")
64
+ result = loader.load_all_libraries
65
+ library = result.first
66
+ expect(library.ruined_books).to be_empty
67
+ end
68
+ end
37
69
  end
@@ -11,17 +11,17 @@ describe Alexandria::Preferences do
11
11
 
12
12
  describe "#get_variable" do
13
13
  it "returns nil fetching unknown setting" do
14
- expect(instance.get_variable("does_not_exist")).to eq nil
14
+ expect(instance.get_variable("does_not_exist")).to be_nil
15
15
  end
16
16
 
17
17
  it "allows fetching by string" do
18
18
  instance.toolbar_visible = false
19
- expect(instance.get_variable("toolbar_visible")).to eq false
19
+ expect(instance.get_variable("toolbar_visible")).to be false
20
20
  end
21
21
 
22
22
  it "allows fetching by symbol" do
23
23
  instance.toolbar_visible = true
24
- expect(instance.get_variable(:toolbar_visible)).to eq true
24
+ expect(instance.get_variable(:toolbar_visible)).to be true
25
25
  end
26
26
  end
27
27
 
@@ -29,23 +29,23 @@ describe Alexandria::Preferences do
29
29
  it "allows setting by string" do
30
30
  instance.toolbar_visible = false
31
31
  instance.set_variable("toolbar_visible", true)
32
- expect(instance.toolbar_visible).to eq true
32
+ expect(instance.toolbar_visible).to be true
33
33
  end
34
34
 
35
35
  it "allows setting by symbol" do
36
36
  instance.toolbar_visible = false
37
37
  instance.set_variable(:toolbar_visible, true)
38
- expect(instance.toolbar_visible).to eq true
38
+ expect(instance.toolbar_visible).to be true
39
39
  end
40
40
  end
41
41
 
42
42
  it "allows setting known setting to false" do
43
43
  instance.toolbar_visible = false
44
- expect(instance.toolbar_visible).to eq false
44
+ expect(instance.toolbar_visible).to be false
45
45
  end
46
46
 
47
47
  it "resets known setting by setting to nil" do
48
48
  instance.toolbar_visible = nil
49
- expect(instance.toolbar_visible).to eq true
49
+ expect(instance.toolbar_visible).to be true
50
50
  end
51
51
  end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (C) 2022 Matijs van Zuijlen
4
+ #
5
+ # Alexandria is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU General Public License as
7
+ # published by the Free Software Foundation; either version 2 of the
8
+ # License, or (at your option) any later version.
9
+ #
10
+ # Alexandria is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public
16
+ # License along with Alexandria; see the file COPYING. If not,
17
+ # write to the Free Software Foundation, Inc., 51 Franklin Street,
18
+ # Fifth Floor, Boston, MA 02110-1301 USA.
19
+
20
+ require "spec_helper"
21
+
22
+ RSpec.describe Alexandria::PseudoMarcParser do
23
+ describe ".marc_text_to_book" do
24
+ let(:marc_text) do
25
+ <<~MARC
26
+ 00991pam 2200289 a 4500
27
+ 001 426456
28
+ 005 19820209000000.0
29
+ 008 811005s1981 maua b 001 0 eng#{' '}
30
+ 035 $9 (DLC) 81017108
31
+ 906 $a 7 $b cbc $c orignew $d 1 $e ocip $f 19 $g y-gencatlg
32
+ 010 $a 81017108#{' '}
33
+ 020 $a 0805335587
34
+ 020 $a 0805335579 (pbk.)
35
+ 040 $a DLC $c DLC $d DLC
36
+ 050 00 $a QA612 $b .G7
37
+ 082 00 $a 514/.2 $2 19
38
+ 100 1 $a Greenberg, Marvin J.
39
+ 245 10 $a Algebraic topology : $b a first course / $c Marvin J. Greenberg, John R. Harper.
40
+ 260 $a Reading, Mass. : $b Benjamin/Cummings Pub. Co., $c 1981.
41
+ 300 $a xi, 311 p. : $b ill. ; $c 24 cm.
42
+ 440 0 $a Mathematics lecture note series ; $v 58
43
+ 500 $a "A revision of the first author's Lectures on algebraic topology"--P.
44
+ 504 $a Bibliography: p. 303-307.
45
+ 500 $a Includes index.
46
+ 650 0 $a Algebraic topology.
47
+ 700 1 $a Harper, John R., $d 1941-
48
+ 991 $b c-GenColl $h QA612 $i .G7 $p 00035736761 $t Copy 1 $w BOOKS
49
+ MARC
50
+ end
51
+
52
+ it "returns a book with the correct attributes" do
53
+ result = described_class.marc_text_to_book(marc_text,
54
+ described_class::USMARC_MAPPINGS)
55
+ aggregate_failures do
56
+ expect(result.title).to eq "Algebraic topology: a first course"
57
+ expect(result.authors).to eq ["Greenberg, Marvin J."]
58
+ end
59
+ end
60
+
61
+ it "returns nil when passed a blank string" do
62
+ result = described_class.marc_text_to_book("", described_class::USMARC_MAPPINGS)
63
+ expect(result).to be_nil
64
+ end
65
+
66
+ it "returns nil when passed nil" do
67
+ result = described_class.marc_text_to_book(nil, described_class::USMARC_MAPPINGS)
68
+ expect(result).to be_nil
69
+ end
70
+ end
71
+ end
@@ -27,10 +27,17 @@ describe Alexandria::Scanners::CueCat do
27
27
  expect(cuecat.name).to match(/CueCat/i)
28
28
  end
29
29
 
30
- it "detects a complete scan only" do
31
- partials.each { |scan| expect(cuecat.match?(scan)).not_to be_truthy }
32
- expect(cuecat.match?(scans[:isbn])).to be_truthy
33
- expect(cuecat.match?(scans[:ib5])).to be_truthy
30
+ it "refuses to detect incomplete scans" do
31
+ aggregate_failures do
32
+ partials.each { |scan| expect(cuecat.match?(scan)).to be false }
33
+ end
34
+ end
35
+
36
+ it "detects complete scans" do
37
+ aggregate_failures do
38
+ expect(cuecat.match?(scans[:isbn])).to be true
39
+ expect(cuecat.match?(scans[:ib5])).to be true
40
+ end
34
41
  end
35
42
 
36
43
  it "decodes ISBN barcodes" do
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is part of Alexandria.
4
+ #
5
+ # See the file README.md for authorship and licensing information.
6
+
7
+ require_relative "../../spec_helper"
8
+
9
+ describe Alexandria::Scanners::KeyboardWedge do
10
+ let(:scanner) { described_class.new }
11
+ let(:partials) do
12
+ ["9",
13
+ "978057507",
14
+ "97805711471"]
15
+ end
16
+ let(:scans) do
17
+ {
18
+ isbn: "978 05711 47168",
19
+ ib5: "978057 5079038 007 99"
20
+ }
21
+ end
22
+
23
+ it "is called KeyboardWedge" do
24
+ expect(scanner.name).to match(/KeyboardWedge/i)
25
+ end
26
+
27
+ it "refuses to detect incomplete scans" do
28
+ aggregate_failures do
29
+ partials.each { |scan| expect(scanner.match?(scan)).to be false }
30
+ end
31
+ end
32
+
33
+ it "detects complete scans" do
34
+ aggregate_failures do
35
+ expect(scanner.match?(scans[:isbn])).to be true
36
+ expect(scanner.match?(scans[:ib5])).to be true
37
+ end
38
+ end
39
+
40
+ it "decodes ISBN barcodes" do
41
+ expect(scanner.decode(scans[:isbn])).to eq("9780571147168")
42
+ end
43
+
44
+ it "decodes ISBN+5 barcodes" do
45
+ expect(scanner.decode(scans[:ib5])).to eq("9780575079038") # 00799
46
+ end
47
+ end