klipbook 0.3.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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