require 'spec_helper' describe Deface::ActionViewExtensions do include_context "mock Rails.application" before supports_updated_at: true do skip "Current Rails doesn't support the updated_at attribute on ActionView" unless supports_updated_at? end let(:template) { ActionView::Template.new( source, path, handler, **options, **(supports_updated_at? ? {updated_at: updated_at} : {}) ) } let(:source) { "

test

" } let(:path) { "/some/path/to/file.erb" } let(:handler) { ActionView::Template::Handlers::ERB } let(:options) {{ virtual_path: virtual_path, format: format, locals: {} }} let(:format) { :html } let(:virtual_path) { "posts/index" } let(:supports_updated_at?) { Deface.before_rails_6? } let(:updated_at) { Time.now - 600 } describe "with no overrides defined" do it "should initialize new template object" do expect(template.is_a?(ActionView::Template)).to eq(true) end it "should return unmodified source" do expect(template.source).to eq("

test

") end it "should not change updated_at", :supports_updated_at do expect(template.updated_at).to eq(updated_at) end end describe "with a single remove override defined" do let(:updated_at) { Time.now - 300 } let(:source) { "

test

<%= raw(text) %>" } before do Deface::Override.new(virtual_path: "posts/index", name: "Posts#index", remove: "p", text: "

Argh!

") end it "should return modified source" do expect(template.source).to eq("<%= raw(text) %>") end it "should change updated_at", :supports_updated_at do expect(template.updated_at).to be > updated_at end end describe "#method_name" do before do ActionView::Template.define_method( :method_name_without_deface, ActionView::Template.instance_method(:method_name) ) end it "returns hash of overrides plus original method_name " do deface_hash = Deface::Override.digest(virtual_path: 'posts/index') super_method = template.method(:method_name).super_method method_name = "_#{Digest::MD5.new.update("#{deface_hash}_#{super_method.call}").hexdigest}" expect(template.send(:method_name)).to eq(method_name) end end describe "non erb or haml template" do let(:source) { "xml.post => :blah" } let(:path) { "/some/path/to/file.erb" } let(:handler) { ActionView::Template::Handlers::Builder } let(:updated_at) { Time.now - 100 } let(:format) { :xml } before(:each) do Deface::Override.new(virtual_path: "posts/index", name: "Posts#index", remove: "p") end it "should return unmodified source" do expect(template.source).to eq("xml.post => :blah") expect(template.source).not_to include("=>") end end describe ".determine_syntax(handler)" do let(:source) { "xml.post => :blah" } let(:format) { :xml } # Not so BDD, but it keeps us from making mistakes in the future for instance, # we test ActionView::Template here with a handler == ....::Handlers::ERB, # while in rails it seems it's an instance of ...::Handlers::ERB. it "recognizes supported syntaxes" do expectations = { Haml::Plugin => :haml, ActionView::Template::Handlers::ERB => :erb, ActionView::Template::Handlers::ERB.new => :erb, ActionView::Template::Handlers::Builder => nil } expectations.each do |handler, expected| expect(template.is_a?(ActionView::Template)).to eq(true) expect(described_class.determine_syntax(handler)).to eq(expected), "unexpected result for handler #{handler}" end end end describe '#render' do let(:source) { "

test

<%= raw(text) %>".inspect } let(:local_assigns) { {text: "some
text"} } let(:lookup_context) { ActionView::LookupContext.new(["#{__dir__}/views"]) } let(:view) do if Rails::VERSION::STRING >= '6.1' ActionView::Base.with_empty_template_cache.new(lookup_context, {}, nil) else ActionView::Base.new(lookup_context) end end let(:options) { { virtual_path: virtual_path, format: format, locals: local_assigns.keys } } let!(:deface) { Deface::Override.new( virtual_path: virtual_path, name: "Posts#index", replace: "p", text: "

Argh!

" ) } it 'renders the template modified by deface' do expect(template.render(view, local_assigns)).to eq(%{"

Argh!

some
text"}) end end end