alexandria-book-collection-manager 0.7.10 → 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 (114) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +5 -1
  3. data/.github/workflows/ruby.yml +33 -19
  4. data/.rubocop.yml +12 -3
  5. data/.rubocop_todo.yml +30 -29
  6. data/CHANGELOG.md +64 -25
  7. data/Gemfile +0 -6
  8. data/Rakefile +2 -2
  9. data/alexandria-book-collection-manager.gemspec +20 -17
  10. data/bin/rake +28 -0
  11. data/bin/rspec +28 -0
  12. data/doc/dependency_decisions.yml +32 -26
  13. data/{bin → exe}/alexandria +1 -3
  14. data/lib/alexandria/about.rb +1 -0
  15. data/lib/alexandria/book_providers/bl_provider.rb +4 -6
  16. data/lib/alexandria/book_providers/{douban.rb → douban_provider.rb} +1 -1
  17. data/lib/alexandria/book_providers/loc_provider.rb +2 -6
  18. data/lib/alexandria/book_providers/sbn_provider.rb +2 -12
  19. data/lib/alexandria/book_providers/thalia_provider.rb +5 -6
  20. data/lib/alexandria/book_providers/{web.rb → website_based_provider.rb} +20 -1
  21. data/lib/alexandria/book_providers/{worldcat.rb → world_cat_provider.rb} +3 -4
  22. data/lib/alexandria/book_providers/z3950_provider.rb +24 -26
  23. data/lib/alexandria/book_providers.rb +14 -10
  24. data/lib/alexandria/config.rb +2 -2
  25. data/lib/alexandria/console.rb +12 -10
  26. data/lib/alexandria/export_format.rb +3 -2
  27. data/lib/alexandria/export_library.rb +31 -36
  28. data/lib/alexandria/import_library.rb +3 -4
  29. data/lib/alexandria/import_library_csv.rb +2 -2
  30. data/lib/alexandria/library_collection.rb +1 -1
  31. data/lib/alexandria/library_store.rb +19 -14
  32. data/lib/alexandria/logging.rb +22 -21
  33. data/lib/alexandria/models/book.rb +1 -2
  34. data/lib/alexandria/models/library.rb +5 -6
  35. data/lib/alexandria/preferences.rb +7 -19
  36. data/lib/alexandria/pseudo_marc_parser.rb +1 -1
  37. data/lib/alexandria/scanners/cue_cat.rb +5 -9
  38. data/lib/alexandria/scanners/{keyboard.rb → keyboard_wedge.rb} +3 -3
  39. data/lib/alexandria/scanners.rb +2 -2
  40. data/lib/alexandria/smart_library.rb +7 -3
  41. data/lib/alexandria/ui/acquire_dialog.rb +42 -45
  42. data/lib/alexandria/ui/alert_dialog.rb +1 -1
  43. data/lib/alexandria/ui/barcode_animation.rb +3 -3
  44. data/lib/alexandria/ui/book_properties_dialog.rb +9 -9
  45. data/lib/alexandria/ui/book_properties_dialog_base.rb +10 -11
  46. data/lib/alexandria/ui/builder_base.rb +1 -1
  47. data/lib/alexandria/ui/callbacks.rb +8 -7
  48. data/lib/alexandria/ui/confirm_erase_dialog.rb +1 -0
  49. data/lib/alexandria/ui/conflict_while_copying_dialog.rb +1 -0
  50. data/lib/alexandria/ui/export_dialog.rb +1 -0
  51. data/lib/alexandria/ui/{iconview.rb → icon_view_manager.rb} +1 -0
  52. data/lib/alexandria/ui/iconview_tooltips.rb +1 -1
  53. data/lib/alexandria/ui/keep_bad_isbn_dialog.rb +1 -0
  54. data/lib/alexandria/ui/libraries_combo.rb +1 -0
  55. data/lib/alexandria/ui/listview.rb +2 -0
  56. data/lib/alexandria/ui/main_app.rb +3 -1
  57. data/lib/alexandria/ui/multi_drag_treeview.rb +0 -2
  58. data/lib/alexandria/ui/new_book_dialog.rb +15 -20
  59. data/lib/alexandria/ui/new_book_dialog_manual.rb +7 -7
  60. data/lib/alexandria/ui/new_provider_dialog.rb +1 -0
  61. data/lib/alexandria/ui/new_smart_library_dialog.rb +2 -1
  62. data/lib/alexandria/ui/preferences_dialog.rb +4 -4
  63. data/lib/alexandria/ui/provider_preferences_dialog.rb +1 -0
  64. data/lib/alexandria/ui/really_delete_dialog.rb +1 -0
  65. data/lib/alexandria/ui/sidepane_manager.rb +49 -48
  66. data/lib/alexandria/ui/skip_entry_dialog.rb +1 -0
  67. data/lib/alexandria/ui/smart_library_properties_dialog.rb +1 -0
  68. data/lib/alexandria/ui/smart_library_properties_dialog_base.rb +2 -1
  69. data/lib/alexandria/ui/{sound.rb → sound_effects_player.rb} +3 -0
  70. data/lib/alexandria/ui/ui_manager.rb +192 -141
  71. data/lib/alexandria/ui.rb +1 -0
  72. data/lib/alexandria/version.rb +1 -1
  73. data/po/Makefile +1 -1
  74. data/po/it.po +64 -82
  75. data/spec/alexandria/book_providers/bl_provider_spec.rb +10 -1
  76. data/spec/alexandria/book_providers/douban_provider_spec.rb +17 -0
  77. data/spec/alexandria/book_providers/loc_provider_spec.rb +8 -0
  78. data/spec/alexandria/book_providers/sbn_provider_spec.rb +9 -1
  79. data/spec/alexandria/book_providers/thalia_provider_spec.rb +8 -0
  80. data/spec/alexandria/book_providers/world_cat_provider_spec.rb +8 -0
  81. data/spec/alexandria/book_providers/z3950_provider_spec.rb +22 -0
  82. data/spec/alexandria/console_spec.rb +1 -1
  83. data/spec/alexandria/export_library_spec.rb +57 -11
  84. data/spec/alexandria/library_collection_spec.rb +24 -0
  85. data/spec/alexandria/library_spec.rb +2 -1
  86. data/spec/alexandria/library_store_spec.rb +32 -0
  87. data/spec/alexandria/scanners/keyboard_wedge_spec.rb +47 -0
  88. data/spec/alexandria/ui/about_dialog_spec.rb +1 -1
  89. data/spec/alexandria/ui/acquire_dialog_spec.rb +8 -3
  90. data/spec/alexandria/ui/alert_dialog_spec.rb +1 -1
  91. data/spec/alexandria/ui/bad_isbns_dialog_spec.rb +1 -1
  92. data/spec/alexandria/ui/book_properties_dialog_spec.rb +1 -1
  93. data/spec/alexandria/ui/confirm_erase_dialog_spec.rb +1 -1
  94. data/spec/alexandria/ui/conflict_while_copying_dialog_spec.rb +1 -1
  95. data/spec/alexandria/ui/error_dialog_spec.rb +1 -1
  96. data/spec/alexandria/ui/export_dialog_spec.rb +3 -3
  97. data/spec/alexandria/ui/{iconview_spec.rb → icon_view_manager_spec.rb} +1 -1
  98. data/spec/alexandria/ui/keep_bad_isbn_dialog_spec.rb +1 -1
  99. data/spec/alexandria/ui/main_app_spec.rb +0 -2
  100. data/spec/alexandria/ui/new_book_dialog_manual_spec.rb +1 -1
  101. data/spec/alexandria/ui/new_book_dialog_spec.rb +6 -3
  102. data/spec/alexandria/ui/preferences_dialog_spec.rb +1 -1
  103. data/spec/alexandria/ui/provider_preferences_dialog_spec.rb +22 -7
  104. data/spec/alexandria/ui/really_delete_dialog_spec.rb +1 -1
  105. data/spec/alexandria/ui/sidepane_manager_spec.rb +1 -1
  106. data/spec/alexandria/ui/skip_entry_dialog_spec.rb +1 -1
  107. data/spec/alexandria/ui/ui_manager_spec.rb +2 -2
  108. data/spec/end_to_end/basic_run_spec.rb +2 -1
  109. data/spec/spec_helper.rb +4 -2
  110. data/tasks/setup.rb +1 -1
  111. data/util/rake/fileinstall.rb +5 -6
  112. data/util/rake/omfgenerate.rb +1 -1
  113. metadata +93 -61
  114. /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")
@@ -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,7 +54,8 @@ 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
@@ -70,7 +70,7 @@ 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
75
  expect(outfile).to be_an_existing_file
76
76
  expect(File.size(outfile)).to be_nonzero
@@ -82,7 +82,7 @@ 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
87
  expect(outfile).to be_an_existing_file
88
88
  expect(File.size(outfile)).to be_nonzero
@@ -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
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,7 +152,7 @@ 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
157
  expect(outfile).to be_an_existing_file
112
158
  expect(File.size(outfile)).to be_nonzero
@@ -118,7 +164,7 @@ 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
@@ -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
@@ -209,7 +209,8 @@ describe Alexandria::Library do
209
209
  my_library.each { |book| my_library.save(book, true) }
210
210
  my_library_reloaded = loader.load_all_libraries[0]
211
211
 
212
- expect(my_library_reloaded.map(&:publisher)).to eq ["O'Reilley", "Addison Wesley"]
212
+ expect(my_library_reloaded.map(&:publisher))
213
+ .to contain_exactly("O'Reilley", "Addison Wesley")
213
214
  end
214
215
  end
215
216
 
@@ -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
@@ -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
@@ -7,7 +7,7 @@
7
7
  require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::AboutDialog do
10
- it "works" do
10
+ it "can be instantiated" do
11
11
  parent = Gtk::Window.new :toplevel
12
12
  expect { described_class.new parent }.not_to raise_error
13
13
  end
@@ -7,8 +7,13 @@
7
7
  require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::AcquireDialog do
10
- it "works" do
11
- parent = Gtk::Window.new :toplevel
12
- expect { described_class.new parent }.not_to raise_error
10
+ let(:parent) { Gtk::Window.new :toplevel }
11
+ let(:library) { Alexandria::Library.new("Hi") }
12
+ let(:ui_manager) { instance_double(Alexandria::UI::UIManager) }
13
+
14
+ it "can be instantiated" do
15
+ allow(ui_manager).to receive :set_status_label
16
+ dialog = described_class.new parent, ui_manager, library
17
+ expect(dialog).to be_a described_class
13
18
  end
14
19
  end
@@ -7,7 +7,7 @@
7
7
  require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::AlertDialog do
10
- it "works" do
10
+ it "can be instantiated" do
11
11
  parent = Gtk::Window.new :toplevel
12
12
  expect do
13
13
  described_class.new(parent, "Hello",
@@ -7,7 +7,7 @@
7
7
  require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::BadIsbnsDialog do
10
- it "works" do
10
+ it "can be instantiated" do
11
11
  parent = Gtk::Window.new :toplevel
12
12
  expect { described_class.new parent, "Careful", [] }.not_to raise_error
13
13
  end
@@ -21,7 +21,7 @@ describe Alexandria::UI::BookPropertiesDialog do
21
21
  library << book
22
22
  end
23
23
 
24
- it "works" do
24
+ it "can be instantiated" do
25
25
  expect { described_class.new parent, library, book }.not_to raise_error
26
26
  end
27
27
 
@@ -9,7 +9,7 @@ require_relative "../../spec_helper"
9
9
  describe Alexandria::UI::ConfirmEraseDialog do
10
10
  let(:parent) { Gtk::Window.new :toplevel }
11
11
 
12
- it "works" do
12
+ it "can be instantiated" do
13
13
  expect { described_class.new parent, "foo-file" }.not_to raise_error
14
14
  end
15
15
 
@@ -7,7 +7,7 @@
7
7
  require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::ConflictWhileCopyingDialog do
10
- it "works" do
10
+ it "can be instantiated" do
11
11
  parent = Gtk::Window.new :toplevel
12
12
  library = instance_double(Alexandria::Library, name: "Bar Library")
13
13
  book = instance_double(Alexandria::Book, title: "Foo Book")
@@ -9,7 +9,7 @@ require_relative "../../spec_helper"
9
9
  describe Alexandria::UI::ErrorDialog do
10
10
  let(:parent) { Gtk::Window.new :toplevel }
11
11
 
12
- it "works" do
12
+ it "can be instantiated" do
13
13
  expect { described_class.new parent, "Boom", "It went boom" }.not_to raise_error
14
14
  end
15
15
 
@@ -11,7 +11,7 @@ describe Alexandria::UI::ExportDialog do
11
11
  let(:library) { Alexandria::Library.new "Bar Library" }
12
12
  let(:sort_order) { Alexandria::LibrarySortOrder::Unsorted.new }
13
13
 
14
- it "works" do
14
+ it "can be instantiated" do
15
15
  expect { described_class.new parent, library, sort_order }.not_to raise_error
16
16
  end
17
17
 
@@ -26,8 +26,8 @@ describe Alexandria::UI::ExportDialog do
26
26
 
27
27
  it "works when response is OK" do
28
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")
29
+ allow(chooser).to receive_messages(run: Gtk::ResponseType::OK,
30
+ filename: File.join(dir, "export"))
31
31
  expect { export_dialog.perform }.not_to raise_error
32
32
  ensure
33
33
  FileUtils.remove_entry dir
@@ -7,7 +7,7 @@
7
7
  require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::IconViewManager do
10
- it "works" do
10
+ it "can be instantiated" do
11
11
  iconview = instance_double(Gtk::IconView).as_null_object
12
12
  parent = instance_double(Alexandria::UI::UIManager, iconview: iconview).as_null_object
13
13
  expect { described_class.new iconview, parent }.not_to raise_error
@@ -7,7 +7,7 @@
7
7
  require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::KeepBadISBNDialog do
10
- it "works" do
10
+ it "can be instantiated" do
11
11
  parent = Gtk::Window.new :toplevel
12
12
  book = instance_double(Alexandria::Book,
13
13
  title: "Foo Book",
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # frozen_string_literal: true
4
-
5
3
  # This file is part of Alexandria.
6
4
  #
7
5
  # See the file README.md for authorship and licensing information.
@@ -13,7 +13,7 @@ describe Alexandria::UI::NewBookDialogManual do
13
13
  store.load_library("Bar Library")
14
14
  end
15
15
 
16
- it "works" do
16
+ it "can be instantiated" do
17
17
  expect { described_class.new parent, library }.not_to raise_error
18
18
  end
19
19
 
@@ -9,14 +9,17 @@ require "spec_helper"
9
9
  describe Alexandria::UI::NewBookDialog do
10
10
  let(:parent) { Gtk::Window.new :toplevel }
11
11
  let(:model) { Gtk::ListStore.new(String, String, GdkPixbuf::Pixbuf) }
12
+ let(:library) { Alexandria::Library.new("Hi") }
13
+ let(:ui_manager) { instance_double(Alexandria::UI::UIManager) }
12
14
 
13
- it "works" do
14
- expect { described_class.new parent }.not_to raise_error
15
+ it "can be instantiated" do
16
+ dialog = described_class.new parent, ui_manager, library
17
+ expect(dialog).to be_a described_class
15
18
  end
16
19
 
17
20
  it "can copy search results into result treeview" do
18
21
  results = [[an_artist_of_the_floating_world, "cover-url"]]
19
- dialog = described_class.new parent
22
+ dialog = described_class.new parent, ui_manager, library
20
23
  expect { dialog.copy_results_to_treeview_model results, model }.not_to raise_error
21
24
  end
22
25
  end
@@ -7,7 +7,7 @@
7
7
  require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::PreferencesDialog do
10
- it "works" do
10
+ it "can be instantiated" do
11
11
  parent = Gtk::Window.new :toplevel
12
12
  expect { described_class.new(parent) { nil } }.not_to raise_error
13
13
  end
@@ -8,9 +8,13 @@ require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::ProviderPreferencesDialog do
10
10
  let(:parent) { Gtk::Window.new :toplevel }
11
+ let(:variable) do
12
+ instance_double(Alexandria::BookProviders::Preferences::Variable,
13
+ name: "foo-bar", description: "Foo Bar", possible_values: nil,
14
+ value: "baz", mandatory?: false)
15
+ end
11
16
  let(:preferences) do
12
- instance_double(Alexandria::BookProviders::Preferences,
13
- length: 0, read: [])
17
+ instance_double(Alexandria::BookProviders::Preferences, length: 0, read: [variable])
14
18
  end
15
19
  let(:provider) do
16
20
  instance_double(Alexandria::BookProviders::GenericProvider,
@@ -23,12 +27,23 @@ describe Alexandria::UI::ProviderPreferencesDialog do
23
27
  end
24
28
 
25
29
  describe "#acquire" do
26
- it "works" do
27
- preferences_dialog = described_class.new parent, provider
28
- gtk_dialog = preferences_dialog.dialog
29
- allow(gtk_dialog).to receive(:run)
30
+ let(:preferences_dialog) { described_class.new parent, provider }
31
+
32
+ before do
33
+ allow(preferences_dialog.dialog).to receive(:run)
34
+ allow(variable).to receive(:new_value=)
35
+ end
36
+
37
+ it "runs the underlying Gtk+ dialog" do
38
+ preferences_dialog.acquire
39
+
40
+ expect(preferences_dialog.dialog).to have_received(:run)
41
+ end
42
+
43
+ it "updates variables" do
44
+ preferences_dialog.acquire
30
45
 
31
- expect { preferences_dialog.acquire }.not_to raise_error
46
+ expect(variable).to have_received(:new_value=).with "baz"
32
47
  end
33
48
  end
34
49
  end
@@ -7,7 +7,7 @@
7
7
  require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::ReallyDeleteDialog do
10
- it "works" do
10
+ it "can be instantiated" do
11
11
  library = instance_double(Alexandria::Library,
12
12
  name: "Bar Library", empty?: false, size: 12)
13
13
  parent = Gtk::Window.new :toplevel
@@ -7,7 +7,7 @@
7
7
  require_relative "../../spec_helper"
8
8
 
9
9
  describe Alexandria::UI::SidepaneManager do
10
- it "works" do
10
+ it "can be instantiated" do
11
11
  library_listview = instance_double(Gtk::TreeView).as_null_object
12
12
  parent = instance_double(Alexandria::UI::UIManager, main_app: nil, append_library: nil)
13
13
  expect { described_class.new library_listview, parent }.not_to raise_error
@@ -9,7 +9,7 @@ require_relative "../../spec_helper"
9
9
  describe Alexandria::UI::SkipEntryDialog do
10
10
  let(:parent) { Gtk::Window.new :toplevel }
11
11
 
12
- it "works" do
12
+ it "can be instantiated" do
13
13
  expect { described_class.new parent, "Foo" }.not_to raise_error
14
14
  end
15
15
 
@@ -9,12 +9,12 @@ require_relative "../../spec_helper"
9
9
  describe Alexandria::UI::UIManager do
10
10
  let(:main_app) { instance_double(Alexandria::UI::MainApp) }
11
11
 
12
- it "works" do
12
+ it "can be instantiated" do
13
13
  expect { described_class.new main_app }.not_to raise_error
14
14
  end
15
15
 
16
16
  describe "#on_new" do
17
- it "works" do
17
+ it "adds one library" do
18
18
  ui = described_class.new main_app
19
19
  libraries = ui.instance_variable_get(:@libraries)
20
20
  libraries_count = libraries.all_libraries.count
@@ -8,7 +8,8 @@ require "gnome_app_driver"
8
8
  require "tmpdir"
9
9
 
10
10
  describe "The Alexandria application" do
11
- let(:driver) { GnomeAppDriver.new "alexandria" }
11
+ # TODO: Remove app_file argument once GnomeAppDriver is smart about executable location
12
+ let(:driver) { GnomeAppDriver.new "alexandria", app_file: "exe/alexandria" }
12
13
 
13
14
  before do
14
15
  ENV["HOME"] = Dir.mktmpdir
data/spec/spec_helper.rb CHANGED
@@ -7,7 +7,6 @@
7
7
  require "rspec"
8
8
  require "alexandria"
9
9
  require "webmock/rspec"
10
- require "pry"
11
10
 
12
11
  LIBDIR = File.expand_path("data/libraries", __dir__)
13
12
  TESTDIR = File.join(LIBDIR, "test")
@@ -26,6 +25,8 @@ RSpec::Matchers.define :have_correct_search_result_for do |query|
26
25
  results = provider.instance.search(query, Alexandria::BookProviders::SEARCH_BY_ISBN)
27
26
  rescue SocketError
28
27
  skip "Service is offline"
28
+ rescue Alexandria::BookProviders::ConnectionError
29
+ skip "Connection failed"
29
30
  end
30
31
 
31
32
  expect(results).to be_instance_of(Array)
@@ -38,7 +39,7 @@ RSpec::Matchers.define :have_correct_search_result_for do |query|
38
39
 
39
40
  canonical_query = Alexandria::Library.canonicalise_ean(query)
40
41
  canonical_result = Alexandria::Library.canonicalise_ean(book.isbn)
41
- expect(canonical_query).to eq(canonical_result)
42
+ expect(canonical_result).to eq(canonical_query)
42
43
 
43
44
  expect(cover_url).to be_instance_of(String) if cover_url
44
45
 
@@ -62,6 +63,7 @@ RSpec.configure do |config|
62
63
 
63
64
  config.before do
64
65
  FileUtils.rm_rf(TESTDIR)
66
+ Alexandria.log.level = Logger::DEBUG if ENV["DEBUG"]
65
67
  end
66
68
 
67
69
  config.after do
data/tasks/setup.rb CHANGED
@@ -28,5 +28,5 @@ require "rake/clean"
28
28
 
29
29
  # Load the other rake files in the tasks folder
30
30
  tasks_dir = __dir__
31
- rakefiles = Dir.glob(File.join(tasks_dir, "*.rake")).sort
31
+ rakefiles = Dir.glob(File.join(tasks_dir, "*.rake"))
32
32
  import(*rakefiles)
@@ -29,7 +29,6 @@
29
29
 
30
30
  require "fileutils"
31
31
  require "pathname"
32
- require "set"
33
32
  require "rake/tasklib"
34
33
 
35
34
  # A file installer task, capable of installing into the system
@@ -77,10 +76,10 @@ class FileInstallTask < Rake::TaskLib
77
76
  # of the @file_groups list
78
77
  def make_tasks
79
78
  tasknames = {}
80
- tasknames[:install] = "install_#{@taskname}".intern
81
- tasknames[:uninstall] = "uninstall_#{@taskname}".intern
82
- tasknames[:uninstall_files] = "uninstall_#{@taskname}_files".intern
83
- tasknames[:uninstall_dirs] = "uninstall_#{@taskname}_dirs".intern
79
+ tasknames[:install] = :"install_#{@taskname}"
80
+ tasknames[:uninstall] = :"uninstall_#{@taskname}"
81
+ tasknames[:uninstall_files] = :"uninstall_#{@taskname}_files"
82
+ tasknames[:uninstall_dirs] = :"uninstall_#{@taskname}_dirs"
84
83
 
85
84
  # INSTALL TASK
86
85
 
@@ -197,7 +196,7 @@ class FileInstallTask < Rake::TaskLib
197
196
  part.gsub!("*", "[^\\/]*")
198
197
  part.gsub!("?", "[^\\/]")
199
198
  end
200
- pattern = real_parts.join("([^\/]+\/)*")
199
+ pattern = real_parts.join("([^/]+/)*")
201
200
  /(#{pattern})/
202
201
  end
203
202
 
@@ -68,7 +68,7 @@ class OmfGenerateTask < Rake::TaskLib
68
68
  path = File.join(@gnome_helpfiles_dir, @projectname,
69
69
  locale_for(t.name), "#{@projectname}.xml")
70
70
  data = File.read(t.source)
71
- data.sub!(/PATH_TO_DOC_FILE/, path)
71
+ data.sub!("PATH_TO_DOC_FILE", path)
72
72
  puts "Generating #{t.name}..."
73
73
  File.open(t.name, "w") { |io| io.puts data }
74
74
  end