klipbook 0.3.0 → 1.0.0

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 (54) hide show
  1. data/Gemfile +6 -5
  2. data/Gemfile.lock +62 -25
  3. data/Guardfile +1 -2
  4. data/README.md +66 -18
  5. data/Rakefile +5 -1
  6. data/bin/klipbook +85 -1
  7. data/example.png +0 -0
  8. data/features/collate.feature +51 -0
  9. data/features/fixtures/clippings-for-three-books.txt +105 -0
  10. data/features/list.feature +31 -0
  11. data/features/step_definitions/collate_steps.rb +61 -0
  12. data/features/step_definitions/list_steps.rb +15 -0
  13. data/features/support/env.rb +5 -1
  14. data/klipbook.gemspec +49 -32
  15. data/lib/klipbook/book.rb +18 -0
  16. data/lib/klipbook/clipping.rb +4 -10
  17. data/lib/klipbook/collator.rb +17 -0
  18. data/lib/klipbook/config.rb +22 -0
  19. data/lib/klipbook/fetcher.rb +29 -0
  20. data/lib/klipbook/invalid_source_error.rb +12 -0
  21. data/lib/klipbook/output/book_helpers.rb +12 -0
  22. data/lib/klipbook/{book_summary.erb → output/html_book_summary.erb} +65 -11
  23. data/lib/klipbook/output/html_summary_writer.rb +42 -0
  24. data/lib/klipbook/printer.rb +18 -0
  25. data/lib/klipbook/sources/amazon_site/book_scraper.rb +67 -0
  26. data/lib/klipbook/sources/amazon_site/scraper.rb +78 -0
  27. data/lib/klipbook/sources/kindle_device/entry.rb +11 -0
  28. data/lib/klipbook/sources/kindle_device/entry_parser.rb +85 -0
  29. data/lib/klipbook/sources/kindle_device/file.rb +57 -0
  30. data/lib/klipbook/sources/kindle_device/file_parser.rb +33 -0
  31. data/lib/klipbook/version.rb +1 -1
  32. data/lib/klipbook.rb +18 -5
  33. data/spec/lib/klipbook/book_spec.rb +33 -0
  34. data/spec/lib/klipbook/collator_spec.rb +40 -0
  35. data/spec/lib/klipbook/fetcher_spec.rb +81 -0
  36. data/spec/lib/klipbook/output/html_summary_writer_spec.rb +90 -0
  37. data/spec/lib/klipbook/printer_spec.rb +45 -0
  38. data/spec/lib/klipbook/sources/kindle_device/entry_parser_spec.rb +275 -0
  39. data/spec/lib/klipbook/sources/kindle_device/file_parser_spec.rb +68 -0
  40. data/spec/lib/klipbook/sources/kindle_device/file_spec.rb +163 -0
  41. metadata +158 -58
  42. data/features/list_books.feature +0 -23
  43. data/features/print_book_summary.feature +0 -10
  44. data/features/step_definitions/klipbook_steps.rb +0 -87
  45. data/lib/klipbook/book_summary.rb +0 -35
  46. data/lib/klipbook/cli.rb +0 -49
  47. data/lib/klipbook/clippings_file.rb +0 -50
  48. data/lib/klipbook/clippings_parser.rb +0 -98
  49. data/lib/klipbook/runner.rb +0 -29
  50. data/spec/lib/klipbook/book_summary_spec.rb +0 -30
  51. data/spec/lib/klipbook/clipping_spec.rb +0 -17
  52. data/spec/lib/klipbook/clippings_file_spec.rb +0 -60
  53. data/spec/lib/klipbook/clippings_parser_spec.rb +0 -367
  54. data/spec/lib/klipbook/runner_spec.rb +0 -87
@@ -1,98 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- module Klipbook
4
- class ClippingsParser
5
- def extract_clippings_from(file_text)
6
- clippings_text_from(file_text).map { |clipping_text| build_clipping_from(clipping_text) }.compact
7
- end
8
-
9
- def build_clipping_from(clipping_text)
10
- return nil if clipping_text.blank?
11
-
12
- attributes = extract_attributes(clipping_text)
13
-
14
- Clipping.new(attributes)
15
- end
16
-
17
- def extract_attributes(clipping_text)
18
-
19
- lines = clipping_text.lstrip.lines.to_a
20
-
21
- return nil if lines.length < 2
22
-
23
- title_line = lines[0].strip
24
- metadata = lines[1].strip
25
- text_lines = lines[3..-1]
26
-
27
- return nil unless valid_metadata?(metadata)
28
-
29
- {
30
- title: extract_title(title_line),
31
- author: extract_author(title_line),
32
- type: extract_type(metadata),
33
- location: extract_location(metadata),
34
- page: extract_page(metadata),
35
- added_on: extract_added_date(metadata),
36
- text: extract_text(text_lines)
37
- }
38
- end
39
-
40
- def strip_control_characters(file_text)
41
- file_text.gsub("\r", '').gsub("\xef\xbb\xbf", '')
42
- end
43
-
44
- private
45
-
46
- def clippings_text_from(file_text)
47
- strip_control_characters(file_text).split('==========')
48
- end
49
-
50
- def valid_metadata?(metadata)
51
- metadata.match(/^-.*Added on/)
52
- end
53
-
54
- def extract_title(title_line)
55
- if title_line =~ /\(.+\)\Z/
56
- title_line.scan(/(.*)\s+\(.+\)\Z/).first.first
57
- else
58
- title_line
59
- end
60
- end
61
-
62
- def extract_author(title_line)
63
- match = title_line.scan /\(([^\(]+)\)\Z/
64
- match.empty? ? nil : match.first.first
65
- end
66
-
67
- def extract_type(metadata)
68
- type = metadata.scan(/^-( Your)? (\w+)/).first[1]
69
- type.downcase.to_sym
70
- end
71
-
72
- def extract_added_date(metadata)
73
- metadata.scan(/Added on (.+)$/i).first.first
74
- end
75
-
76
- def extract_location(metadata)
77
- match = metadata.scan(/Loc(ation|\.) ([0-9]+-?)/)
78
-
79
- return nil if match.empty?
80
-
81
- location = match.first[1]
82
- location.to_i
83
- end
84
-
85
- def extract_page(metadata)
86
- match = metadata.scan(/Page (\d+)/)
87
-
88
- return nil if match.empty?
89
-
90
- location = match.first.first
91
- location.to_i
92
- end
93
-
94
- def extract_text(text_lines)
95
- text_lines.join('').rstrip
96
- end
97
- end
98
- end
@@ -1,29 +0,0 @@
1
- module Klipbook
2
- class Runner
3
- def initialize(input_file)
4
- @clippings_file = Klipbook::ClippingsFile.new(input_file.read.strip)
5
- end
6
-
7
- def list_books(output=$stdout)
8
- if @clippings_file.books.empty?
9
- output.puts 'Your clippings file contains no books'
10
- else
11
- output.puts 'The list of books in your clippings file:'
12
- @clippings_file.books.each_with_index do |book, index|
13
- author = book.author ? " by #{book.author}" : ''
14
- output.puts "[#{index + 1}] #{book.title}#{author}"
15
- end
16
- end
17
- end
18
-
19
- def print_book_summary(book_number, output, options={})
20
- if book_number < 1 or book_number > @clippings_file.books.length
21
- $stderr.puts "Sorry but you must specify a book index between 1 and #{@clippings_file.books.length}"
22
- return
23
- end
24
-
25
- book_summary = @clippings_file.books[book_number - 1]
26
- output.write book_summary.as_html(options)
27
- end
28
- end
29
- end
@@ -1,30 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Klipbook::BookSummary do
4
- describe '#clippings' do
5
- subject { Klipbook::BookSummary.new('fake title', 'fake author', clippings).clippings }
6
-
7
- let(:first_clipping) { FakeClipping.new(order: 10) }
8
- let(:second_clipping) { FakeClipping.new(order: 22) }
9
- let(:third_clipping) { FakeClipping.new(order: 200) }
10
-
11
- let(:clippings) do
12
- [
13
- third_clipping,
14
- second_clipping,
15
- first_clipping
16
- ]
17
- end
18
-
19
- it 'provides clippings in sorted order' do
20
- subject.should == [ first_clipping, second_clipping, third_clipping ]
21
- end
22
- end
23
-
24
- # A fake clipping that will naturally sort even if the order attribute isn't set
25
- class FakeClipping < OpenStruct
26
- def <=>(other)
27
- self.order <=> other.order
28
- end
29
- end
30
- end
@@ -1,17 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Klipbook::Clipping do
4
- it 'treats the added_on attribute as a date when created' do
5
- clipping = Klipbook::Clipping.new(added_on: "Sunday, December 4, 2011, 07:33 AM")
6
- clipping.added_on.should == DateTime.new(2011,12,4,7,33)
7
- end
8
-
9
- it 'sort based upon location, treating nils as 0' do
10
- first_clipping = Klipbook::Clipping.new(location: nil)
11
- second_clipping = Klipbook::Clipping.new(location: 23)
12
- third_clipping = Klipbook::Clipping.new(location: 345)
13
-
14
- sorted_clippings = [second_clipping, third_clipping, first_clipping].sort
15
- sorted_clippings.should == [ first_clipping, second_clipping, third_clipping ]
16
- end
17
- end
@@ -1,60 +0,0 @@
1
- require 'spec_helper'
2
- require 'ostruct'
3
-
4
- describe Klipbook::ClippingsFile do
5
-
6
- let(:clippings_file) { Klipbook::ClippingsFile.new('', parser) }
7
-
8
- let (:parser) do
9
- fake_parser = Object.new
10
- stub(fake_parser).extract_clippings_from { clippings }
11
- fake_parser
12
- end
13
-
14
- describe '#books' do
15
- subject { clippings_file.books }
16
-
17
- context 'with an empty clippings file' do
18
- let(:clippings) { [] }
19
-
20
- it { should be_empty }
21
- end
22
-
23
- context 'with a single clipping for a single book' do
24
- let(:clippings) do
25
- [ OpenStruct.new(title: 'First fake book title') ]
26
- end
27
-
28
- it 'contains an entry for the book' do
29
- subject.map(&:title).should == [ 'First fake book title' ]
30
- end
31
- end
32
-
33
- context 'with clippings for two books' do
34
- let(:clippings) do
35
- [
36
- OpenStruct.new(title: 'Second fake book title'),
37
- OpenStruct.new(title: 'First fake book title')
38
- ]
39
- end
40
-
41
- it 'contains entries for the two books in alphabetical order' do
42
- subject.map(&:title).should == [ 'First fake book title', 'Second fake book title' ]
43
- end
44
- end
45
-
46
- context 'with multiple clippings for two books' do
47
- let(:clippings) do
48
- [
49
- OpenStruct.new(title: 'First fake book title'),
50
- OpenStruct.new(title: 'Second fake book title'),
51
- OpenStruct.new(title: 'First fake book title')
52
- ]
53
- end
54
-
55
- it 'contains entries for the two books in alphabetical order' do
56
- subject.map(&:title).should == [ 'First fake book title', 'Second fake book title' ]
57
- end
58
- end
59
- end
60
- end
@@ -1,367 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require 'spec_helper'
4
-
5
- describe Klipbook::ClippingsParser do
6
-
7
- describe '#extract_attributes' do
8
-
9
- subject { Klipbook::ClippingsParser.new.extract_attributes(content) }
10
-
11
- context 'on a clipping with the title line "Book title (Author\'s Name)"' do
12
- let (:content) do
13
- "Book title (Author's Name)\n" +
14
- "- Highlight Loc. 466-69 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
15
- "\n" +
16
- "Highlight text\n"
17
- end
18
-
19
- it 'extracts the title as "Book title"' do
20
- subject[:title].should == 'Book title'
21
- end
22
-
23
- it 'extracts the author as "Author\'s Name"' do
24
- subject[:author].should == "Author's Name"
25
- end
26
- end
27
-
28
- context 'on a clipping with the title line "Book title (sub title) (Author\'s Name)"' do
29
- let (:content) do
30
- "Book title (sub title) (Author's Name)\n" +
31
- "- Highlight Loc. 466-69 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
32
- "\n" +
33
- "Highlight text\n"
34
- end
35
-
36
- it 'extracts the title as "Book title (sub title)"' do
37
- subject[:title].should == 'Book title (sub title)'
38
- end
39
-
40
- it 'extracts the author "Author\'s Name"' do
41
- subject[:author].should == "Author's Name"
42
- end
43
- end
44
-
45
- context 'on a clipping with the title line "Book title"' do
46
- let (:content) do
47
- "Book title\n" +
48
- "- Highlight Loc. 466-69 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
49
- "\n" +
50
- "Highlight text\n"
51
- end
52
-
53
- it 'extracts the title as "Book title"' do
54
- subject[:title].should == 'Book title'
55
- end
56
-
57
- it 'extracts no author' do
58
- subject[:author].should be_nil
59
- end
60
- end
61
-
62
- context 'on a highlight' do
63
- let (:content) do
64
- "Book title\n" +
65
- "- Highlight Loc. 466-69 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
66
- "\n" +
67
- "The first line of the highlight\n" +
68
- "The second line of the highlight"
69
- end
70
-
71
- it 'marks the clipping as a highlight' do
72
- subject[:type].should == :highlight
73
- end
74
-
75
- it 'extracts the highlighted text' do
76
- subject[:text].should == "The first line of the highlight\nThe second line of the highlight"
77
- end
78
- end
79
-
80
- context 'on a 4th-generation highlight' do
81
- let (:content) do
82
- "Book title\n" +
83
- "- Your Highlight Location 466-69 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
84
- "\n" +
85
- "The first line of the highlight\n" +
86
- "The second line of the highlight"
87
- end
88
-
89
- it 'marks the clipping as a highlight' do
90
- subject[:type].should == :highlight
91
- end
92
-
93
- it 'extracts the highlighted text' do
94
- subject[:text].should == "The first line of the highlight\nThe second line of the highlight"
95
- end
96
- end
97
-
98
- context 'on a note' do
99
- let (:content) do
100
- "Book title\n" +
101
- "- Note Loc. 623 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
102
- "\n" +
103
- "The note text"
104
- end
105
-
106
- it 'marks the clipping as a note' do
107
- subject[:type].should == :note
108
- end
109
-
110
- it 'extracts the note text' do
111
- subject[:text].should == "The note text"
112
- end
113
- end
114
-
115
- context 'on a 4th-generation note' do
116
- let (:content) do
117
- "Book title\n" +
118
- "- Your Note Location 623 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
119
- "\n" +
120
- "The note text"
121
- end
122
-
123
- it 'marks the clipping as a note' do
124
- subject[:type].should == :note
125
- end
126
-
127
- it 'extracts the note text' do
128
- subject[:text].should == "The note text"
129
- end
130
- end
131
-
132
- context 'on a bookmark' do
133
- let (:content) do
134
- "Book title\n" +
135
- "- Bookmark on Page 1 | Loc. 406 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
136
- "\n" +
137
- "\n"
138
- end
139
-
140
- it 'marks the clipping as a bookmark' do
141
- subject[:type].should == :bookmark
142
- end
143
-
144
- it 'extracts empty text' do
145
- subject[:text].should == ''
146
- end
147
- end
148
-
149
- context 'on a 4th-generation bookmark' do
150
- let (:content) do
151
- "Book title\n" +
152
- "- Your Bookmark on Page 1 | Location 406 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
153
- "\n" +
154
- "\n"
155
- end
156
-
157
- it 'marks the clipping as a bookmark' do
158
- subject[:type].should == :bookmark
159
- end
160
-
161
- it 'extracts empty text' do
162
- subject[:text].should == ''
163
- end
164
- end
165
-
166
- context 'on a clipping with a single location value' do
167
- let (:content) do
168
- "Book title\n" +
169
- "- Highlight Loc. 465 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
170
- "\n" +
171
- "The first line of the highlight\n" +
172
- "The second line of the highlight"
173
- end
174
-
175
- it 'extracts the location' do
176
- subject[:location].should == 465
177
- end
178
-
179
- it 'extracts the added_on date' do
180
- subject[:added_on].should == 'Thursday, April 21, 2011, 07:31 AM'
181
- end
182
- end
183
-
184
- context 'on a 4th-generation clipping with a single location value' do
185
- let (:content) do
186
- "Book title\n" +
187
- "- Your Highlight Location 465 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
188
- "\n" +
189
- "The first line of the highlight\n" +
190
- "The second line of the highlight"
191
- end
192
-
193
- it 'extracts the location' do
194
- subject[:location].should == 465
195
- end
196
-
197
- it 'extracts the added_on date' do
198
- subject[:added_on].should == 'Thursday, April 21, 2011, 07:31 AM'
199
- end
200
- end
201
-
202
- context 'on a clipping with a location range' do
203
- let (:content) do
204
- "Book title\n" +
205
- "- Highlight Loc. 466-69 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
206
- "\n" +
207
- "The first line of the highlight\n" +
208
- "The second line of the highlight"
209
- end
210
-
211
- it 'extracts the first element of the location range' do
212
- subject[:location].should == 466
213
- end
214
-
215
- it 'extracts the added_on date' do
216
- subject[:added_on].should == 'Thursday, April 21, 2011, 07:31 AM'
217
- end
218
- end
219
-
220
- context 'on a 4th-generation clipping with a location range' do
221
- let (:content) do
222
- "Book title\n" +
223
- "- Your Highlight Location 466-69 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
224
- "\n" +
225
- "The first line of the highlight\n" +
226
- "The second line of the highlight"
227
- end
228
-
229
- it 'extracts the first element of the location range' do
230
- subject[:location].should == 466
231
- end
232
-
233
- it 'extracts the added_on date' do
234
- subject[:added_on].should == 'Thursday, April 21, 2011, 07:31 AM'
235
- end
236
- end
237
-
238
- context 'on a highlight with a page number and location range' do
239
- let (:content) do
240
- "Book title\n" +
241
- "- Highlight on Page 171 | Loc. 1858-59 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
242
- "\n" +
243
- "Some highlighted text\n" +
244
- "\n"
245
- end
246
-
247
- it 'extracts the first element of the location range' do
248
- subject[:location].should == 1858
249
- end
250
-
251
- it 'extracts the page number' do
252
- subject[:page].should == 171
253
- end
254
-
255
- it 'extracts the date' do
256
- subject[:added_on].should == 'Thursday, April 21, 2011, 07:31 AM'
257
- end
258
- end
259
-
260
- context 'on a 4th-generation highlight with a page number and location range' do
261
- let (:content) do
262
- "Book title\n" +
263
- "- Your Highlight on Page 171 | Location 1858-59 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
264
- "\n" +
265
- "Some highlighted text\n" +
266
- "\n"
267
- end
268
-
269
- it 'extracts the first element of the location range' do
270
- subject[:location].should == 1858
271
- end
272
-
273
- it 'extracts the page number' do
274
- subject[:page].should == 171
275
- end
276
-
277
- it 'extracts the date' do
278
- subject[:added_on].should == 'Thursday, April 21, 2011, 07:31 AM'
279
- end
280
- end
281
-
282
- context 'on a highlight with a page number and no location' do
283
- let (:content) do
284
- "Book title\n" +
285
- "- Highlight on Page 9 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
286
- "\n" +
287
- "Clipping"
288
- end
289
-
290
- it 'extracts no location' do
291
- subject[:location].should be_nil
292
- end
293
-
294
- it 'extracts the page number' do
295
- subject[:page].should == 9
296
- end
297
-
298
- it 'extracts the date' do
299
- subject[:added_on].should == 'Thursday, April 21, 2011, 07:31 AM'
300
- end
301
- end
302
-
303
- context 'on a 4th-generation highlight with a page number and no location' do
304
- let (:content) do
305
- "Book title\n" +
306
- "- Your Highlight on Page 9 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
307
- "\n" +
308
- "Clipping"
309
- end
310
-
311
- it 'extracts no location' do
312
- subject[:location].should be_nil
313
- end
314
-
315
- it 'extracts the page number' do
316
- subject[:page].should == 9
317
- end
318
-
319
- it 'extracts the date' do
320
- subject[:added_on].should == 'Thursday, April 21, 2011, 07:31 AM'
321
- end
322
- end
323
- end
324
-
325
- describe '#build_clipping_from' do
326
-
327
- let(:it) { Klipbook::ClippingsParser.new }
328
-
329
- context 'with an empty string' do
330
- subject { it.build_clipping_from(" ") }
331
-
332
- it { should be_nil }
333
- end
334
-
335
- it 'builds a clipping using the extracted attributes' do
336
- attributes = {
337
- title: 'Dummy title',
338
- type: :highlight,
339
- location: 42,
340
- added_on: '10 August 2011',
341
- text: 'Some highlighted text'
342
- }
343
- stub(it).extract_attributes { attributes }
344
- stub(Klipbook::Clipping).new
345
-
346
- it.build_clipping_from('Dummy content')
347
-
348
- Klipbook::Clipping.should have_received.new.with(attributes)
349
- end
350
- end
351
-
352
- describe "#strip_control_characters" do
353
- let(:it) { Klipbook::ClippingsParser.new }
354
-
355
- it "removes all carriage return characters" do
356
- processed_text = it.strip_control_characters("An example \r clippings text\r")
357
- processed_text.should_not include("\r")
358
- end
359
-
360
- it "removes all Unicode byte order marks" do
361
- processed_text = it.strip_control_characters("An example \xef\xbb\xbf clippings text\xef\xbb\xbf")
362
- processed_text.should_not include("\xef\xbb\xbf")
363
- end
364
- end
365
- end
366
-
367
-
@@ -1,87 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Klipbook::Runner do
4
-
5
- let (:input_file) do
6
- input_file = Object.new
7
- stub(input_file).read { '' }
8
- input_file
9
- end
10
-
11
- let (:output) do
12
- output = Object.new
13
- stub(output).puts
14
- output
15
- end
16
-
17
- let (:clippings_file) do
18
- clipplings = Object.new
19
- stub(clipplings).books { books }
20
- clipplings
21
- end
22
-
23
- before :each do
24
- stub(Klipbook::ClippingsFile).new { clippings_file }
25
- end
26
-
27
- describe '#list_books' do
28
-
29
- subject { Klipbook::Runner.new(input_file).list_books(output) }
30
-
31
- context 'with an empty clippings file' do
32
-
33
- let (:books) { [] }
34
-
35
- it 'displays a message saying that the clipping file contains no books' do
36
- subject
37
- output.should have_received.puts('Your clippings file contains no books')
38
- end
39
- end
40
-
41
- context 'with a clipping file with multiple books' do
42
- let (:books) do
43
- [ OpenStruct.new(title: 'My first fake title'), OpenStruct.new(title: 'Another fake book', author: 'Rock Riphard') ]
44
- end
45
-
46
- it 'displays a message describing the book list' do
47
- subject
48
- output.should have_received.puts('The list of books in your clippings file:')
49
- end
50
-
51
- it 'displays an indexed list of book titles including the author when available' do
52
- subject
53
- output.should have_received.puts('[1] My first fake title')
54
- output.should have_received.puts('[2] Another fake book by Rock Riphard')
55
- end
56
- end
57
- end
58
-
59
- describe '#print_book_summary' do
60
-
61
- describe 'with a clipping files with two books' do
62
- let (:book_two) do
63
- book_two = Object.new
64
- end
65
-
66
- let (:books) do
67
- [ OpenStruct.new(title: 'My first fake title'), book_two ]
68
- end
69
-
70
- [0, 3].each do |book_number|
71
- it "displays an error message if the book index requested is #{book_number}" do
72
- stub($stderr).puts
73
- Klipbook::Runner.new(input_file).print_book_summary(book_number, output)
74
- $stderr.should have_received.puts('Sorry but you must specify a book index between 1 and 2')
75
- end
76
- end
77
-
78
- it 'outputs the html summary of the book selected' do
79
- mock_html_output = Object.new
80
- stub(output).write
81
- stub(book_two).as_html { mock_html_output }
82
- Klipbook::Runner.new(input_file).print_book_summary(2, output)
83
- output.should have_received.write(mock_html_output)
84
- end
85
- end
86
- end
87
- end