Back to Repositories

Testing JSONB Version Queries for Vegetable Model in PaperTrail

This test suite validates the versioning functionality of the Vegetable model in PaperTrail, specifically focusing on JSONB-based version queries in PostgreSQL. The tests verify various methods for querying version history based on attribute changes and object states.

Test Coverage Overview

The test suite provides comprehensive coverage of version querying capabilities:

  • Attribute change detection through where_attribute_changes
  • Object state transitions using where_object_changes_from and where_object_changes_to
  • Historical object state queries with where_object
  • Change tracking verification with where_object_changes

Implementation Analysis

The testing approach utilizes RSpec’s describe and context blocks to organize related test cases. The implementation leverages PaperTrail’s JSONB-specific version querying methods, with each test focusing on a specific query scenario. The suite employs let blocks for test data setup and before hooks for establishing test state.

Technical Details

Key technical components include:

  • PostgreSQL with JSONB support
  • RSpec testing framework
  • PaperTrail versioning gem
  • Custom JsonbVersion model
  • Environment-specific test execution (DB=postgres)

Best Practices Demonstrated

The test suite exemplifies several testing best practices:

  • Isolated test cases with clear expectations
  • Proper test data setup and cleanup
  • Conditional test execution based on environment
  • Consistent assertion patterns
  • Clear test descriptions that document functionality

paper-trail-gem/paper_trail

spec/models/vegetable_spec.rb

            
# frozen_string_literal: true

require "spec_helper"
require "support/performance_helpers"

if ENV["DB"] == "postgres" && JsonbVersion.table_exists?
  ::RSpec.describe Vegetable do
    describe "queries of versions", versioning: true do
      let!(:vegetable) { described_class.create(name: "Veggie", mass: 1, color: "green") }

      before do
        vegetable.update(name: "Fidget")
        vegetable.update(name: "Digit")
        described_class.create(name: "Cucumber")
      end

      it "return the vegetable whose name has changed" do
        result = JsonbVersion.where_attribute_changes(:name).map(&:item)
        expect(result).to include(vegetable)
      end

      it "returns the vegetable whose name was Fidget" do
        result = JsonbVersion.where_object_changes_from({ name: "Fidget" }).map(&:item)
        expect(result).to include(vegetable)
      end

      it "returns the vegetable whose name became Digit" do
        result = JsonbVersion.where_object_changes_to({ name: "Digit" }).map(&:item)
        expect(result).to include(vegetable)
      end

      it "returns the vegetable where the object was named Fidget before it changed" do
        result = JsonbVersion.where_object({ name: "Fidget" }).map(&:item)
        expect(result).to include(vegetable)
      end

      it "returns the vegetable that changed to Fidget" do
        result = JsonbVersion.where_object_changes({ name: "Fidget" }).map(&:item)
        expect(result).to include(vegetable)
      end
    end
  end
end