Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ActionMailbox spec helpers and test type (#2119)
* Add ActionMailbox spec helpers and test type Adds the following helpers to example groups with `:type => :mailbox` * process(mail_or_attributes) - send mail directly to the mailbox under test for `process`ing. * receive_inbound_email(mail_or_attributes) - matcher for asserting whether incoming email would route to the mailbox under test. * have_been_delivered - matcher for asserting whether an incoming email object was delivered. * have_bounced - matcher for asserting whether an incoming email object has bounced. * have_failed - matcher for asserting whether an incoming email object has failed. Also adds an ActionMailbox test generator * Add style changes from code review
- Loading branch information
1 parent
b4a2682
commit 8840963
Showing
11 changed files
with
328 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
require 'generators/rspec' | ||
|
||
module Rspec | ||
module Generators | ||
# @private | ||
class MailboxGenerator < Base | ||
def create_mailbox_spec | ||
template('mailbox_spec.rb.erb', | ||
File.join('spec/mailboxes', class_path, "#{file_name}_mailbox_spec.rb") | ||
) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
require 'rails_helper' | ||
|
||
<% module_namespacing do -%> | ||
RSpec.describe <%= class_name %>Mailbox, <%= type_metatag(:mailbox) %> do | ||
pending "add some examples to (or delete) #{__FILE__}" | ||
end | ||
<% end -%> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
module RSpec | ||
module Rails | ||
# @api public | ||
# Container module for mailbox spec functionality. | ||
module MailboxExampleGroup | ||
extend ActiveSupport::Concern | ||
|
||
if RSpec::Rails::FeatureCheck.has_action_mailbox? | ||
require 'action_mailbox/test_helper' | ||
extend ::ActionMailbox::TestHelper | ||
|
||
def self.create_inbound_email(arg) | ||
case arg | ||
when Hash | ||
create_inbound_email_from_mail(arg) | ||
else | ||
create_inbound_email_from_source(arg.to_s) | ||
end | ||
end | ||
else | ||
def self.create_inbound_email(_arg) | ||
raise "Could not load ActionMailer::TestHelper" | ||
end | ||
end | ||
|
||
class_methods do | ||
# @private | ||
def mailbox_class | ||
described_class | ||
end | ||
end | ||
|
||
included do | ||
subject { described_class } | ||
end | ||
|
||
# Verify the status of any inbound email | ||
# | ||
# @example | ||
# describe ForwardsMailbox do | ||
# it "can describe what happened to the inbound email" do | ||
# mail = process(args) | ||
# | ||
# # can use any of: | ||
# expect(mail).to have_been_delivered | ||
# expect(mail).to have_bounced | ||
# expect(mail).to have_failed | ||
# end | ||
# end | ||
def have_been_delivered | ||
satisfy('have been delivered', &:delivered?) | ||
end | ||
|
||
def have_bounced | ||
satisfy('have bounced', &:bounced?) | ||
end | ||
|
||
def have_failed | ||
satisfy('have failed', &:failed?) | ||
end | ||
|
||
# Process an inbound email message directly, bypassing routing. | ||
# | ||
# @param message [Hash, Mail::Message] a mail message or hash of | ||
# attributes used to build one | ||
# @return [ActionMaibox::InboundMessage] | ||
def process(message) | ||
MailboxExampleGroup.create_inbound_email(message).tap do |mail| | ||
self.class.mailbox_class.receive(mail) | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
module RSpec | ||
module Rails | ||
module Matchers | ||
# Namespace for various implementations of ActionMailbox features | ||
# | ||
# @api private | ||
module ActionMailbox | ||
# @private | ||
class Base < RSpec::Rails::Matchers::BaseMatcher | ||
private | ||
|
||
def create_inbound_email(message) | ||
RSpec::Rails::MailboxExampleGroup.create_inbound_email(message) | ||
end | ||
end | ||
|
||
# @private | ||
class ReceiveInboundEmail < Base | ||
def initialize(message) | ||
super() | ||
|
||
@inbound_email = create_inbound_email(message) | ||
end | ||
|
||
def matches?(mailbox) | ||
@mailbox = mailbox | ||
@receiver = ApplicationMailbox.router.send(:match_to_mailbox, inbound_email) | ||
|
||
@receiver == @mailbox | ||
end | ||
|
||
def failure_message | ||
"expected #{describe_inbound_email} to route to #{mailbox}".tap do |msg| | ||
if receiver | ||
msg << ", but routed to #{receiver} instead" | ||
end | ||
end | ||
end | ||
|
||
def failure_message_when_negated | ||
"expected #{describe_inbound_email} not to route to #{mailbox}" | ||
end | ||
|
||
private | ||
|
||
attr_reader :inbound_email, :mailbox, :receiver | ||
|
||
def describe_inbound_email | ||
"mail to #{inbound_email.mail.to.to_sentence}" | ||
end | ||
end | ||
end | ||
|
||
# @api public | ||
# Passes if the given inbound email would be routed to the subject inbox. | ||
# | ||
# @param message [Hash, Mail::Message] a mail message or hash of | ||
# attributes used to build one | ||
def receive_inbound_email(message) | ||
ActionMailbox::ReceiveInboundEmail.new(message) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Generators are not automatically loaded by Rails | ||
require 'generators/rspec/mailbox/mailbox_generator' | ||
require 'support/generators' | ||
|
||
RSpec.describe Rspec::Generators::MailboxGenerator, :type => :generator, :skip => !RSpec::Rails::FeatureCheck.has_action_mailbox? do | ||
setup_default_destination | ||
|
||
describe 'the generated files' do | ||
before { run_generator %w[forwards] } | ||
|
||
subject { file('spec/mailboxes/forwards_mailbox_spec.rb') } | ||
|
||
it { is_expected.to exist } | ||
it { is_expected.to contain(/require 'rails_helper'/) } | ||
it { is_expected.to contain(/describe ForwardsMailbox, #{type_metatag(:mailbox)}/) } | ||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
require "spec_helper" | ||
require "rspec/rails/feature_check" | ||
|
||
class ApplicationMailbox | ||
class << self | ||
attr_accessor :received | ||
|
||
def receive(*) | ||
self.received += 1 | ||
end | ||
end | ||
|
||
self.received = 0 | ||
end | ||
|
||
module RSpec | ||
module Rails | ||
describe MailboxExampleGroup, :skip => !RSpec::Rails::FeatureCheck.has_active_job? do | ||
it_behaves_like "an rspec-rails example group mixin", :mailbox, | ||
'./spec/mailboxes/', '.\\spec\\mailboxes\\' | ||
|
||
def group_for(klass) | ||
RSpec::Core::ExampleGroup.describe klass do | ||
include MailboxExampleGroup | ||
end | ||
end | ||
|
||
let(:group) { group_for(::ApplicationMailbox) } | ||
let(:example) { group.new } | ||
|
||
describe '#have_been_delivered' do | ||
it 'raises on undelivered mail' do | ||
expect { | ||
expect(double('IncomingEmail', :delivered? => false)).to example.have_been_delivered | ||
}.to raise_error(/have been delivered/) | ||
end | ||
|
||
it 'does not raise otherwise' do | ||
expect(double('IncomingEmail', :delivered? => true)).to example.have_been_delivered | ||
end | ||
end | ||
|
||
describe '#have_bounced' do | ||
it 'raises on unbounced mail' do | ||
expect { | ||
expect(double('IncomingEmail', :bounced? => false)).to example.have_bounced | ||
}.to raise_error(/have bounced/) | ||
end | ||
|
||
it 'does not raise otherwise' do | ||
expect(double('IncomingEmail', :bounced? => true)).to example.have_bounced | ||
end | ||
end | ||
|
||
describe '#have_failed' do | ||
it 'raises on unfailed mail' do | ||
expect { | ||
expect(double('IncomingEmail', :failed? => false)).to example.have_failed | ||
}.to raise_error(/have failed/) | ||
end | ||
|
||
it 'does not raise otherwise' do | ||
expect(double('IncomingEmail', :failed? => true)).to example.have_failed | ||
end | ||
end | ||
|
||
describe '#process' do | ||
before do | ||
allow(RSpec::Rails::MailboxExampleGroup).to receive(:create_inbound_email) do |attributes| | ||
mail = double('Mail::Message', attributes) | ||
double('InboundEmail', :mail => mail) | ||
end | ||
end | ||
|
||
it 'sends mail to the mailbox' do | ||
expect { | ||
example.process(:to => ['test@example.com']) | ||
}.to change(::ApplicationMailbox, :received).by(1) | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
require "spec_helper" | ||
require "rspec/rails/feature_check" | ||
|
||
class ApplicationMailbox | ||
class Router | ||
def match_to_mailbox(*) | ||
Inbox | ||
end | ||
end | ||
|
||
def self.router | ||
Router.new | ||
end | ||
end | ||
|
||
class Inbox < ApplicationMailbox; end | ||
class Otherbox < ApplicationMailbox; end | ||
|
||
RSpec.describe "ActionMailbox matchers", :skip => !RSpec::Rails::FeatureCheck.has_active_job? do | ||
include RSpec::Rails::Matchers::ActionMailbox | ||
|
||
describe "receive_inbound_email" do | ||
let(:to) { ['to@example.com'] } | ||
|
||
before do | ||
allow(RSpec::Rails::MailboxExampleGroup).to receive(:create_inbound_email) do |attributes| | ||
mail = double('Mail::Message', attributes) | ||
double('InboundEmail', :mail => mail) | ||
end | ||
end | ||
|
||
it "passes when it receives inbound email" do | ||
expect(Inbox).to receive_inbound_email(:to => to) | ||
end | ||
|
||
it "passes when negated when it doesn't receive inbound email" do | ||
expect(Otherbox).not_to receive_inbound_email(:to => to) | ||
end | ||
|
||
it "fails when it doesn't receive inbound email" do | ||
expect { | ||
expect(Otherbox).to receive_inbound_email(:to => to) | ||
}.to raise_error(/expected mail to to@example.com to route to Otherbox, but routed to Inbox/) | ||
end | ||
|
||
it "fails when negated when it receives inbound email" do | ||
expect { | ||
expect(Inbox).not_to receive_inbound_email(:to => to) | ||
}.to raise_error(/expected mail to to@example.com not to route to Inbox/) | ||
end | ||
end | ||
end |