require "spec_helper" describe Scamp do before do @valid_params = {:api_key => "6124d98749365e3db2c9e5b27ca04db6", :subdomain => "oxygen"} @valid_user_cache_data = {123 => {"name" => "foo"}, 456 => {"name" => "bar"}} @valid_channel_cache_data = {123 => {"name" => "foo"}, 456 => {"name" => "bar"}} end describe "#initialize" do it "should work with valid params" do a(Scamp).should be_a(Scamp) end it "should warn if given an option it doesn't know" do mock_logger a(Scamp, :fred => "estaire").should be_a(Scamp) logger_output.should =~ /WARN.*Scamp initialized with :fred => "estaire" but NO UNDERSTAND!/ end end describe "#verbose" do it "should default to false" do a(Scamp).verbose.should be_false end it "should be overridable at initialization" do a(Scamp, :verbose => true).verbose.should be_true end end describe "#logger" do context "default logger" do before { @bot = a Scamp } it { @bot.logger.should be_a(Logger) } it { @bot.logger.level.should be == Logger::INFO } end context "default logger in verbose mode" do before { @bot = a Scamp, :verbose => true } it { @bot.logger.level.should be == Logger::DEBUG } end context "overriding default" do before do @custom_logger = Logger.new("/dev/null") @bot = a Scamp, :logger => @custom_logger end it { @bot.logger.should be == @custom_logger } end end describe "#first_match_only" do it "should default to false" do a(Scamp).first_match_only.should be_false end it "should be settable" do a(Scamp, :first_match_only => true).first_match_only.should be_true end end describe "private methods" do describe "#process_message" do before do @bot = a Scamp $attempts = 0 # Yes, I hate it too. Works though. @message = {:body => "my message here"} @bot.behaviour do 2.times { match(/.*/) { $attempts += 1 } } end end after { $attempts = nil } context "with first_match_only not set" do before { @bot.first_match_only.should be_false } it "should process all matchers which attempt the message" do @bot.send(:process_message, @message) $attempts.should be == 2 end end context "with first_match_only set" do before do @bot.first_match_only = true @bot.first_match_only.should be_true end it "should only process the first matcher which attempts the message" do @bot.send(:process_message, @message) $attempts.should be == 1 end end end end describe "matching" do context "with conditions" do it "should limit matches by channel id" do canary = mock canary.expects(:lives).once canary.expects(:bang).never bot = a Scamp bot.behaviour do match("a string", :conditions => {:channel => 123}) {canary.lives} match("a string", :conditions => {:channel => 456}) {canary.bang} end bot.send(:process_message, {:room_id => 123, :body => "a string"}) end it "should limit matches by channel name" do canary = mock canary.expects(:lives).once canary.expects(:bang).never bot = a Scamp bot.behaviour do match("a string", :conditions => {:channel => "foo"}) {canary.lives} match("a string", :conditions => {:channel => "bar"}) {canary.bang} end bot.channel_cache = @valid_channel_cache_data bot.send(:process_message, {:room_id => 123, :body => "a string"}) end it "should limit matches by user id" do canary = mock canary.expects(:lives).once canary.expects(:bang).never bot = a Scamp bot.behaviour do match("a string", :conditions => {:user => 123}) {canary.lives} match("a string", :conditions => {:user => 456}) {canary.bang} end bot.send(:process_message, {:user_id => 123, :body => "a string"}) end it "should limit matches by user name" do canary = mock canary.expects(:lives).once canary.expects(:bang).never bot = a Scamp bot.behaviour do match("a string", :conditions => {:user => "foo"}) {canary.lives} match("a string", :conditions => {:user => "bar"}) {canary.bang} end bot.user_cache = @valid_user_cache_data bot.send(:process_message, {:user_id => 123, :body => "a string"}) end it "should limit matches by channel and user" do canary = mock canary.expects(:lives).once canary.expects(:bang).never bot = a Scamp bot.behaviour do match("a string", :conditions => {:channel => 123, :user => 123}) {canary.lives} match("a string", :conditions => {:channel => 456, :user => 456}) {canary.bang} end bot.channel_cache = @valid_channel_cache_data bot.user_cache = @valid_user_cache_data bot.send(:process_message, {:room_id => 123, :user_id => 123, :body => "a string"}) bot.send(:process_message, {:room_id => 123, :user_id => 456, :body => "a string"}) bot.send(:process_message, {:room_id => 456, :user_id => 123, :body => "a string"}) end end describe "strings" do it "should match an exact string" do canary = mock canary.expects(:lives).once canary.expects(:bang).never bot = a Scamp bot.behaviour do match("a string") {canary.lives} match("another string") {canary.bang} match("a string like no other") {canary.bang} end bot.send(:process_message, {:body => "a string"}) end end describe "regexes" do it "should match a regex" do canary = mock canary.expects(:ping).twice bot = a Scamp bot.behaviour do match /foo/ do canary.ping end end bot.send(:process_message, {:body => "something foo other thing"}) bot.send(:process_message, {:body => "foomaster"}) end it "should make named captures vailable as methods" do canary = mock canary.expects(:one).with("first") canary.expects(:two).with("the rest of it") bot = a Scamp bot.behaviour do match /^please match (?<yousaidthis>\w+) and (?<andthis>.+)$/ do canary.one(yousaidthis) canary.two(andthis) end end bot.send(:process_message, {:body => "please match first and the rest of it"}) end it "should make matches available in an array" do canary = mock canary.expects(:one).with("first") canary.expects(:two).with("the rest of it") bot = a Scamp bot.behaviour do match /^please match (\w+) and (.+)$/ do canary.one(matches[0]) canary.two(matches[1]) end end bot.send(:process_message, {:body => "please match first and the rest of it"}) end end end def a klass, params={} params ||= {} params = @valid_params.merge(params) if klass == Scamp klass.new(params) end # Urg def mock_logger @logger_string = StringIO.new @fake_logger = Logger.new(@logger_string) Scamp.any_instance.should_receive(:logger).and_return(@fake_logger) end # Bleurgh def logger_output str = @logger_string.dup str.rewind str.read end end