require "test_helper"
require "support/custom_assertions"
require "support/crud_test_model"

# Test TableHelper
class TableHelperTest < ActionView::TestCase
  include UtilityHelper
  include FormatHelper
  include I18nHelper
  include CustomAssertions
  include CrudTestHelper

  attr_accessor :params

  setup :reset_db, :setup_db, :create_test_data, :empty_params
  teardown :reset_db

  attr_reader :entries

  def format_size(obj)
    "#{f(obj.size)} items"
  end

  def format_string_size(obj)
    "#{f(obj.size)} chars"
  end

  def empty_params
    @params = {}
  end

  test "empty table renders message" do
    result = plain_table_or_message([])
    assert result.html_safe?
    assert_match(/<div class=["']table["']>.*<\/div>/, result)
  end

  test "non empty table renders table" do
    result = plain_table_or_message(%w[foo bar]) do |t|
      t.attrs :size, :upcase
    end
    assert result.html_safe?
    assert_match(/^<table.*<\/table>$/, result)
  end

  test "table with attrs" do
    expected = DryCrud::Table::Builder.table(
      %w[foo bar], self,
      class: "table table-striped table-hover"
    ) do |t|
      t.attrs :size, :upcase
    end
    actual = plain_table(%w[foo bar], :size, :upcase)
    assert actual.html_safe?
    assert_equal expected, actual
  end

  test "standard list table" do
    @entries = CrudTestModel.all

    table = with_test_routing do
      list_table
    end

    assert_count 7, REGEXP_ROWS, table
    assert_count 14, REGEXP_SORT_HEADERS, table
  end

  test "custom list table with attributes" do
    @entries = CrudTestModel.all

    table = with_test_routing do
      list_table :name, :children, :companion_id
    end

    assert_count 7, REGEXP_ROWS, table
    assert_count 3, REGEXP_SORT_HEADERS, table
  end

  test "custom list table with block" do
    @entries = CrudTestModel.all

    table = with_test_routing do
      list_table do |t|
        t.attrs :name, :children, :companion_id
        t.col("head") { |e| tag.span(e.income.to_s) }
      end
    end

    assert_count 7, REGEXP_ROWS, table
    assert_count 4, REGEXP_HEADERS, table
    assert_count 0, REGEXP_SORT_HEADERS, table
    assert_count 6, /<span>.+?<\/span>/, table
  end

  test "custom list table with attributes and block" do
    @entries = CrudTestModel.all

    table = with_test_routing do
      list_table :name, :children, :companion_id do |t|
        t.col("head") { |e| tag.span(e.income.to_s) }
      end
    end

    assert_count 7, REGEXP_ROWS, table
    assert_count 3, REGEXP_SORT_HEADERS, table
    assert_count 4, REGEXP_HEADERS, table
    assert_count 6, /<span>.+?<\/span>/, table
  end

  test "standard list table with ascending sort params" do
    @params = { sort: "children", sort_dir: "asc" }
    @entries = CrudTestModel.all

    table = with_test_routing do
      list_table
    end

    sort_header_desc = %r{<th><a .*?sort_dir=desc.*?>Children</a> &darr;</th>}
    assert_count 7, REGEXP_ROWS, table
    assert_count 13, REGEXP_SORT_HEADERS, table
    assert_count 1, sort_header_desc, table
  end

  test "standard list table with descending sort params" do
    @params = { sort: "children", sort_dir: "desc" }
    @entries = CrudTestModel.all

    table = with_test_routing do
      list_table
    end

    sort_header_asc = %r{<th><a .*?sort_dir=asc.*?>Children</a> &uarr;</th>}
    assert_count 7, REGEXP_ROWS, table
    assert_count 13, REGEXP_SORT_HEADERS, table
    assert_count 1, sort_header_asc, table
  end

  test "list table with custom column sort params" do
    @params = { sort: "chatty", sort_dir: "asc" }
    @entries = CrudTestModel.all

    table = with_test_routing do
      list_table :name, :children, :chatty
    end

    sort_header_desc = %r{<th><a .*?sort_dir=desc.*?>Chatty</a> &darr;</th>}
    assert_count 7, REGEXP_ROWS, table
    assert_count 2, REGEXP_SORT_HEADERS, table
    assert_count 1, sort_header_desc, table
  end

  test "standard crud table" do
    @entries = CrudTestModel.all

    table = with_test_routing do
      crud_table
    end

    assert_count 7, REGEXP_ROWS, table
    assert_count 14, REGEXP_SORT_HEADERS, table
    assert_count 12, REGEXP_ACTION_CELL, table      # edit, delete links
  end

  test "custom crud table with attributes" do
    @entries = CrudTestModel.all

    table = with_test_routing do
      crud_table :name, :children, :companion_id
    end

    assert_count 7, REGEXP_ROWS, table
    assert_count 3, REGEXP_SORT_HEADERS, table
    assert_count 12, REGEXP_ACTION_CELL, table      # edit, delete links
  end

  test "custom crud table with block" do
    @entries = CrudTestModel.all

    table = with_test_routing do
      crud_table do |t|
        t.attrs :name, :children, :companion_id
        t.col("head") { |e| tag.span(e.income.to_s) }
      end
    end

    assert_count 7, REGEXP_ROWS, table
    assert_count 6, REGEXP_HEADERS, table
    assert_count 6, /<span>.+?<\/span>/m, table
    assert_count 12, REGEXP_ACTION_CELL, table      # edit, delete links
  end

  test "custom crud table with attributes and block" do
    @entries = CrudTestModel.all

    table = with_test_routing do
      crud_table :name, :children, :companion_id do |t|
        t.col("head") { |e| tag.span(e.income.to_s) }
      end
    end

    assert_count 7, REGEXP_ROWS, table
    assert_count 3, REGEXP_SORT_HEADERS, table
    assert_count 6, REGEXP_HEADERS, table
    assert_count 6, /<span>.+?<\/span>/m, table
    assert_count 12, REGEXP_ACTION_CELL, table      # edit, delete links
  end

  def entry
    @entry ||= CrudTestModel.first
  end
end
