Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

How would you DRY up this RSpec code?

require "spec_helper"

describe InvoiceMailer do
  let(:user) { create(:user) }
  let(:student) { create(:student, user: user) }
  let(:body) { "And I for one will join with anyone, don't care what color you are. As long as you want change this miserable condition that exists on this earth." }
  subject(:mail) { InvoiceMailer.issue(student, body) }

  describe "issue" do
    subject(:mail) { InvoiceMailer.issue(student, body) }

    it "renders the subject" do
      expect(mail.subject).to eq "New Invoice!"
    end

    it "renders the receiver email" do
      expect(mail.to).to eq [student.user.email]
    end

    it "renders the sender email" do
      expect(mail.from).to eq ["[email protected]"]
    end
  end

  describe "rescind" do
    subject(:mail) { InvoiceMailer.rescind(student, body) }

    it "renders the subject" do
      expect(mail.subject).to eq "Invoice Rescinded!"
    end

    it "renders the receiver email" do
      expect(mail.to).to eq [student.user.email]
    end

    it "renders the sender email" do
      expect(mail.from).to eq ["[email protected]"]
    end
  end

end
share|improve this question

1 Answer 1

up vote 3 down vote accepted

You can use the its syntax:

require "spec_helper"

describe InvoiceMailer do
  let(:user) { create(:user) }
  let(:student) { create(:student, user: user) }
  let(:body) { "And I for one will join with anyone, don't care what color you are. As long as you want change this miserable condition that exists on this earth." }

  describe "issue" do
    subject { InvoiceMailer.issue(student, body) }

    its(:subject) { should eq "New Invoice!" }

    its(:to) { should eq [student.user.email] }

    its(:from) { should eq ["[email protected]"] }
  end

  describe "rescind" do
    subject { InvoiceMailer.rescind(student, body) }

    its(:subject) { should eq "Invoice Rescinded!" }

    its(:to) { should eq [student.user.email] }

    its(:from) { should eq ["[email protected]"] }
  end

end

You can further DRY it up using example groups

describe InvoiceMailer do
  let(:user) { create(:user) }
  let(:student) { create(:student, user: user) }
  let(:body) { "And I for one will join with anyone, don't care what color you are. As long as you want change this miserable condition that exists on this earth." }

  shared_examples_for "outgoing mail" do |method, mail_subject|
    subject { InvoiceMailer.send(method, student, body) }

    its(:subject) { should eq mail_subject }

    its(:to) { should eq [student.user.email] }

    its(:from) { should eq ["[email protected]"] }
  end

  describe "issue" do
    it_should_behave_like "outgoing mail", :issue, 'New Invoice!'
  end

  describe "rescind" do
    it_should_behave_like "outgoing mail", :rescind, 'Invoice Rescinded!'
  end
end
share|improve this answer
    
Thanks for this answer! I don't usually like its but in this case it's very readable. I feel like there is still a lot of duplication between the the issue and rescind describe blocks though. The only differences between the two are the methods on InvoiceMailer and the subject. Any thoughts? –  niftygrifty Feb 25 '14 at 2:34
    
Added an option with example groups –  Uri Agassi Feb 25 '14 at 7:15
    
Oh! That's exactly what I was looking for! –  niftygrifty Feb 25 '14 at 11:49

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.