require 'test_helper'

module ActionController
  class Base
    def render_to_string(opts = {})
      opts.to_s
    end

    def self.alias_method_chain(_target, _feature); end
  end
end

module ActionControllerMock
  class Base
    def render(_)
      [:base]
    end

    def render_to_string; end

    def self.after_action(_); end
  end
end

class PdfHelperTest < ActionController::TestCase
  module SomePatch
    def render(_)
      super.tap do |s|
        s << :patched
      end
    end
  end

  def setup
    @ac = ActionController::Base.new
  end

  def teardown
    @ac = nil
  end

  test 'should prerender header and footer :template options' do
    options = @ac.send(:prerender_header_and_footer,
                       :header => { :html => { :template => 'hf.html.erb' } })
    assert_match %r{^file:\/\/\/.*wicked_header_pdf.*\.html}, options[:header][:html][:url]
  end

  test 'should not interfere with already prepended patches' do
    # Emulate railtie
    if Rails::VERSION::MAJOR >= 5
      # this spec tests the following:
      # if another gem prepends a render method to ActionController::Base
      # before wicked_pdf does, does calling render trigger an infinite loop?
      # this spec fails with 6392bea1fe3a41682dfd7c20fd9c179b5a758f59 because PdfHelper
      # aliases the render method prepended by the other gem to render_without_pdf, then
      # base_evals its own definition of render, which calls render_with_pdf -> render_without_pdf.
      # If the other gem uses the prepend inhertinance pattern (calling super instead of aliasing),
      # when it calls super it calls the base_eval'd version of render instead of going up the
      # inheritance chain, causing an infinite loop.

      # This fiddling with consts is required to get around the fact that PdfHelper checks
      # that it is being prepended to ActionController::Base
      OriginalBase = ActionController::Base
      ActionController.send(:remove_const, :Base)
      ActionController.const_set(:Base, ActionControllerMock::Base)

      # Emulate another gem being loaded before wicked
      ActionController::Base.prepend(SomePatch)
      ActionController::Base.prepend(::WickedPdf::PdfHelper)

      begin
        # test that wicked's render method is actually called
        ac = ActionController::Base.new
        ac.expects(:render_with_wicked_pdf)
        ac.render(:cats)

        # test that calling render does not trigger infinite loop
        ac = ActionController::Base.new
        assert_equal %i[base patched], ac.render(:cats)
      rescue SystemStackError
        assert_equal true, false # force spec failure
      ensure
        ActionController.send(:remove_const, :Base)
        ActionController.const_set(:Base, OriginalBase)
      end
    end
  end

  test 'should call after_action instead of after_filter when able' do
    ActionController::Base.expects(:after_filter).with(:clean_temp_files).never
    ActionController::Base.expects(:after_action).with(:clean_temp_files).once
    ActionController::Base.class_eval do
      include ::WickedPdf::PdfHelper
    end
  end
end
