2018-12-05 23:21:45 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
require 'fast_spec_helper'
|
|
|
|
|
|
|
|
# Patching ActiveSupport::Concern
|
|
|
|
require_relative '../../../../config/initializers/0_as_concern'
|
|
|
|
|
2020-07-28 23:09:34 +05:30
|
|
|
RSpec.describe Gitlab::Patch::Prependable do
|
2018-12-05 23:21:45 +05:30
|
|
|
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,
|
2019-12-21 20:55:43 +05:30
|
|
|
ee.const_get(:ClassMethods, false),
|
|
|
|
ce.const_get(:ClassMethods, false)])
|
2018-12-05 23:21:45 +05:30
|
|
|
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))
|
2019-12-21 20:55:43 +05:30
|
|
|
.to eq([ee.const_get(:ClassMethods, false),
|
|
|
|
ce.const_get(:ClassMethods, false),
|
2018-12-05 23:21:45 +05:30
|
|
|
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))
|
2019-12-21 20:55:43 +05:30
|
|
|
.to eq([ee.const_get(:ClassMethods, false),
|
2018-12-05 23:21:45 +05:30
|
|
|
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
|
2021-03-11 19:13:27 +05:30
|
|
|
|
|
|
|
describe 'the extra hack for override verification' do
|
|
|
|
context 'when ENV["STATIC_VERIFICATION"] is not defined' do
|
|
|
|
it 'does not extend ClassMethods onto the defining module' do
|
|
|
|
expect(ee).not_to respond_to(:class_name)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when ENV["STATIC_VERIFICATION"] is defined' do
|
|
|
|
before do
|
|
|
|
stub_env('STATIC_VERIFICATION', 'true')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does extend ClassMethods onto the defining module' do
|
|
|
|
expect(ee).to respond_to(:class_name)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2018-12-05 23:21:45 +05:30
|
|
|
end
|