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