1

I have a model with two custom validation rules. When I remove these rules, RSpec for model validation passes. But adding those validation in model, RSpec can't pass which were previously passing. How can I solve this error and also how can I write RSpec for these custom validations?

My model file leave.rb

class Leave < ApplicationRecord
  scope :sorted_asc, lambda { order(id: :asc) }
  validates :start_day, :end_day,  :reason, :status, presence: true
  validate :start_day_cant_be_past, :end_day_cant_be_less_than_start_day
  enum category: { 'Sick': 0, 'Leave in Policy': 1, 'Out of Policy': 2 }

  def start_day_cant_be_past
    if start_day < Date.today
      errors.add(:start_day, 'can not be in the past')
    end
  end

  def end_day_cant_be_less_than_start_day
    if end_day < start_day
      errors.add(:end_day, 'can not be less than start day')
    end
  end
end

My RSpec file for model leave_spec.rb

require 'rails_helper'

RSpec.describe Leave, type: :model do
  it { should define_enum_for(:category).with(['Sick', 'Leave in Policy', 'Out of Policy']) }
  it { is_expected.to validate_presence_of(:start_day) }
  it { is_expected.to validate_presence_of(:end_day) }
  it { is_expected.to validate_presence_of(:reason) }
  it { is_expected.to validate_presence_of(:status) }
end

And the error I get is...

Leave should validate that :start_day cannot be empty/falsy
     Failure/Error: if start_day < Date.today

     NoMethodError:
       undefined method `<' for nil:NilClass

1 Answer 1

2

You get an error because start_day is nil. I would add guards to custom validtors:

def start_day_cant_be_past
  return unless start_day

  if start_day < Date.today
    errors.add(:start_day, 'can not be in the past')
  end
end

def end_day_cant_be_less_than_start_day
  return unless end_day && start_day

  if end_day < start_day
    errors.add(:end_day, 'can not be less than start day')
  end
end

To test those custom validators, I'd write regular test examples, e.g.:

it 'is invalid with start day in the past' do
  leave = Leave.new(start_day: 2.days.ago)
  expect(leave).to be_invalid
  expect(leave.errors[:start_day]).not_to be_empty
end

it 'is invalid with start day later than end day' do
  leave = Leave.new(start_day: 2.days.ago, start_day: 5.days.ago)
  expect(leave).to be_invalid
  expect(leave.errors[:end_day]).not_to be_empty
end
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.