Home > Enterprise >  Rails 7 system tests gives an error because of model callback, how can i fix this?
Rails 7 system tests gives an error because of model callback, how can i fix this?

Time:04-27

I am trying to test my form behavior but when i click save, callback throw an error like below. If i comment the code below everything works fine. Here i don't want to test callback but it is preventing me to test behavior successfully.

What can i do to fix this.

#before_create :assign_depth
#before_save   :assign_depth

fond.yml | fixture

first:
  name: At vero eos et accusamus
  explanation: some explanation
  parent: 
second:
  name: laborum et dolorum fuga. Et
  explanation: some explanation
  parent: first

fond.rb model

class Fond < ApplicationRecord
    ...
  before_create :assign_depth
  before_save   :assign_depth
  
  belongs_to :parent, class_name: "Fond", optional: true
  has_many :children, class_name: "Fond", foreign_key: "parent_id", dependent: :nullify

  private
    def assign_depth
      self.depth = (self.parent.present? ? parent.depth   1 : 0)
    end
end

test

require "application_system_test_case"

class FondsTest < ApplicationSystemTestCase
  setup do
    login_as users(:admin)
    @fond_related = fonds(:second)
  end

  test "should create related fond" do
    visit fonds_url
    click_on "New fond"

    fill_in "Name", with: "Test Test Test"
    fill_in "Explanation", with: @fond_related.explanation
    first(:xpath, "/html/body/div[2]/div[2]/form/div[3]/div").click()
    
    find('div.item', text: @fond_related.name).click()

    click_on ("Fond Kaydet")

    assert_text "Fond was successfully created"
  end
end

test result

E

Error:
FondsTest#test_should_create_related_fond:
NoMethodError: undefined method ` ' for nil:NilClass
    app/models/fond.rb:29:in `assign_depth'
    app/controllers/fonds_controller.rb:29:in `block in create'
    app/controllers/fonds_controller.rb:28:in `create'

CodePudding user response:

In the callback you're checking for parent presence but parent.depth is nil and nil 1 is bad. System test is a full stack test, no skips here (if I'm the admin here, I'm looking at error 500 now).

Your test is doing exactly what it supposed to do, check the behavior and find bugs. You've successfully found one. You should have default depth set as 0 in the database and null: false so it would never return nil. Migration should look like this:

def change
  create_table :fonds do |t|
    t.integer :depth, default: 0, null: false
  end
end

To change existing column

def change
  change_column_default(:fonds, :depth, from: nil, to: 0)
  change_column_null(:fonds, :depth, false)
end

Anything less than that would mean you have to check for depth every time you want to manipulate it. Also you should have a validation in the Fond model

validates :depth, presence: true, numericality: true
  • Related