Back to Repositories

Testing Destroy Event Data Handling in PaperTrail

This test suite validates the destroy event functionality in PaperTrail, focusing on data handling during model destruction and attribute tracking. It ensures proper versioning behavior and attribute management when objects are destroyed.

Test Coverage Overview

The test suite covers critical aspects of PaperTrail’s destroy event handling, including:

  • Item subtype verification for inheritance hierarchies
  • Attribute skipping functionality during object destruction
  • Object changes tracking with YAML serialization
  • Handling of timestamp and custom attributes

Implementation Analysis

The testing approach utilizes RSpec’s describe and context blocks to organize related test cases. It implements versioning through a custom flag and leverages factory objects to validate destroy event behavior. The tests specifically focus on data serialization and attribute filtering.

Technical Details

  • RSpec testing framework
  • YAML serialization handling
  • Custom versioning configuration
  • Model factories for test data
  • Conditional logic for different YAML implementations

Best Practices Demonstrated

The test suite demonstrates several testing best practices including isolated test cases, proper context separation, and comprehensive attribute verification. It handles both legacy and modern YAML implementations while maintaining clean test organization and clear expectations.

paper-trail-gem/paper_trail

spec/paper_trail/events/destroy_spec.rb

            
# frozen_string_literal: true

require "spec_helper"

module PaperTrail
  module Events
    ::RSpec.describe Destroy do
      describe "#data", versioning: true do
        it "includes correct item_subtype" do
          carter = Family::CelebrityFamily.new(
            name: "Carter",
            path_to_stardom: "Mexican radio"
          )
          data = described_class.new(carter, true).data
          expect(data[:item_type]).to eq("Family::Family")
          expect(data[:item_subtype]).to eq("Family::CelebrityFamily")
        end

        context "with skipper" do
          let(:skipper) { Skipper.create!(another_timestamp: Time.current) }
          let(:data) { described_class.new(skipper, false).data }

          it "includes `object` without skipped attributes" do
            object = if ::YAML.respond_to?(:unsafe_load)
                       YAML.unsafe_load(data[:object])
                     else
                       YAML.load(data[:object])
                     end
            expect(object["id"]).to eq(skipper.id)
            expect(object).to have_key("updated_at")
            expect(object).to have_key("created_at")
            expect(object).not_to have_key("another_timestamp")
          end

          it "includes `object_changes` without skipped and ignored attributes" do
            changes = if ::YAML.respond_to?(:unsafe_load)
                        YAML.unsafe_load(data[:object_changes])
                      else
                        YAML.load(data[:object_changes])
                      end
            expect(changes["id"]).to eq([skipper.id, nil])
            expect(changes["updated_at"][0]).to be_present
            expect(changes["updated_at"][1]).to be_nil
            expect(changes).not_to have_key("created_at")
            expect(changes).not_to have_key("another_timestamp")
          end
        end
      end
    end
  end
end