Back to Repositories

Testing SimpleForm Hint Generation and Internationalization in heartcombo/simple_form

This test suite validates the hint functionality in SimpleForm, focusing on HTML generation, i18n support, and custom wrapper configurations. It ensures proper hint rendering across different scenarios and localization requirements.

Test Coverage Overview

The test suite provides comprehensive coverage of SimpleForm’s hint functionality:
  • Default hint behavior and optional text handling
  • HTML attribute management and sanitization
  • Custom tag support and HTML options
  • i18n integration for model/attribute translations
  • Edge cases including nil objects and decorated models

Implementation Analysis

The testing approach employs ActionView::TestCase for form builder validation:
  • Helper method ‘with_hint_for’ encapsulates form generation
  • Assert_select matchers verify HTML output
  • Modular test organization by feature category
  • Integration with i18n translation system

Technical Details

Testing infrastructure includes:
  • Minitest framework with ActionView test helpers
  • Custom assertions for HTML validation
  • Translation store helpers for i18n testing
  • Wrapper configuration support

Best Practices Demonstrated

The test suite exemplifies robust testing practices:
  • Isolated test cases with clear purpose
  • Comprehensive edge case coverage
  • HTML safety and escaping verification
  • Clean test organization with descriptive names
  • Proper setup and teardown management

heartcombo/simple_form

test/form_builder/hint_test.rb

            
# frozen_string_literal: true
require 'test_helper'

# Tests for f.hint
class HintTest < ActionView::TestCase
  def with_hint_for(object, *args)
    with_concat_form_for(object) do |f|
      f.hint(*args)
    end
  end

  test 'hint does not be generated by default' do
    with_hint_for @user, :name
    assert_no_select 'span.hint'
  end

  test 'hint is generated with optional text' do
    with_hint_for @user, :name, hint: 'Use with care...'
    assert_select 'span.hint', 'Use with care...'
  end

  test 'hint is generated with decorated object responsive to #to_model' do
    with_hint_for @decorated_user, :name, hint: 'Use with care...'
    assert_select 'span.hint', 'Use with care...'
  end

  test 'hint does not modify the options hash' do
    options = { hint: 'Use with care...' }
    with_hint_for @user, :name, options
    assert_select 'span.hint', 'Use with care...'
    assert_equal({ hint: 'Use with care...' }, options)
  end

  test 'hint is generated cleanly with optional text' do
    with_hint_for @user, :name, hint: 'Use with care...', hint_tag: :span
    assert_no_select 'span.hint[hint]'
    assert_no_select 'span.hint[hint_tag]'
    assert_no_select 'span.hint[hint_html]'
  end

  test 'hint uses the current component tag set' do
    with_hint_for @user, :name, hint: 'Use with care...', hint_tag: :p
    assert_select 'p.hint', 'Use with care...'
  end

  test 'hint is able to pass html options' do
    with_hint_for @user, :name, hint: 'Yay!', id: 'hint', class: 'yay'
    assert_select 'span#hint.hint.yay'
  end

  test 'hint is output as html_safe' do
    with_hint_for @user, :name, hint: '<b>Bold</b> and not...'.html_safe
    assert_select 'span.hint', 'Bold and not...'
    assert_select 'span.hint b', 'Bold'
  end

  test 'builder escapes hint text' do
    with_hint_for @user, :name, hint: '<script>alert(1337)</script>'
    assert_no_select 'span.hint script'
  end

  # Without attribute name

  test 'hint without attribute name' do
    with_hint_for @validating_user, 'Hello World!'
    assert_select 'span.hint', 'Hello World!'
  end

  test 'hint without attribute name generates component tag with a clean HTML' do
    with_hint_for @validating_user, 'Hello World!'
    assert_no_select 'span.hint[hint]'
    assert_no_select 'span.hint[hint_html]'
  end

  test 'hint without attribute name uses the current component tag set' do
    with_hint_for @user, 'Hello World!', hint_tag: :p
    assert_no_select 'p.hint[hint]'
    assert_no_select 'p.hint[hint_html]'
    assert_no_select 'p.hint[hint_tag]'
  end

  test 'hint without attribute name is able to pass html options' do
    with_hint_for @user, 'Yay', id: 'hint', class: 'yay'
    assert_select 'span#hint.hint.yay', 'Yay'
  end

  # I18n

  test 'hint uses i18n based on model, action, and attribute to lookup translation' do
    store_translations(:en, simple_form: { hints: { user: {
      edit: { name: 'Content of this input will be truncated...' }
    } } }) do
      with_hint_for @user, :name
      assert_select 'span.hint', 'Content of this input will be truncated...'
    end
  end

  test 'hint uses i18n with model and attribute to lookup translation' do
    store_translations(:en, simple_form: { hints: { user: {
      name: 'Content of this input will be capitalized...'
    } } }) do
      with_hint_for @user, :name
      assert_select 'span.hint', 'Content of this input will be capitalized...'
    end
  end

  test 'hint uses i18n under defaults namespace to lookup translation' do
    store_translations(:en, simple_form: {
      hints: { defaults: { name: 'Content of this input will be downcased...' } }
    }) do
      with_hint_for @user, :name
      assert_select 'span.hint', 'Content of this input will be downcased...'
    end
  end

  test 'hint uses i18n with lookup for association name' do
    store_translations(:en, simple_form: { hints: {
      user: { company: 'My company!' }
    } } ) do
      with_hint_for @user, :company_id, as: :string, reflection: Association.new(Company, :company, {})
      assert_select 'span.hint', /My company!/
    end
  end

  test 'hint outputs translations as html_safe' do
    store_translations(:en, simple_form: { hints: { user: {
      edit: { name: '<b>This is bold</b> and this is not...' }
    } } }) do
      with_hint_for @user, :name
      assert_select 'span.hint', 'This is bold and this is not...'
    end
  end


  # No object

  test 'hint generates properly when object is not present' do
    with_hint_for :project, :name, hint: 'Test without object'
    assert_select 'span.hint', 'Test without object'
  end

  # Custom wrappers

  test 'hint with custom wrappers works' do
    swap_wrapper do
      with_hint_for @user, :name, hint: "cannot be blank"
      assert_select 'div.omg_hint', "cannot be blank"
    end
  end
end