JoaoPhelippe
JoaoPhelippe

Reputation: 57

How to test with RSpec on Rails a past date if I cant create an object with past date being prohibited inside the model?

I have a model Appointment that prohibit the object to be created using a past date or update if the field day is in the past.

class Appointment < ApplicationRecord
  belongs_to :user

  ...

  validate :not_past, on: [:create, :update]

  private

  ...

  def not_past
    if day.past?
      errors.add(:day, '...')
    end
  end
end

But I need to make a test file using RSpec to test if it really cannot be edited if the field day is a past date.

require 'rails_helper'

RSpec.describe Appointment, type: :model do
...
  it 'Cannot be edited if the date has past' do
    @user = User.last
    r = Appointment.new
    r.day = (Time.now - 2.days).strftime("%d/%m/%Y")
    r.hour = "10:00"
    r.description = "Some Description"
    r.duration = 1.0
    r.user = @user
    r.save!
    x = Appointment.last
    x.description = "Other"
    expect(x.save).to be_falsey
  end
  ...
end

The trouble is, the test can't be accurate due to an error that prohibit the creation of an Appointment object with the past day.

What should I do to force, or even maybe make a fake object with a past date for I can finally test it?

Upvotes: 1

Views: 452

Answers (1)

Christian Bruckmayer
Christian Bruckmayer

Reputation: 2187

You can use update_attribute which will skip validations.

  it 'Cannot be edited if the date has past' do
    @user = User.last
    r = Appointment.new
    r.day = (Time.now - 2.days).strftime("%d/%m/%Y")
    r.hour = "10:00"
    r.description = "Some Description"
    r.duration = 1.0
    r.user = @user
    r.save!
    x = Appointment.last
    x.description = "Other"

    r.update_attribute(:day, (Time.now - 2.days).strftime("%d/%m/%Y"))

    expect(x.save).to be_falsey
  end

Also you have a lot of noise in your test (data which is not asserted) which you should avoid by e.g. creating a helper function or using factories.

it 'Cannot be edited if the date has past' do
  appointment = create_appointment
  appointment.update_attribute(:day, (Time.now - 2.days).strftime("%d/%m/%Y"))

  appointment.description = 'new'

  assert(appointment.valid?).to eq false
end

def create_appointment
  Appointment.create!(
    day: Time.now.strftime("%d/%m/%Y"),
    hour: '10:00',
    description: 'description',
    duration: 1.0,
    user: User.last
  )
end

Also you test for falsey which will also match nil values. What you want to do in this case is test for false with eq false.

Upvotes: 1

Related Questions