summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorRobert Speicher <robert@gitlab.com>2018-09-14 17:38:29 +0000
committerRobert Speicher <robert@gitlab.com>2018-09-14 17:38:29 +0000
commit165e9a99c0363934e7676f3968e974af73c6cf95 (patch)
treeddeb4bbd45faaf3a8cd3efc8e28dd22c55a6f617 /spec
parent69925767b7ac49b59c0292608b6655edb117e31d (diff)
parentebe89e8bd259a848d737b33a793298220054a023 (diff)
downloadgitlab-ce-165e9a99c0363934e7676f3968e974af73c6cf95.tar.gz
Merge branch '50824-fix-prepend-concern' into 'master'
CE: Properly implement prepending for Concern See merge request gitlab-org/gitlab-ce!21444
Diffstat (limited to 'spec')
-rw-r--r--spec/lib/gitlab/patch/prependable_spec.rb234
-rw-r--r--spec/support/helpers/stub_configuration.rb3
2 files changed, 237 insertions, 0 deletions
diff --git a/spec/lib/gitlab/patch/prependable_spec.rb b/spec/lib/gitlab/patch/prependable_spec.rb
new file mode 100644
index 00000000000..725d733d176
--- /dev/null
+++ b/spec/lib/gitlab/patch/prependable_spec.rb
@@ -0,0 +1,234 @@
+# 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
diff --git a/spec/support/helpers/stub_configuration.rb b/spec/support/helpers/stub_configuration.rb
index 8475f91799b..776119564ec 100644
--- a/spec/support/helpers/stub_configuration.rb
+++ b/spec/support/helpers/stub_configuration.rb
@@ -1,5 +1,8 @@
require 'active_support/core_ext/hash/transform_values'
require 'active_support/hash_with_indifferent_access'
+require 'active_support/dependencies'
+
+require_dependency 'gitlab'
module StubConfiguration
def stub_application_setting(messages)