alexandria-book-collection-manager 0.7.5 → 0.7.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +9 -0
  3. data/.github/workflows/ruby.yml +72 -0
  4. data/.gitignore +4 -1
  5. data/.rubocop.yml +65 -30
  6. data/.rubocop_todo.yml +49 -165
  7. data/.simplecov +5 -2
  8. data/CHANGELOG.md +64 -0
  9. data/ChangeLog.0 +19 -19
  10. data/INSTALL.md +26 -16
  11. data/README.md +31 -35
  12. data/Rakefile +18 -16
  13. data/alexandria-book-collection-manager.gemspec +35 -29
  14. data/doc/FAQ +2 -2
  15. data/doc/dependency_decisions.yml +22 -3
  16. data/lib/alexandria/about.rb +1 -1
  17. data/lib/alexandria/book_providers/bl_provider.rb +88 -0
  18. data/lib/alexandria/book_providers/douban.rb +2 -2
  19. data/lib/alexandria/book_providers/loc_provider.rb +38 -0
  20. data/lib/alexandria/book_providers/pseudomarc.rb +61 -71
  21. data/lib/alexandria/book_providers/sbn_provider.rb +108 -0
  22. data/lib/alexandria/book_providers/{thalia.rb → thalia_provider.rb} +37 -74
  23. data/lib/alexandria/book_providers/web.rb +2 -2
  24. data/lib/alexandria/book_providers/worldcat.rb +34 -38
  25. data/lib/alexandria/book_providers/z3950_provider.rb +199 -0
  26. data/lib/alexandria/book_providers.rb +48 -65
  27. data/lib/alexandria/default_preferences.rb +2 -1
  28. data/lib/alexandria/execution_queue.rb +13 -12
  29. data/lib/alexandria/export_library.rb +21 -22
  30. data/lib/alexandria/image_fetcher.rb +25 -0
  31. data/lib/alexandria/import_library.rb +46 -70
  32. data/lib/alexandria/import_library_csv.rb +16 -16
  33. data/lib/alexandria/library_sort_order.rb +3 -1
  34. data/lib/alexandria/library_store.rb +19 -20
  35. data/lib/alexandria/logging.rb +5 -9
  36. data/lib/alexandria/models/book.rb +15 -2
  37. data/lib/alexandria/models/library.rb +31 -35
  38. data/lib/alexandria/net.rb +1 -2
  39. data/lib/alexandria/preferences.rb +27 -33
  40. data/lib/alexandria/scanners/cue_cat.rb +6 -6
  41. data/lib/alexandria/scanners/keyboard.rb +1 -1
  42. data/lib/alexandria/scanners.rb +2 -2
  43. data/lib/alexandria/smart_library.rb +22 -26
  44. data/lib/alexandria/ui/about_dialog.rb +1 -1
  45. data/lib/alexandria/ui/acquire_dialog.rb +15 -19
  46. data/lib/alexandria/ui/alert_dialog.rb +36 -19
  47. data/lib/alexandria/ui/bad_isbns_dialog.rb +13 -9
  48. data/lib/alexandria/ui/barcode_animation.rb +6 -6
  49. data/lib/alexandria/ui/book_properties_dialog.rb +2 -3
  50. data/lib/alexandria/ui/book_properties_dialog_base.rb +35 -137
  51. data/lib/alexandria/ui/calendar_popup.rb +58 -0
  52. data/lib/alexandria/ui/callbacks.rb +144 -123
  53. data/lib/alexandria/ui/completion_models.rb +2 -6
  54. data/lib/alexandria/ui/confirm_erase_dialog.rb +1 -1
  55. data/lib/alexandria/ui/conflict_while_copying_dialog.rb +2 -2
  56. data/lib/alexandria/ui/error_dialog.rb +1 -1
  57. data/lib/alexandria/ui/export_dialog.rb +19 -18
  58. data/lib/alexandria/ui/icons.rb +34 -40
  59. data/lib/alexandria/ui/iconview_tooltips.rb +40 -53
  60. data/lib/alexandria/ui/import_dialog.rb +49 -48
  61. data/lib/alexandria/ui/init.rb +14 -12
  62. data/lib/alexandria/ui/keep_bad_isbn_dialog.rb +2 -2
  63. data/lib/alexandria/ui/libraries_combo.rb +10 -9
  64. data/lib/alexandria/ui/listview.rb +6 -7
  65. data/lib/alexandria/ui/main_app.rb +2 -2
  66. data/lib/alexandria/ui/multi_drag_treeview.rb +5 -7
  67. data/lib/alexandria/ui/new_book_dialog.rb +63 -65
  68. data/lib/alexandria/ui/new_book_dialog_manual.rb +1 -1
  69. data/lib/alexandria/ui/new_provider_dialog.rb +12 -11
  70. data/lib/alexandria/ui/new_smart_library_dialog.rb +39 -27
  71. data/lib/alexandria/ui/preferences_dialog.rb +25 -84
  72. data/lib/alexandria/ui/provider_preferences_base_dialog.rb +10 -6
  73. data/lib/alexandria/ui/provider_preferences_dialog.rb +5 -5
  74. data/lib/alexandria/ui/really_delete_dialog.rb +2 -2
  75. data/lib/alexandria/ui/sidepane_manager.rb +38 -38
  76. data/lib/alexandria/ui/skip_entry_dialog.rb +3 -2
  77. data/lib/alexandria/ui/smart_library_properties_dialog.rb +35 -36
  78. data/lib/alexandria/ui/smart_library_properties_dialog_base.rb +61 -244
  79. data/lib/alexandria/ui/smart_library_rule_box.rb +119 -0
  80. data/lib/alexandria/ui/sound.rb +4 -6
  81. data/lib/alexandria/ui/ui_manager.rb +80 -83
  82. data/lib/alexandria/ui.rb +7 -7
  83. data/lib/alexandria/version.rb +2 -2
  84. data/lib/alexandria/web_themes.rb +15 -15
  85. data/lib/alexandria.rb +2 -2
  86. data/po/cs.po +947 -865
  87. data/po/cy.po +913 -864
  88. data/po/de.po +961 -865
  89. data/po/el.po +956 -861
  90. data/po/es.po +952 -857
  91. data/po/fr.po +950 -865
  92. data/po/ga.po +866 -819
  93. data/po/gl.po +946 -861
  94. data/po/it.po +945 -858
  95. data/po/ja.po +921 -836
  96. data/po/mk.po +953 -858
  97. data/po/nb.po +932 -847
  98. data/po/nl.po +955 -849
  99. data/po/pl.po +999 -963
  100. data/po/pt.po +946 -850
  101. data/po/pt_BR.po +944 -859
  102. data/po/ru.po +959 -868
  103. data/po/sk.po +950 -863
  104. data/po/sv.po +944 -859
  105. data/po/uk.po +925 -846
  106. data/po/zh_TW.po +926 -841
  107. data/schemas/alexandria.schemas +1 -1
  108. data/share/alexandria/glade/main_app__builder.glade +6 -21
  109. data/share/gnome/help/alexandria/C/adding-books.xml +3 -4
  110. data/share/gnome/help/alexandria/C/introduction.xml +0 -16
  111. data/share/gnome/help/alexandria/C/searching.xml +1 -4
  112. data/share/gnome/help/alexandria/C/settings.xml +0 -30
  113. data/share/gnome/help/alexandria/C/smart-libraries.xml +2 -2
  114. data/share/gnome/help/alexandria/C/working-with-libraries.xml +1 -1
  115. data/share/gnome/help/alexandria/fr/alexandria.xml +5 -160
  116. data/share/gnome/help/alexandria/ja/adding-books.xml +1 -1
  117. data/share/gnome/help/alexandria/ja/introduction.xml +0 -15
  118. data/share/gnome/help/alexandria/ja/searching.xml +3 -7
  119. data/share/gnome/help/alexandria/ja/settings.xml +0 -27
  120. data/share/gnome/help/alexandria/ja/smart-libraries.xml +1 -1
  121. data/spec/alexandria/book_providers/bl_provider_spec.rb +13 -0
  122. data/spec/alexandria/book_providers/loc_provider_spec.rb +17 -0
  123. data/spec/alexandria/book_providers/sbn_provider_spec.rb +13 -0
  124. data/spec/alexandria/book_providers/thalia_provider_spec.rb +119 -0
  125. data/spec/alexandria/book_providers/world_cat_provider_spec.rb +160 -0
  126. data/spec/alexandria/book_providers_spec.rb +0 -154
  127. data/spec/alexandria/console_spec.rb +0 -5
  128. data/spec/alexandria/export_library_spec.rb +27 -38
  129. data/spec/alexandria/library_spec.rb +76 -46
  130. data/spec/alexandria/preferences_spec.rb +29 -3
  131. data/spec/alexandria/scanners/cue_cat_spec.rb +1 -1
  132. data/spec/alexandria/ui/about_dialog_spec.rb +1 -1
  133. data/spec/alexandria/ui/acquire_dialog_spec.rb +1 -1
  134. data/spec/alexandria/ui/alert_dialog_spec.rb +1 -1
  135. data/spec/alexandria/ui/bad_isbns_dialog_spec.rb +1 -1
  136. data/spec/alexandria/ui/book_properties_dialog_spec.rb +47 -5
  137. data/spec/alexandria/ui/confirm_erase_dialog_spec.rb +1 -1
  138. data/spec/alexandria/ui/conflict_while_copying_dialog_spec.rb +1 -1
  139. data/spec/alexandria/ui/error_dialog_spec.rb +1 -1
  140. data/spec/alexandria/ui/export_dialog_spec.rb +25 -4
  141. data/spec/alexandria/ui/icons_spec.rb +26 -0
  142. data/spec/alexandria/ui/iconview_spec.rb +1 -1
  143. data/spec/alexandria/ui/import_dialog_spec.rb +35 -3
  144. data/spec/alexandria/ui/keep_bad_isbn_dialog_spec.rb +1 -1
  145. data/spec/alexandria/ui/main_app_spec.rb +1 -1
  146. data/spec/alexandria/ui/new_book_dialog_manual_spec.rb +39 -3
  147. data/spec/alexandria/ui/new_provider_dialog_spec.rb +19 -3
  148. data/spec/alexandria/ui/new_smart_library_dialog_spec.rb +28 -3
  149. data/spec/alexandria/ui/preferences_dialog_spec.rb +2 -2
  150. data/spec/alexandria/ui/provider_preferences_dialog_spec.rb +23 -8
  151. data/spec/alexandria/ui/really_delete_dialog_spec.rb +1 -1
  152. data/spec/alexandria/ui/sidepane_manager_spec.rb +2 -2
  153. data/spec/alexandria/ui/skip_entry_dialog_spec.rb +1 -1
  154. data/spec/alexandria/ui/smart_library_properties_dialog_spec.rb +37 -6
  155. data/spec/alexandria/ui/ui_manager_spec.rb +116 -2
  156. data/spec/data/libraries/0.6.2/My Library/9780571147168.yaml +2 -0
  157. data/spec/end_to_end/basic_run_spec.rb +3 -8
  158. data/spec/fixtures/cover.jpg +0 -0
  159. data/spec/spec_helper.rb +47 -3
  160. data/tasks/spec.rake +3 -5
  161. data/util/rake/fileinstall.rb +16 -15
  162. data/util/rake/omfgenerate.rb +1 -1
  163. metadata +141 -52
  164. data/.travis.yml +0 -39
  165. data/lib/alexandria/book_providers/adlibris.rb +0 -196
  166. data/lib/alexandria/book_providers/amazon_aws.rb +0 -252
  167. data/lib/alexandria/book_providers/amazon_ecs_util.rb +0 -388
  168. data/lib/alexandria/book_providers/barnes_and_noble.rb +0 -209
  169. data/lib/alexandria/book_providers/proxis.rb +0 -175
  170. data/lib/alexandria/book_providers/siciliano.rb +0 -257
  171. data/lib/alexandria/book_providers/z3950.rb +0 -415
  172. data/spec/alexandria/ui/ui_utilities_spec.rb +0 -62
  173. data/spec/alexandria/utilities_spec.rb +0 -52
@@ -78,10 +78,6 @@ describe Alexandria::Library do
78
78
  FileUtils.mkdir(TESTDIR) unless File.exist? TESTDIR
79
79
  end
80
80
 
81
- after do
82
- FileUtils.rm_rf(TESTDIR)
83
- end
84
-
85
81
  it "disallows multiple deletion of the same copy of a book" do
86
82
  first_copy = an_artist_of_the_floating_world
87
83
  my_library << first_copy
@@ -104,53 +100,64 @@ describe Alexandria::Library do
104
100
  end
105
101
 
106
102
  describe ".import_as_isbn_list" do
107
- def __test_fake_import_isbns
103
+ before do
108
104
  libraries = Alexandria::LibraryCollection.instance
109
- library = Alexandria::Library.new("Test Library")
105
+ library = described_class.new("Test Library")
110
106
  libraries.add_library(library)
111
- [library, libraries]
107
+
108
+ allow(Alexandria::BookProviders)
109
+ .to receive(:isbn_search)
110
+ .and_raise Alexandria::BookProviders::SearchEmptyError
111
+ allow(Alexandria::BookProviders)
112
+ .to receive(:isbn_search).with("0595371086")
113
+ .and_return(an_artist_of_the_floating_world)
112
114
  end
113
115
 
114
- it "doesn't work quite yet" do
115
- skip
116
- # Doesn't work quite yet.
117
- on_iterate_cb = proc {}
118
- on_error_cb = proc {}
119
- library, _libraries = __test_fake_import_isbns
120
- test_file = "data/isbns.txt"
121
- library.import_as_isbn_list("Test Library", test_file, on_iterate_cb, on_error_cb)
116
+ it "imports books with correct isbn and search result" do
117
+ library, bad_isbns, failed_lookup_isbns =
118
+ described_class.import_as_isbn_list("Test Library", "spec/data/isbns.txt",
119
+ proc {}, proc {})
120
+
121
+ aggregate_failures do
122
+ expect(library.to_a).to eq [an_artist_of_the_floating_world]
123
+ expect(bad_isbns).to eq ["0911826449"]
124
+ expect(failed_lookup_isbns).to eq ["0740704923"]
125
+ end
122
126
  end
123
127
  end
124
128
 
125
129
  context "when importing from 0.6.1 data files" do
130
+ let(:libs) { loader.load_all_libraries }
131
+ let(:my_library) { libs[0] }
132
+
126
133
  before do
127
134
  lib_version = File.join(LIBDIR, "0.6.1")
128
135
  FileUtils.cp_r(lib_version, TESTDIR)
129
136
  end
130
137
 
131
- after do
132
- FileUtils.rm_rf(TESTDIR)
138
+ it "can be loaded" do
139
+ expect(libs.size).to eq(1)
140
+ expect(my_library.size).to eq(3)
133
141
  end
134
142
 
135
143
  it "imports cleanly from version 0.6.1 data format" do
136
- libs = loader.load_all_libraries
137
- expect(libs.size).to eq(1)
138
- my_library = libs[0]
139
- expect(my_library.size).to eq(3)
140
144
  # Malory
141
- malory_book = my_library.select { |b| b.isbn == "9780192812179" }[0]
145
+ malory_book = my_library.find { |b| b.isbn == "9780192812179" }
142
146
  expect(malory_book.publisher).to eq("Oxford University Press")
143
147
  expect(malory_book.authors.include?("Vinaver")).to be_truthy
144
148
  expect(malory_book.version).to eq(Alexandria::DATA_VERSION)
145
149
 
146
150
  # Guide to LaTeX
147
- latex_book = my_library.select { |b| b.title.include? "Latex" }[0]
151
+ latex_book = my_library.find { |b| b.title.include? "Latex" }
148
152
  expect(latex_book.isbn).to eq("9780201398250")
149
- expect(latex_book.publisher).to eq("Addison Wesley") # note, no Ruby-Amazon cruft
153
+ expect(latex_book.publisher).to eq("Addison Wesley")
150
154
  end
151
155
  end
152
156
 
153
157
  context "when importing from 0.6.1 with books without an ISBN" do
158
+ let(:libs) { loader.load_all_libraries }
159
+ let(:my_library) { libs[0] }
160
+
154
161
  before do
155
162
  lib_version = File.join(LIBDIR, "0.6.1-noisbn")
156
163
  FileUtils.cp_r(lib_version, TESTDIR)
@@ -160,58 +167,63 @@ describe Alexandria::Library do
160
167
  FileUtils.rm_rf(TESTDIR)
161
168
  end
162
169
 
163
- it "allows books to have no ISBN" do
164
- libs = loader.load_all_libraries
170
+ it "can be loaded" do
165
171
  expect(libs.size).to eq(1)
166
- my_library = libs[0]
167
172
  expect(my_library.size).to eq(2)
173
+ end
168
174
 
175
+ it "loads a book with ISBN" do
169
176
  # Guide to LaTeX
170
- latex_book = my_library.select { |b| b.title.include? "Latex" }[0]
177
+ latex_book = my_library.find { |b| b.title.include? "Latex" }
171
178
  expect(latex_book.isbn).to eq("9780201398250")
172
- expect(latex_book.publisher).to eq("Addison Wesley") # note, no Ruby-Amazon cruft
179
+ expect(latex_book.publisher).to eq("Addison Wesley")
173
180
  expect(latex_book.version).to eq(Alexandria::DATA_VERSION)
181
+ end
174
182
 
183
+ it "loads a book without ISBN" do
175
184
  # Lex and Yacc
176
- lex_and_yacc_book = my_library.select { |b| b.title.include? "Lex" }[0]
185
+ lex_and_yacc_book = my_library.find { |b| b.title.include? "Lex" }
177
186
  expect(lex_and_yacc_book.publisher).to eq("O'Reilley")
187
+ end
178
188
 
179
- my_library.each do |book|
180
- my_library.save(book, true)
181
- end
182
-
183
- libraries_reloaded = loader.load_all_libraries
184
- my_library_reloaded = libraries_reloaded[0]
185
-
189
+ it "saves loaded books properly" do
190
+ my_library.each { |book| my_library.save(book, true) }
191
+ my_library_reloaded = loader.load_all_libraries[0]
186
192
  expect(my_library_reloaded.size).to eq(2)
187
193
 
188
- latex_book = my_library_reloaded.select { |b| b.title.include? "Latex" }[0]
189
- expect(latex_book).not_to be_nil
194
+ latex_book = my_library_reloaded.find { |b| b.title.include? "Latex" }
190
195
  expect(latex_book.publisher).to eq("Addison Wesley")
191
196
 
192
- lex_and_yacc_book = my_library_reloaded.select { |b| b.title.include? "Lex" }[0]
193
- expect(lex_and_yacc_book).not_to be_nil
197
+ lex_and_yacc_book = my_library_reloaded.find { |b| b.title.include? "Lex" }
194
198
  expect(lex_and_yacc_book.publisher).to eq("O'Reilley")
195
199
  end
196
200
  end
197
201
 
198
202
  describe ".move" do
203
+ let(:source) { loader.load_library("My Library") }
204
+ let(:target) { loader.load_library("Target") }
205
+ let(:book) { source.first }
206
+
199
207
  before do
200
208
  lib_version = File.join(LIBDIR, "0.6.2")
201
209
  FileUtils.cp_r(lib_version, TESTDIR)
202
210
  end
203
211
 
204
- it "moves the given book from source to target" do
205
- source = loader.load_library("My Library")
212
+ it "changes the number of books in the source and target libraries" do
206
213
  count = source.count
207
- book = source.first
208
- target = loader.load_library("Target")
209
214
 
210
- described_class.move(source, target, source.first)
215
+ described_class.move(source, target, book)
211
216
 
212
217
  aggregate_failures do
213
218
  expect(source.count).to eq count - 1
214
219
  expect(target.count).to eq 1
220
+ end
221
+ end
222
+
223
+ it "moves the book files from source to target" do
224
+ described_class.move(source, target, book)
225
+
226
+ aggregate_failures do
215
227
  expect(File.exist?(source.yaml(book))).to be_falsey
216
228
  expect(File.exist?(source.cover(book))).to be_falsey
217
229
  expect(File.exist?(target.yaml(book))).to be_truthy
@@ -219,4 +231,22 @@ describe Alexandria::Library do
219
231
  end
220
232
  end
221
233
  end
234
+
235
+ describe "#name=" do
236
+ let(:my_library) { loader.load_library("Empty") }
237
+
238
+ before do
239
+ FileUtils.mkdir(TESTDIR) unless File.exist? TESTDIR
240
+ end
241
+
242
+ it "changes the library's name" do
243
+ my_library.name = "Really Empty"
244
+ expect(my_library.name).to eq "Really Empty"
245
+ end
246
+
247
+ it "moves the library's directory" do
248
+ my_library.name = "Really Empty"
249
+ expect(File.exist?(File.join(TESTDIR, "Really Empty"))).to be_truthy
250
+ end
251
+ end
222
252
  end
@@ -4,13 +4,39 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require File.dirname(__FILE__) + "/../spec_helper"
7
+ require_relative "../spec_helper"
8
8
 
9
9
  describe Alexandria::Preferences do
10
10
  let(:instance) { described_class.instance }
11
11
 
12
- it "returns nil fetching unknown setting" do
13
- expect(instance.does_not_exist).to eq nil
12
+ describe "#get_variable" do
13
+ it "returns nil fetching unknown setting" do
14
+ expect(instance.get_variable("does_not_exist")).to eq nil
15
+ end
16
+
17
+ it "allows fetching by string" do
18
+ instance.toolbar_visible = false
19
+ expect(instance.get_variable("toolbar_visible")).to eq false
20
+ end
21
+
22
+ it "allows fetching by symbol" do
23
+ instance.toolbar_visible = true
24
+ expect(instance.get_variable(:toolbar_visible)).to eq true
25
+ end
26
+ end
27
+
28
+ describe "#set_variable" do
29
+ it "allows setting by string" do
30
+ instance.toolbar_visible = false
31
+ instance.set_variable("toolbar_visible", true)
32
+ expect(instance.toolbar_visible).to eq true
33
+ end
34
+
35
+ it "allows setting by symbol" do
36
+ instance.toolbar_visible = false
37
+ instance.set_variable(:toolbar_visible, true)
38
+ expect(instance.toolbar_visible).to eq true
39
+ end
14
40
  end
15
41
 
16
42
  it "allows setting known setting to false" do
@@ -4,7 +4,7 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require File.dirname(__FILE__) + "/../../spec_helper"
7
+ require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::Scanners::CueCat do
10
10
  let(:cuecat) { described_class.new }
@@ -4,7 +4,7 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require File.dirname(__FILE__) + "/../../spec_helper"
7
+ require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::AboutDialog do
10
10
  it "works" do
@@ -4,7 +4,7 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require File.dirname(__FILE__) + "/../../spec_helper"
7
+ require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::AcquireDialog do
10
10
  it "works" do
@@ -4,7 +4,7 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require File.dirname(__FILE__) + "/../../spec_helper"
7
+ require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::AlertDialog do
10
10
  it "works" do
@@ -4,7 +4,7 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require File.dirname(__FILE__) + "/../../spec_helper"
7
+ require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::BadIsbnsDialog do
10
10
  it "works" do
@@ -4,14 +4,56 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require File.dirname(__FILE__) + "/../../spec_helper"
7
+ require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::BookPropertiesDialog do
10
+ let(:parent) { Gtk::Window.new :toplevel }
11
+ let(:library) do
12
+ store = Alexandria::LibraryCollection.instance.library_store
13
+ store.load_library("Bar Library")
14
+ end
15
+ let(:book) do
16
+ Alexandria::Book.new("Foo Book", ["Jane Doe"], "98765432", "Bar Publisher",
17
+ 1972, "edition")
18
+ end
19
+
20
+ before do
21
+ library << book
22
+ end
23
+
10
24
  it "works" do
11
- parent = Gtk::Window.new :toplevel
12
- library = instance_double(Alexandria::Library, name: "Bar Library", cover: "")
13
- book = Alexandria::Book.new("Foo Book", ["Jane Doe"], "98765432", "Bar Publisher",
14
- 1972, "edition")
15
25
  described_class.new parent, library, book
16
26
  end
27
+
28
+ describe "#on_change_cover" do
29
+ let(:dialog) { described_class.new parent, library, book }
30
+ let(:filechooser) { instance_double(Gtk::FileChooserDialog).as_null_object }
31
+
32
+ before do
33
+ allow(Gtk::FileChooserDialog).to receive(:new).and_return(filechooser)
34
+ allow(filechooser).to receive(:filename)
35
+ .and_return File.join(__dir__, "../../fixtures/cover.jpg")
36
+ end
37
+
38
+ it "works when response is accept" do
39
+ allow(filechooser)
40
+ .to receive(:run).and_return(Gtk::ResponseType::ACCEPT)
41
+
42
+ dialog.on_change_cover
43
+ end
44
+
45
+ it "works when response is reject" do
46
+ allow(filechooser)
47
+ .to receive(:run).and_return(Gtk::ResponseType::REJECT)
48
+
49
+ dialog.on_change_cover
50
+ end
51
+
52
+ it "works when response is cancel" do
53
+ allow(filechooser)
54
+ .to receive(:run).and_return(Gtk::ResponseType::CANCEL)
55
+
56
+ dialog.on_change_cover
57
+ end
58
+ end
17
59
  end
@@ -4,7 +4,7 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require File.dirname(__FILE__) + "/../../spec_helper"
7
+ require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::ConfirmEraseDialog do
10
10
  it "works" do
@@ -4,7 +4,7 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require File.dirname(__FILE__) + "/../../spec_helper"
7
+ require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::ConflictWhileCopyingDialog do
10
10
  it "works" do
@@ -4,7 +4,7 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require File.dirname(__FILE__) + "/../../spec_helper"
7
+ require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::ErrorDialog do
10
10
  it "works" do
@@ -4,12 +4,33 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require File.dirname(__FILE__) + "/../../spec_helper"
7
+ require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::ExportDialog do
10
+ let(:parent) { Gtk::Window.new :toplevel }
11
+ let(:library) { Alexandria::Library.new "Bar Library" }
12
+ let(:sort_order) { Alexandria::LibrarySortOrder::Unsorted.new }
13
+
10
14
  it "works" do
11
- parent = Gtk::Window.new :toplevel
12
- library = instance_double(Alexandria::Library, name: "Bar Library")
13
- described_class.new parent, library, :ascending
15
+ described_class.new parent, library, sort_order
16
+ end
17
+
18
+ describe "#perform" do
19
+ let(:export_dialog) { described_class.new parent, library, sort_order }
20
+ let(:chooser) { export_dialog.dialog }
21
+
22
+ it "works when response is cancel" do
23
+ allow(chooser).to receive(:run).and_return(Gtk::ResponseType::CANCEL)
24
+ export_dialog.perform
25
+ end
26
+
27
+ it "works when response is OK" do
28
+ dir = Dir.mktmpdir
29
+ allow(chooser).to receive(:run).and_return(Gtk::ResponseType::OK)
30
+ allow(chooser).to receive(:filename).and_return File.join(dir, "export")
31
+ export_dialog.perform
32
+ ensure
33
+ FileUtils.remove_entry dir
34
+ end
14
35
  end
15
36
  end
@@ -0,0 +1,26 @@
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::UI::Icons do
10
+ describe ".tag_icon" do
11
+ let(:loader) { Alexandria::LibraryStore.new(TESTDIR) }
12
+ let(:lib_version) { File.join(LIBDIR, "0.6.2") }
13
+
14
+ before do
15
+ FileUtils.cp_r(lib_version, TESTDIR)
16
+ end
17
+
18
+ it "returns a pixbuf" do
19
+ library = loader.load_all_libraries.first
20
+ icon = described_class.cover(library, library.first)
21
+
22
+ tagged_icon = described_class.tag_icon(icon, described_class::FAVORITE_TAG)
23
+ expect(tagged_icon).to be_a GdkPixbuf::Pixbuf
24
+ end
25
+ end
26
+ end
@@ -4,7 +4,7 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require File.dirname(__FILE__) + "/../../spec_helper"
7
+ require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::IconViewManager do
10
10
  it "works" do
@@ -4,11 +4,43 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require File.dirname(__FILE__) + "/../../spec_helper"
7
+ require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::ImportDialog do
10
- it "works" do
11
- parent = Gtk::Window.new :toplevel
10
+ let(:parent) { Gtk::Window.new :toplevel }
11
+
12
+ it "can be instantiated" do
12
13
  described_class.new parent
13
14
  end
15
+
16
+ it "handles a selection change" do
17
+ importdialog = described_class.new parent
18
+ importdialog.dialog.signal_emit "selection_changed"
19
+ end
20
+
21
+ describe "#acquire" do
22
+ let(:import_dialog) { described_class.new parent }
23
+ let(:chooser) { import_dialog.dialog }
24
+
25
+ before do
26
+ allow(chooser).to receive(:filename).and_return("spec/data/isbns.txt")
27
+ allow(Alexandria::BookProviders).to receive(:isbn_search)
28
+ .and_raise Alexandria::BookProviders::SearchEmptyError
29
+ allow(Alexandria::BookProviders).to receive(:isbn_search).with("0595371086")
30
+ .and_return(an_artist_of_the_floating_world)
31
+ end
32
+
33
+ it "works when response is cancel" do
34
+ allow(chooser).to receive(:run).and_return(Gtk::ResponseType::CANCEL)
35
+ import_dialog.acquire { nil }
36
+ end
37
+
38
+ it "works when response is OK" do
39
+ allow(chooser).to receive(:run).and_return(Gtk::ResponseType::OK)
40
+
41
+ result = nil
42
+ import_dialog.acquire { |*args| result = args }
43
+ expect(result.first.to_a).to eq [an_artist_of_the_floating_world]
44
+ end
45
+ end
14
46
  end
@@ -4,7 +4,7 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require File.dirname(__FILE__) + "/../../spec_helper"
7
+ require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::KeepBadISBNDialog do
10
10
  it "works" do
@@ -6,7 +6,7 @@
6
6
  #
7
7
  # See the file README.md for authorship and licensing information.
8
8
 
9
- require File.dirname(__FILE__) + "/../../spec_helper"
9
+ require_relative "../../spec_helper"
10
10
 
11
11
  describe Alexandria::UI::MainApp do
12
12
  it "is a singleton" do
@@ -4,12 +4,48 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require File.dirname(__FILE__) + "/../../spec_helper"
7
+ require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::NewBookDialogManual do
10
+ let(:parent) { Gtk::Window.new :toplevel }
11
+ let(:library) do
12
+ store = Alexandria::LibraryCollection.instance.library_store
13
+ store.load_library("Bar Library")
14
+ end
15
+
10
16
  it "works" do
11
- parent = Gtk::Window.new :toplevel
12
- library = instance_double(Alexandria::Library)
13
17
  described_class.new parent, library
14
18
  end
19
+
20
+ describe "#on_change_cover" do
21
+ let(:dialog) { described_class.new parent, library }
22
+ let(:filechooser) { instance_double(Gtk::FileChooserDialog).as_null_object }
23
+
24
+ before do
25
+ allow(Gtk::FileChooserDialog).to receive(:new).and_return(filechooser)
26
+ allow(filechooser).to receive(:filename)
27
+ .and_return File.join(__dir__, "../../fixtures/cover.jpg")
28
+ end
29
+
30
+ it "works when response is accept" do
31
+ allow(filechooser)
32
+ .to receive(:run).and_return(Gtk::ResponseType::ACCEPT)
33
+
34
+ dialog.on_change_cover
35
+ end
36
+
37
+ it "works when response is reject" do
38
+ allow(filechooser)
39
+ .to receive(:run).and_return(Gtk::ResponseType::REJECT)
40
+
41
+ dialog.on_change_cover
42
+ end
43
+
44
+ it "works when response is cancel" do
45
+ allow(filechooser)
46
+ .to receive(:run).and_return(Gtk::ResponseType::CANCEL)
47
+
48
+ dialog.on_change_cover
49
+ end
50
+ end
15
51
  end
@@ -4,11 +4,27 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require File.dirname(__FILE__) + "/../../spec_helper"
7
+ require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::NewProviderDialog do
10
- it "works" do
11
- parent = Gtk::Window.new :toplevel
10
+ let(:parent) { Gtk::Window.new :toplevel }
11
+
12
+ it "can be instantiated" do
12
13
  described_class.new parent
13
14
  end
15
+
16
+ describe "#acquire" do
17
+ let(:provider_dialog) { described_class.new parent }
18
+ let(:gtk_dialog) { provider_dialog.dialog }
19
+
20
+ it "works when response is cancel" do
21
+ allow(gtk_dialog).to receive(:run).and_return(Gtk::ResponseType::CANCEL)
22
+ provider_dialog.acquire
23
+ end
24
+
25
+ it "works when response is accept" do
26
+ allow(gtk_dialog).to receive(:run).and_return(Gtk::ResponseType::ACCEPT)
27
+ provider_dialog.acquire
28
+ end
29
+ end
14
30
  end
@@ -4,11 +4,36 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require File.dirname(__FILE__) + "/../../spec_helper"
7
+ require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::NewSmartLibraryDialog do
10
- it "works" do
11
- parent = Gtk::Window.new :toplevel
10
+ let(:parent) { Gtk::Window.new :toplevel }
11
+
12
+ it "can be instantiated" do
12
13
  described_class.new parent
13
14
  end
15
+
16
+ describe "#acquire" do
17
+ let(:properties_dialog) { described_class.new parent }
18
+ let(:gtk_dialog) { properties_dialog.dialog }
19
+
20
+ it "works when response is cancel" do
21
+ allow(gtk_dialog).to receive(:run).and_return(Gtk::ResponseType::CANCEL)
22
+ properties_dialog.acquire
23
+ end
24
+
25
+ it "returns a smart library that can be saved when response is ok" do
26
+ allow(gtk_dialog).to receive(:run).and_return(Gtk::ResponseType::OK)
27
+
28
+ # Make sure entered rule is valid
29
+ rules_box = properties_dialog.instance_variable_get(:@rules_box)
30
+ entry = rules_box.children.first.children[2]
31
+ entry.text = "foo"
32
+
33
+ result = properties_dialog.acquire
34
+
35
+ expect(result).to be_a Alexandria::SmartLibrary
36
+ expect { result.save }.not_to raise_error
37
+ end
38
+ end
14
39
  end
@@ -4,11 +4,11 @@
4
4
  #
5
5
  # See the file README.md for authorship and licensing information.
6
6
 
7
- require File.dirname(__FILE__) + "/../../spec_helper"
7
+ require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::PreferencesDialog do
10
10
  it "works" do
11
11
  parent = Gtk::Window.new :toplevel
12
- described_class.new(parent) {}
12
+ described_class.new(parent) { nil }
13
13
  end
14
14
  end