# 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
