Back to Repositories

Testing Grouped Collection Select Components in Simple Form

This test suite validates the GroupedCollectionSelectInput functionality in Simple Form, focusing on handling grouped select inputs with various collection formats and customization options. The tests ensure proper rendering of optgroups and options with different data structures and methods.

Test Coverage Overview

Comprehensive test coverage for grouped select inputs including:
  • Array and hash collection formats
  • Empty collections handling
  • Proc-based collections
  • Custom label and value methods
  • Association-based grouping
  • HTML options integration

Implementation Analysis

The testing approach utilizes ActionView::TestCase for DOM-based assertions, employing with_input_for helper to simulate form input generation. Tests validate proper HTML structure using assert_select matchers to verify optgroup and option elements rendering.

Implementation covers both simple collections and complex scenarios with custom methods and associations.

Technical Details

Testing tools and configuration:
  • Minitest framework
  • ActionView test helpers
  • DOM assertion methods
  • Struct-based test objects
  • Custom TagGroup and Tag model stubs

Best Practices Demonstrated

The test suite exemplifies robust testing practices including:
  • Isolated test cases for each feature
  • Comprehensive edge case coverage
  • Clear test naming conventions
  • Structured assertions for HTML output
  • Modular test organization

heartcombo/simple_form

test/inputs/grouped_collection_select_input_test.rb

            
# frozen_string_literal: true
# encoding: UTF-8
require 'test_helper'

class GroupedCollectionSelectInputTest < ActionView::TestCase
  test 'grouped collection accepts array collection form' do
    with_input_for @user, :tag_ids, :grouped_select,
      collection: [['Authors', %w[Jose Carlos]], ['General', %w[Bob John]]],
      group_method: :last

    assert_select 'select.grouped_select#user_tag_ids' do
      assert_select 'optgroup[label=Authors]' do
        assert_select 'option', 'Jose'
        assert_select 'option', 'Carlos'
      end

      assert_select 'optgroup[label=General]' do
        assert_select 'option', 'Bob'
        assert_select 'option', 'John'
      end
    end
  end

  test 'grouped collection accepts empty array collection form' do
    with_input_for @user, :tag_ids, :grouped_select,
      collection: [],
      group_method: :last

    assert_select 'select.grouped_select#user_tag_ids'
  end


  test 'grouped collection accepts proc as collection' do
    with_input_for @user, :tag_ids, :grouped_select,
      collection: proc { [['Authors', %w[Jose Carlos]], ['General', %w[Bob John]]] },
      group_method: :last

    assert_select 'select.grouped_select#user_tag_ids' do
      assert_select 'optgroup[label=Authors]' do
        assert_select 'option', 'Jose'
        assert_select 'option', 'Carlos'
      end

      assert_select 'optgroup[label=General]' do
        assert_select 'option', 'Bob'
        assert_select 'option', 'John'
      end
    end
  end

  test 'grouped collection accepts hash collection form' do
    with_input_for @user, :tag_ids, :grouped_select,
      collection: { Authors: %w[Jose Carlos], General: %w[Bob John] },
      group_method: :last

    assert_select 'select.grouped_select#user_tag_ids' do
      assert_select 'optgroup[label=Authors]' do
        assert_select 'option', 'Jose'
        assert_select 'option', 'Carlos'
      end

      assert_select 'optgroup[label=General]' do
        assert_select 'option', 'Bob'
        assert_select 'option', 'John'
      end
    end
  end

  test 'grouped collection allows overriding group_method using a lambda' do
    with_input_for @user, :tag_ids, :grouped_select,
      collection: { Authors: %w[Jose Carlos] },
      group_method: ->(i) { i.last }

    assert_select 'select.grouped_select#user_tag_ids' do
      assert_select 'optgroup[label=Authors]' do
        assert_select 'option[value=Jose]', 'Jose'
        assert_select 'option[value=Carlos]', 'Carlos'
      end
    end
  end

  test 'grouped collection accepts group_label_method option' do
    with_input_for @user, :tag_ids, :grouped_select,
      collection: { %w[Jose Carlos] => 'Authors' },
      group_method: :first,
      group_label_method: :last

    assert_select 'select.grouped_select#user_tag_ids' do
      assert_select 'optgroup[label=Authors]' do
        assert_select 'option', 'Jose'
        assert_select 'option', 'Carlos'
      end
    end
  end

  test 'grouped collection finds default label methods on the group objects' do
    option_list = %w[Jose Carlos]

    GroupedClass = Struct.new(:to_label, :options)
    group = GroupedClass.new("Authors", option_list)

    with_input_for @user, :tag_ids, :grouped_select,
      collection: [group],
      group_method: :options

    assert_select 'select.grouped_select#user_tag_ids' do
      assert_select 'optgroup[label=Authors]' do
        assert_select 'option', 'Jose'
        assert_select 'option', 'Carlos'
      end
    end
  end

  test 'grouped collections finds the default label method from the first non-empty object' do
    Agent = Struct.new(:id, :name)
    agents = [["First", []], ["Second", [Agent.new(7, 'Bond'), Agent.new(47, 'Hitman')]]]

    with_input_for @user, :tag_ids, :grouped_select,
      collection: agents,
      group_label_method: :first,
      group_method: :last,
      include_blank: false

    assert_select 'select.grouped_select#user_tag_ids' do
      assert_select 'optgroup[label=Second]' do
        assert_select 'option[value="7"]', 'Bond'
        assert_select 'option[value="47"]', 'Hitman'
      end
    end
  end

  test 'grouped collection accepts label and value methods options' do
    with_input_for @user, :tag_ids, :grouped_select,
      collection: { Authors: %w[Jose Carlos] },
      group_method: :last,
      label_method: :upcase,
      value_method: :downcase

    assert_select 'select.grouped_select#user_tag_ids' do
      assert_select 'optgroup[label=Authors]' do
        assert_select 'option[value=jose]', 'JOSE'
        assert_select 'option[value=carlos]', 'CARLOS'
      end
    end
  end

  test 'grouped collection allows overriding label and value methods using a lambda' do
    with_input_for @user, :tag_ids, :grouped_select,
      collection: { Authors: %w[Jose Carlos] },
      group_method: :last,
      label_method: ->(i) { i.upcase },
      value_method: ->(i) { i.downcase }

    assert_select 'select.grouped_select#user_tag_ids' do
      assert_select 'optgroup[label=Authors]' do
        assert_select 'option[value=jose]', 'JOSE'
        assert_select 'option[value=carlos]', 'CARLOS'
      end
    end
  end

  test 'grouped collection with associations' do
    tag_groups = [
      TagGroup.new(1, "Group of Tags", [Tag.new(1, "Tag 1"), Tag.new(2, "Tag 2")]),
      TagGroup.new(2, "Other group", [Tag.new(3, "Tag 3"), Tag.new(4, "Tag 4")])
    ]

    with_input_for @user, :tag_ids, :grouped_select,
      collection: tag_groups, group_method: :tags

    assert_select 'select.grouped_select#user_tag_ids' do
      assert_select 'optgroup[label="Group of Tags"]' do
        assert_select 'option[value="1"]', 'Tag 1'
        assert_select 'option[value="2"]', 'Tag 2'
      end

      assert_select 'optgroup[label="Other group"]' do
        assert_select 'option[value="3"]', 'Tag 3'
        assert_select 'option[value="4"]', 'Tag 4'
      end
    end
  end

  test 'grouped collection accepts html options as the last element of collection' do
    with_input_for @user, :tag_ids, :grouped_select,
      collection: [['Authors', [['Jose', 'jose', class: 'foo'], ['Carlos', 'carlos', class: 'bar']]]],
      group_method: :last

    assert_select 'select.grouped_select#user_tag_ids' do
      assert_select 'optgroup[label=Authors]' do
        assert_select 'option.foo', 'Jose'
        assert_select 'option.bar', 'Carlos'
      end
    end
  end
end