Back to Repositories

Testing Value Node Type Casting in Ransack

This test suite validates the Value node functionality in Ransack’s type casting system, focusing on data type conversions and value handling. It ensures accurate casting of various data types including dates, timestamps, booleans, and numeric values within the Ransack query framework.

Test Coverage Overview

The test suite provides comprehensive coverage of Ransack’s Value node type casting capabilities.

  • Tests date and timestamp conversions with timezone handling
  • Validates boolean value casting for both true and false cases
  • Covers numeric type conversions including integer, float, decimal, and money formats
  • Tests edge cases with different input formats and values

Implementation Analysis

The testing approach uses RSpec’s context-based structure to organize related test cases systematically.

  • Leverages RSpec’s let blocks for test data setup
  • Uses shared examples for similar data type conversions
  • Implements expect assertions to verify type and value accuracy
  • Utilizes Constants module for predefined test values

Technical Details

  • RSpec testing framework with shared context support
  • Integration with Ransack’s Context and Value classes
  • Ruby standard library date/time parsing
  • BigDecimal for precise decimal handling
  • ActiveSupport::TimeZone integration

Best Practices Demonstrated

The test suite exemplifies high-quality testing practices in Ruby development.

  • Systematic organization of related test cases
  • Comprehensive type conversion validation
  • Clear test descriptions and expectations
  • Efficient test data setup and reuse
  • Proper isolation of test cases

activerecord-hackery/ransack

spec/ransack/nodes/value_spec.rb

            
require 'spec_helper'

module Ransack
  module Nodes
    describe Value do
      let(:context) { Context.for(Person) }

      subject do
        Value.new(context, raw_value)
      end

      context "with a date value" do
        let(:raw_value) { "2022-05-23" }

        [:date].each do |type|
          it "should cast #{type} correctly" do
            result = subject.cast(type)

            expect(result).to be_a_kind_of(Date)
            expect(result).to eq(Date.parse(raw_value))
          end
        end
      end

      context "with a timestamp value" do
        let(:raw_value) { "2022-05-23 10:40:02 -0400" }

        [:datetime, :timestamp, :time, :timestamptz].each do |type|
          it "should cast #{type} correctly" do
            result = subject.cast(type)

            expect(result).to be_a_kind_of(Time)
            expect(result).to eq(Time.zone.parse(raw_value))
          end
        end
      end

      Constants::TRUE_VALUES.each do |value|
        context "with a true boolean value (#{value})" do
          let(:raw_value) { value.to_s }

          it "should cast boolean correctly" do
            result = subject.cast(:boolean)
            expect(result).to eq(true)
          end
        end
      end

      Constants::FALSE_VALUES.each do |value|
        context "with a false boolean value (#{value})" do
          let(:raw_value) { value.to_s }

          it "should cast boolean correctly" do
            result = subject.cast(:boolean)

            expect(result).to eq(false)
          end
        end
      end

      ["12", "101.5"].each do |value|
        context "with an integer value (#{value})" do
          let(:raw_value) { value }

          it "should cast #{value} to integer correctly" do
            result = subject.cast(:integer)

            expect(result).to be_an(Integer)
            expect(result).to eq(value.to_i)
          end
        end
      end

      ["12", "101.5"].each do |value|
        context "with a float value (#{value})" do
          let(:raw_value) { value }

          it "should cast #{value} to float correctly" do
            result = subject.cast(:float)

            expect(result).to be_an(Float)
            expect(result).to eq(value.to_f)
          end
        end
      end

      ["12", "101.5"].each do |value|
        context "with a decimal value (#{value})" do
          let(:raw_value) { value }

          it "should cast #{value} to decimal correctly" do
            result = subject.cast(:decimal)

            expect(result).to be_a(BigDecimal)
            expect(result).to eq(value.to_d)
          end
        end
      end

      ["12", "101.513"].each do |value|
        context "with a money value (#{value})" do
          let(:raw_value) { value }

          it "should cast #{value} to money correctly" do
            result = subject.cast(:money)

            expect(result).to be_a(String)
            expect(result).to eq(value.to_f.to_s)
          end
        end
      end

    end
  end
end