Back to Repositories

Testing Ransack Grouping Node Attribute Validation in activerecord-hackery/ransack

This test suite evaluates the Grouping class functionality within Ransack’s node system, focusing on attribute method validation and condition handling. The tests verify attribute detection and duplicate condition management in search queries.

Test Coverage Overview

The test suite provides comprehensive coverage of the Ransack::Nodes::Grouping class functionality.

Key areas tested include:
  • Attribute method validation for various naming patterns
  • Handling of special attribute name cases containing ‘_and_’ and ‘_or_’
  • Processing of attributes with ‘_start’ and ‘_end’ suffixes
  • Condition deduplication logic
  • Ransacker arguments differentiation

Implementation Analysis

The testing approach utilizes RSpec’s describe/context/it blocks to organize test cases hierarchically. The implementation leverages RSpec’s subject and let helpers for clean test setup, with before blocks for shared context initialization.

The tests demonstrate pattern matching and boolean expectations for attribute validation, alongside complex hash structure handling for condition testing.

Technical Details

Testing tools and configuration:
  • RSpec as the testing framework
  • Context setup using Person model
  • Custom matcher implementation for attribute validation
  • Hash-based condition structure testing
  • Before hooks for test initialization

Best Practices Demonstrated

The test suite exemplifies several testing best practices in Ruby.

Notable practices include:
  • Consistent context organization
  • Descriptive test naming
  • Isolated test cases
  • Clear setup and expectations
  • DRY principle application through shared contexts
  • Edge case coverage

activerecord-hackery/ransack

spec/ransack/nodes/grouping_spec.rb

            
require 'spec_helper'

module Ransack
  module Nodes
    describe Grouping do

      before do
        @g = 1
      end

      let(:context) { Context.for(Person) }

      subject { described_class.new(context) }

      describe '#attribute_method?' do
        context 'for attributes of the context' do
          it 'is true' do
            expect(subject.attribute_method?('name')).to be true
          end

          context "when the attribute contains '_and_'" do
            it 'is true' do
              expect(subject.attribute_method?('terms_and_conditions')).to be true
            end
          end

          context "when the attribute contains '_or_'" do
            it 'is true' do
              expect(subject.attribute_method?('true_or_false')).to be true
            end
          end

          context "when the attribute ends with '_start'" do
            it 'is true' do
              expect(subject.attribute_method?('life_start')).to be true
            end
          end

          context "when the attribute ends with '_end'" do
            it 'is true' do
              expect(subject.attribute_method?('stop_end')).to be true
            end
          end
        end

        context 'for unknown attributes' do
          it 'is false' do
            expect(subject.attribute_method?('not_an_attribute')).to be false
          end
        end
      end

      describe '#conditions=' do
        context 'when conditions are identical' do
          let(:conditions) do
            {
              '0' => {
                'a' => { '0'=> { 'name' => 'name', 'ransacker_args' => '' } },
                'p' => 'cont',
                'v' => { '0' => { 'value' => 'John' } }
              },
              '1' => {
                'a' => { '0' => { 'name' => 'name', 'ransacker_args' => '' } },
                'p' => 'cont',
                'v' => { '0' => { 'value' => 'John' } }
              }
            }
          end
          before { subject.conditions = conditions }

          it 'expect duplicates to be removed' do
            expect(subject.conditions.count).to eq 1
          end
        end

        context 'when conditions differ only by ransacker_args' do
          let(:conditions) do
            {
              '0' => {
                'a' => {
                  '0' => {
                    'name' => 'with_arguments',
                    'ransacker_args' => [1, 2]
                  }
                },
                'p' => 'eq',
                'v' => { '0' => { 'value' => '10' } }
              },
              '1' => {
                'a' => {
                  '0' => {
                    'name' => 'with_arguments',
                    'ransacker_args' => [3, 4]
                  }
                },
                'p' => 'eq',
                'v' => { '0' => { 'value' => '10' } }
              }
            }
          end
          before { subject.conditions = conditions }

          it 'expect them to be parsed as different and not as duplicates' do
            expect(subject.conditions.count).to eq 2
          end
        end
      end

    end
  end
end