mr_poole 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/spec/command_spec.rb CHANGED
@@ -1,290 +1,348 @@
1
1
  require 'spec_helper'
2
-
3
2
  require 'mr_poole'
4
3
 
5
4
  module MrPoole
6
5
  describe Commands do
7
6
 
8
- before :all do
9
- @date_regex = %r{\d{4}-\d{2}-\d{2}}
10
- end
11
-
12
- before :each do
13
- @c = Commands.new
14
- @olddir, @tmpdir = make_jekyll_dir
15
- end
16
-
17
- after :each do
18
- clean_tmp_files(@tmpdir, @olddir)
19
- end
7
+ let(:date_regex) { %r{\d{4}-\d{2}-\d{2}} }
8
+ let(:c) { Commands.new }
9
+ before(:each) { @olddir, @tmpdir = make_jekyll_dir }
10
+ after(:each) { clean_tmp_files(@tmpdir, @olddir) }
20
11
 
21
12
  describe "#post" do
22
13
  context 'title only' do
23
-
24
14
  it "should create a new post in the _posts directory" do
25
- @c.post("test_post")
26
- Dir.glob("_posts/*.md").length.should == 1
27
- end
28
-
29
- it "should create a timestamped post in the _posts directory" do
30
- @c.post("test_post")
31
- fn = Dir.glob("_posts/*.md").first
32
- fn.should match(/#{@date_regex}-test_post[.]md$/)
15
+ fn = c.post({title: "test_post"})
16
+ expect(File.exists?(fn)).to be_true
33
17
  end
34
18
 
35
19
  it "should return path to the newly created post" do
36
- returned = @c.post("test_post")
20
+ returned = c.post({title: "test_post"})
37
21
  determined = Dir.glob("_posts/*.md").first
38
- returned.should == determined
22
+ expect(returned).to eq(determined)
23
+ end
24
+
25
+ it "should create a timestamped post in the _posts directory" do
26
+ fn = c.post({title: "test_post" })
27
+ expect(fn).to match(/#{date_regex}-test_post[.]md$/)
39
28
  end
40
29
 
41
30
  it "should downcase a title" do
42
- @c.post("Test_Post_With_Uppercase")
43
- fn = Dir.glob("_posts/*.md").first
44
- fn.should match(/#{@date_regex}-test_post_with_uppercase[.]md/)
31
+ fn = c.post({title: "Test_Post_With_Uppercase"})
32
+ expect(fn).to match(/#{date_regex}-test_post_with_uppercase[.]md/)
45
33
  end
46
34
 
47
35
  it "should sub underscores for spaces in title" do
48
- @c.post("Test Post with Spaces")
49
- fn = Dir.glob("_posts/*.md").first
50
- fn.should match(/#{@date_regex}-test_post_with_spaces[.]md/)
36
+ fn = c.post({title: "Test Post with Spaces"})
37
+ expect(fn).to match(/#{date_regex}-test_post_with_spaces[.]md/)
51
38
  end
52
39
 
53
40
  it "should remove non-word characters for slug" do
54
- @c.post("On (function() {}()) in JavaScript")
55
- fn = Dir.glob("_posts/*.md").first
56
- fn.should match(/#{@date_regex}-on_function_in_javascript[.]md/)
41
+ fn = c.post({title: "On (function() {}()) in JavaScript"})
42
+ expect(fn).to match(/#{date_regex}-on_function_in_javascript[.]md/)
57
43
  end
58
44
 
59
45
  it "should update the title in the file itself" do
60
- @c.post("Testing Post {}")
61
- fn = Dir.glob("_posts/*.md").first
46
+ fn = c.post({title: "Testing Post {}"})
62
47
  content = File.open(fn, 'r').read
63
- content.should match(/title: Testing Post {}/)
48
+ expect(content).to match(/title: Testing Post {}/)
64
49
  end
65
50
 
66
51
  it "should update the date in the file itself" do
67
- @c.post("Date test post")
68
- fn = Dir.glob("_posts/*.md").first
52
+ fn = c.post({title: "Date test post"})
69
53
 
70
54
  # date in filename should match date in file itself
71
- date = fn.match(/(#{@date_regex})-date_test_post[.]md/)[1]
55
+ date = fn.match(/(#{date_regex})-date_test_post[.]md/)[1]
72
56
  content = File.open(fn, 'r').read
73
- content.should match(/date: #{date}/)
57
+ expect(content).to match(/date: #{date}/)
74
58
  end
75
-
76
59
  end # end context title only
77
60
 
78
61
  context 'title and slug' do
79
-
80
62
  it "should create a post named for slug" do
81
- @c.post("Test Post", 'unique_slug')
82
- fn = Dir.glob("_posts/*.md").first
83
- fn.should match(/#{@date_regex}-unique_slug[.]md$/)
63
+ fn = c.post({title: "Test Post", slug: 'unique_slug'})
64
+ expect(fn).to match(/#{date_regex}-unique_slug[.]md$/)
84
65
  end
85
66
 
86
67
  it "should sub any weird characters in slug" do
87
- @c.post("Test Post with Spaces", "(stupid] {slüg/")
88
- fn = Dir.glob("_posts/*.md").first
89
- fn.should match(/#{@date_regex}-stupid_slg[.]md/)
68
+ fn = c.post({title: "Test Post with Spaces", slug: "(stupid] {slüg/"})
69
+ expect(fn).to match(/#{date_regex}-stupid_slg[.]md/)
90
70
  end
91
71
 
92
72
  it "should update the title in the file itself" do
93
- @c.post("Testing Post {}", 'shouldnt_be_in_title')
94
- fn = Dir.glob("_posts/*.md").first
73
+ fn = c.post({title: "Testing Post {}", slug: 'shouldnt_be_in_title'})
95
74
  content = File.open(fn, 'r').read
96
- content.should match(/title: Testing Post {}/)
75
+ expect(content).to match(/title: Testing Post {}/)
97
76
  end
98
-
99
77
  end # end context title & slug
100
78
 
79
+ context 'with custom layout' do
80
+ let(:layout_path) { write_custom_layout }
81
+
82
+ it "should exit if layout path doesn't exist" do
83
+ expect {
84
+ capture_stdout do
85
+ c.post({title: 'test_post', layout: 'bogus_path.md'})
86
+ end
87
+ }.to raise_error(SystemExit)
88
+ end
89
+
90
+ it 'should not use the default layout' do
91
+ fn = c.post({title: 'test_post', layout: layout_path})
92
+ content = File.open(fn, 'r').read
93
+ expect(content).not_to match(/layout: post/)
94
+ end
95
+
96
+ it 'should use the custom layout' do
97
+ fn = c.post({title: 'test_post', layout: layout_path})
98
+ content = File.open(fn, 'r').read
99
+ expect(content).to match(/tags: testing/)
100
+ end
101
+ end # context custom layout
101
102
  end # end describe post
102
103
 
103
104
  describe "#draft" do
104
105
  context 'title only' do
105
-
106
106
  it "should create a _drafts directory" do
107
- @c.draft('draft post')
108
- Dir.exists?('_drafts').should be_true
109
- end
110
-
111
- it "should create a new draft in the _drafts directory" do
112
- @c.draft('draft post')
113
- Dir.glob("_drafts/*.md").length.should == 1
107
+ c.draft({title: 'draft post'})
108
+ expect(Dir.exists?('_drafts')).to be_true
114
109
  end
115
110
 
116
111
  it "should return path to the newly created draft" do
117
- returned = @c.draft("test_draft")
112
+ returned = c.draft({title: "test_draft"})
118
113
  determined = Dir.glob("_drafts/*.md").first
119
- returned.should == determined
114
+ expect(returned).to eq(determined)
115
+ end
116
+
117
+ it "should create a new draft in the _drafts directory" do
118
+ fn = c.draft({title: 'draft post'})
119
+ expect(File.exists?(fn)).to be_true
120
120
  end
121
121
 
122
122
  it "should create a non-timestamped draft" do
123
- @c.draft('draft post')
124
- fn = Dir.glob("_drafts/*.md").first
125
- fn.should_not match(/#{@date_regex}/)
123
+ fn = c.draft({title: 'draft post'})
124
+ expect(fn).not_to match(/#{date_regex}/)
126
125
  end
127
126
 
128
127
  it "should downcase and underscore title for slug" do
129
- @c.draft("Test Post with Spaces")
130
- fn = Dir.glob("_drafts/*.md").first
131
- fn.should match(/test_post_with_spaces[.]md/)
128
+ fn = c.draft({title: "Test Post with Spaces"})
129
+ expect(fn).to match(/test_post_with_spaces[.]md/)
132
130
  end
133
131
 
134
132
  it "should remove non-word characters for slug" do
135
- @c.draft("On (function() {}()) in JavaScript")
136
- fn = Dir.glob("_drafts/*.md").first
137
- fn.should match(/on_function_in_javascript[.]md/)
133
+ fn = c.draft({title: "On (function() {}()) in JavaScript"})
134
+ expect(fn).to match(/on_function_in_javascript[.]md/)
138
135
  end
139
136
 
140
137
  it "should update the title in the file itself" do
141
- @c.draft("Testing Draft {}")
142
- fn = Dir.glob("_drafts/*.md").first
138
+ fn = c.draft({title: "Testing Draft {}"})
143
139
  content = File.open(fn, 'r').read
144
- content.should match(/title: Testing Draft {}/)
140
+ expect(content).to match(/title: Testing Draft {}/)
145
141
  end
146
142
 
147
143
  it "should not update the date in the file itself" do
148
- @c.draft("Date test post")
149
- fn = Dir.glob("_drafts/*.md").first
150
-
151
- # date in filename should match date in file itself
144
+ fn = c.draft({title: "Date test post"})
152
145
  content = File.open(fn, 'r').read
153
- content.should match(/date:\s*\n/)
146
+ expect(content).to match(/date:\s*\n/)
154
147
  end
155
-
156
148
  end # end context title only
157
149
 
158
150
  context 'title and slug' do
159
-
160
151
  it "should create a draft named for slug" do
161
- @c.draft("Test Draft", 'unique_slug')
162
- fn = Dir.glob("_drafts/*.md").first
163
- fn.should match(/unique_slug[.]md$/)
152
+ fn = c.draft({title: "Test Draft", slug: 'unique_slug'})
153
+ expect(fn).to match(/unique_slug[.]md$/)
164
154
  end
165
155
 
166
156
  it "should sub any weird characters in slug" do
167
- @c.draft("Test Post with Spaces", "(stupid] {slüg/")
168
- fn = Dir.glob("_drafts/*.md").first
169
- fn.should match(/stupid_slg[.]md/)
157
+ fn = c.draft({title: "Test Post with Spaces", slug: "(stupid] {slüg/"})
158
+ expect(fn).to match(/stupid_slg[.]md/)
170
159
  end
171
160
 
172
161
  it "should update the title in the file itself" do
173
- @c.draft("Testing Post {}", 'shouldnt_be_in_title')
174
- fn = Dir.glob("_drafts/*.md").first
162
+ fn = c.draft({title: "Testing Post {}", slug: 'shouldnt_be_in_title'})
175
163
  content = File.open(fn, 'r').read
176
- content.should match(/title: Testing Post {}/)
164
+ expect(content).to match(/title: Testing Post {}/)
177
165
  end
166
+ end # context title & slug
178
167
 
179
- end # end context title & slug
168
+ context 'with custom layout' do
169
+ let(:layout_path) { write_custom_layout }
170
+
171
+ it "should exit if layout path doesn't exist" do
172
+ expect {
173
+ capture_stdout do
174
+ c.draft({title: 'test_post', layout: 'bogus_path.md'})
175
+ end
176
+ }.to raise_error(SystemExit)
177
+ end
178
+
179
+ it 'should not use the default layout' do
180
+ fn = c.draft({title: 'test_post', layout: layout_path})
181
+ content = File.open(fn, 'r').read
182
+ expect(content).not_to match(/layout: post/)
183
+ end
180
184
 
185
+ it 'should use the custom layout' do
186
+ fn = c.draft({title: 'test_post', layout: layout_path})
187
+ content = File.open(fn, 'r').read
188
+ expect(content).to match(/tags: testing/)
189
+ end
190
+ end # context custom layout
181
191
  end # end describe draft
182
192
 
183
193
  describe "#publish" do
194
+ let(:d_path) { c.draft({title: 'test_draft'}) }
184
195
 
185
- before :each do
186
- @d_path = @c.draft('test_draft')
196
+ it 'should return path to newly created post' do
197
+ returned = c.publish(d_path)
198
+ determined = Dir.glob("_posts/*.md").first
199
+ expect(returned).to eq(determined)
187
200
  end
188
201
 
189
202
  it 'should create a timestamped post in the _posts folder' do
190
- @c.publish(@d_path)
191
- fn = Dir.glob("_posts/*.md").first
192
- fn.should match(/#{@date_regex}-test_draft[.]md$/)
203
+ fn = c.publish(d_path)
204
+ expect(fn).to match(/#{date_regex}-test_draft[.]md$/)
193
205
  end
194
206
 
195
207
  it 'should remove file in the _drafts folder' do
196
- @c.publish(@d_path)
197
- File.exist?(@d_path).should be_false
198
- end
199
-
200
- it 'should return path to newly created post' do
201
- returned = @c.publish(@d_path)
202
- determined = Dir.glob("_posts/*.md").first
203
- returned.should == determined
208
+ c.publish(d_path)
209
+ expect(File.exist?(d_path)).to be_false
204
210
  end
205
211
 
206
212
  it 'should create post with matching slug' do
207
- post = @c.publish(@d_path)
208
-
209
- draft_slug = File.basename(@d_path, '.md')
210
- post_slug = post.match(/#{@date_regex}-(.*)[.]md/)[1]
211
-
212
- post_slug.should == draft_slug
213
+ post = c.publish(d_path)
214
+ draft_slug = File.basename(d_path, '.md')
215
+ post_slug = post.match(/#{date_regex}-(.*)[.]md/)[1]
216
+ expect(post_slug).to eq(draft_slug)
213
217
  end
214
218
 
215
219
  it 'should update timestamp in actual file' do
216
- post = @c.publish(@d_path)
220
+ post = c.publish(d_path)
217
221
  content = File.open(post, 'r').read
218
- content.should match(/date: #{@date_regex} \d{2}:\d{2}\n/)
222
+ expect(content).to match(/date: #{date_regex} \d{2}:\d{2}\n/)
219
223
  end
220
224
 
221
225
  it 'should copy contents of draft into post' do
222
226
  # first add some content to the draft
223
- f = File.open(@d_path, 'a')
227
+ f = File.open(d_path, 'a')
224
228
  f.write("Some new content for my blog\n")
225
229
  f.close
226
230
 
227
- post = @c.publish(@d_path)
231
+ post = c.publish(d_path)
228
232
  content = File.open(post, 'r').read
229
- content.should match(/Some new content for my blog/)
233
+ expect(content).to match(/Some new content for my blog/)
230
234
  end
231
-
232
235
  end # end describe publish
233
236
 
234
237
  describe "#unpublish" do
238
+ let(:p_path) { c.post({title: 'test_post'}) }
235
239
 
236
- before :each do
237
- @p_path = @c.post('test_post')
240
+ it 'should return path to newly created draft' do
241
+ returned = c.unpublish(p_path)
242
+ determined = Dir.glob("_drafts/*.md").first
243
+ expect(returned).to eq(determined)
238
244
  end
239
245
 
240
246
  it 'should create a _drafts directory' do
241
- @c.unpublish(@p_path)
242
- Dir.exists?('_drafts').should be_true
247
+ c.unpublish(p_path)
248
+ expect(Dir.exists?('_drafts')).to be_true
243
249
  end
244
250
 
245
251
  it 'should create an untimestamped draft in the _drafts folder' do
246
- @c.unpublish(@p_path)
247
- fn = Dir.glob("_drafts/*.md").first
248
- fn.should_not match(/#{@date_regex}/)
252
+ fn = c.unpublish(p_path)
253
+ expect(fn).not_to match(/#{date_regex}/)
249
254
  end
250
255
 
251
256
  it 'should remove file in the _posts folder' do
252
- @c.unpublish(@p_path)
253
- File.exist?(@p_path).should be_false
254
- end
255
-
256
- it 'should return path to newly created draft' do
257
- returned = @c.unpublish(@p_path)
258
- determined = Dir.glob("_drafts/*.md").first
259
- returned.should == determined
257
+ c.unpublish(p_path)
258
+ expect(File.exist?(p_path)).to be_false
260
259
  end
261
260
 
262
261
  it 'should create draft with matching slug' do
263
- draft = @c.unpublish(@p_path)
264
-
265
- post_slug = @p_path.match(/#{@date_regex}-(.*)[.]md$/)[1]
262
+ draft = c.unpublish(p_path)
263
+ post_slug = p_path.match(/#{date_regex}-(.*)[.]md$/)[1]
266
264
  draft_slug = File.basename(draft, '.md')
267
-
268
- draft_slug.should == post_slug
265
+ expect(draft_slug).to eq(post_slug)
269
266
  end
270
267
 
271
268
  it 'should delete timestamp in actual file' do
272
- draft = @c.unpublish(@p_path)
269
+ draft = c.unpublish(p_path)
273
270
  content = File.open(draft, 'r').read
274
- content.should match(/date:\s*\n/)
271
+ expect(content).to match(/date:\s*\n/)
275
272
  end
276
273
 
277
274
  it 'should copy contents of post into draft' do
278
275
  # first add some content to the draft
279
- f = File.open(@p_path, 'a')
276
+ f = File.open(p_path, 'a')
280
277
  f.write("Some new content for my blog\n")
281
278
  f.close
282
279
 
283
- draft = @c.unpublish(@p_path)
280
+ draft = c.unpublish(p_path)
284
281
  content = File.open(draft, 'r').read
285
- content.should match(/Some new content for my blog/)
282
+ expect(content).to match(/Some new content for my blog/)
286
283
  end
287
284
 
288
285
  end # end describe unpublish
286
+
287
+ context 'with custom extension' do
288
+ let(:commands) { Commands.new('textile') }
289
+
290
+ it 'post should use custom extension' do
291
+ fn = commands.post({title: 'post title'})
292
+ expect(fn).to match(/textile$/)
293
+ end
294
+
295
+ it 'draft should use custom extension' do
296
+ fn = commands.draft({title: 'post title'})
297
+ expect(fn).to match(/textile$/)
298
+ end
299
+
300
+ it 'publish should use custom extension' do
301
+ draft_path = commands.draft({title: 'post title'})
302
+ fn = commands.publish(draft_path)
303
+ expect(fn).to match(/textile$/)
304
+ end
305
+
306
+ it 'unpublish should use custom extension' do
307
+ post_path = commands.post({title: 'post title'})
308
+ fn = commands.unpublish(post_path)
309
+ expect(fn).to match(/textile$/)
310
+ end
311
+
312
+ end
313
+
314
+ context 'with layout override' do
315
+
316
+ it "post should inherit layout's file extension" do
317
+ layout_path = write_custom_layout_textile
318
+ fn = c.post({title: 'post title', layout: layout_path})
319
+ expect(fn).not_to match(/md/)
320
+ expect(fn).to match(/textile$/)
321
+ end
322
+
323
+ it "draft should inherit layout's file extension" do
324
+ layout_path = write_custom_layout_textile
325
+ fn = c.draft({title: 'post title', layout: layout_path})
326
+ expect(fn).not_to match(/md/)
327
+ expect(fn).to match(/textile$/)
328
+ end
329
+
330
+ it "publish should inherit draft's extension" do
331
+ layout_path = write_custom_layout_textile
332
+ draft_path = c.draft({title: 'post title', layout: layout_path})
333
+ fn = c.publish(draft_path)
334
+ expect(fn).not_to match(/md/)
335
+ expect(fn).to match(/textile$/)
336
+ end
337
+
338
+ it "unpublish should inherit post's extension" do
339
+ layout_path = write_custom_layout_textile
340
+ post_path = c.post({title: 'post title', layout: layout_path})
341
+ fn = c.publish(post_path)
342
+ expect(fn).not_to match(/md/)
343
+ expect(fn).to match(/textile$/)
344
+ end
345
+
346
+ end
289
347
  end
290
348
  end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+ require 'mr_poole'
3
+
4
+ def write_config_file
5
+ f = File.open('_config.yml', 'w')
6
+ f.puts 'poole:'
7
+ f.puts ' default_layout: _layouts/poole.md'
8
+ f.puts ' default_extension: md'
9
+ f.close
10
+ end
11
+
12
+ def write_config_file_no_poole
13
+ f = File.open('_config.yml', 'w')
14
+ f.puts 'name: Douglas N. Adams'
15
+ f.puts 'description: Life, the universe, and everything'
16
+ f.close
17
+ end
18
+
19
+ module MrPoole
20
+ describe Config do
21
+ before(:each) { @olddir, @tmpdir = make_jekyll_dir }
22
+ after(:each) { clean_tmp_files(@tmpdir, @olddir) }
23
+
24
+ describe '::initialize' do
25
+ it 'is empty with no config file' do
26
+ config = Config.new
27
+ expect(config).to be_empty
28
+ end
29
+
30
+ it "is empty with no 'poole' key in config file" do
31
+ write_config_file_no_poole
32
+ config = Config.new
33
+ expect(config).to be_empty
34
+ end
35
+
36
+ it "is not empty with 'poole' key in config file" do
37
+ write_config_file
38
+ config = Config.new
39
+ expect(config).not_to be_empty
40
+ end
41
+
42
+ end
43
+
44
+ describe '#method_missing' do
45
+ before(:each) { write_config_file }
46
+ let(:config) { Config.new }
47
+
48
+ it 'allows access to defined members' do
49
+ expect(config.default_extension).to eq('md')
50
+ end
51
+
52
+ it 'returns nil for unknown key' do
53
+ expect(config.bogus_key).to be_nil
54
+ end
55
+ end
56
+
57
+ end
58
+ end
data/spec/spec_helper.rb CHANGED
@@ -38,7 +38,7 @@ def clean_tmp_files(tmpdir, restoredir)
38
38
  FileUtils.rm_rf(tmpdir)
39
39
  end
40
40
 
41
- def poole_with_args(argv)
41
+ def poole(argv)
42
42
  return Proc.new do
43
43
  action = argv.shift
44
44
  cli = MrPoole::CLI.new(argv)
@@ -46,7 +46,7 @@ def poole_with_args(argv)
46
46
  end
47
47
  end
48
48
 
49
- def poole_with_args_no_stdout(argv)
49
+ def poole_no_stdout(argv)
50
50
  return Proc.new do
51
51
  capture_stdout do
52
52
  action = argv.shift
@@ -55,3 +55,73 @@ def poole_with_args_no_stdout(argv)
55
55
  end
56
56
  end
57
57
  end
58
+
59
+ # This captures SystemExit exceptions and returns stdout
60
+ def aborted_poole_output(argv)
61
+ return Proc.new do
62
+ output = capture_stdout do
63
+ begin
64
+ action = argv.shift
65
+ cli = MrPoole::CLI.new(argv)
66
+ cli.execute(action)
67
+ rescue SystemExit
68
+ end
69
+ end
70
+ output
71
+ end
72
+ end
73
+
74
+ def write_custom_layout
75
+ filename = 'custom_layout.md'
76
+ f = File.open(filename, 'w')
77
+ f.puts '---'
78
+ f.puts 'title:'
79
+ f.puts 'date:'
80
+ f.puts 'tags: testing'
81
+ f.puts '---'
82
+ f.puts ''
83
+ f.close
84
+
85
+ filename
86
+ end
87
+
88
+ def write_custom_layout_textile
89
+ filename = 'custom_layout.textile'
90
+ f = File.open(filename, 'w')
91
+ f.puts '---'
92
+ f.puts 'title:'
93
+ f.puts 'date:'
94
+ f.puts 'tags: testing'
95
+ f.puts '---'
96
+ f.puts ''
97
+ f.close
98
+
99
+ filename
100
+ end
101
+
102
+ def write_config_file_custom_layout
103
+ filename = 'default_layout.md'
104
+
105
+ l = File.open(filename, 'w')
106
+ l.puts '---'
107
+ l.puts 'title:'
108
+ l.puts 'date:'
109
+ l.puts 'tags: from_config'
110
+ l.puts '---'
111
+ l.puts ''
112
+ l.close
113
+
114
+ c = File.open('_config.yml', 'w')
115
+ c.puts 'poole:'
116
+ c.puts " default_layout: #{filename}"
117
+ c.close
118
+
119
+ filename
120
+ end
121
+
122
+ def write_config_file_custom_extension
123
+ c = File.open('_config.yml', 'w')
124
+ c.puts 'poole:'
125
+ c.puts " default_extension: textile"
126
+ c.close
127
+ end