mint 0.2.9 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,242 @@
1
+ require 'spec_helper'
2
+
3
+ # Mimics the requirement to actually require plugins for
4
+ # them to be registered/work.
5
+ require 'mint/plugins/epub'
6
+
7
+ module Mint
8
+ describe Document do
9
+ describe "#chapters" do
10
+ it "splits a document's final text into chapters and maps onto IDs" do
11
+ # TODO: Clean up these long lines
12
+ chapters = Document.new('content.md').chapters
13
+ chapters[0].should =~ /This is just a test.*Paragraph number two/m
14
+ chapters[1].should =~ /Third sentence.*Fourth sentence/m
15
+ end
16
+ end
17
+ end
18
+
19
+ describe EPub do
20
+ describe "#after_publish" do
21
+ let(:document) do
22
+ Document.new 'content.md', :destination => 'directory'
23
+ end
24
+
25
+ before do
26
+ document.publish!
27
+ document_length = File.read('directory/content.html').length
28
+ EPub.after_publish(document)
29
+
30
+ # We're going to consider a document successfully split
31
+ # if its two chapters are less than half of it's length,
32
+ # not including the DOCTYPE/HTML chrome that we introduce
33
+ # into each split document (~150 characters)
34
+ @target_length = document_length / 2 + 200
35
+ end
36
+
37
+ after do
38
+ FileUtils.rm_r 'directory.epub'
39
+ end
40
+
41
+ it "does nothing if no destination is specified" do
42
+ invalid_document = Document.new 'content.md'
43
+ lambda do
44
+ EPub.after_publish(invalid_document)
45
+ end.should raise_error(InvalidDocumentError)
46
+ end
47
+
48
+ it "replaces the monolithic published file with a packaged ePub file" do
49
+ File.exist?('directory/content.html').should be_false
50
+ File.exist?('directory.epub').should be_true
51
+ end
52
+
53
+ it "produces a valid ePub file" do
54
+ pending "need to integrate epubcheck script if found on system"
55
+ end
56
+
57
+ it "ensures all files were compressed using PKZIP" do
58
+ File.read('directory.epub')[0..1].should == 'PK'
59
+ end
60
+
61
+ context "when the ePub file is unzipped" do
62
+ before do
63
+ # Copy instead of moving to make test cleanup more
64
+ # predictable in nested contexts.
65
+ FileUtils.cp 'directory.epub', 'directory.zip'
66
+
67
+ # I will later replace this with my own EPub.unzip! function
68
+ # but don't want to get too distracted now.
69
+ `unzip -o directory.zip -d directory`
70
+
71
+ # EPub.unzip! 'directory.zip'
72
+ end
73
+
74
+ after do
75
+ FileUtils.rm_r 'directory.zip'
76
+ FileUtils.rm_r 'directory'
77
+ end
78
+
79
+ it "contains a META-INF directory" do
80
+ File.exist?('directory/META-INF/container.xml').should be_true
81
+ end
82
+
83
+ it "contains an OPS directory" do
84
+ File.exist?('directory/OPS').should be_true
85
+ end
86
+
87
+ it "contains a mimetype file" do
88
+ File.exist?('directory/mimetype').should be_true
89
+ File.read('directory/mimetype').chomp.should == 'application/epub+zip'
90
+ end
91
+
92
+ it "contains a container file that points to the OPF file" do
93
+ File.exist?('directory/META-INF/container.xml').should be_true
94
+ end
95
+
96
+ it "contains an OPF manifest with book metadata" do
97
+ File.exist?('directory/OPS/content.opf').should be_true
98
+ end
99
+
100
+ it "contains an NCX file with book spine and TOC" do
101
+ File.exist?('directory/OPS/toc.ncx').should be_true
102
+ end
103
+
104
+ it "splits the document into chapters" do
105
+ chapter1 = File.read 'directory/OPS/chapter-1.html'
106
+ chapter2 = File.read 'directory/OPS/chapter-2.html'
107
+
108
+ chapter1.length.should < @target_length
109
+ chapter2.length.should < @target_length
110
+ end
111
+
112
+ it "creates a stylesheet for all pages"
113
+ end
114
+ end
115
+
116
+ describe "#split_on" do
117
+ it "returns a copy of the HTML text it is passed, grouping elements" do
118
+ Document.new('content.md').publish!
119
+
120
+ html_text = File.read 'content.html'
121
+ html_document = Nokogiri::HTML.parse(html_text)
122
+
123
+ chapters = EPub.split_on(html_document, 'h2')
124
+
125
+ expected_document = Nokogiri::HTML.parse <<-HTML
126
+ <div id='container'>
127
+ <div>
128
+ <h2>Header</h2>
129
+ <p>This is just a test.</p>
130
+ <p>Paragraph number two.</p>
131
+ </div>
132
+
133
+ <div>
134
+ <h2>Header 2</h2>
135
+ <p>Third sentence.</p>
136
+ <p>Fourth sentence.</p>
137
+ </div>
138
+ </div>
139
+ HTML
140
+
141
+ expected_chapters = expected_document.search 'div div'
142
+
143
+ cleanse(chapters).should == cleanse(expected_chapters)
144
+ end
145
+ end
146
+
147
+ describe "#zip!" do
148
+ before do
149
+ FileUtils.mkdir 'directory'
150
+
151
+ files = {
152
+ first: 'First content',
153
+ second: 'Second content',
154
+ third: 'Third content'
155
+ }
156
+
157
+ files.each do |name, content|
158
+ File.open "directory/#{name}", 'w' do |f|
159
+ f << content
160
+ end
161
+ end
162
+ end
163
+
164
+ after do
165
+ Dir['directory*'].each {|dir| FileUtils.rm_r dir }
166
+ # FileUtils.rm 'directory.zip'
167
+ # FileUtils.rm_r 'directory'
168
+ end
169
+
170
+ # This is not a great test of Zip functionality,
171
+ # but I don't really care to spend time on this right now.
172
+ # Most of the details of the Zip file creation will be tested
173
+ # above.
174
+ it "compresses the named file into a directory" do
175
+ EPub.zip! 'directory'
176
+ File.exist?('directory.zip').should be_true
177
+ end
178
+
179
+ it "accepts an extension parameter" do
180
+ EPub.zip! 'directory', :extension => 'epub'
181
+ File.exist?('directory.epub').should be_true
182
+ end
183
+
184
+ it "creates a mimetype entry if specified" do
185
+ pending "a more robust Zip testing strategy"
186
+ EPub.zip! 'directory', :mimetype => 'text/epub'
187
+ end
188
+ end
189
+
190
+ describe "#create!" do
191
+ before do
192
+ EPub.should_receive(:create_from_template!).and_return
193
+ end
194
+
195
+ it "accepts a block for configuration options" do
196
+ lambda do
197
+ EPub.create! do |file|
198
+ file.type = 'container'
199
+ end
200
+ end.should_not raise_error
201
+ end
202
+
203
+ it "render a container file" do
204
+ EPub.should_receive(:container_defaults).once.and_return({})
205
+ EPub.create! do |file|
206
+ file.type = 'container'
207
+ end
208
+ end
209
+
210
+ it "render a content file" do
211
+ EPub.should_receive(:content_defaults).once.and_return({})
212
+ EPub.create! do |file|
213
+ file.type = 'content'
214
+ end
215
+ end
216
+
217
+ it "render a table of contents file" do
218
+ EPub.should_receive(:toc_defaults).once.and_return({})
219
+ EPub.create! do |file|
220
+ file.type = 'toc'
221
+ end
222
+ end
223
+
224
+ it "defaults to a type of 'container'" do
225
+ EPub.should_receive(:container_defaults).once.and_return({})
226
+ EPub.create!
227
+ end
228
+ end
229
+
230
+ describe "#create_chapters!" do
231
+ it "calls #create_chapter! for each chapter" do
232
+ EPub.should_receive(:create_chapter!).once.ordered
233
+ EPub.should_receive(:create_chapter!).once.ordered
234
+ EPub.create_chapters! ['text1', 'text2']
235
+ end
236
+ end
237
+
238
+ def cleanse(dom)
239
+ dom.to_s.squeeze.chomp.gsub(/^\s/, '')
240
+ end
241
+ end
242
+ end
@@ -0,0 +1,135 @@
1
+ require 'spec_helper'
2
+
3
+ module Mint
4
+ describe Resource do
5
+ before do
6
+ @tmp_dir = Dir.getwd
7
+ @alternative_root = "#{@tmp_dir}/alternative-root"
8
+ @full_content_file = "#{@tmp_dir}/#{@content_file}"
9
+ @full_alt_content_file = "#{@alternative_root}/#{@content_file}"
10
+ end
11
+
12
+ shared_examples_for "all resources" do
13
+ subject { resource }
14
+
15
+ its(:root_directory_path) { should be_path(resource.root_directory) }
16
+ its(:source_file_path) { should be_path(resource.source_file) }
17
+ its(:source_directory_path) { should be_path(resource.source_directory) }
18
+ its(:destination_file_path) { should be_path(resource.destination_file) }
19
+ its(:destination_directory_path) do
20
+ should be_path(resource.destination_directory)
21
+ end
22
+ end
23
+
24
+ context "when created with a relative path and no root" do
25
+ let(:resource) { Resource.new @content_file }
26
+ subject { resource }
27
+
28
+ its(:name) { should == 'content.html' }
29
+ its(:root) { should == @tmp_dir }
30
+ its(:source) { should == @content_file }
31
+ its(:source_file) { should == @full_content_file }
32
+ its(:source_directory) { should == @tmp_dir }
33
+ its(:destination) { should be_nil }
34
+ its(:destination_file) { should == "#{@tmp_dir}/content.html" }
35
+ its(:destination_directory) { should == @tmp_dir }
36
+
37
+ it_should_behave_like "all resources"
38
+ end
39
+
40
+ # TODO: This is wrong, need to rework this -- probably build slightly
41
+ # more comprehensive system in spec_helper for these edge cases,
42
+ # then build up compound variables in before block for this particular
43
+ # spec (which has more edge cases than most)
44
+ context "when created with a relative path and absolute root" do
45
+ let(:resource) { Resource.new @content_file, :root => @alternative_root }
46
+ subject { resource }
47
+
48
+ its(:name) { should == 'content.html' }
49
+ its(:root) { should == @alternative_root }
50
+ its(:source) { should == @content_file }
51
+ its(:source_file) { should == @full_alt_content_file }
52
+ its(:source_directory) { should == @alternative_root }
53
+ its(:destination) { should be_nil }
54
+ its(:destination_file) { should == "#{@alternative_root}/content.html" }
55
+ its(:destination_directory) { should == @alternative_root }
56
+
57
+ it_should_behave_like "all resources"
58
+ end
59
+
60
+ context "when created with an absolute path, no root" do
61
+ before do
62
+ # This is a use case we will only ever test here, so
63
+ # I'm not going to include it in the spec_helper
64
+ FileUtils.mkdir_p @alternative_root
65
+ File.open(@full_alt_content_file, 'w') do |f|
66
+ f << @content
67
+ end
68
+ end
69
+
70
+ let(:resource) { Resource.new @full_alt_content_file }
71
+ subject { resource }
72
+
73
+ its(:name) { should == 'content.html' }
74
+ its(:root) { should == @alternative_root }
75
+ its(:source) { should == @full_alt_content_file }
76
+ its(:source_file) { should == @full_alt_content_file}
77
+ its(:source_directory) { should == @alternative_root }
78
+ its(:destination) { should be_nil }
79
+ its(:destination_file) { should == "#{@alternative_root}/content.html" }
80
+ its(:destination_directory) { should == @alternative_root }
81
+
82
+ it_should_behave_like "all resources"
83
+ end
84
+
85
+ # The root should *not* override a source file absolute path but
86
+ # *should* affect the destination file path.
87
+ # I should also test this when neither the source nor the root
88
+ # are in Dir.getwd, which is the default root.
89
+ context "when created with an absolute path and root" do
90
+ let(:resource) { Resource.new @full_content_file,
91
+ :root => @alternative_root }
92
+
93
+ subject { resource }
94
+
95
+ its(:name) { should == 'content.html' }
96
+ its(:root) { should == @alternative_root }
97
+ its(:source) { should == @full_content_file }
98
+ its(:source_file) { should == @full_content_file }
99
+ its(:source_directory) { should == @tmp_dir }
100
+ its(:destination) { should be_nil }
101
+ its(:destination_file) { should == "#{@alternative_root}/content.html" }
102
+ its(:destination_directory) { should == @alternative_root }
103
+
104
+ it_should_behave_like "all resources"
105
+ end
106
+
107
+ context "when it's created with a block" do
108
+ let(:resource) do
109
+ Resource.new @content_file do |resource|
110
+ resource.root = @alternative_root
111
+ resource.destination = 'destination'
112
+ end
113
+ end
114
+
115
+ subject { resource }
116
+
117
+ its(:name) { should == 'content.html' }
118
+ its(:root) { should == @alternative_root }
119
+ its(:source) { should == @content_file }
120
+ its(:source_file) { should == @full_alt_content_file }
121
+ its(:source_directory) { should == @alternative_root }
122
+ its(:destination) { should == 'destination' }
123
+
124
+ its(:destination_file) do
125
+ should == "#{@alternative_root}/destination/content.html"
126
+ end
127
+
128
+ its(:destination_directory) do
129
+ should == "#{@alternative_root}/destination"
130
+ end
131
+
132
+ it_should_behave_like "all resources"
133
+ end
134
+ end
135
+ end
@@ -1,6 +1,12 @@
1
1
  require 'pathname'
2
2
  require 'mint'
3
3
 
4
+ def delete_class(klass)
5
+ klass = nil
6
+ GC.start
7
+ sleep 1
8
+ end
9
+
4
10
  RSpec::Matchers.define :be_in_directory do |name|
5
11
  match {|resource| resource.source_directory =~ /#{name}/ }
6
12
  end
@@ -41,10 +47,22 @@ RSpec.configure do |config|
41
47
  @dynamic_style_file = 'dynamic.sass'
42
48
 
43
49
  @content = <<-HERE
50
+ ---
51
+ metadata: true
52
+
44
53
  Header
45
54
  ------
46
55
 
47
56
  This is just a test.
57
+
58
+ Paragraph number two.
59
+
60
+ Header 2
61
+ --------
62
+
63
+ Third sentence.
64
+
65
+ Fourth sentence.
48
66
  HERE
49
67
 
50
68
  @layout = <<-HERE
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ module Mint
4
+ describe Style do
5
+ before { @tmp_dir = Dir.getwd }
6
+
7
+ context "when it's created from a static file" do
8
+ let(:style) { Style.new @static_style_file }
9
+ subject { style }
10
+
11
+ its(:destination) { should be_nil }
12
+ its(:destination_file) { should == "#{@tmp_dir}/static.css" }
13
+
14
+ it { should_not be_rendered }
15
+ it "'renders' itself verbatim" do
16
+ style.render.should == File.read(@static_style_file)
17
+ end
18
+ end
19
+
20
+ context "when it's created from a dynamic file" do
21
+ let(:style) { Style.new @dynamic_style_file }
22
+ subject { style }
23
+
24
+ its(:destination) { should be_nil }
25
+ its(:destination_file) { should == "#{@tmp_dir}/dynamic.css" }
26
+
27
+ it { should be_rendered }
28
+ it "renders itself from a templating language to Html" do
29
+ style.render.gsub("\n", " ").should ==
30
+ File.read(@static_style_file).gsub("\n", " ")
31
+ end
32
+ end
33
+
34
+ context "when it's created with a specified destination" do
35
+ let(:style) { Style.new @static_style_file,
36
+ :destination => 'destination' }
37
+ subject { style }
38
+
39
+ its(:destination) { should == 'destination' }
40
+ its(:destination_file) do
41
+ should == "#{@tmp_dir}/destination/static.css"
42
+ end
43
+ end
44
+
45
+ # TODO: Create local-scope templates directory that I can test this with,
46
+ # and use it to beef up other specs (like document_spec and mint_spec)
47
+ # context "when it's created from a static template file" do
48
+ # let(:style) { Style.new(Mint.lookup_template(:static_test, :style)) }
49
+ # it "#destination" do
50
+ # style.destination.should be_nil
51
+ # end
52
+
53
+ # it "#destination_file" do
54
+ # style.destination_file.should ==
55
+ # Mint.path_for_scope(:local) + '/templates/static_test/style.css'
56
+ # end
57
+ # end
58
+
59
+ context "when it's created from a dynamic template file" do
60
+ let(:style) { Style.new(Mint.lookup_template(:default, :style)) }
61
+ subject { style }
62
+
63
+ its(:destination) { should == 'css' }
64
+ its(:destination_file) do
65
+ should == "#{Mint.root}/templates/default/css/style.css"
66
+ end
67
+ end
68
+ end
69
+ end