mint 0.2.9 → 0.5.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.
@@ -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