bjeanes-twibot 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +24 -0
- data/Rakefile +30 -0
- data/Readme.rdoc +175 -0
- data/lib/hash.rb +8 -0
- data/lib/twibot/bot.rb +231 -0
- data/lib/twibot/config.rb +138 -0
- data/lib/twibot/handlers.rb +111 -0
- data/lib/twibot/macros.rb +66 -0
- data/lib/twibot/tweets.rb +4 -0
- data/lib/twibot.rb +87 -0
- data/test/test_bot.rb +185 -0
- data/test/test_config.rb +89 -0
- data/test/test_handler.rb +191 -0
- data/test/test_hash.rb +34 -0
- data/test/test_helper.rb +44 -0
- data/test/test_twibot.rb +1 -0
- data/twibot.gemspec +38 -0
- metadata +95 -0
@@ -0,0 +1,111 @@
|
|
1
|
+
module Twibot
|
2
|
+
module Handlers
|
3
|
+
#
|
4
|
+
# Add a handler for this bot
|
5
|
+
#
|
6
|
+
def add_handler(type, handler)
|
7
|
+
handlers[type] << handler
|
8
|
+
handler
|
9
|
+
end
|
10
|
+
|
11
|
+
def dispatch(type, message)
|
12
|
+
handlers[type].each { |handler| handler.dispatch(message) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def handlers
|
16
|
+
@handlers ||= {
|
17
|
+
:message => [],
|
18
|
+
:reply => [],
|
19
|
+
:tweet => []
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def handlers=(hash)
|
24
|
+
@handlers = hash
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# A Handler object is an object which can handle a direct message, tweet or
|
30
|
+
# at reply.
|
31
|
+
#
|
32
|
+
class Handler
|
33
|
+
def initialize(pattern = nil, options = {}, &blk)
|
34
|
+
if pattern.is_a?(Hash)
|
35
|
+
options = pattern
|
36
|
+
pattern = nil
|
37
|
+
end
|
38
|
+
|
39
|
+
@options = options
|
40
|
+
@options[:from].collect! { |s| s.to_s } if @options[:from] && @options[:from].is_a?(Array)
|
41
|
+
@options[:from] = [@options[:from].to_s] if @options[:from] && @options[:from].is_a?(String)
|
42
|
+
@handler = nil
|
43
|
+
@handler = block_given? ? blk : nil
|
44
|
+
self.pattern = pattern
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Parse pattern string and set options
|
49
|
+
#
|
50
|
+
def pattern=(pattern)
|
51
|
+
return if pattern.nil? || pattern == ""
|
52
|
+
|
53
|
+
if pattern.is_a?(Regexp)
|
54
|
+
@options[:pattern] = pattern
|
55
|
+
return
|
56
|
+
end
|
57
|
+
|
58
|
+
words = pattern.split.collect { |s| s.strip } # Get all words in pattern
|
59
|
+
@options[:tokens] = words.inject([]) do |sum, token| # Find all tokens, ie :symbol :like :names
|
60
|
+
next sum unless token =~ /^:.*/ # Don't process regular words
|
61
|
+
sym = token.sub(":", "").to_sym # Turn token string into symbol, ie ":token" => :token
|
62
|
+
regex = @options[sym] || '[^\s]+' # Fetch regex if configured, else use any character but space matching
|
63
|
+
pattern.sub!(/(^|\s)#{token}(\s|$)/, '\1(' + regex.to_s + ')\2') # Make sure regex captures named switch
|
64
|
+
sum << sym
|
65
|
+
end
|
66
|
+
|
67
|
+
@options[:pattern] = /#{pattern}(\s.+)?/
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Determines if this handler is suited to handle an incoming message
|
72
|
+
#
|
73
|
+
def recognize?(message)
|
74
|
+
return false if @options[:pattern] && message.text !~ @options[:pattern] # Pattern check
|
75
|
+
|
76
|
+
users = @options[:from] ? @options[:from] : nil
|
77
|
+
sender = message.respond_to?(:sender) ? message.sender : message.user
|
78
|
+
return false if users && !users.include?(sender.screen_name.downcase) # Check allowed senders
|
79
|
+
true
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# Process message to build params hash and pass message along with params of
|
84
|
+
# to +handle+
|
85
|
+
#
|
86
|
+
def dispatch(message)
|
87
|
+
return unless recognize?(message)
|
88
|
+
@params = {}
|
89
|
+
|
90
|
+
if @options[:pattern] && @options[:tokens]
|
91
|
+
matches = message.text.match(@options[:pattern])
|
92
|
+
@options[:tokens].each_with_index { |token, i| @params[token] = matches[i+1] }
|
93
|
+
@params[:text] = (matches[@options[:tokens].length+1] || "").strip
|
94
|
+
elsif @options[:pattern] && !@options[:tokens]
|
95
|
+
@params = message.text.match(@options[:pattern]).to_a[1..-1] || []
|
96
|
+
else
|
97
|
+
@params[:text] = message.text
|
98
|
+
end
|
99
|
+
|
100
|
+
handle(message, @params)
|
101
|
+
end
|
102
|
+
|
103
|
+
#
|
104
|
+
# Handle a message. Calls the internal Proc with the message and the params
|
105
|
+
# hash as parameters.
|
106
|
+
#
|
107
|
+
def handle(message, params)
|
108
|
+
@handler.call(message, params) if @handler
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Twibot
|
2
|
+
@@prompt = false
|
3
|
+
|
4
|
+
def self.prompt=(p)
|
5
|
+
@@prompt = f
|
6
|
+
end
|
7
|
+
|
8
|
+
module Macros
|
9
|
+
def self.included(mod)
|
10
|
+
@@bot = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def configure(&blk)
|
14
|
+
bot.configure(&blk)
|
15
|
+
end
|
16
|
+
|
17
|
+
def message(pattern = nil, options = {}, &blk)
|
18
|
+
add_handler(:message, pattern, options, &blk)
|
19
|
+
end
|
20
|
+
|
21
|
+
def reply(pattern = nil, options = {}, &blk)
|
22
|
+
add_handler(:reply, pattern, options, &blk)
|
23
|
+
end
|
24
|
+
|
25
|
+
def tweet(pattern = nil, options = {}, &blk)
|
26
|
+
add_handler(:tweet, pattern, options, &blk)
|
27
|
+
end
|
28
|
+
|
29
|
+
def twitter
|
30
|
+
bot.twitter
|
31
|
+
end
|
32
|
+
|
33
|
+
alias_method :client, :twitter
|
34
|
+
|
35
|
+
def post_tweet(msg)
|
36
|
+
message = msg.respond_to?(:text) ? msg.text : msg
|
37
|
+
puts message
|
38
|
+
client.status(:post, message)
|
39
|
+
end
|
40
|
+
|
41
|
+
def run?
|
42
|
+
!@@bot.nil?
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
def add_handler(type, pattern, options, &blk)
|
47
|
+
bot.add_handler(type, Twibot::Handler.new(pattern, options, &blk))
|
48
|
+
end
|
49
|
+
|
50
|
+
def bot
|
51
|
+
return @@bot unless @@bot.nil?
|
52
|
+
|
53
|
+
begin
|
54
|
+
@@bot = Twibot::Bot.new nil, true
|
55
|
+
rescue Exception
|
56
|
+
@@bot = Twibot::Bot.new(Twibot::Config.default << Twibot::CliConfig.new, true)
|
57
|
+
end
|
58
|
+
|
59
|
+
@@bot
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.bot=(bot)
|
63
|
+
@@bot = bot
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/twibot.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'twitter'
|
3
|
+
require 'twitter/client'
|
4
|
+
require 'yaml'
|
5
|
+
require File.join(File.dirname(__FILE__), 'hash')
|
6
|
+
|
7
|
+
module Twibot
|
8
|
+
|
9
|
+
# :stopdoc:
|
10
|
+
VERSION = '0.1.6'
|
11
|
+
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
12
|
+
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
13
|
+
# :startdoc:
|
14
|
+
|
15
|
+
# Returns the version string for the library.
|
16
|
+
#
|
17
|
+
def self.version
|
18
|
+
VERSION
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the library path for the module. If any arguments are given,
|
22
|
+
# they will be joined to the end of the libray path using
|
23
|
+
# <tt>File.join</tt>.
|
24
|
+
#
|
25
|
+
def self.libpath( *args )
|
26
|
+
args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the lpath for the module. If any arguments are given,
|
30
|
+
# they will be joined to the end of the path using
|
31
|
+
# <tt>File.join</tt>.
|
32
|
+
#
|
33
|
+
def self.path( *args )
|
34
|
+
args.empty? ? PATH : ::File.join(PATH, args.flatten)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Utility method used to require all files ending in .rb that lie in the
|
38
|
+
# directory below this file that has the same name as the filename passed
|
39
|
+
# in. Optionally, a specific _directory_ name can be passed in such that
|
40
|
+
# the _filename_ does not have to be equivalent to the directory.
|
41
|
+
#
|
42
|
+
def self.require_all_libs_relative_to( fname, dir = nil )
|
43
|
+
dir ||= File.basename(fname, '.*')
|
44
|
+
search_me = File.expand_path(File.join(File.dirname(fname), dir, '**', '*.rb'))
|
45
|
+
Dir.glob(search_me).sort.each {|rb| require rb }
|
46
|
+
end
|
47
|
+
|
48
|
+
@@app_file = lambda do
|
49
|
+
ignore = [
|
50
|
+
/lib\/twibot.*\.rb/, # Library
|
51
|
+
/\(.*\)/, # Generated code
|
52
|
+
/custom_require\.rb/ # RubyGems require
|
53
|
+
]
|
54
|
+
|
55
|
+
path = caller.map { |line| line.split(/:\d/, 2).first }.find do |file|
|
56
|
+
next if ignore.any? { |pattern| file =~ pattern }
|
57
|
+
file
|
58
|
+
end
|
59
|
+
|
60
|
+
path || $0
|
61
|
+
end.call
|
62
|
+
|
63
|
+
#
|
64
|
+
# File name of the application file. Inspired by Sinatra
|
65
|
+
#
|
66
|
+
def self.app_file
|
67
|
+
@@app_file
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Runs application if application file is the script being executed
|
72
|
+
#
|
73
|
+
def self.run?
|
74
|
+
self.app_file == $0
|
75
|
+
end
|
76
|
+
|
77
|
+
end # module Twibot
|
78
|
+
|
79
|
+
Twitter::Client.configure do |config|
|
80
|
+
config.application_name = 'Twibot'
|
81
|
+
config.application_version = Twibot.version
|
82
|
+
config.application_url = 'http://github.com/cjohansen/twibot'
|
83
|
+
end
|
84
|
+
|
85
|
+
Twibot.require_all_libs_relative_to(__FILE__)
|
86
|
+
|
87
|
+
# EOF
|
data/test/test_bot.rb
ADDED
@@ -0,0 +1,185 @@
|
|
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
|
+
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
|
+
should "raise errors when initialized without config file" do
|
12
|
+
assert_raise SystemExit do
|
13
|
+
Twibot::Bot.new
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
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
|
+
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
|
+
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
|
+
should "respect configured log 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
|
+
should "should return false from receive 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
|
+
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, {}).returns([twitter_message("cjno", "Hei der!")])
|
62
|
+
|
63
|
+
assert bot.receive_messages
|
64
|
+
end
|
65
|
+
|
66
|
+
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, {}).returns([twitter_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
|
+
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, {}).returns([tweet("cjno", "Hei der!")])
|
80
|
+
|
81
|
+
assert_equal 1, bot.receive_tweets
|
82
|
+
end
|
83
|
+
|
84
|
+
should "receive friend tweets if configured" do
|
85
|
+
bot = Twibot::Bot.new(Twibot::Config.new({:log_level => "error", :include_friends => true}))
|
86
|
+
bot.add_handler(:tweet, Twibot::Handler.new)
|
87
|
+
Twitter::Client.any_instance.expects(:timeline_for).with(:friends, {}).returns([tweet("cjno", "Hei der!")])
|
88
|
+
|
89
|
+
assert_equal 1, bot.receive_tweets
|
90
|
+
end
|
91
|
+
|
92
|
+
should "remember received tweets" do
|
93
|
+
bot = Twibot::Bot.new(Twibot::Config.new(:log_level => "error"))
|
94
|
+
bot.add_handler(:tweet, Twibot::Handler.new)
|
95
|
+
Twitter::Client.any_instance.expects(:timeline_for).with(:me, {}).returns([tweet("cjno", "Hei der!")])
|
96
|
+
assert_equal 1, bot.receive_tweets
|
97
|
+
|
98
|
+
Twitter::Client.any_instance.expects(:timeline_for).with(:me, { :since_id => 1 }).returns([])
|
99
|
+
assert_equal 0, bot.receive_tweets
|
100
|
+
end
|
101
|
+
|
102
|
+
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(:status).with(:replies, {}).returns([tweet("cjno", "@irbno Hei der!")])
|
106
|
+
|
107
|
+
assert_equal 1, bot.receive_replies
|
108
|
+
end
|
109
|
+
|
110
|
+
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(:status).with(:replies, {}).returns([tweet("cjno", "@irbno Hei der!")])
|
114
|
+
assert_equal 1, bot.receive_replies
|
115
|
+
|
116
|
+
Twitter::Client.any_instance.expects(:status).with(:replies, { :since_id => 1 }).returns([])
|
117
|
+
assert_equal 0, bot.receive_replies
|
118
|
+
end
|
119
|
+
|
120
|
+
should "use public as default timeline method for tweet 'verb'" do
|
121
|
+
bot = Twibot::Bot.new(Twibot::Config.default)
|
122
|
+
assert_equal :public, bot.instance_eval { @config.to_hash[:timeline_for] }
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
class TestBotMacros < Test::Unit::TestCase
|
127
|
+
should "provide configure macro" do
|
128
|
+
assert respond_to?(:configure)
|
129
|
+
end
|
130
|
+
|
131
|
+
should "yield configuration" do
|
132
|
+
Twibot::Macros.bot = Twibot::Bot.new Twibot::Config.default
|
133
|
+
bot.prompt = false
|
134
|
+
|
135
|
+
conf = nil
|
136
|
+
assert_nothing_raised { configure { |c| conf = c } }
|
137
|
+
assert conf.is_a?(Twibot::Config)
|
138
|
+
end
|
139
|
+
|
140
|
+
should "add handler" do
|
141
|
+
Twibot::Macros.bot = Twibot::Bot.new Twibot::Config.default
|
142
|
+
bot.prompt = false
|
143
|
+
|
144
|
+
handler = add_handler(:message, ":command", :from => :cjno)
|
145
|
+
assert handler.is_a?(Twibot::Handler), handler.class
|
146
|
+
end
|
147
|
+
|
148
|
+
should "provide twitter macro" do
|
149
|
+
assert respond_to?(:twitter)
|
150
|
+
assert respond_to?(:client)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
class TestBotHandlers < Test::Unit::TestCase
|
155
|
+
|
156
|
+
should "include handlers" do
|
157
|
+
bot = Twibot::Bot.new(Twibot::Config.new)
|
158
|
+
|
159
|
+
assert_not_nil bot.handlers
|
160
|
+
assert_not_nil bot.handlers[:message]
|
161
|
+
assert_not_nil bot.handlers[:reply]
|
162
|
+
assert_not_nil bot.handlers[:tweet]
|
163
|
+
end
|
164
|
+
|
165
|
+
should "add handler" do
|
166
|
+
bot = Twibot::Bot.new(Twibot::Config.new)
|
167
|
+
bot.add_handler :message, Twibot::Handler.new
|
168
|
+
assert_equal 1, bot.handlers[:message].length
|
169
|
+
|
170
|
+
bot.add_handler :message, Twibot::Handler.new
|
171
|
+
assert_equal 2, bot.handlers[:message].length
|
172
|
+
|
173
|
+
bot.add_handler :reply, Twibot::Handler.new
|
174
|
+
assert_equal 1, bot.handlers[:reply].length
|
175
|
+
|
176
|
+
bot.add_handler :reply, Twibot::Handler.new
|
177
|
+
assert_equal 2, bot.handlers[:reply].length
|
178
|
+
|
179
|
+
bot.add_handler :tweet, Twibot::Handler.new
|
180
|
+
assert_equal 1, bot.handlers[:tweet].length
|
181
|
+
|
182
|
+
bot.add_handler :tweet, Twibot::Handler.new
|
183
|
+
assert_equal 2, bot.handlers[:tweet].length
|
184
|
+
end
|
185
|
+
end
|
data/test/test_config.rb
ADDED
@@ -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
|
+
should "default configuration be a hash" do
|
6
|
+
assert_not_nil Twibot::Config::DEFAULT
|
7
|
+
assert Twibot::Config::DEFAULT.is_a?(Hash)
|
8
|
+
end
|
9
|
+
|
10
|
+
should "initialize with no options" do
|
11
|
+
assert_hashes_equal({}, Twibot::Config.new.settings)
|
12
|
+
end
|
13
|
+
|
14
|
+
should "return config from add" do
|
15
|
+
config = Twibot::Config.new
|
16
|
+
assert_equal config, config.add(Twibot::Config.new)
|
17
|
+
end
|
18
|
+
|
19
|
+
should "alias add to <<" do
|
20
|
+
config = Twibot::Config.new
|
21
|
+
assert config.respond_to?(:<<)
|
22
|
+
assert config << Twibot::Config.new
|
23
|
+
end
|
24
|
+
|
25
|
+
should "mirror method_missing 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
|
+
should "mirror missing methods 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
|
+
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
|
+
should "return merged configuration from to_hash" 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
|
+
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
|
+
should "subclass config for file config" do
|
77
|
+
assert Twibot::FileConfig.new(StringIO.new).is_a?(Twibot::Config)
|
78
|
+
end
|
79
|
+
|
80
|
+
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
|