twibot 0.1.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/tasks/setup.rb ADDED
@@ -0,0 +1,300 @@
1
+
2
+ require 'rubygems'
3
+ require 'rake'
4
+ require 'rake/clean'
5
+ require 'fileutils'
6
+ require 'ostruct'
7
+ require 'find'
8
+
9
+ class OpenStruct; undef :gem; end
10
+
11
+ # TODO: make my own openstruct type object that includes descriptions
12
+ # TODO: use the descriptions to output help on the available bones options
13
+
14
+ PROJ = OpenStruct.new(
15
+ # Project Defaults
16
+ :name => nil,
17
+ :summary => nil,
18
+ :description => nil,
19
+ :changes => nil,
20
+ :authors => nil,
21
+ :email => nil,
22
+ :url => "\000",
23
+ :version => ENV['VERSION'] || '0.0.0',
24
+ :exclude => %w(tmp$ bak$ ~$ CVS \.svn/ \.git/ ^pkg/),
25
+ :release_name => ENV['RELEASE'],
26
+
27
+ # System Defaults
28
+ :ruby_opts => %w(-w),
29
+ :libs => [],
30
+ :history_file => 'History.txt',
31
+ :readme_file => 'README.txt',
32
+ :ignore_file => '.bnsignore',
33
+
34
+ # Announce
35
+ :ann => OpenStruct.new(
36
+ :file => 'announcement.txt',
37
+ :text => nil,
38
+ :paragraphs => [],
39
+ :email => {
40
+ :from => nil,
41
+ :to => %w(ruby-talk@ruby-lang.org),
42
+ :server => 'localhost',
43
+ :port => 25,
44
+ :domain => ENV['HOSTNAME'],
45
+ :acct => nil,
46
+ :passwd => nil,
47
+ :authtype => :plain
48
+ }
49
+ ),
50
+
51
+ # Gem Packaging
52
+ :gem => OpenStruct.new(
53
+ :dependencies => [],
54
+ :development_dependencies => [],
55
+ :executables => nil,
56
+ :extensions => FileList['ext/**/extconf.rb'],
57
+ :files => nil,
58
+ :need_tar => true,
59
+ :need_zip => false,
60
+ :extras => {}
61
+ ),
62
+
63
+ # File Annotations
64
+ :notes => OpenStruct.new(
65
+ :exclude => %w(^tasks/setup\.rb$),
66
+ :extensions => %w(.txt .rb .erb .rdoc) << '',
67
+ :tags => %w(FIXME OPTIMIZE TODO)
68
+ ),
69
+
70
+ # Rcov
71
+ :rcov => OpenStruct.new(
72
+ :dir => 'coverage',
73
+ :opts => %w[--sort coverage -T],
74
+ :threshold => 90.0,
75
+ :threshold_exact => false
76
+ ),
77
+
78
+ # Rdoc
79
+ :rdoc => OpenStruct.new(
80
+ :opts => [],
81
+ :include => %w(^lib/ ^bin/ ^ext/ \.txt$ \.rdoc$),
82
+ :exclude => %w(extconf\.rb$),
83
+ :main => nil,
84
+ :dir => 'doc',
85
+ :remote_dir => nil
86
+ ),
87
+
88
+ # Rubyforge
89
+ :rubyforge => OpenStruct.new(
90
+ :name => "\000"
91
+ ),
92
+
93
+ # Rspec
94
+ :spec => OpenStruct.new(
95
+ :files => FileList['spec/**/*_spec.rb'],
96
+ :opts => []
97
+ ),
98
+
99
+ # Subversion Repository
100
+ :svn => OpenStruct.new(
101
+ :root => nil,
102
+ :path => '',
103
+ :trunk => 'trunk',
104
+ :tags => 'tags',
105
+ :branches => 'branches'
106
+ ),
107
+
108
+ # Test::Unit
109
+ :test => OpenStruct.new(
110
+ :files => FileList['test/**/test_*.rb'],
111
+ :file => 'test/all.rb',
112
+ :opts => []
113
+ )
114
+ )
115
+
116
+ # Load the other rake files in the tasks folder
117
+ tasks_dir = File.expand_path(File.dirname(__FILE__))
118
+ post_load_fn = File.join(tasks_dir, 'post_load.rake')
119
+ rakefiles = Dir.glob(File.join(tasks_dir, '*.rake')).sort
120
+ rakefiles.unshift(rakefiles.delete(post_load_fn)).compact!
121
+ import(*rakefiles)
122
+
123
+ # Setup the project libraries
124
+ %w(lib ext).each {|dir| PROJ.libs << dir if test ?d, dir}
125
+
126
+ # Setup some constants
127
+ WIN32 = %r/djgpp|(cyg|ms|bcc)win|mingw/ =~ RUBY_PLATFORM unless defined? WIN32
128
+
129
+ DEV_NULL = WIN32 ? 'NUL:' : '/dev/null'
130
+
131
+ def quiet( &block )
132
+ io = [STDOUT.dup, STDERR.dup]
133
+ STDOUT.reopen DEV_NULL
134
+ STDERR.reopen DEV_NULL
135
+ block.call
136
+ ensure
137
+ STDOUT.reopen io.first
138
+ STDERR.reopen io.last
139
+ $stdout, $stderr = STDOUT, STDERR
140
+ end
141
+
142
+ DIFF = if WIN32 then 'diff.exe'
143
+ else
144
+ if quiet {system "gdiff", __FILE__, __FILE__} then 'gdiff'
145
+ else 'diff' end
146
+ end unless defined? DIFF
147
+
148
+ SUDO = if WIN32 then ''
149
+ else
150
+ if quiet {system 'which sudo'} then 'sudo'
151
+ else '' end
152
+ end
153
+
154
+ RCOV = WIN32 ? 'rcov.bat' : 'rcov'
155
+ RDOC = WIN32 ? 'rdoc.bat' : 'rdoc'
156
+ GEM = WIN32 ? 'gem.bat' : 'gem'
157
+
158
+ %w(rcov spec/rake/spectask rubyforge bones facets/ansicode).each do |lib|
159
+ begin
160
+ require lib
161
+ Object.instance_eval {const_set "HAVE_#{lib.tr('/','_').upcase}", true}
162
+ rescue LoadError
163
+ Object.instance_eval {const_set "HAVE_#{lib.tr('/','_').upcase}", false}
164
+ end
165
+ end
166
+ HAVE_SVN = (Dir.entries(Dir.pwd).include?('.svn') and
167
+ system("svn --version 2>&1 > #{DEV_NULL}"))
168
+ HAVE_GIT = (Dir.entries(Dir.pwd).include?('.git') and
169
+ system("git --version 2>&1 > #{DEV_NULL}"))
170
+
171
+ # Add bones as a development dependency
172
+ #
173
+ if HAVE_BONES
174
+ PROJ.gem.development_dependencies << ['bones', ">= #{Bones::VERSION}"]
175
+ end
176
+
177
+ # Reads a file at +path+ and spits out an array of the +paragraphs+
178
+ # specified.
179
+ #
180
+ # changes = paragraphs_of('History.txt', 0..1).join("\n\n")
181
+ # summary, *description = paragraphs_of('README.txt', 3, 3..8)
182
+ #
183
+ def paragraphs_of( path, *paragraphs )
184
+ title = String === paragraphs.first ? paragraphs.shift : nil
185
+ ary = File.read(path).delete("\r").split(/\n\n+/)
186
+
187
+ result = if title
188
+ tmp, matching = [], false
189
+ rgxp = %r/^=+\s*#{Regexp.escape(title)}/i
190
+ paragraphs << (0..-1) if paragraphs.empty?
191
+
192
+ ary.each do |val|
193
+ if val =~ rgxp
194
+ break if matching
195
+ matching = true
196
+ rgxp = %r/^=+/i
197
+ elsif matching
198
+ tmp << val
199
+ end
200
+ end
201
+ tmp
202
+ else ary end
203
+
204
+ result.values_at(*paragraphs)
205
+ end
206
+
207
+ # Adds the given gem _name_ to the current project's dependency list. An
208
+ # optional gem _version_ can be given. If omitted, the newest gem version
209
+ # will be used.
210
+ #
211
+ def depend_on( name, version = nil )
212
+ spec = Gem.source_index.find_name(name).last
213
+ version = spec.version.to_s if version.nil? and !spec.nil?
214
+
215
+ PROJ.gem.dependencies << case version
216
+ when nil; [name]
217
+ when %r/^\d/; [name, ">= #{version}"]
218
+ else [name, version] end
219
+ end
220
+
221
+ # Adds the given arguments to the include path if they are not already there
222
+ #
223
+ def ensure_in_path( *args )
224
+ args.each do |path|
225
+ path = File.expand_path(path)
226
+ $:.unshift(path) if test(?d, path) and not $:.include?(path)
227
+ end
228
+ end
229
+
230
+ # Find a rake task using the task name and remove any description text. This
231
+ # will prevent the task from being displayed in the list of available tasks.
232
+ #
233
+ def remove_desc_for_task( names )
234
+ Array(names).each do |task_name|
235
+ task = Rake.application.tasks.find {|t| t.name == task_name}
236
+ next if task.nil?
237
+ task.instance_variable_set :@comment, nil
238
+ end
239
+ end
240
+
241
+ # Change working directories to _dir_, call the _block_ of code, and then
242
+ # change back to the original working directory (the current directory when
243
+ # this method was called).
244
+ #
245
+ def in_directory( dir, &block )
246
+ curdir = pwd
247
+ begin
248
+ cd dir
249
+ return block.call
250
+ ensure
251
+ cd curdir
252
+ end
253
+ end
254
+
255
+ # Scans the current working directory and creates a list of files that are
256
+ # candidates to be in the manifest.
257
+ #
258
+ def manifest
259
+ files = []
260
+ exclude = PROJ.exclude.dup
261
+ comment = %r/^\s*#/
262
+
263
+ # process the ignore file and add the items there to the exclude list
264
+ if test(?f, PROJ.ignore_file)
265
+ ary = []
266
+ File.readlines(PROJ.ignore_file).each do |line|
267
+ next if line =~ comment
268
+ line.chomp!
269
+ line.strip!
270
+ next if line.nil? or line.empty?
271
+
272
+ glob = line =~ %r/\*\./ ? File.join('**', line) : line
273
+ Dir.glob(glob).each {|fn| ary << "^#{Regexp.escape(fn)}"}
274
+ end
275
+ exclude.concat ary
276
+ end
277
+
278
+ # generate a regular expression from the exclude list
279
+ exclude = Regexp.new(exclude.join('|'))
280
+
281
+ Find.find '.' do |path|
282
+ path.sub! %r/^(\.\/|\/)/o, ''
283
+ next unless test ?f, path
284
+ next if path =~ exclude
285
+ files << path
286
+ end
287
+ files.sort!
288
+ end
289
+
290
+ # We need a "valid" method thtat determines if a string is suitable for use
291
+ # in the gem specification.
292
+ #
293
+ class Object
294
+ def valid?
295
+ return !(self.empty? or self == "\000") if self.respond_to?(:to_str)
296
+ return false
297
+ end
298
+ end
299
+
300
+ # EOF
data/tasks/spec.rake ADDED
@@ -0,0 +1,54 @@
1
+
2
+ if HAVE_SPEC_RAKE_SPECTASK and not PROJ.spec.files.to_a.empty?
3
+ require 'spec/rake/verify_rcov'
4
+
5
+ namespace :spec do
6
+
7
+ desc 'Run all specs with basic output'
8
+ Spec::Rake::SpecTask.new(:run) do |t|
9
+ t.ruby_opts = PROJ.ruby_opts
10
+ t.spec_opts = PROJ.spec.opts
11
+ t.spec_files = PROJ.spec.files
12
+ t.libs += PROJ.libs
13
+ end
14
+
15
+ desc 'Run all specs with text output'
16
+ Spec::Rake::SpecTask.new(:specdoc) do |t|
17
+ t.ruby_opts = PROJ.ruby_opts
18
+ t.spec_opts = PROJ.spec.opts + ['--format', 'specdoc']
19
+ t.spec_files = PROJ.spec.files
20
+ t.libs += PROJ.libs
21
+ end
22
+
23
+ if HAVE_RCOV
24
+ desc 'Run all specs with RCov'
25
+ Spec::Rake::SpecTask.new(:rcov) do |t|
26
+ t.ruby_opts = PROJ.ruby_opts
27
+ t.spec_opts = PROJ.spec.opts
28
+ t.spec_files = PROJ.spec.files
29
+ t.libs += PROJ.libs
30
+ t.rcov = true
31
+ t.rcov_dir = PROJ.rcov.dir
32
+ t.rcov_opts = PROJ.rcov.opts + ['--exclude', 'spec']
33
+ end
34
+
35
+ RCov::VerifyTask.new(:verify) do |t|
36
+ t.threshold = PROJ.rcov.threshold
37
+ t.index_html = File.join(PROJ.rcov.dir, 'index.html')
38
+ t.require_exact_threshold = PROJ.rcov.threshold_exact
39
+ end
40
+
41
+ task :verify => :rcov
42
+ remove_desc_for_task %w(spec:clobber_rcov)
43
+ end
44
+
45
+ end # namespace :spec
46
+
47
+ desc 'Alias to spec:run'
48
+ task :spec => 'spec:run'
49
+
50
+ task :clobber => 'spec:clobber_rcov' if HAVE_RCOV
51
+
52
+ end # if HAVE_SPEC_RAKE_SPECTASK
53
+
54
+ # EOF
data/tasks/svn.rake ADDED
@@ -0,0 +1,47 @@
1
+
2
+ if HAVE_SVN
3
+
4
+ unless PROJ.svn.root
5
+ info = %x/svn info ./
6
+ m = %r/^Repository Root:\s+(.*)$/.match(info)
7
+ PROJ.svn.root = (m.nil? ? '' : m[1])
8
+ end
9
+ PROJ.svn.root = File.join(PROJ.svn.root, PROJ.svn.path) unless PROJ.svn.path.empty?
10
+
11
+ namespace :svn do
12
+
13
+ # A prerequisites task that all other tasks depend upon
14
+ task :prereqs
15
+
16
+ desc 'Show tags from the SVN repository'
17
+ task :show_tags => 'svn:prereqs' do |t|
18
+ tags = %x/svn list #{File.join(PROJ.svn.root, PROJ.svn.tags)}/
19
+ tags.gsub!(%r/\/$/, '')
20
+ tags = tags.split("\n").sort {|a,b| b <=> a}
21
+ puts tags
22
+ end
23
+
24
+ desc 'Create a new tag in the SVN repository'
25
+ task :create_tag => 'svn:prereqs' do |t|
26
+ v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
27
+ abort "Versions don't match #{v} vs #{PROJ.version}" if v != PROJ.version
28
+
29
+ svn = PROJ.svn
30
+ trunk = File.join(svn.root, svn.trunk)
31
+ tag = "%s-%s" % [PROJ.name, PROJ.version]
32
+ tag = File.join(svn.root, svn.tags, tag)
33
+ msg = "Creating tag for #{PROJ.name} version #{PROJ.version}"
34
+
35
+ puts "Creating SVN tag '#{tag}'"
36
+ unless system "svn cp -m '#{msg}' #{trunk} #{tag}"
37
+ abort "Tag creation failed"
38
+ end
39
+ end
40
+
41
+ end # namespace :svn
42
+
43
+ task 'gem:release' => 'svn:create_tag'
44
+
45
+ end # if PROJ.svn.path
46
+
47
+ # EOF
data/tasks/test.rake ADDED
@@ -0,0 +1,40 @@
1
+
2
+ if test(?e, PROJ.test.file) or not PROJ.test.files.to_a.empty?
3
+ require 'rake/testtask'
4
+
5
+ namespace :test do
6
+
7
+ Rake::TestTask.new(:run) do |t|
8
+ t.libs = PROJ.libs
9
+ t.test_files = if test(?f, PROJ.test.file) then [PROJ.test.file]
10
+ else PROJ.test.files end
11
+ t.ruby_opts += PROJ.ruby_opts
12
+ t.ruby_opts += PROJ.test.opts
13
+ end
14
+
15
+ if HAVE_RCOV
16
+ desc 'Run rcov on the unit tests'
17
+ task :rcov => :clobber_rcov do
18
+ opts = PROJ.rcov.opts.dup << '-o' << PROJ.rcov.dir
19
+ opts = opts.join(' ')
20
+ files = if test(?f, PROJ.test.file) then [PROJ.test.file]
21
+ else PROJ.test.files end
22
+ files = files.join(' ')
23
+ sh "#{RCOV} #{files} #{opts}"
24
+ end
25
+
26
+ task :clobber_rcov do
27
+ rm_r 'coverage' rescue nil
28
+ end
29
+ end
30
+
31
+ end # namespace :test
32
+
33
+ desc 'Alias to test:run'
34
+ task :test => 'test:run'
35
+
36
+ task :clobber => 'test:clobber_rcov' if HAVE_RCOV
37
+
38
+ end
39
+
40
+ # EOF
data/test/test_bot.rb ADDED
@@ -0,0 +1,177 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper')) unless defined?(Twibot)
2
+ require 'fileutils'
3
+
4
+ class TestBot < Test::Unit::TestCase
5
+ test "should not raise errors when initialized" do
6
+ assert_nothing_raised do
7
+ Twibot::Bot.new Twibot::Config.new
8
+ end
9
+ end
10
+
11
+ test "should raise errors when initialized without config file" do
12
+ assert_raise SystemExit do
13
+ Twibot::Bot.new
14
+ end
15
+ end
16
+
17
+ test "should not raise error on initialize when config file exists" do
18
+ if File.exists?("config")
19
+ FileUtils.rm("config/bot.yml")
20
+ else
21
+ FileUtils.mkdir("config")
22
+ end
23
+
24
+ File.open("config/bot.yml", "w") { |f| f.puts "" }
25
+
26
+ assert_nothing_raised do
27
+ Twibot::Bot.new
28
+ end
29
+
30
+ FileUtils.rm_rf("config")
31
+ end
32
+
33
+ test "should provide configuration settings as methods" do
34
+ bot = Twibot::Bot.new Twibot::Config.new(:max_interval => 3)
35
+ assert_equal 3, bot.max_interval
36
+ end
37
+
38
+ test "log should return logger instance" do
39
+ bot = Twibot::Bot.new(Twibot::Config.default << Twibot::Config.new)
40
+ assert bot.log.is_a?(Logger)
41
+ end
42
+
43
+ test "logger should respect configured level" do
44
+ bot = Twibot::Bot.new(Twibot::Config.new(:log_level => "info"))
45
+ assert_equal Logger::INFO, bot.log.level
46
+
47
+ bot = Twibot::Bot.new(Twibot::Config.new(:log_level => "warn"))
48
+ assert_equal Logger::WARN, bot.log.level
49
+ end
50
+
51
+ test "receive should return false without handlers" do
52
+ bot = Twibot::Bot.new(Twibot::Config.new)
53
+ assert !bot.receive_messages
54
+ assert !bot.receive_replies
55
+ assert !bot.receive_tweets
56
+ end
57
+
58
+ test "should receive message" do
59
+ bot = Twibot::Bot.new(Twibot::Config.new(:log_level => "error"))
60
+ bot.add_handler(:message, Twibot::Handler.new)
61
+ Twitter::Client.any_instance.expects(:messages).with(:received, nil).returns([message("cjno", "Hei der!")])
62
+
63
+ assert bot.receive_messages
64
+ end
65
+
66
+ test "should remember last received message" do
67
+ bot = Twibot::Bot.new(Twibot::Config.new(:log_level => "error"))
68
+ bot.add_handler(:message, Twibot::Handler.new)
69
+ Twitter::Client.any_instance.expects(:messages).with(:received, nil).returns([message("cjno", "Hei der!")])
70
+ assert_equal 1, bot.receive_messages
71
+
72
+ Twitter::Client.any_instance.expects(:messages).with(:received, { :since_id => 1 }).returns([])
73
+ assert_equal 0, bot.receive_messages
74
+ end
75
+
76
+ test "should receive tweet" do
77
+ bot = Twibot::Bot.new(Twibot::Config.new(:log_level => "error"))
78
+ bot.add_handler(:tweet, Twibot::Handler.new)
79
+ Twitter::Client.any_instance.expects(:timeline_for).with(:me, nil).returns([tweet("cjno", "Hei der!")])
80
+
81
+ assert_equal 1, bot.receive_tweets
82
+ end
83
+
84
+ test "should remember received tweets" do
85
+ bot = Twibot::Bot.new(Twibot::Config.new(:log_level => "error"))
86
+ bot.add_handler(:tweet, Twibot::Handler.new)
87
+ Twitter::Client.any_instance.expects(:timeline_for).with(:me, nil).returns([tweet("cjno", "Hei der!")])
88
+ assert_equal 1, bot.receive_tweets
89
+
90
+ Twitter::Client.any_instance.expects(:timeline_for).with(:me, { :id => 1 }).returns([])
91
+ assert_equal 0, bot.receive_tweets
92
+ end
93
+
94
+ test "should not receive reply when tweet does not start with login" do
95
+ bot = Twibot::Bot.new(Twibot::Config.new(:log_level => "error", :login => "irbno"))
96
+ bot.add_handler(:reply, Twibot::Handler.new)
97
+ Twitter::Client.any_instance.expects(:timeline_for).with(:me, nil).returns([tweet("cjno", "Hei der!")])
98
+
99
+ assert_equal 0, bot.receive_replies
100
+ end
101
+
102
+ test "should receive reply when tweet starts with login" do
103
+ bot = Twibot::Bot.new(Twibot::Config.new(:log_level => "error", :login => "irbno"))
104
+ bot.add_handler(:reply, Twibot::Handler.new)
105
+ Twitter::Client.any_instance.expects(:timeline_for).with(:me, nil).returns([tweet("cjno", "@irbno Hei der!")])
106
+
107
+ assert_equal 1, bot.receive_replies
108
+ end
109
+
110
+ test "should remember received replies" do
111
+ bot = Twibot::Bot.new(Twibot::Config.new(:log_level => "error", :login => "irbno"))
112
+ bot.add_handler(:reply, Twibot::Handler.new)
113
+ Twitter::Client.any_instance.expects(:timeline_for).with(:me, nil).returns([tweet("cjno", "@irbno Hei der!")])
114
+ assert_equal 1, bot.receive_replies
115
+
116
+ Twitter::Client.any_instance.expects(:timeline_for).with(:me, { :id => 1 }).returns([])
117
+ assert_equal 0, bot.receive_replies
118
+ end
119
+ end
120
+
121
+ class TestBotMacros < Test::Unit::TestCase
122
+ test "should provide configure macro" do
123
+ assert respond_to?(:configure)
124
+ end
125
+
126
+ test "configure should yield configuration" do
127
+ Twibot::Macros.bot = Twibot::Bot.new Twibot::Config.default
128
+ bot.prompt = false
129
+
130
+ conf = nil
131
+ assert_nothing_raised { configure { |c| conf = c } }
132
+ assert conf.is_a?(Twibot::Config)
133
+ end
134
+
135
+ test "should add handler" do
136
+ handler = add_handler(:message, ":command", :from => :cjno)
137
+ assert handler.is_a?(Twibot::Handler), handler.class
138
+ end
139
+
140
+ test "should provide twitter macro" do
141
+ assert respond_to?(:twitter)
142
+ assert respond_to?(:client)
143
+ end
144
+ end
145
+
146
+ class TestBotHandlers < Test::Unit::TestCase
147
+
148
+ test "should include handlers" do
149
+ bot = Twibot::Bot.new(Twibot::Config.new)
150
+
151
+ assert_not_nil bot.handlers
152
+ assert_not_nil bot.handlers[:message]
153
+ assert_not_nil bot.handlers[:reply]
154
+ assert_not_nil bot.handlers[:tweet]
155
+ end
156
+
157
+ test "should add handler" do
158
+ bot = Twibot::Bot.new(Twibot::Config.new)
159
+ bot.add_handler :message, Twibot::Handler.new
160
+ assert_equal 1, bot.handlers[:message].length
161
+
162
+ bot.add_handler :message, Twibot::Handler.new
163
+ assert_equal 2, bot.handlers[:message].length
164
+
165
+ bot.add_handler :reply, Twibot::Handler.new
166
+ assert_equal 1, bot.handlers[:reply].length
167
+
168
+ bot.add_handler :reply, Twibot::Handler.new
169
+ assert_equal 2, bot.handlers[:reply].length
170
+
171
+ bot.add_handler :tweet, Twibot::Handler.new
172
+ assert_equal 1, bot.handlers[:tweet].length
173
+
174
+ bot.add_handler :tweet, Twibot::Handler.new
175
+ assert_equal 2, bot.handlers[:tweet].length
176
+ end
177
+ end
@@ -0,0 +1,89 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper')) unless defined?(Twibot)
2
+ require 'stringio'
3
+
4
+ class TestConfig < Test::Unit::TestCase
5
+ test "default configuration should be a hash" do
6
+ assert_not_nil Twibot::Config::DEFAULT
7
+ assert Twibot::Config::DEFAULT.is_a?(Hash)
8
+ end
9
+
10
+ test "should initialize with no options" do
11
+ assert_hashes_equal({}, Twibot::Config.new.settings)
12
+ end
13
+
14
+ test "add config should return config" do
15
+ config = Twibot::Config.new
16
+ assert_equal config, config.add(Twibot::Config.new)
17
+ end
18
+
19
+ test "add config should be aliased to <<" do
20
+ config = Twibot::Config.new
21
+ assert config.respond_to?(:<<)
22
+ assert config << Twibot::Config.new
23
+ end
24
+
25
+ test "missing methods should act as config getters" do
26
+ config = Twibot::Config.default << Twibot::Config.new
27
+ assert_equal Twibot::Config::DEFAULT[:min_interval], config.min_interval
28
+ assert_equal Twibot::Config::DEFAULT[:login], config.login
29
+ end
30
+
31
+ test "missing methods should act as config setters" do
32
+ config = Twibot::Config.default << Twibot::Config.new
33
+ assert_equal Twibot::Config::DEFAULT[:min_interval], config.min_interval
34
+
35
+ val = config.min_interval
36
+ config.min_interval = val + 5
37
+ assert_not_equal Twibot::Config::DEFAULT[:min_interval], config.min_interval
38
+ assert_equal val + 5, config.min_interval
39
+ end
40
+
41
+ test "default configuration should not override default hash" do
42
+ config = Twibot::Config.default
43
+ hash = Twibot::Config::DEFAULT
44
+
45
+ config.min_interval = 0
46
+ config.max_interval = 0
47
+
48
+ assert_hashes_not_equal Twibot::Config::DEFAULT, config.to_hash
49
+ assert_hashes_equal hash, Twibot::Config::DEFAULT
50
+ end
51
+
52
+ test "to_hash should return merged configuration" do
53
+ config = Twibot::Config.new
54
+ config.min_interval = 10
55
+ config.max_interval = 10
56
+
57
+ config2 = Twibot::Config.new({})
58
+ config2.min_interval = 1
59
+ config << config2
60
+ options = config.to_hash
61
+
62
+ assert_equal 10, options[:max_interval]
63
+ assert_equal 1, options[:min_interval]
64
+ end
65
+ end
66
+
67
+ class TestCliConfig < Test::Unit::TestCase
68
+ test "should configure from options" do
69
+ config = Twibot::CliConfig.new %w{--min-interval 10 --max-interval 15}
70
+ assert_equal 10, config.min_interval
71
+ assert_equal 15, config.max_interval
72
+ end
73
+ end
74
+
75
+ class TestFileConfig < Test::Unit::TestCase
76
+ test "file config should subclass config" do
77
+ assert Twibot::FileConfig.new(StringIO.new).is_a?(Twibot::Config)
78
+ end
79
+
80
+ test "should read settings from stream" do
81
+ config = Twibot::FileConfig.new(StringIO.new <<-YAML)
82
+ min_interval: 10
83
+ max_interval: 20
84
+ YAML
85
+
86
+ assert_equal 10, config.min_interval
87
+ assert_equal 20, config.max_interval
88
+ end
89
+ end