Permalink
Browse files

Better test coverage, make strategy methods public

Closes #7. This change makes Strategy#authenticate and Strategy#receive
public by default, and refactors test coverage to execute #receive rather
than instantiating the receiver and then testing the result of #message,
which is why the tests didn't catch the protected method bug in the first
place.
  • Loading branch information...
joshuap committed Apr 30, 2013
1 parent ef43f6d commit 85510f600e78dece6bd4e9cafac232fe892c4c74
View
@@ -1,2 +1,9 @@
source :rubygems
gemspec
group :development, :test do
gem 'guard'
gem 'guard-rspec'
gem 'rb-fsevent', '~> 0.9'
end
View
@@ -39,6 +39,7 @@ GEM
method_source (~> 0.8)
slop (~> 3.4)
rake (10.0.3)
rb-fsevent (0.9.3)
rspec (2.13.0)
rspec-core (~> 2.13.0)
rspec-expectations (~> 2.13.0)
@@ -62,4 +63,5 @@ DEPENDENCIES
guard-rspec
incoming!
rake
rb-fsevent (~> 0.9)
rspec
View
@@ -1,4 +1,4 @@
guard 'rspec', :version => 2, :cli => '--fail-fast', :all_after_pass => false do
guard 'rspec', :cli => '--fail-fast', :all_after_pass => false do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { "spec" }
View
@@ -21,7 +21,4 @@ Gem::Specification.new do |s|
s.add_development_dependency 'rake'
s.add_development_dependency 'rspec'
s.add_development_dependency 'guard'
s.add_development_dependency 'guard-rspec'
end
@@ -1,3 +1,5 @@
require 'json'
module Incoming
module Strategies
class SendGrid
View
@@ -72,9 +72,7 @@ def setup(opts = {})
# Public: Translates arguments into a Mail::Message object
def initialize(*args) ; end
protected
# Protected: Evaluates message and performs appropriate action.
# Public: Evaluates message and performs appropriate action.
# Override in subclass
#
# mail - A Mail::Message object
@@ -84,7 +82,7 @@ def receive(mail)
raise NotImplementedError.new('You must implement #receive')
end
# Protected: Authenticates request before performing #receive
# Public: Authenticates request before performing #receive
#
# Examples:
#
@@ -23,13 +23,13 @@
end
describe 'message' do
subject { Incoming::Strategies::CloudMailin.new(@mock_request).message }
subject { receiver.receive(@mock_request) }
it { subject.should be_a Mail::Message }
it { subject.to[0].should eq 'josh@joshuawood.net' }
it { subject.from[0].should eq 'notifications@incoming.test' }
it { subject.subject.should eq 'Jack Kerouac has replied to Test' }
it { subject.body.decoded.should match /Reply ABOVE THIS LINE/ }
it { should be_a Mail::Message }
its('to.first') { should eq 'josh@joshuawood.net' }
its('from.first') { should eq 'notifications@incoming.test' }
its('subject') { should eq 'Jack Kerouac has replied to Test' }
its('body.decoded') { should match(/Reply ABOVE THIS LINE/) }
end
end
@@ -14,13 +14,15 @@
end
describe 'message' do
subject { Incoming::Strategies::HTTPPost.new(@mock_request).message }
subject { receiver.receive(@mock_request) }
before(:each) { OpenSSL::HMAC.stub(:hexdigest).and_return('foo') }
it { subject.should be_a Mail::Message }
it { subject.to[0].should eq 'josh@joshuawood.net' }
it { subject.from[0].should eq 'notifications@incoming.test' }
it { subject.subject.should eq 'Jack Kerouac has replied to Test' }
it { subject.body.decoded.should match /Reply ABOVE THIS LINE/ }
it { should be_a Mail::Message }
its('to.first') { should eq 'josh@joshuawood.net' }
its('from.first') { should eq 'notifications@incoming.test' }
its('subject') { should eq 'Jack Kerouac has replied to Test' }
its('body.decoded') { should match /Reply ABOVE THIS LINE/ }
end
it 'returns false from #authenticate when hexidigest is invalid' do
@@ -1,11 +1,7 @@
require 'spec_helper'
describe Incoming::Strategies::Mailgun do
class MailgunReceiver < Incoming::Strategies::Mailgun
def receive(mail)
'success'
end
end
let(:receiver) { test_receiver(:api_key => 'asdf') }
before do
attachment = stub(:original_filename => 'hello.txt', :read => 'hello world')
@@ -27,59 +23,51 @@ def receive(mail)
@mock_request = stub()
@mock_request.stub(:params).and_return(@params)
MailgunReceiver.class_eval do
setup :api_key => 'asdf'
end
end
describe 'non-mime request' do
describe 'message' do
subject { MailgunReceiver.new(@mock_request).message }
describe 'receive' do
subject { receiver.receive(@mock_request) }
before(:each) { OpenSSL::HMAC.stub(:hexdigest).and_return('foo') }
it { subject.should be_a Mail::Message }
it { should be_a Mail::Message }
it { subject.to[0].should eq @params['recipient'] }
it { subject.from[0].should eq @params['sender'] }
it { subject.subject.should eq @params['subject'] }
it { subject.body.decoded.should eq @params['body-plain'] }
it { subject.text_part.body.decoded.should eq @params['body-plain'] }
it { subject.html_part.body.decoded.should eq @params['body-html'] }
it { subject.attachments[0].filename.should eq 'hello.txt' }
it { subject.attachments[0].read.should eq 'hello world' }
its('to.first') { should eq @params['recipient'] }
its('from.first') { should eq @params['sender'] }
its('subject') { should eq @params['subject'] }
its('body.decoded') { should eq @params['body-plain'] }
its('text_part.body.decoded') { should eq @params['body-plain'] }
its('html_part.body.decoded') { should eq @params['body-html'] }
its('attachments.first.filename') { should eq 'hello.txt' }
its('attachments.first.read') { should eq 'hello world' }
context 'stripped option is true' do
before do
MailgunReceiver.class_eval do
setup :api_key => 'asdf', :stripped => true
end
end
let(:receiver) { test_receiver(:api_key => 'asdf', :stripped => true) }
it { should be_a Mail::Message }
it { subject.should be_a Mail::Message }
it { subject.body.decoded.should eq @params['stripped-text'] }
it { subject.text_part.body.decoded.should eq @params['stripped-text'] }
it { subject.html_part.body.decoded.should eq @params['stripped-html'] }
its('body.decoded') { should eq @params['stripped-text'] }
its('text_part.body.decoded') { should eq @params['stripped-text'] }
its('html_part.body.decoded') { should eq @params['stripped-html'] }
end
end
end
it 'it fails authentication when hexidigest is invalid' do
it 'returns false from #authenticate when hexidigest is invalid' do
OpenSSL::HMAC.stub(:hexdigest).and_return('bar')
mailgun = MailgunReceiver.receive(@mock_request)
mailgun.should be_false
mailgun = receiver.new(@mock_request)
mailgun.authenticate.should be_false
end
it 'authenticates when hexidigest is valid' do
OpenSSL::HMAC.stub(:hexdigest).and_return('foo')
mailgun = MailgunReceiver.receive(@mock_request)
mailgun.should eq 'success'
mailgun = receiver.new(@mock_request)
mailgun.authenticate.should be_true
end
it 'raises an exception when api key is not provided' do
MailgunReceiver.class_eval { setup({ :api_key => nil }) }
expect {
MailgunReceiver.new(@mock_request)
test_receiver(:api_key => nil).new(@mock_request)
}.to raise_error Incoming::Strategy::RequiredOptionError
end
end
@@ -12,14 +12,15 @@
end
describe '#message' do
subject { Incoming::Strategies::Postmark.new(@mock_request).message }
subject { receiver.receive(@mock_request) }
it { should be_a Mail::Message }
it { subject.to[0].should eq '451d9b70cf9364d23ff6f9d51d870251569e+ahoy@inbound.postmarkapp.com' }
it { subject.from[0].should eq 'user@email.com' }
it { subject.subject.should eq 'This is an inbound message' }
it { subject.body.decoded.should eq '[ASCII]' }
it { subject.attachments[0].filename.should eq 'hello.txt' }
it { subject.attachments[0].read.should eq 'hello world' }
its('to.first') { should eq '451d9b70cf9364d23ff6f9d51d870251569e+ahoy@inbound.postmarkapp.com' }
its('from.first') { should eq 'user@email.com' }
its('subject') { should eq 'This is an inbound message' }
its('body.decoded') { should eq '[ASCII]' }
its('attachments.first.filename') { should eq 'hello.txt' }
its('attachments.first.read') { should eq 'hello world' }
end
end
@@ -27,16 +27,17 @@
end
describe 'message' do
subject { Incoming::Strategies::SendGrid.new(@mock_request).message }
subject { receiver.receive(@mock_request) }
it { should be_a Mail::Message }
it { subject.to[0].should eq 'jack@example.com' }
it { subject.from[0].should eq 'japhy@example.com' }
it { subject.subject.should eq @params['subject'] }
it { subject.body.decoded.should eq @params['text'] }
it { subject.text_part.body.decoded.should eq @params['text'] }
it { subject.html_part.body.decoded.should eq @params['html'] }
it { subject.attachments[0].filename.should eq 'hello.txt' }
it { subject.attachments[0].read.should eq 'hello world' }
its('to.first') { should eq 'jack@example.com' }
its('from.first') { should eq 'japhy@example.com' }
its('subject') { should eq @params['subject'] }
its('body.decoded') { should eq @params['text'] }
its('text_part.body.decoded') { should eq @params['text'] }
its('html_part.body.decoded') { should eq @params['html'] }
its('attachments.first.filename') { should eq 'hello.txt' }
its('attachments.first.read') { should eq 'hello world' }
end
end
@@ -1,26 +1,21 @@
require 'spec_helper'
describe Incoming::Strategy do
class Strategy
include Incoming::Strategy
option :api_key, nil
end
class MailReceiver < Strategy
def receive(mail)
end
end
class TestStrategy
include Incoming::Strategy
option :api_key, nil
end
describe TestStrategy do
describe 'self.setup with hash' do
it 'raises an exception when invalid options have been set' do
expect {
MailReceiver.class_eval { setup({ :foo => 'invalid' }) }
receiver.class_eval { setup({ :foo => 'invalid' }) }
}.to raise_error(Incoming::Strategy::InvalidOptionError)
end
it 'raises no exception when valid options are set' do
expect {
MailReceiver.class_eval { setup({ :api_key => 'valid' }) }
receiver.class_eval { setup({ :api_key => 'valid' }) }
}.to_not raise_error
end
end
@@ -34,8 +29,8 @@ def receive(mail)
object.stub(:message).once.and_return('foo')
object.stub(:receive).with('foo').once
MailReceiver.should_receive(:new).with(*args).and_return(object)
MailReceiver.receive(*args)
receiver.should_receive(:new).with(*args).and_return(object)
receiver.receive(*args)
end
end
end
View
@@ -5,4 +5,22 @@
c.mock_with :rspec
c.color_enabled = true
c.tty = true
module Helpers
def self.included(base)
base.let(:receiver) { test_receiver }
end
def test_receiver(options = {})
Class.new(described_class) do
setup(options)
def receive(mail)
mail
end
end
end
end
c.include Helpers
end

0 comments on commit 85510f6

Please sign in to comment.