summaryrefslogtreecommitdiff
path: root/spec/models
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models')
-rw-r--r--spec/models/ci/pipeline_spec.rb24
-rw-r--r--spec/models/clusters/applications/helm_spec.rb14
-rw-r--r--spec/models/clusters/applications/ingress_spec.rb9
-rw-r--r--spec/models/clusters/applications/jupyter_spec.rb9
-rw-r--r--spec/models/clusters/applications/prometheus_spec.rb35
-rw-r--r--spec/models/clusters/applications/runner_spec.rb9
-rw-r--r--spec/models/clusters/cluster_spec.rb4
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb24
-rw-r--r--spec/models/concerns/avatarable_spec.rb20
-rw-r--r--spec/models/concerns/case_sensitivity_spec.rb202
-rw-r--r--spec/models/concerns/triggerable_hooks_spec.rb24
-rw-r--r--spec/models/hooks/active_hook_filter_spec.rb68
-rw-r--r--spec/models/hooks/web_hook_spec.rb20
-rw-r--r--spec/models/project_spec.rb40
-rw-r--r--spec/models/user_spec.rb17
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