Skip to content
Benjamin Roth edited this page Nov 16, 2016 · 1 revision

Given:

class AuthenticateUser
  include Waterfall
  include ActiveModel::Validations

  validates :user, presence: true
  attr_reader :user

  def initialize(email, password)
    @email, @password = email, @password
  end

  def call
    with_transaction do
      self
        .chain { @user = User.authenticate(@email, @password) }
        .when_falsy { valid? }
          .dam { errors }
        .chain(:user) { user }
    end
  end
end

You could spec this way:

describe AuthenticateUser do
  let(:email)    { '[email protected]' }
  let(:password) { 'password' }
  subject(:service) { AuthenticateUser.new(email, password).call }

  context "when given valid credentials" do
    let(:user) { double(:user) }

    before do
      allow(User).to receive(:authenticate).with(email, password).and_return(user)
    end

    it "succeeds" do
      expect(service.dammed?).to be false
    end

    it "provides the user" do
      expect(service.outflow.user).to eq(user)
    end
  end

  context "when given invalid credentials" do
    before do
      allow(User).to receive(:authenticate).with(email, password).and_return(nil)
    end

    it "fails" do
      expect(service.dammed?).to be true
    end

    it "provides a failure message" do
      expect(service.error_pool).to be_present
    end
  end
end
Clone this wiki locally