diff options
Diffstat (limited to 'spec/models')
-rw-r--r-- | spec/models/ci/pipeline_spec.rb | 24 | ||||
-rw-r--r-- | spec/models/clusters/applications/helm_spec.rb | 14 | ||||
-rw-r--r-- | spec/models/clusters/applications/ingress_spec.rb | 9 | ||||
-rw-r--r-- | spec/models/clusters/applications/jupyter_spec.rb | 9 | ||||
-rw-r--r-- | spec/models/clusters/applications/prometheus_spec.rb | 35 | ||||
-rw-r--r-- | spec/models/clusters/applications/runner_spec.rb | 9 | ||||
-rw-r--r-- | spec/models/clusters/cluster_spec.rb | 4 | ||||
-rw-r--r-- | spec/models/clusters/platforms/kubernetes_spec.rb | 24 | ||||
-rw-r--r-- | spec/models/concerns/avatarable_spec.rb | 20 | ||||
-rw-r--r-- | spec/models/concerns/case_sensitivity_spec.rb | 202 | ||||
-rw-r--r-- | spec/models/concerns/triggerable_hooks_spec.rb | 24 | ||||
-rw-r--r-- | spec/models/hooks/active_hook_filter_spec.rb | 68 | ||||
-rw-r--r-- | spec/models/hooks/web_hook_spec.rb | 20 | ||||
-rw-r--r-- | spec/models/project_spec.rb | 40 | ||||
-rw-r--r-- | spec/models/user_spec.rb | 17 |
15 files changed, 324 insertions, 195 deletions
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 77b7332a761..14ccc2960bb 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -1941,4 +1941,28 @@ describe Ci::Pipeline, :mailer do expect(pipeline.total_size).to eq(5) end end + + describe '#status' do + context 'when transitioning to failed' do + context 'when pipeline has autodevops as source' do + let(:pipeline) { create(:ci_pipeline, :running, :auto_devops_source) } + + it 'calls autodevops disable service' do + expect(AutoDevops::DisableWorker).to receive(:perform_async).with(pipeline.id) + + pipeline.drop + end + end + + context 'when pipeline has other source' do + let(:pipeline) { create(:ci_pipeline, :running, :repository_source) } + + it 'does not call auto devops disable service' do + expect(AutoDevops::DisableWorker).not_to receive(:perform_async) + + pipeline.drop + end + end + end + end end diff --git a/spec/models/clusters/applications/helm_spec.rb b/spec/models/clusters/applications/helm_spec.rb index e5b2bdc8a4e..2c37cd20ecc 100644 --- a/spec/models/clusters/applications/helm_spec.rb +++ b/spec/models/clusters/applications/helm_spec.rb @@ -47,5 +47,19 @@ describe Clusters::Applications::Helm do cert = OpenSSL::X509::Certificate.new(subject.files[:'cert.pem']) expect(cert.not_after).to be > 999.years.from_now end + + describe 'rbac' do + context 'non rbac cluster' do + it { expect(subject).not_to be_rbac } + end + + context 'rbac cluster' do + before do + helm.cluster.platform_kubernetes.rbac! + end + + it { expect(subject).to be_rbac } + end + end end end diff --git a/spec/models/clusters/applications/ingress_spec.rb b/spec/models/clusters/applications/ingress_spec.rb index 21f75ced8c3..c55953c8d22 100644 --- a/spec/models/clusters/applications/ingress_spec.rb +++ b/spec/models/clusters/applications/ingress_spec.rb @@ -88,9 +88,18 @@ describe Clusters::Applications::Ingress do expect(subject.name).to eq('ingress') expect(subject.chart).to eq('stable/nginx-ingress') expect(subject.version).to eq('0.23.0') + expect(subject).not_to be_rbac expect(subject.files).to eq(ingress.files) end + context 'on a rbac enabled cluster' do + before do + ingress.cluster.platform_kubernetes.rbac! + end + + it { is_expected.to be_rbac } + end + context 'application failed to install previously' do let(:ingress) { create(:clusters_applications_ingress, :errored, version: 'nginx') } diff --git a/spec/models/clusters/applications/jupyter_spec.rb b/spec/models/clusters/applications/jupyter_spec.rb index 027b732681b..591a01d78a9 100644 --- a/spec/models/clusters/applications/jupyter_spec.rb +++ b/spec/models/clusters/applications/jupyter_spec.rb @@ -51,10 +51,19 @@ describe Clusters::Applications::Jupyter do expect(subject.name).to eq('jupyter') expect(subject.chart).to eq('jupyter/jupyterhub') expect(subject.version).to eq('v0.6') + expect(subject).not_to be_rbac expect(subject.repository).to eq('https://jupyterhub.github.io/helm-chart/') expect(subject.files).to eq(jupyter.files) end + context 'on a rbac enabled cluster' do + before do + jupyter.cluster.platform_kubernetes.rbac! + end + + it { is_expected.to be_rbac } + end + context 'application failed to install previously' do let(:jupyter) { create(:clusters_applications_jupyter, :errored, version: '0.0.1') } diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb index 26b75c75e1d..f34b4ece8db 100644 --- a/spec/models/clusters/applications/prometheus_spec.rb +++ b/spec/models/clusters/applications/prometheus_spec.rb @@ -1,6 +1,8 @@ require 'rails_helper' describe Clusters::Applications::Prometheus do + include KubernetesHelpers + include_examples 'cluster application core specs', :clusters_applications_prometheus include_examples 'cluster application status specs', :cluster_application_prometheus @@ -107,26 +109,14 @@ describe Clusters::Applications::Prometheus do end context 'cluster has kubeclient' do - let(:kubernetes_url) { 'http://example.com' } - let(:k8s_discover_response) do - { - resources: [ - { - name: 'service', - kind: 'Service' - } - ] - } - end - - let(:kube_client) { Kubeclient::Client.new(kubernetes_url) } + let(:kubernetes_url) { subject.cluster.platform_kubernetes.api_url } + let(:kube_client) { subject.cluster.kubeclient.core_client } - let(:cluster) { create(:cluster) } - subject { create(:clusters_applications_prometheus, cluster: cluster) } + subject { create(:clusters_applications_prometheus) } before do - allow(kube_client.rest_client).to receive(:get).and_return(k8s_discover_response.to_json) - allow(subject.cluster).to receive(:kubeclient).and_return(kube_client) + subject.cluster.platform_kubernetes.namespace = 'a-namespace' + stub_kubeclient_discover(subject.cluster.platform_kubernetes.api_url) end it 'creates proxy prometheus rest client' do @@ -134,7 +124,7 @@ describe Clusters::Applications::Prometheus do end it 'creates proper url' do - expect(subject.prometheus_client.url).to eq('http://example.com/api/v1/namespaces/gitlab-managed-apps/service/prometheus-prometheus-server:80/proxy') + expect(subject.prometheus_client.url).to eq("#{kubernetes_url}/api/v1/namespaces/gitlab-managed-apps/services/prometheus-prometheus-server:80/proxy") end it 'copies options and headers from kube client to proxy client' do @@ -164,9 +154,18 @@ describe Clusters::Applications::Prometheus do expect(subject.name).to eq('prometheus') expect(subject.chart).to eq('stable/prometheus') expect(subject.version).to eq('6.7.3') + expect(subject).not_to be_rbac expect(subject.files).to eq(prometheus.files) end + context 'on a rbac enabled cluster' do + before do + prometheus.cluster.platform_kubernetes.rbac! + end + + it { is_expected.to be_rbac } + end + context 'application failed to install previously' do let(:prometheus) { create(:clusters_applications_prometheus, :errored, version: '2.0.0') } diff --git a/spec/models/clusters/applications/runner_spec.rb b/spec/models/clusters/applications/runner_spec.rb index d84f125e246..eda8d519f60 100644 --- a/spec/models/clusters/applications/runner_spec.rb +++ b/spec/models/clusters/applications/runner_spec.rb @@ -46,10 +46,19 @@ describe Clusters::Applications::Runner do expect(subject.name).to eq('runner') expect(subject.chart).to eq('runner/gitlab-runner') expect(subject.version).to eq('0.1.31') + expect(subject).not_to be_rbac expect(subject.repository).to eq('https://charts.gitlab.io') expect(subject.files).to eq(gitlab_runner.files) end + context 'on a rbac enabled cluster' do + before do + gitlab_runner.cluster.platform_kubernetes.rbac! + end + + it { is_expected.to be_rbac } + end + context 'application failed to install previously' do let(:gitlab_runner) { create(:clusters_applications_runner, :errored, runner: ci_runner, version: '0.1.13') } diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb index 6f66515b45f..2727191eb9b 100644 --- a/spec/models/clusters/cluster_spec.rb +++ b/spec/models/clusters/cluster_spec.rb @@ -13,6 +13,10 @@ describe Clusters::Cluster do it { is_expected.to delegate_method(:status_reason).to(:provider) } it { is_expected.to delegate_method(:status_name).to(:provider) } it { is_expected.to delegate_method(:on_creation?).to(:provider) } + it { is_expected.to delegate_method(:active?).to(:platform_kubernetes).with_prefix } + it { is_expected.to delegate_method(:rbac?).to(:platform_kubernetes).with_prefix } + it { is_expected.to delegate_method(:installed?).to(:application_helm).with_prefix } + it { is_expected.to delegate_method(:installed?).to(:application_ingress).with_prefix } it { is_expected.to respond_to :project } describe '.enabled' do diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb index ab7f89f9bf4..66198d5ee2b 100644 --- a/spec/models/clusters/platforms/kubernetes_spec.rb +++ b/spec/models/clusters/platforms/kubernetes_spec.rb @@ -92,6 +92,30 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching end end + describe '#kubeclient' do + subject { kubernetes.kubeclient } + + let(:kubernetes) { build(:cluster_platform_kubernetes, :configured, namespace: 'a-namespace') } + + it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::KubeClient) } + end + + describe '#rbac?' do + subject { kubernetes.rbac? } + + let(:kubernetes) { build(:cluster_platform_kubernetes, :configured) } + + context 'when authorization type is rbac' do + let(:kubernetes) { build(:cluster_platform_kubernetes, :rbac_enabled, :configured) } + + it { is_expected.to be_truthy } + end + + context 'when authorization type is nil' do + it { is_expected.to be_falsey } + end + end + describe '#actual_namespace' do subject { kubernetes.actual_namespace } diff --git a/spec/models/concerns/avatarable_spec.rb b/spec/models/concerns/avatarable_spec.rb index 76f734079b7..7d617cb7b19 100644 --- a/spec/models/concerns/avatarable_spec.rb +++ b/spec/models/concerns/avatarable_spec.rb @@ -12,6 +12,26 @@ describe Avatarable do stub_config_setting(relative_url_root: relative_url_root) end + describe '#update' do + let(:validator) { project._validators[:avatar].detect { |v| v.is_a?(FileSizeValidator) } } + + context 'when avatar changed' do + it 'validates the file size' do + expect(validator).to receive(:validate_each).and_call_original + + project.update(avatar: 'uploads/avatar.png') + end + end + + context 'when avatar was not changed' do + it 'skips validation of file size' do + expect(validator).not_to receive(:validate_each) + + project.update(name: 'Hello world') + end + end + end + describe '#avatar_path' do using RSpec::Parameterized::TableSyntax diff --git a/spec/models/concerns/case_sensitivity_spec.rb b/spec/models/concerns/case_sensitivity_spec.rb index 5c0dfaeb4d3..1bf6c9b3404 100644 --- a/spec/models/concerns/case_sensitivity_spec.rb +++ b/spec/models/concerns/case_sensitivity_spec.rb @@ -3,186 +3,50 @@ require 'spec_helper' describe CaseSensitivity do describe '.iwhere' do let(:connection) { ActiveRecord::Base.connection } - let(:model) { Class.new { include CaseSensitivity } } - - describe 'using PostgreSQL' do - before do - allow(Gitlab::Database).to receive(:postgresql?).and_return(true) - allow(Gitlab::Database).to receive(:mysql?).and_return(false) - end - - describe 'with a single column/value pair' do - it 'returns the criteria for a column and a value' do - criteria = double(:criteria) - - expect(connection).to receive(:quote_table_name) - .with(:foo) - .and_return('"foo"') - - expect(model).to receive(:where) - .with(%q{LOWER("foo") = LOWER(:value)}, value: 'bar') - .and_return(criteria) - - expect(model.iwhere(foo: 'bar')).to eq(criteria) - end - - it 'returns the criteria for a column with a table, and a value' do - criteria = double(:criteria) - - expect(connection).to receive(:quote_table_name) - .with(:'foo.bar') - .and_return('"foo"."bar"') - - expect(model).to receive(:where) - .with(%q{LOWER("foo"."bar") = LOWER(:value)}, value: 'bar') - .and_return(criteria) - - expect(model.iwhere('foo.bar'.to_sym => 'bar')).to eq(criteria) - end - end - - describe 'with multiple column/value pairs' do - it 'returns the criteria for a column and a value' do - initial = double(:criteria) - final = double(:criteria) - - expect(connection).to receive(:quote_table_name) - .with(:foo) - .and_return('"foo"') - - expect(connection).to receive(:quote_table_name) - .with(:bar) - .and_return('"bar"') - - expect(model).to receive(:where) - .with(%q{LOWER("foo") = LOWER(:value)}, value: 'bar') - .and_return(initial) - - expect(initial).to receive(:where) - .with(%q{LOWER("bar") = LOWER(:value)}, value: 'baz') - .and_return(final) - - got = model.iwhere(foo: 'bar', bar: 'baz') - - expect(got).to eq(final) - end - - it 'returns the criteria for a column with a table, and a value' do - initial = double(:criteria) - final = double(:criteria) - - expect(connection).to receive(:quote_table_name) - .with(:'foo.bar') - .and_return('"foo"."bar"') - - expect(connection).to receive(:quote_table_name) - .with(:'foo.baz') - .and_return('"foo"."baz"') - - expect(model).to receive(:where) - .with(%q{LOWER("foo"."bar") = LOWER(:value)}, value: 'bar') - .and_return(initial) - - expect(initial).to receive(:where) - .with(%q{LOWER("foo"."baz") = LOWER(:value)}, value: 'baz') - .and_return(final) - - got = model.iwhere('foo.bar'.to_sym => 'bar', - 'foo.baz'.to_sym => 'baz') - - expect(got).to eq(final) - end + let(:model) do + Class.new(ActiveRecord::Base) do + include CaseSensitivity + self.table_name = 'namespaces' end end - describe 'using MySQL' do - before do - allow(Gitlab::Database).to receive(:postgresql?).and_return(false) - allow(Gitlab::Database).to receive(:mysql?).and_return(true) - end - - describe 'with a single column/value pair' do - it 'returns the criteria for a column and a value' do - criteria = double(:criteria) - - expect(connection).to receive(:quote_table_name) - .with(:foo) - .and_return('`foo`') - - expect(model).to receive(:where) - .with(%q{`foo` = :value}, value: 'bar') - .and_return(criteria) + let!(:model_1) { model.create(path: 'mOdEl-1', name: 'mOdEl 1') } + let!(:model_2) { model.create(path: 'mOdEl-2', name: 'mOdEl 2') } - expect(model.iwhere(foo: 'bar')).to eq(criteria) - end + it 'finds a single instance by a single attribute regardless of case' do + expect(model.iwhere(path: 'MODEL-1')).to contain_exactly(model_1) + end - it 'returns the criteria for a column with a table, and a value' do - criteria = double(:criteria) + it 'finds multiple instances by a single attribute regardless of case' do + expect(model.iwhere(path: %w(MODEL-1 model-2))).to contain_exactly(model_1, model_2) + end - expect(connection).to receive(:quote_table_name) - .with(:'foo.bar') - .and_return('`foo`.`bar`') + it 'finds instances by multiple attributes' do + expect(model.iwhere(path: %w(MODEL-1 model-2), name: 'model 1')) + .to contain_exactly(model_1) + end - expect(model).to receive(:where) - .with(%q{`foo`.`bar` = :value}, value: 'bar') - .and_return(criteria) + # Using `mysql` & `postgresql` metadata-tags here because both adapters build + # the query slightly differently + context 'for MySQL', :mysql do + it 'builds a simple query' do + query = model.iwhere(path: %w(MODEL-1 model-2), name: 'model 1').to_sql + expected_query = <<~QRY.strip + SELECT `namespaces`.* FROM `namespaces` WHERE (`namespaces`.`path` IN ('MODEL-1', 'model-2')) AND (`namespaces`.`name` = 'model 1') + QRY - expect(model.iwhere('foo.bar'.to_sym => 'bar')) - .to eq(criteria) - end + expect(query).to eq(expected_query) end + end - describe 'with multiple column/value pairs' do - it 'returns the criteria for a column and a value' do - initial = double(:criteria) - final = double(:criteria) - - expect(connection).to receive(:quote_table_name) - .with(:foo) - .and_return('`foo`') - - expect(connection).to receive(:quote_table_name) - .with(:bar) - .and_return('`bar`') - - expect(model).to receive(:where) - .with(%q{`foo` = :value}, value: 'bar') - .and_return(initial) - - expect(initial).to receive(:where) - .with(%q{`bar` = :value}, value: 'baz') - .and_return(final) - - got = model.iwhere(foo: 'bar', bar: 'baz') - - expect(got).to eq(final) - end - - it 'returns the criteria for a column with a table, and a value' do - initial = double(:criteria) - final = double(:criteria) - - expect(connection).to receive(:quote_table_name) - .with(:'foo.bar') - .and_return('`foo`.`bar`') - - expect(connection).to receive(:quote_table_name) - .with(:'foo.baz') - .and_return('`foo`.`baz`') - - expect(model).to receive(:where) - .with(%q{`foo`.`bar` = :value}, value: 'bar') - .and_return(initial) - - expect(initial).to receive(:where) - .with(%q{`foo`.`baz` = :value}, value: 'baz') - .and_return(final) - - got = model.iwhere('foo.bar'.to_sym => 'bar', - 'foo.baz'.to_sym => 'baz') + context 'for PostgreSQL', :postgresql do + it 'builds a query using LOWER' do + query = model.iwhere(path: %w(MODEL-1 model-2), name: 'model 1').to_sql + expected_query = <<~QRY.strip + SELECT \"namespaces\".* FROM \"namespaces\" WHERE (LOWER(\"namespaces\".\"path\") IN (LOWER('MODEL-1'), LOWER('model-2'))) AND (LOWER(\"namespaces\".\"name\") = LOWER('model 1')) + QRY - expect(got).to eq(final) - end + expect(query).to eq(expected_query) end end end diff --git a/spec/models/concerns/triggerable_hooks_spec.rb b/spec/models/concerns/triggerable_hooks_spec.rb index 621d2d38eae..265abd6bd72 100644 --- a/spec/models/concerns/triggerable_hooks_spec.rb +++ b/spec/models/concerns/triggerable_hooks_spec.rb @@ -40,4 +40,28 @@ RSpec.describe TriggerableHooks do end end end + + describe '.select_active' do + it 'returns hooks that match the active filter' do + TestableHook.create!(url: 'http://example1.com', push_events: true) + TestableHook.create!(url: 'http://example2.com', push_events: true) + filter1 = double(:filter1) + filter2 = double(:filter2) + allow(ActiveHookFilter).to receive(:new).exactly(2).times.and_return(filter1, filter2) + expect(filter1).to receive(:matches?).and_return(true) + expect(filter2).to receive(:matches?).and_return(false) + + hooks = TestableHook.push_hooks.order_id_asc + expect(hooks.select_active(:push_hooks, {})).to eq [hooks.first] + end + + it 'returns empty list if no hooks match the active filter' do + TestableHook.create!(url: 'http://example1.com', push_events: true) + filter = double(:filter) + allow(ActiveHookFilter).to receive(:new).and_return(filter) + expect(filter).to receive(:matches?).and_return(false) + + expect(TestableHook.push_hooks.select_active(:push_hooks, {})).to eq [] + end + end end diff --git a/spec/models/hooks/active_hook_filter_spec.rb b/spec/models/hooks/active_hook_filter_spec.rb new file mode 100644 index 00000000000..df7edda2213 --- /dev/null +++ b/spec/models/hooks/active_hook_filter_spec.rb @@ -0,0 +1,68 @@ +require 'spec_helper' + +describe ActiveHookFilter do + subject(:filter) { described_class.new(hook) } + + describe '#matches?' do + context 'for push event hooks' do + let(:hook) do + create(:project_hook, push_events: true, push_events_branch_filter: branch_filter) + end + + context 'branch filter is specified' do + let(:branch_filter) { 'master' } + + it 'returns true if branch matches' do + expect(filter.matches?(:push_hooks, { ref: 'refs/heads/master' })).to be true + end + + it 'returns false if branch does not match' do + expect(filter.matches?(:push_hooks, { ref: 'refs/heads/my_branch' })).to be false + end + + it 'returns false if ref is nil' do + expect(filter.matches?(:push_hooks, {})).to be false + end + + context 'branch filter contains wildcard' do + let(:branch_filter) { 'features/*' } + + it 'returns true if branch matches' do + expect(filter.matches?(:push_hooks, { ref: 'refs/heads/features/my-branch' })).to be true + expect(filter.matches?(:push_hooks, { ref: 'refs/heads/features/my-branch/something' })).to be true + end + + it 'returns false if branch does not match' do + expect(filter.matches?(:push_hooks, { ref: 'refs/heads/master' })).to be false + end + end + end + + context 'branch filter is not specified' do + let(:branch_filter) { nil } + + it 'returns true' do + expect(filter.matches?(:push_hooks, { ref: 'refs/heads/master' })).to be true + end + end + + context 'branch filter is empty string' do + let(:branch_filter) { '' } + + it 'acts like branch is not specified' do + expect(filter.matches?(:push_hooks, { ref: 'refs/heads/master' })).to be true + end + end + end + + context 'for non-push-events hooks' do + let(:hook) do + create(:project_hook, issues_events: true, push_events: false, push_events_branch_filter: '') + end + + it 'returns true as branch filters are not yet supported for these' do + expect(filter.matches?(:issues_events, { ref: 'refs/heads/master' })).to be true + end + end + end +end diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb index ea6d6e53ef5..a4181631f01 100644 --- a/spec/models/hooks/web_hook_spec.rb +++ b/spec/models/hooks/web_hook_spec.rb @@ -35,6 +35,26 @@ describe WebHook do it { is_expected.not_to allow_values("foo\nbar", "foo\r\nbar").for(:token) } end + + describe 'push_events_branch_filter' do + it { is_expected.to allow_values("good_branch_name", "another/good-branch_name").for(:push_events_branch_filter) } + it { is_expected.to allow_values("").for(:push_events_branch_filter) } + it { is_expected.not_to allow_values("bad branch name", "bad~branchname").for(:push_events_branch_filter) } + + it 'gets rid of whitespace' do + hook.push_events_branch_filter = ' branch ' + hook.save + + expect(hook.push_events_branch_filter).to eq('branch') + end + + it 'stores whitespace only as empty' do + hook.push_events_branch_filter = ' ' + hook.save + + expect(hook.push_events_branch_filter).to eq('') + end + end end describe 'execute' do diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 7cfffbde42f..264632dba4b 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -3734,21 +3734,45 @@ describe Project do end describe '#execute_hooks' do - it 'executes the projects hooks with the specified scope' do - hook1 = create(:project_hook, merge_requests_events: true, tag_push_events: false) - hook2 = create(:project_hook, merge_requests_events: false, tag_push_events: true) - project = create(:project, hooks: [hook1, hook2]) + let(:data) { { ref: 'refs/heads/master', data: 'data' } } + it 'executes active projects hooks with the specified scope' do + hook = create(:project_hook, merge_requests_events: false, push_events: true) + expect(ProjectHook).to receive(:select_active) + .with(:push_hooks, data) + .and_return([hook]) + project = create(:project, hooks: [hook]) expect_any_instance_of(ProjectHook).to receive(:async_execute).once - project.execute_hooks({}, :tag_push_hooks) + project.execute_hooks(data, :push_hooks) + end + + it 'does not execute project hooks that dont match the specified scope' do + hook = create(:project_hook, merge_requests_events: true, push_events: false) + project = create(:project, hooks: [hook]) + + expect_any_instance_of(ProjectHook).not_to receive(:async_execute).once + + project.execute_hooks(data, :push_hooks) + end + + it 'does not execute project hooks which are not active' do + hook = create(:project_hook, push_events: true) + expect(ProjectHook).to receive(:select_active) + .with(:push_hooks, data) + .and_return([]) + project = create(:project, hooks: [hook]) + + expect_any_instance_of(ProjectHook).not_to receive(:async_execute).once + + project.execute_hooks(data, :push_hooks) end it 'executes the system hooks with the specified scope' do - expect_any_instance_of(SystemHooksService).to receive(:execute_hooks).with({ data: 'data' }, :merge_request_hooks) + expect_any_instance_of(SystemHooksService).to receive(:execute_hooks).with(data, :merge_request_hooks) project = build(:project) - project.execute_hooks({ data: 'data' }, :merge_request_hooks) + project.execute_hooks(data, :merge_request_hooks) end it 'executes the system hooks when inside a transaction' do @@ -3763,7 +3787,7 @@ describe Project do # actually get to the `after_commit` hook that queues these jobs. expect do project.transaction do - project.execute_hooks({ data: 'data' }, :merge_request_hooks) + project.execute_hooks(data, :merge_request_hooks) end end.not_to raise_error # Sidekiq::Worker::EnqueueFromTransactionError end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index fd99acb3bb2..2a7aff39240 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -405,6 +405,23 @@ describe User do end end end + + describe '.by_username' do + it 'finds users regardless of the case passed' do + user = create(:user, username: 'CaMeLcAsEd') + user2 = create(:user, username: 'UPPERCASE') + + expect(described_class.by_username(%w(CAMELCASED uppercase))) + .to contain_exactly(user, user2) + end + + it 'finds a single user regardless of the case passed' do + user = create(:user, username: 'CaMeLcAsEd') + + expect(described_class.by_username('CAMELCASED')) + .to contain_exactly(user) + end + end end describe "Respond to" do |