# coding: utf-8
require 'htmlbeautifier'
module TableBuilderHelper
  include Pundit
end
describe TableBuilderHelper, type: :helper do
  let(:features){ [] }
  before do
    allow_any_instance_of(AF83::Decorator::Link).to receive(:check_feature){|f|
      features.include?(f)
    }
  end
  describe "#table_builder_2" do
    it "builds a table" do
      referential = create(:workbench_referential)
      workbench = referential.workbench
      referential.organisation.workbenches << workbench
      user_context = UserContext.new(
        build_stubbed(
          :user,
          organisation: referential.organisation,
          permissions: [
            'referentials.create',
            'referentials.update',
            'referentials.destroy',
          ]
        ),
        referential: referential
      )
      allow(helper).to receive(:pundit_user).and_return(user_context)
      allow(helper).to receive(:current_user).and_return(user_context.user)
      referentials = [referential]
      allow(referentials).to receive(:model).and_return(Referential)
      stub_policy_scope(referential)
      allow(helper).to receive(:params).and_return({
        controller: 'workbenches',
        action: 'show',
        id: referentials[0].workbench.id
      })
      referentials = ReferentialDecorator.decorate(
        referentials
      )
      expected = <<-HTML
      HTML
      html_str = helper.table_builder_2(
        referentials,
        [
          TableBuilderHelper::Column.new(
            key: :name,
            attribute: 'name',
            link_to: lambda do |referential|
              referential_path(referential)
            end
          ),
          TableBuilderHelper::Column.new(
            key: :status,
            attribute: Proc.new do |w|
              if w.referential_read_only?
                ("Conservé
").html_safe
              else
                ("En préparation
").html_safe
              end
            end
          ),
          TableBuilderHelper::Column.new(
            key: :organisation,
            attribute: Proc.new {|w| w.organisation.name}
          ),
          TableBuilderHelper::Column.new(
            key: :validity_period,
            attribute: Proc.new do |w|
              if w.validity_period.nil?
                '-'
              else
                t(
                  'validity_range',
                  debut: l(w.try(:validity_period).try(:begin), format: :short),
                  end: l(w.try(:validity_period).try(:end), format: :short)
                )
              end
            end
          ),
          TableBuilderHelper::Column.new(
            key: :lines,
            attribute: Proc.new {|w| w.lines.count}
          ),
          TableBuilderHelper::Column.new(
            key: :created_at,
            attribute: Proc.new {|w| l(w.created_at, format: :short)}
          ),
          TableBuilderHelper::Column.new(
            key: :updated_at,
            attribute: Proc.new {|w| l(w.updated_at, format: :short)}
          ),
          TableBuilderHelper::Column.new(
            key: :merged_at,
            attribute: ''
          )
        ],
        selectable: true,
        action: :index,
        cls: 'table has-filter has-search'
      )
      beautified_html = HtmlBeautifier.beautify(html_str, indent: '    ')
      expect(beautified_html).to eq(expected.chomp)
    end
    it "can set a column as non-sortable" do
      company = build_stubbed(:company)
      line_referential = build_stubbed(
        :line_referential,
        companies: [company]
      )
      referential = build_stubbed(
        :referential,
        line_referential: line_referential
      )
      user_context = UserContext.new(
        build_stubbed(
          :user,
          organisation: referential.organisation,
          permissions: [
            'referentials.create',
            'referentials.edit',
            'referentials.destroy'
          ]
        ),
        referential: referential
      )
      allow(helper).to receive(:pundit_user).and_return(user_context)
      allow(helper).to receive(:current_user).and_return(user_context.user)
      allow(helper).to receive(:current_referential)
        .and_return(referential)
      companies = [company]
      allow(companies).to receive(:model).and_return(Chouette::Company)
      allow(helper).to receive(:params).and_return({
        controller: 'referential_companies',
        action: 'index',
        referential_id: referential.id
      })
      companies = CompanyDecorator.decorate(
        companies,
        context: { referential: referential }
      )
      stub_policy_scope(company)
      expected = <<-HTML
      HTML
      html_str = helper.table_builder_2(
        companies,
        [
          TableBuilderHelper::Column.new(
            name: 'ID Codif',
            attribute: Proc.new { |n| n.try(:get_objectid).try(:local_id) },
            sortable: false
          ),
          TableBuilderHelper::Column.new(
            key: :name,
            attribute: 'name',
            link_to: lambda do |company|
              referential_company_path(referential, company)
            end
          ),
          TableBuilderHelper::Column.new(
            key: :phone,
            attribute: 'phone'
          ),
          TableBuilderHelper::Column.new(
            key: :email,
            attribute: 'email'
          ),
          TableBuilderHelper::Column.new(
            key: :url,
            attribute: 'url'
          ),
        ],
        links: [:show, :edit, :delete],
        cls: 'table has-search'
      )
      beautified_html = HtmlBeautifier.beautify(html_str, indent: '    ')
      expect(beautified_html).to eq(expected.chomp)
    end
    it "can set all columns as non-sortable" do
      company = build_stubbed(:company)
      line_referential = build_stubbed(
        :line_referential,
        companies: [company]
      )
      referential = build_stubbed(
        :referential,
        line_referential: line_referential
      )
      user_context = UserContext.new(
        build_stubbed(
          :user,
          organisation: referential.organisation,
          permissions: [
            'referentials.create',
            'referentials.edit',
            'referentials.destroy'
          ]
        ),
        referential: referential
      )
      allow(helper).to receive(:pundit_user).and_return(user_context)
      allow(helper).to receive(:current_user).and_return(user_context.user)
      allow(helper).to receive(:current_referential)
        .and_return(referential)
      companies = [company]
      allow(companies).to receive(:model).and_return(Chouette::Company)
      allow(helper).to receive(:params).and_return({
        controller: 'referential_companies',
        action: 'index',
        referential_id: referential.id
      })
      companies = CompanyDecorator.decorate(
        companies,
        context: { referential: line_referential }
      )
      stub_policy_scope(company)
      expected = <<-HTML
    
        
            | ID Codif | Nom | Numéro de téléphone | Email | Page web associée |  | 
    
    
        
            | #{company.get_objectid.local_id} | #{company.name} |  |  |  |  | 
    
      HTML
      html_str = helper.table_builder_2(
        companies,
        [
          TableBuilderHelper::Column.new(
            name: 'ID Codif',
            attribute: Proc.new { |n| n.try(:get_objectid).try(:local_id) }
          ),
          TableBuilderHelper::Column.new(
            key: :name,
            attribute: 'name',
            link_to: lambda do |company|
              referential_company_path(referential, company)
            end
          ),
          TableBuilderHelper::Column.new(
            key: :phone,
            attribute: 'phone'
          ),
          TableBuilderHelper::Column.new(
            key: :email,
            attribute: 'email'
          ),
          TableBuilderHelper::Column.new(
            key: :url,
            attribute: 'url'
          ),
        ],
        sortable: false,
        cls: 'table has-search'
      )
      beautified_html = HtmlBeautifier.beautify(html_str, indent: '    ')
      expect(beautified_html).to eq(expected.chomp)
    end
    context "on a single row" do
      let(:referential){ build_stubbed :workbench_referential }
      let(:other_referential){ build_stubbed :workbench_referential }
      let(:user_context){
        UserContext.new(
          build_stubbed(
            :user,
            organisation: referential.organisation,
            permissions: [
              'referentials.create',
              'referentials.update',
              'referentials.destroy',
            ]
          ),
          referential: referential
        )
      }
      let(:columns){
        [
          TableBuilderHelper::Column.new(
            key: :name,
            attribute: 'name'
          ),
        ]
      }
      let(:item){ referential.decorate }
      let(:other_item){ other_referential.decorate }
      let(:selectable){ false }
      let(:links){ [:show] }
      let(:overhead){ [] }
      let(:model_name){ "referential" }
      let(:other_tr){ helper.send(:tr, other_item, columns, selectable, links, overhead, model_name) }
      let(:items){ [item, other_item] }
      before(:each){
        allow(helper).to receive(:pundit_user).and_return(user_context)
        allow(helper).to receive(:current_user).and_return(user_context.user)
        allow(helper).to receive(:mutual_workbench).and_return(referential.workbench)
      }
      context "with a condition" do
        let(:columns){
          [
            TableBuilderHelper::Column.new(
              key: :name,
              attribute: 'name',
              if: condition
            ),
          ]
        }
        context "when the condition is true" do
          let(:condition){ ->(obj){true} }
          it "should show the value" do
            items.each do |i|
              tr = helper.send(:tr, i, columns, selectable, links, overhead, model_name, :index)
              klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{i.id}"
              expect(tr).to include(i.name)
            end
          end
        end
        context "when the condition depends on the object" do
          let(:condition){ ->(obj){ obj == referential } }
          it "should show the value accordingly" do
            tr = helper.send(:tr, item, columns, selectable, links, overhead, model_name, :index)
            klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{referential.id}"
            expect(tr).to include(referential.name)
            tr = helper.send(:tr, other_item, columns, selectable, links, overhead, model_name, :index)
            klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{other_referential.id}"
            expect(tr).to_not include(other_referential.name)
          end
        end
        context "when the condition is false" do
          let(:condition){ ->(obj){false} }
          it "should not show the value" do
            items.each do |i|
              tr = helper.send(:tr, i, columns, selectable, links, overhead, model_name, :index)
              klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{i.id}"
              expect(tr).to_not include(i.name)
            end
          end
        end
      end
      context "with all rows non-selectable" do
        let(:selectable){ false }
        it "sets all rows as non selectable" do
          items.each do |i|
            tr = helper.send(:tr, i, columns, selectable, links, overhead, model_name, :index)
            klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{i.id}"
            selector = "tr.#{klass} [type=checkbox]"
            expect(tr).to_not have_selector selector
          end
        end
      end
      context "with all rows selectable" do
        let(:selectable){ true }
        it "adds a checkbox in all rows" do
          items.each do |i|
            tr = helper.send(:tr, i, columns, selectable, links, overhead, model_name, :index)
            klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{i.id}"
            selector = "tr.#{klass} [type=checkbox]"
            expect(tr).to have_selector selector
          end
        end
      end
      context "with THIS row non selectable" do
        let(:selectable){ ->(i){ i.id != item.id } }
        it "adds a checkbox in all rows" do
          items.each do |i|
            tr = helper.send(:tr, i, columns, selectable, links, overhead, model_name, :index)
            klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{i.id}"
            selector = "tr.#{klass} [type=checkbox]"
            expect(tr).to have_selector selector
          end
        end
        it "disables this rows checkbox" do
          tr = helper.send(:tr, item, columns, selectable, links, overhead, model_name, :index)
          klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{item.id}"
          selector = "tr.#{klass} [type=checkbox][disabled]"
          expect(tr).to have_selector selector
        end
      end
    end
  end
end