235 lines
4.7 KiB
Ruby
235 lines
4.7 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
require 'fast_spec_helper'
|
||
|
|
||
|
# Patching ActiveSupport::Concern
|
||
|
require_relative '../../../../config/initializers/0_as_concern'
|
||
|
|
||
|
describe Gitlab::Patch::Prependable do
|
||
|
before do
|
||
|
@prepended_modules = []
|
||
|
end
|
||
|
|
||
|
let(:ee) do
|
||
|
# So that block in Module.new could see them
|
||
|
prepended_modules = @prepended_modules
|
||
|
|
||
|
Module.new do
|
||
|
extend ActiveSupport::Concern
|
||
|
|
||
|
class_methods do
|
||
|
def class_name
|
||
|
super.tr('C', 'E')
|
||
|
end
|
||
|
end
|
||
|
|
||
|
this = self
|
||
|
prepended do
|
||
|
prepended_modules << [self, this]
|
||
|
end
|
||
|
|
||
|
def name
|
||
|
super.tr('c', 'e')
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
let(:ce) do
|
||
|
# So that block in Module.new could see them
|
||
|
prepended_modules = @prepended_modules
|
||
|
ee_ = ee
|
||
|
|
||
|
Module.new do
|
||
|
extend ActiveSupport::Concern
|
||
|
prepend ee_
|
||
|
|
||
|
class_methods do
|
||
|
def class_name
|
||
|
'CE'
|
||
|
end
|
||
|
end
|
||
|
|
||
|
this = self
|
||
|
prepended do
|
||
|
prepended_modules << [self, this]
|
||
|
end
|
||
|
|
||
|
def name
|
||
|
'ce'
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe 'a class including a concern prepending a concern' do
|
||
|
subject { Class.new.include(ce) }
|
||
|
|
||
|
it 'returns values from prepended module ee' do
|
||
|
expect(subject.new.name).to eq('ee')
|
||
|
expect(subject.class_name).to eq('EE')
|
||
|
end
|
||
|
|
||
|
it 'has the expected ancestors' do
|
||
|
expect(subject.ancestors.take(3)).to eq([subject, ee, ce])
|
||
|
expect(subject.singleton_class.ancestors.take(3))
|
||
|
.to eq([subject.singleton_class,
|
||
|
ee.const_get(:ClassMethods),
|
||
|
ce.const_get(:ClassMethods)])
|
||
|
end
|
||
|
|
||
|
it 'prepends only once even if called twice' do
|
||
|
2.times { ce.prepend(ee) }
|
||
|
|
||
|
subject
|
||
|
|
||
|
expect(@prepended_modules).to eq([[ce, ee]])
|
||
|
end
|
||
|
|
||
|
context 'overriding methods' do
|
||
|
before do
|
||
|
subject.module_eval do
|
||
|
def self.class_name
|
||
|
'Custom'
|
||
|
end
|
||
|
|
||
|
def name
|
||
|
'custom'
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
it 'returns values from the class' do
|
||
|
expect(subject.new.name).to eq('custom')
|
||
|
expect(subject.class_name).to eq('Custom')
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe 'a class prepending a concern prepending a concern' do
|
||
|
subject { Class.new.prepend(ce) }
|
||
|
|
||
|
it 'returns values from prepended module ee' do
|
||
|
expect(subject.new.name).to eq('ee')
|
||
|
expect(subject.class_name).to eq('EE')
|
||
|
end
|
||
|
|
||
|
it 'has the expected ancestors' do
|
||
|
expect(subject.ancestors.take(3)).to eq([ee, ce, subject])
|
||
|
expect(subject.singleton_class.ancestors.take(3))
|
||
|
.to eq([ee.const_get(:ClassMethods),
|
||
|
ce.const_get(:ClassMethods),
|
||
|
subject.singleton_class])
|
||
|
end
|
||
|
|
||
|
it 'prepends only once' do
|
||
|
subject.prepend(ce)
|
||
|
|
||
|
expect(@prepended_modules).to eq([[ce, ee], [subject, ce]])
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe 'a class prepending a concern' do
|
||
|
subject do
|
||
|
ee_ = ee
|
||
|
|
||
|
Class.new do
|
||
|
prepend ee_
|
||
|
|
||
|
def self.class_name
|
||
|
'CE'
|
||
|
end
|
||
|
|
||
|
def name
|
||
|
'ce'
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
it 'returns values from prepended module ee' do
|
||
|
expect(subject.new.name).to eq('ee')
|
||
|
expect(subject.class_name).to eq('EE')
|
||
|
end
|
||
|
|
||
|
it 'has the expected ancestors' do
|
||
|
expect(subject.ancestors.take(2)).to eq([ee, subject])
|
||
|
expect(subject.singleton_class.ancestors.take(2))
|
||
|
.to eq([ee.const_get(:ClassMethods),
|
||
|
subject.singleton_class])
|
||
|
end
|
||
|
|
||
|
it 'prepends only once' do
|
||
|
subject.prepend(ee)
|
||
|
|
||
|
expect(@prepended_modules).to eq([[subject, ee]])
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe 'simple case' do
|
||
|
subject do
|
||
|
foo_ = foo
|
||
|
|
||
|
Class.new do
|
||
|
prepend foo_
|
||
|
|
||
|
def value
|
||
|
10
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
let(:foo) do
|
||
|
Module.new do
|
||
|
extend ActiveSupport::Concern
|
||
|
|
||
|
prepended do
|
||
|
def self.class_value
|
||
|
20
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def value
|
||
|
super * 10
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context 'class methods' do
|
||
|
it "has a method" do
|
||
|
expect(subject).to respond_to(:class_value)
|
||
|
end
|
||
|
|
||
|
it 'can execute a method' do
|
||
|
expect(subject.class_value).to eq(20)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context 'instance methods' do
|
||
|
it "has a method" do
|
||
|
expect(subject.new).to respond_to(:value)
|
||
|
end
|
||
|
|
||
|
it 'chains a method execution' do
|
||
|
expect(subject.new.value).to eq(100)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context 'having two prepended blocks' do
|
||
|
subject do
|
||
|
Module.new do
|
||
|
extend ActiveSupport::Concern
|
||
|
|
||
|
prepended do
|
||
|
end
|
||
|
|
||
|
prepended do
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
it "raises an error" do
|
||
|
expect { subject }
|
||
|
.to raise_error(described_class::MultiplePrependedBlocks)
|
||
|
end
|
||
|
end
|
||
|
end
|