audrey2 0.2.1 → 0.3.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.
- data/README.rdoc +14 -0
- data/Rakefile +4 -2
- data/VERSION +1 -1
- data/audrey2.conf.sample +1 -1
- data/audrey2.gemspec +31 -5
- data/bin/feedme +8 -39
- data/lib/audrey2.rb +121 -38
- data/test/helper.rb +35 -0
- data/test/test_config.rb +148 -0
- data/test/test_email.rb +202 -0
- data/test/test_misc.rb +50 -0
- data/test/test_options.rb +69 -0
- data/test/test_parse.rb +87 -0
- data/test/test_recipes.rb +99 -0
- data/test/test_sort.rb +65 -0
- data/test/test_themes.rb +110 -0
- metadata +58 -9
data/test/test_email.rb
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'mail'
|
3
|
+
|
4
|
+
class TestEmail < Test::Unit::TestCase
|
5
|
+
context "With an initialized Aggregator all configurated with SMTP email delivery" do
|
6
|
+
setup do
|
7
|
+
@config
|
8
|
+
File.stubs(:exist?).with('configfile').returns(true)
|
9
|
+
File.stubs(:readable?).with('configfile').returns(true)
|
10
|
+
YAML.stubs(:load_file).with('configfile').returns({
|
11
|
+
'recipes_folder' => 'recipes_folder',
|
12
|
+
'themes_folder' => 'themes_folder',
|
13
|
+
'user_agent' => 'user_agent',
|
14
|
+
'sort' => 'sort',
|
15
|
+
'email' => {'to' => 'admin@test.com',
|
16
|
+
'from' => 'audrey2@test.com',
|
17
|
+
'via' => 'smtp',
|
18
|
+
'smtp' => {'address' => 'mail.test.com',
|
19
|
+
'port' => '25',
|
20
|
+
'domain' => 'test.com'}
|
21
|
+
}
|
22
|
+
})
|
23
|
+
File.stubs(:exist?).with('recipes_folder').returns(true)
|
24
|
+
File.stubs(:readable?).with('recipes_folder').returns(true)
|
25
|
+
File.stubs(:exist?).with('themes_folder').returns(true)
|
26
|
+
File.stubs(:readable?).with('themes_folder').returns(true)
|
27
|
+
@aggregator = Audrey2::Aggregator.new('configfile')
|
28
|
+
recipefile = File.join('recipes_folder', 'recipe')
|
29
|
+
outputfile = File.join('output_folder', 'output_file')
|
30
|
+
File.stubs(:exist?).with(recipefile).returns(true)
|
31
|
+
File.stubs(:readable?).with(recipefile).returns(true)
|
32
|
+
@feed = { 'name' => 'feed', 'url' => 'http://test.com/feed.xml' }
|
33
|
+
YAML.stubs(:load_file).with(recipefile).returns({
|
34
|
+
'feeds' => [@feed],
|
35
|
+
'theme' => 'theme',
|
36
|
+
'output_file' => outputfile
|
37
|
+
})
|
38
|
+
File.stubs(:exist?).with('output_folder').returns(true)
|
39
|
+
File.stubs(:writable?).with('output_folder').returns(true)
|
40
|
+
File.stubs(:exist?).with(outputfile).returns(false)
|
41
|
+
theme_path = File.join('themes_folder', 'theme')
|
42
|
+
File.stubs(:exist?).with(theme_path).returns(true)
|
43
|
+
File.stubs(:readable?).with(theme_path).returns(true)
|
44
|
+
entry_template_path = File.join(theme_path, 'entry.haml')
|
45
|
+
File.stubs(:exist?).with(entry_template_path).returns(true)
|
46
|
+
File.stubs(:readable?).with(entry_template_path).returns(true)
|
47
|
+
File.stubs(:read).with(entry_template_path).returns('%p= entry.title')
|
48
|
+
helpers_file_path = File.join(theme_path, 'helpers.rb')
|
49
|
+
File.stubs(:exist?).with(helpers_file_path).returns(false)
|
50
|
+
@feed_content =<<-EOF
|
51
|
+
<?xml version="1.0"?>
|
52
|
+
<rss version="2.0">
|
53
|
+
<channel>
|
54
|
+
<title>Test</title>
|
55
|
+
<link>http://test.com/</link>
|
56
|
+
<description>Test channel</description>
|
57
|
+
<item>
|
58
|
+
<title>Title</title>
|
59
|
+
<link>http://test.com/title</link>
|
60
|
+
<description>Test description</description>
|
61
|
+
<pubDate>Sun, 15 Aug 2010 16:46:00 EDT</pubDate>
|
62
|
+
</item>
|
63
|
+
</channel>
|
64
|
+
</rss>
|
65
|
+
EOF
|
66
|
+
end
|
67
|
+
|
68
|
+
should 'report feed-opening error via email' do
|
69
|
+
@aggregator.expects(:open).with('http://test.com/feed.xml', {'User-Agent' => 'user_agent'}).raises(Exception.new('404 Not Found'))
|
70
|
+
Mail::Message.any_instance.expects(:[]=).at_least_once.with(:from, 'audrey2@test.com')
|
71
|
+
Mail::Message.any_instance.expects(:[]=).at_least_once.with(:to, 'admin@test.com')
|
72
|
+
Mail::Message.any_instance.expects(:[]=).at_least_once.with(:subject, '[AUDREY 2.0] Exception Notification')
|
73
|
+
Mail::Message.any_instance.expects(:[]=).at_least_once.with(:body, all_of(
|
74
|
+
regexp_matches(/An exception occurred while running recipe recipe/),
|
75
|
+
regexp_matches(/Exception occurred when opening feed feed at http:\/\/test.com\/feed.xml:/),
|
76
|
+
regexp_matches(/404 Not Found/)
|
77
|
+
))
|
78
|
+
Mail::Message.any_instance.expects(:delivery_method) .with(:smtp, all_of(
|
79
|
+
has_entry(:address => 'mail.test.com'),
|
80
|
+
has_entry(:port => '25'),
|
81
|
+
has_entry(:domain => 'test.com')
|
82
|
+
))
|
83
|
+
Mail::Message.any_instance.stubs(:deliver)
|
84
|
+
@aggregator.feed_me('recipe')
|
85
|
+
end
|
86
|
+
|
87
|
+
should 'report feed-parsing error via email' do
|
88
|
+
@aggregator.stubs(:open).with('http://test.com/feed.xml', {'User-Agent' => 'user_agent'}).returns(@feed_content)
|
89
|
+
FeedNormalizer::FeedNormalizer.stubs(:parse).with(@feed_content).raises(Exception.new("Parsing exception"))
|
90
|
+
Mail::Message.any_instance.expects(:[]=).at_least_once.with(:from, 'audrey2@test.com')
|
91
|
+
Mail::Message.any_instance.expects(:[]=).at_least_once.with(:to, 'admin@test.com')
|
92
|
+
Mail::Message.any_instance.expects(:[]=).at_least_once.with(:subject, '[AUDREY 2.0] Exception Notification')
|
93
|
+
Mail::Message.any_instance.expects(:[]=).at_least_once.with(:body, all_of(
|
94
|
+
regexp_matches(/An exception occurred while running recipe recipe/),
|
95
|
+
regexp_matches(/Exception occurred when parsing feed feed which was downloaded from http:\/\/test.com\/feed.xml:/),
|
96
|
+
regexp_matches(/Parsing exception/)
|
97
|
+
))
|
98
|
+
Mail::Message.any_instance.expects(:delivery_method) .with(:smtp, all_of(
|
99
|
+
has_entry(:address => 'mail.test.com'),
|
100
|
+
has_entry(:port => '25'),
|
101
|
+
has_entry(:domain => 'test.com')
|
102
|
+
))
|
103
|
+
Mail::Message.any_instance.stubs(:deliver)
|
104
|
+
@aggregator.feed_me('recipe')
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
context "With an initialized Aggregator all configurated with sendmail email delivery" do
|
110
|
+
setup do
|
111
|
+
@config
|
112
|
+
File.stubs(:exist?).with('configfile').returns(true)
|
113
|
+
File.stubs(:readable?).with('configfile').returns(true)
|
114
|
+
YAML.stubs(:load_file).with('configfile').returns({
|
115
|
+
'recipes_folder' => 'recipes_folder',
|
116
|
+
'themes_folder' => 'themes_folder',
|
117
|
+
'user_agent' => 'user_agent',
|
118
|
+
'sort' => 'sort',
|
119
|
+
'email' => {'to' => 'admin@test.com',
|
120
|
+
'from' => 'audrey2@test.com',
|
121
|
+
'via' => 'sendmail'
|
122
|
+
}
|
123
|
+
})
|
124
|
+
File.stubs(:exist?).with('recipes_folder').returns(true)
|
125
|
+
File.stubs(:readable?).with('recipes_folder').returns(true)
|
126
|
+
File.stubs(:exist?).with('themes_folder').returns(true)
|
127
|
+
File.stubs(:readable?).with('themes_folder').returns(true)
|
128
|
+
@aggregator = Audrey2::Aggregator.new('configfile')
|
129
|
+
recipefile = File.join('recipes_folder', 'recipe')
|
130
|
+
outputfile = File.join('output_folder', 'output_file')
|
131
|
+
File.stubs(:exist?).with(recipefile).returns(true)
|
132
|
+
File.stubs(:readable?).with(recipefile).returns(true)
|
133
|
+
@feed = { 'name' => 'feed', 'url' => 'http://test.com/feed.xml' }
|
134
|
+
YAML.stubs(:load_file).with(recipefile).returns({
|
135
|
+
'feeds' => [@feed],
|
136
|
+
'theme' => 'theme',
|
137
|
+
'output_file' => outputfile
|
138
|
+
})
|
139
|
+
File.stubs(:exist?).with('output_folder').returns(true)
|
140
|
+
File.stubs(:writable?).with('output_folder').returns(true)
|
141
|
+
File.stubs(:exist?).with(outputfile).returns(false)
|
142
|
+
theme_path = File.join('themes_folder', 'theme')
|
143
|
+
File.stubs(:exist?).with(theme_path).returns(true)
|
144
|
+
File.stubs(:readable?).with(theme_path).returns(true)
|
145
|
+
entry_template_path = File.join(theme_path, 'entry.haml')
|
146
|
+
File.stubs(:exist?).with(entry_template_path).returns(true)
|
147
|
+
File.stubs(:readable?).with(entry_template_path).returns(true)
|
148
|
+
File.stubs(:read).with(entry_template_path).returns('%p= entry.title')
|
149
|
+
helpers_file_path = File.join(theme_path, 'helpers.rb')
|
150
|
+
File.stubs(:exist?).with(helpers_file_path).returns(false)
|
151
|
+
@feed_content =<<-EOF
|
152
|
+
<?xml version="1.0"?>
|
153
|
+
<rss version="2.0">
|
154
|
+
<channel>
|
155
|
+
<title>Test</title>
|
156
|
+
<link>http://test.com/</link>
|
157
|
+
<description>Test channel</description>
|
158
|
+
<item>
|
159
|
+
<title>Title</title>
|
160
|
+
<link>http://test.com/title</link>
|
161
|
+
<description>Test description</description>
|
162
|
+
<pubDate>Sun, 15 Aug 2010 16:46:00 EDT</pubDate>
|
163
|
+
</item>
|
164
|
+
</channel>
|
165
|
+
</rss>
|
166
|
+
EOF
|
167
|
+
end
|
168
|
+
|
169
|
+
should 'report feed-opening error via email' do
|
170
|
+
@aggregator.expects(:open).with('http://test.com/feed.xml', {'User-Agent' => 'user_agent'}).raises(Exception.new('404 Not Found'))
|
171
|
+
Mail::Message.any_instance.expects(:[]=).at_least_once.with(:from, 'audrey2@test.com')
|
172
|
+
Mail::Message.any_instance.expects(:[]=).at_least_once.with(:to, 'admin@test.com')
|
173
|
+
Mail::Message.any_instance.expects(:[]=).at_least_once.with(:subject, '[AUDREY 2.0] Exception Notification')
|
174
|
+
Mail::Message.any_instance.expects(:[]=).at_least_once.with(:body, all_of(
|
175
|
+
regexp_matches(/An exception occurred while running recipe recipe/),
|
176
|
+
regexp_matches(/Exception occurred when opening feed feed at http:\/\/test.com\/feed.xml:/),
|
177
|
+
regexp_matches(/404 Not Found/)
|
178
|
+
))
|
179
|
+
Mail::Message.any_instance.expects(:delivery_method) .with(:sendmail)
|
180
|
+
Mail::Message.any_instance.stubs(:deliver)
|
181
|
+
@aggregator.feed_me('recipe')
|
182
|
+
end
|
183
|
+
|
184
|
+
should 'report feed-parsing error via email' do
|
185
|
+
@aggregator.stubs(:open).with('http://test.com/feed.xml', {'User-Agent' => 'user_agent'}).returns(@feed_content)
|
186
|
+
FeedNormalizer::FeedNormalizer.stubs(:parse).with(@feed_content).raises(Exception.new("Parsing exception"))
|
187
|
+
Mail::Message.any_instance.expects(:[]=).at_least_once.with(:from, 'audrey2@test.com')
|
188
|
+
Mail::Message.any_instance.expects(:[]=).at_least_once.with(:to, 'admin@test.com')
|
189
|
+
Mail::Message.any_instance.expects(:[]=).at_least_once.with(:subject, '[AUDREY 2.0] Exception Notification')
|
190
|
+
Mail::Message.any_instance.expects(:[]=).at_least_once.with(:body, all_of(
|
191
|
+
regexp_matches(/An exception occurred while running recipe recipe/),
|
192
|
+
regexp_matches(/Exception occurred when parsing feed feed which was downloaded from http:\/\/test.com\/feed.xml:/),
|
193
|
+
regexp_matches(/Parsing exception/)
|
194
|
+
))
|
195
|
+
Mail::Message.any_instance.expects(:delivery_method) .with(:sendmail)
|
196
|
+
Mail::Message.any_instance.stubs(:deliver)
|
197
|
+
@aggregator.feed_me('recipe')
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
end
|
data/test/test_misc.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestMisc < Test::Unit::TestCase
|
4
|
+
context "With HashExtensions loaded, Hash " do
|
5
|
+
setup do
|
6
|
+
@hash = {
|
7
|
+
'key1' => 'value1',
|
8
|
+
'key2' => :value2,
|
9
|
+
:key3 => 'value3',
|
10
|
+
:key4 => :value4,
|
11
|
+
'key5' => { 'key5.1' => 'value5.1', 'key5.2' => {'key5.2.1' => 'value5.2.1'}},
|
12
|
+
'key6' => [ {'key6.1' => 'value6.1'}, {'key6.2' => 'value6.2'}]
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
should "mixin HashExtensions" do
|
17
|
+
assert Hash.ancestors.include? HashExtensions
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
should "respond to recursively_symbolize_keys" do
|
22
|
+
assert @hash.respond_to? :recursively_symbolize_keys
|
23
|
+
end
|
24
|
+
|
25
|
+
context "output by Hash#recursively_symbolize_keys" do
|
26
|
+
setup do
|
27
|
+
@symbolized_hash = @hash.recursively_symbolize_keys
|
28
|
+
end
|
29
|
+
|
30
|
+
should 'convert string keys to symbols' do
|
31
|
+
[:key1, :key2, :key5, :key6].each { |key| assert @symbolized_hash.has_key? key }
|
32
|
+
end
|
33
|
+
|
34
|
+
should 'leave symbol keys untouched' do
|
35
|
+
[:key3, :key4].each { |key| assert @symbolized_hash.has_key? key }
|
36
|
+
end
|
37
|
+
|
38
|
+
should 'recurse into child hashes' do
|
39
|
+
[:'key5.1', :'key5.2'].each { |key| assert @symbolized_hash[:key5].has_key? key }
|
40
|
+
assert @symbolized_hash[:key5].has_key? :'key5.2'
|
41
|
+
assert @symbolized_hash[:key5][:'key5.2'].has_key? :'key5.2.1'
|
42
|
+
end
|
43
|
+
|
44
|
+
should 'recurse into child arrays which contain hashes' do
|
45
|
+
[:'key6.1', :'key6.2'].each_with_index { |key, i| assert @symbolized_hash[:key6][i].has_key? key }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestOptions < Test::Unit::TestCase
|
4
|
+
context 'Calling Options::parse' do
|
5
|
+
|
6
|
+
context 'without a configfile location specified' do
|
7
|
+
setup do
|
8
|
+
@options = Audrey2::Options.parse([])
|
9
|
+
end
|
10
|
+
|
11
|
+
should 'use the default configfile location' do
|
12
|
+
assert_equal '/etc/audrey2.conf', @options[:config]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'with a configfile location specified' do
|
17
|
+
setup do
|
18
|
+
@options = Audrey2::Options.parse(['--config', 'my_config_file'])
|
19
|
+
end
|
20
|
+
|
21
|
+
should 'use the specified configfile location' do
|
22
|
+
assert_equal 'my_config_file', @options[:config]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'with various options and recipes' do
|
27
|
+
setup do
|
28
|
+
@args = ['--config', 'my_config_file', 'recipe1', 'recipe2']
|
29
|
+
Audrey2::Options.parse(@args)
|
30
|
+
end
|
31
|
+
|
32
|
+
should 'consume the options and leave the recipe list' do
|
33
|
+
assert_equal 2, @args.length
|
34
|
+
assert_equal 'recipe1', @args[0]
|
35
|
+
assert_equal 'recipe2', @args[1]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'with an invalid option' do
|
40
|
+
setup { @args = ['--invalid'] }
|
41
|
+
|
42
|
+
should 'report error, print usage, and exit' do
|
43
|
+
err = capture_stderr { assert_raise(SystemExit) { Audrey2::Options.parse(@args) } }
|
44
|
+
assert err.string =~ /invalid option: --invalid/
|
45
|
+
assert err.string =~ /Usage:/
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'with a missing option argument' do
|
50
|
+
setup { @args = ['--config'] }
|
51
|
+
|
52
|
+
should 'report error, print usage, and exit' do
|
53
|
+
err = capture_stderr { assert_raise(SystemExit) { Audrey2::Options.parse(@args) } }
|
54
|
+
assert err.string =~ /missing argument: --config/
|
55
|
+
assert err.string =~ /Usage:/
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'with --help' do
|
60
|
+
setup { @args = ['--help']}
|
61
|
+
|
62
|
+
should 'print usage and exit' do
|
63
|
+
out = capture_stdout { assert_raise(SystemExit) { Audrey2::Options.parse(@args) } }
|
64
|
+
assert out.string =~ /Usage:/
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
data/test/test_parse.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestParse < Test::Unit::TestCase
|
4
|
+
context "With an initialized Aggregator and all configuration met (no email)" do
|
5
|
+
setup do
|
6
|
+
@config
|
7
|
+
File.stubs(:exist?).with('configfile').returns(true)
|
8
|
+
File.stubs(:readable?).with('configfile').returns(true)
|
9
|
+
YAML.stubs(:load_file).with('configfile').returns({
|
10
|
+
'recipes_folder' => 'recipes_folder',
|
11
|
+
'themes_folder' => 'themes_folder',
|
12
|
+
'user_agent' => 'user_agent',
|
13
|
+
'sort' => 'sort'
|
14
|
+
})
|
15
|
+
File.stubs(:exist?).with('recipes_folder').returns(true)
|
16
|
+
File.stubs(:readable?).with('recipes_folder').returns(true)
|
17
|
+
File.stubs(:exist?).with('themes_folder').returns(true)
|
18
|
+
File.stubs(:readable?).with('themes_folder').returns(true)
|
19
|
+
@aggregator = Audrey2::Aggregator.new('configfile')
|
20
|
+
recipefile = File.join('recipes_folder', 'recipe')
|
21
|
+
outputfile = File.join('output_folder', 'output_file')
|
22
|
+
File.stubs(:exist?).with(recipefile).returns(true)
|
23
|
+
File.stubs(:readable?).with(recipefile).returns(true)
|
24
|
+
@feed = { 'name' => 'feed', 'url' => 'http://test.com/feed.xml' }
|
25
|
+
YAML.stubs(:load_file).with(recipefile).returns({
|
26
|
+
'feeds' => [@feed],
|
27
|
+
'theme' => 'theme',
|
28
|
+
'output_file' => outputfile
|
29
|
+
})
|
30
|
+
File.stubs(:exist?).with('output_folder').returns(true)
|
31
|
+
File.stubs(:writable?).with('output_folder').returns(true)
|
32
|
+
File.stubs(:exist?).with(outputfile).returns(false)
|
33
|
+
theme_path = File.join('themes_folder', 'theme')
|
34
|
+
File.stubs(:exist?).with(theme_path).returns(true)
|
35
|
+
File.stubs(:readable?).with(theme_path).returns(true)
|
36
|
+
entry_template_path = File.join(theme_path, 'entry.haml')
|
37
|
+
File.stubs(:exist?).with(entry_template_path).returns(true)
|
38
|
+
File.stubs(:readable?).with(entry_template_path).returns(true)
|
39
|
+
File.stubs(:read).with(entry_template_path).returns('%p= entry.title')
|
40
|
+
helpers_file_path = File.join(theme_path, 'helpers.rb')
|
41
|
+
File.stubs(:exist?).with(helpers_file_path).returns(false)
|
42
|
+
@feed_content =<<-EOF
|
43
|
+
<?xml version="1.0"?>
|
44
|
+
<rss version="2.0">
|
45
|
+
<channel>
|
46
|
+
<title>Test</title>
|
47
|
+
<link>http://test.com/</link>
|
48
|
+
<description>Test channel</description>
|
49
|
+
<item>
|
50
|
+
<title>Title</title>
|
51
|
+
<link>http://test.com/title</link>
|
52
|
+
<description>Test description</description>
|
53
|
+
<pubDate>Sun, 15 Aug 2010 16:46:00 EDT</pubDate>
|
54
|
+
</item>
|
55
|
+
</channel>
|
56
|
+
</rss>
|
57
|
+
EOF
|
58
|
+
end
|
59
|
+
|
60
|
+
should 'download, parse, and write templatized output' do
|
61
|
+
@aggregator.expects(:open).with('http://test.com/feed.xml', {'User-Agent' => 'user_agent'}).returns(@feed_content)
|
62
|
+
s = StringIO.new
|
63
|
+
s.expects(:<<).with("<p>Title</p>\n")
|
64
|
+
File.expects(:open).with(File.join('output_folder', 'output_file'), 'w').yields s
|
65
|
+
@aggregator.feed_me('recipe')
|
66
|
+
assert_equal '%p= entry.title', @aggregator.instance_variable_get('@entry_template')
|
67
|
+
end
|
68
|
+
|
69
|
+
should 'report feed-opening error via exit' do
|
70
|
+
@aggregator.expects(:open).with('http://test.com/feed.xml', {'User-Agent' => 'user_agent'}).raises(Exception.new('404 Not Found'))
|
71
|
+
err = capture_stderr { assert_raise(SystemExit) { @aggregator.feed_me('recipe') } }
|
72
|
+
assert err.string =~ /An exception occurred while running recipe recipe:/
|
73
|
+
assert err.string =~ /Exception occurred when opening feed feed at http:\/\/test.com\/feed.xml:/
|
74
|
+
assert err.string =~ /404 Not Found/
|
75
|
+
end
|
76
|
+
|
77
|
+
should 'report feed-parsing error via exit' do
|
78
|
+
@aggregator.stubs(:open).with('http://test.com/feed.xml', {'User-Agent' => 'user_agent'}).returns(@feed_content)
|
79
|
+
FeedNormalizer::FeedNormalizer.expects(:parse).with(@feed_content).raises(Exception.new("Parsing exception"))
|
80
|
+
err = capture_stderr { assert_raise(SystemExit) { @aggregator.feed_me('recipe') } }
|
81
|
+
assert err.string =~ /An exception occurred while running recipe recipe:/
|
82
|
+
assert err.string =~ /Exception occurred when parsing feed feed which was downloaded from http:\/\/test.com\/feed.xml:/
|
83
|
+
assert err.string =~ /Parsing exception/
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestRecipes < Test::Unit::TestCase
|
4
|
+
context "With an initialized Aggregator" do
|
5
|
+
setup do
|
6
|
+
@config
|
7
|
+
File.stubs(:exist?).with('configfile').returns(true)
|
8
|
+
File.stubs(:readable?).with('configfile').returns(true)
|
9
|
+
YAML.stubs(:load_file).with('configfile').returns({
|
10
|
+
'recipes_folder' => 'recipes_folder',
|
11
|
+
'themes_folder' => 'themes_folder',
|
12
|
+
'user_agent' => 'user_agent',
|
13
|
+
'sort' => 'sort'
|
14
|
+
})
|
15
|
+
File.stubs(:exist?).with('recipes_folder').returns(true)
|
16
|
+
File.stubs(:readable?).with('recipes_folder').returns(true)
|
17
|
+
File.stubs(:exist?).with('themes_folder').returns(true)
|
18
|
+
File.stubs(:readable?).with('themes_folder').returns(true)
|
19
|
+
@aggregator = Audrey2::Aggregator.new('configfile')
|
20
|
+
end
|
21
|
+
|
22
|
+
context "and a nonexistent recipe file" do
|
23
|
+
should 'report error and exit' do
|
24
|
+
recipefile = File.join('recipes_folder', 'recipe')
|
25
|
+
File.expects(:exist?).with(recipefile).returns(false)
|
26
|
+
err = capture_stderr { assert_raise(SystemExit) { @aggregator.feed_me('recipe') } }
|
27
|
+
assert_match /ERROR: Recipe file #{recipefile} does not exist/, err.string
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "and an unreadable recipe file" do
|
32
|
+
should 'report error and exit' do
|
33
|
+
recipefile = File.join('recipes_folder', 'recipe')
|
34
|
+
File.stubs(:exist?).with(recipefile).returns(true)
|
35
|
+
File.expects(:readable?).with(recipefile).returns(false)
|
36
|
+
err = capture_stderr { assert_raise(SystemExit) { @aggregator.feed_me('recipe') } }
|
37
|
+
assert_match /ERROR: Recipe file #{recipefile} is not readable/, err.string
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "with an unparsable recipe file" do
|
42
|
+
should 'report error and exit' do
|
43
|
+
recipefile = File.join('recipes_folder', 'recipe')
|
44
|
+
File.stubs(:exist?).with(recipefile).returns(true)
|
45
|
+
File.stubs(:readable?).with(recipefile).returns(true)
|
46
|
+
YAML.expects(:load_file).with(recipefile).raises(Exception)
|
47
|
+
err = capture_stderr { assert_raise(SystemExit) { @aggregator.feed_me('recipe') } }
|
48
|
+
assert_match /ERROR: Problem parsing recipe file #{recipefile}/, err.string
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "and a recipe file" do
|
53
|
+
setup do
|
54
|
+
recipefile = File.join('recipes_folder', 'recipe')
|
55
|
+
@outputfile = File.join('output_folder', 'output_file')
|
56
|
+
File.stubs(:exist?).with(recipefile).returns(true)
|
57
|
+
File.stubs(:readable?).with(recipefile).returns(true)
|
58
|
+
YAML.stubs(:load_file).with(recipefile).returns({
|
59
|
+
'feeds' => [{ 'name' => 'feed', 'url' => 'http://test.com/feed.xml' }],
|
60
|
+
'theme' => 'theme',
|
61
|
+
'output_file' => @outputfile
|
62
|
+
})
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'with an invalid output folder' do
|
66
|
+
should 'report error and exit' do
|
67
|
+
File.expects(:exist?).with('output_folder').returns(false)
|
68
|
+
err = capture_stderr { assert_raise(SystemExit) { @aggregator.feed_me('recipe') } }
|
69
|
+
assert_match /ERROR: Output folder output_folder does not exist/, err.string
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "and an unwritable output folder" do
|
74
|
+
should 'report error and exit' do
|
75
|
+
File.stubs(:exist?).with('output_folder').returns(true)
|
76
|
+
File.expects(:writable?).with('output_folder').returns(false)
|
77
|
+
err = capture_stderr { assert_raise(SystemExit) { @aggregator.feed_me('recipe') } }
|
78
|
+
assert_match /ERROR: Output folder output_folder is not writable/, err.string
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "and an existing but unwritable output file" do
|
83
|
+
setup do
|
84
|
+
File.stubs(:exist?).with('output_folder').returns(true)
|
85
|
+
File.stubs(:writable?).with('output_folder').returns(true)
|
86
|
+
end
|
87
|
+
|
88
|
+
should 'report error and exit' do
|
89
|
+
File.expects(:exist?).with(@outputfile).returns(true)
|
90
|
+
File.expects(:writable?).with(@outputfile).returns(false)
|
91
|
+
err = capture_stderr { assert_raise(SystemExit) { @aggregator.feed_me('recipe') } }
|
92
|
+
assert_match /ERROR: Output file #{@outputfile} is not writable/, err.string
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# TODO: Verify max_entries behavior
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/test/test_sort.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestOptions < Test::Unit::TestCase
|
4
|
+
context "With an initialized Aggregator" do
|
5
|
+
setup do
|
6
|
+
@config
|
7
|
+
File.stubs(:exist?).with('configfile').returns(true)
|
8
|
+
File.stubs(:readable?).with('configfile').returns(true)
|
9
|
+
YAML.stubs(:load_file).with('configfile').returns({
|
10
|
+
'recipes_folder' => 'recipes_folder',
|
11
|
+
'themes_folder' => 'themes_folder',
|
12
|
+
'user_agent' => 'user_agent'
|
13
|
+
})
|
14
|
+
File.stubs(:exist?).with('recipes_folder').returns(true)
|
15
|
+
File.stubs(:readable?).with('recipes_folder').returns(true)
|
16
|
+
File.stubs(:exist?).with('themes_folder').returns(true)
|
17
|
+
File.stubs(:readable?).with('themes_folder').returns(true)
|
18
|
+
@aggregator = Audrey2::Aggregator.new('configfile')
|
19
|
+
end
|
20
|
+
|
21
|
+
context "And an unordered set of entries" do
|
22
|
+
setup do
|
23
|
+
class TestEntry
|
24
|
+
attr_accessor :date_published
|
25
|
+
def initialize(date_published); @date_published = date_published; end
|
26
|
+
end
|
27
|
+
@entry1 = TestEntry.new(Date.parse('2010-08-08'))
|
28
|
+
@entry2 = TestEntry.new(Date.parse('2010-08-09'))
|
29
|
+
@entry3 = TestEntry.new(Date.parse('2010-08-10'))
|
30
|
+
@entries = [@entry3, @entry1, @entry2]
|
31
|
+
end
|
32
|
+
|
33
|
+
should "sort in reverse order under reverse_chronological sort" do
|
34
|
+
assert_equal @entry3, @entries[0]
|
35
|
+
assert_equal @entry1, @entries[1]
|
36
|
+
assert_equal @entry2, @entries[2]
|
37
|
+
@entries.sort! &@aggregator.send(:entry_sort_comparator, :reverse_chronological)
|
38
|
+
assert_equal @entry3, @entries[0]
|
39
|
+
assert_equal @entry2, @entries[1]
|
40
|
+
assert_equal @entry1, @entries[2]
|
41
|
+
end
|
42
|
+
|
43
|
+
should "sort in chronological order under chronological sort" do
|
44
|
+
assert_equal @entry3, @entries[0]
|
45
|
+
assert_equal @entry1, @entries[1]
|
46
|
+
assert_equal @entry2, @entries[2]
|
47
|
+
@entries.sort! &@aggregator.send(:entry_sort_comparator, :chronological)
|
48
|
+
assert_equal @entry1, @entries[0]
|
49
|
+
assert_equal @entry2, @entries[1]
|
50
|
+
assert_equal @entry3, @entries[2]
|
51
|
+
end
|
52
|
+
|
53
|
+
should "sort in reverse order by default" do
|
54
|
+
assert_equal @entry3, @entries[0]
|
55
|
+
assert_equal @entry1, @entries[1]
|
56
|
+
assert_equal @entry2, @entries[2]
|
57
|
+
@entries.sort! &@aggregator.send(:entry_sort_comparator, :reverse_chronological)
|
58
|
+
assert_equal @entry3, @entries[0]
|
59
|
+
assert_equal @entry2, @entries[1]
|
60
|
+
assert_equal @entry1, @entries[2]
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|