summaryrefslogtreecommitdiff
path: root/spec/models
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models')
-rw-r--r--spec/models/ci/build_spec.rb32
-rw-r--r--spec/models/clusters/applications/prometheus_spec.rb10
-rw-r--r--spec/models/clusters/cluster_spec.rb68
-rw-r--r--spec/models/clusters/group_spec.rb8
-rw-r--r--spec/models/clusters/kubernetes_namespace_spec.rb85
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb59
-rw-r--r--spec/models/concerns/awardable_spec.rb18
-rw-r--r--spec/models/concerns/blob_language_from_git_attributes_spec.rb25
-rw-r--r--spec/models/concerns/cacheable_attributes_spec.rb4
-rw-r--r--spec/models/concerns/issuable_spec.rb4
-rw-r--r--spec/models/concerns/redactable_spec.rb69
-rw-r--r--spec/models/concerns/token_authenticatable_spec.rb272
-rw-r--r--spec/models/environment_status_spec.rb32
-rw-r--r--spec/models/global_milestone_spec.rb35
-rw-r--r--spec/models/group_spec.rb18
-rw-r--r--spec/models/lfs_object_spec.rb21
-rw-r--r--spec/models/merge_request_diff_spec.rb33
-rw-r--r--spec/models/merge_request_spec.rb64
-rw-r--r--spec/models/milestone_spec.rb37
-rw-r--r--spec/models/personal_access_token_spec.rb28
-rw-r--r--spec/models/project_services/hipchat_service_spec.rb18
-rw-r--r--spec/models/project_services/kubernetes_service_spec.rb6
-rw-r--r--spec/models/project_spec.rb34
-rw-r--r--spec/models/project_wiki_spec.rb4
-rw-r--r--spec/models/upload_spec.rb2
-rw-r--r--spec/models/user_spec.rb8
26 files changed, 811 insertions, 183 deletions
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index a046541031e..13a4aaa8936 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -216,14 +216,6 @@ describe Ci::Build do
let(:build) { create(:ci_build, :created, :schedulable, project: project) }
it { expect(subject).to be_truthy }
-
- context 'when feature flag is diabled' do
- before do
- stub_feature_flags(ci_enable_scheduled_build: false)
- end
-
- it { expect(subject).to be_falsy }
- end
end
context 'when build is not schedulable' do
@@ -327,10 +319,6 @@ describe Ci::Build do
describe '#enqueue_scheduled' do
subject { build.enqueue_scheduled }
- before do
- stub_feature_flags(ci_enable_scheduled_build: true)
- end
-
context 'when build is scheduled and the right time has not come yet' do
let(:build) { create(:ci_build, :scheduled, pipeline: pipeline) }
@@ -2027,17 +2015,17 @@ describe Ci::Build do
it { is_expected.to include(tag_variable) }
end
- context 'when secret variable is defined' do
- let(:secret_variable) do
+ context 'when CI variable is defined' do
+ let(:ci_variable) do
{ key: 'SECRET_KEY', value: 'secret_value', public: false }
end
before do
create(:ci_variable,
- secret_variable.slice(:key, :value).merge(project: project))
+ ci_variable.slice(:key, :value).merge(project: project))
end
- it { is_expected.to include(secret_variable) }
+ it { is_expected.to include(ci_variable) }
end
context 'when protected variable is defined' do
@@ -2072,17 +2060,17 @@ describe Ci::Build do
end
end
- context 'when group secret variable is defined' do
- let(:secret_variable) do
+ context 'when group CI variable is defined' do
+ let(:ci_variable) do
{ key: 'SECRET_KEY', value: 'secret_value', public: false }
end
before do
create(:ci_group_variable,
- secret_variable.slice(:key, :value).merge(group: group))
+ ci_variable.slice(:key, :value).merge(group: group))
end
- it { is_expected.to include(secret_variable) }
+ it { is_expected.to include(ci_variable) }
end
context 'when group protected variable is defined' do
@@ -2357,7 +2345,7 @@ describe Ci::Build do
.to receive(:predefined_variables) { [project_pre_var] }
allow_any_instance_of(Project)
- .to receive(:secret_variables_for)
+ .to receive(:ci_variables_for)
.with(ref: 'master', environment: nil) do
[create(:ci_variable, key: 'secret', value: 'value')]
end
@@ -2508,7 +2496,7 @@ describe Ci::Build do
end
describe '#scoped_variables_hash' do
- context 'when overriding secret variables' do
+ context 'when overriding CI variables' do
before do
project.variables.create!(key: 'MY_VAR', value: 'my value 1')
pipeline.variables.create!(key: 'MY_VAR', value: 'my value 2')
diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb
index f9776acd4c8..48ba163b38c 100644
--- a/spec/models/clusters/applications/prometheus_spec.rb
+++ b/spec/models/clusters/applications/prometheus_spec.rb
@@ -109,14 +109,20 @@ describe Clusters::Applications::Prometheus do
end
context 'cluster has kubeclient' do
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:kubernetes_url) { subject.cluster.platform_kubernetes.api_url }
let(:kube_client) { subject.cluster.kubeclient.core_client }
- subject { create(:clusters_applications_prometheus) }
+ subject { create(:clusters_applications_prometheus, cluster: cluster) }
before do
subject.cluster.platform_kubernetes.namespace = 'a-namespace'
- stub_kubeclient_discover(subject.cluster.platform_kubernetes.api_url)
+ stub_kubeclient_discover(cluster.platform_kubernetes.api_url)
+
+ create(:cluster_kubernetes_namespace,
+ cluster: cluster,
+ cluster_project: cluster.cluster_project,
+ project: cluster.cluster_project.project)
end
it 'creates proxy prometheus rest client' do
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index f5c4b0b66ae..19b76ca8cfb 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -4,7 +4,10 @@ require 'spec_helper'
describe Clusters::Cluster do
it { is_expected.to belong_to(:user) }
+ it { is_expected.to have_many(:cluster_projects) }
it { is_expected.to have_many(:projects) }
+ it { is_expected.to have_many(:cluster_groups) }
+ it { is_expected.to have_many(:groups) }
it { is_expected.to have_one(:provider_gcp) }
it { is_expected.to have_one(:platform_kubernetes) }
it { is_expected.to have_one(:application_helm) }
@@ -13,6 +16,7 @@ describe Clusters::Cluster do
it { is_expected.to have_one(:application_runner) }
it { is_expected.to have_many(:kubernetes_namespaces) }
it { is_expected.to have_one(:kubernetes_namespace) }
+ it { is_expected.to have_one(:cluster_project) }
it { is_expected.to delegate_method(:status).to(:provider) }
it { is_expected.to delegate_method(:status_reason).to(:provider) }
@@ -178,6 +182,53 @@ describe Clusters::Cluster do
it { expect(cluster.update(enabled: false)).to be_truthy }
end
end
+
+ describe 'cluster_type validations' do
+ let(:instance_cluster) { create(:cluster, :instance) }
+ let(:group_cluster) { create(:cluster, :group) }
+ let(:project_cluster) { create(:cluster, :project) }
+
+ it 'validates presence' do
+ cluster = build(:cluster, :project, cluster_type: nil)
+
+ expect(cluster).not_to be_valid
+ expect(cluster.errors.full_messages).to include("Cluster type can't be blank")
+ end
+
+ context 'project_type cluster' do
+ it 'does not allow setting group' do
+ project_cluster.groups << build(:group)
+
+ expect(project_cluster).not_to be_valid
+ expect(project_cluster.errors.full_messages).to include('Cluster cannot have groups assigned')
+ end
+ end
+
+ context 'group_type cluster' do
+ it 'does not allow setting project' do
+ group_cluster.projects << build(:project)
+
+ expect(group_cluster).not_to be_valid
+ expect(group_cluster.errors.full_messages).to include('Cluster cannot have projects assigned')
+ end
+ end
+
+ context 'instance_type cluster' do
+ it 'does not allow setting group' do
+ instance_cluster.groups << build(:group)
+
+ expect(instance_cluster).not_to be_valid
+ expect(instance_cluster.errors.full_messages).to include('Cluster cannot have groups assigned')
+ end
+
+ it 'does not allow setting project' do
+ instance_cluster.projects << build(:project)
+
+ expect(instance_cluster).not_to be_valid
+ expect(instance_cluster.errors.full_messages).to include('Cluster cannot have projects assigned')
+ end
+ end
+ end
end
describe '#provider' do
@@ -229,6 +280,23 @@ describe Clusters::Cluster do
end
end
+ describe '#group' do
+ subject { cluster.group }
+
+ context 'when cluster belongs to a group' do
+ let(:cluster) { create(:cluster, :group) }
+ let(:group) { cluster.groups.first }
+
+ it { is_expected.to eq(group) }
+ end
+
+ context 'when cluster does not belong to any group' do
+ let(:cluster) { create(:cluster) }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
describe '#applications' do
set(:cluster) { create(:cluster) }
diff --git a/spec/models/clusters/group_spec.rb b/spec/models/clusters/group_spec.rb
new file mode 100644
index 00000000000..ba145342cb8
--- /dev/null
+++ b/spec/models/clusters/group_spec.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Clusters::Group do
+ it { is_expected.to belong_to(:cluster) }
+ it { is_expected.to belong_to(:group) }
+end
diff --git a/spec/models/clusters/kubernetes_namespace_spec.rb b/spec/models/clusters/kubernetes_namespace_spec.rb
index dea58fa26c7..0dfeea5cd2f 100644
--- a/spec/models/clusters/kubernetes_namespace_spec.rb
+++ b/spec/models/clusters/kubernetes_namespace_spec.rb
@@ -10,23 +10,15 @@ RSpec.describe Clusters::KubernetesNamespace, type: :model do
describe 'namespace uniqueness validation' do
let(:cluster_project) { create(:cluster_project) }
-
- let(:kubernetes_namespace) do
- build(:cluster_kubernetes_namespace,
- cluster: cluster_project.cluster,
- project: cluster_project.project,
- cluster_project: cluster_project)
- end
+ let(:kubernetes_namespace) { build(:cluster_kubernetes_namespace, namespace: 'my-namespace') }
subject { kubernetes_namespace }
context 'when cluster is using the namespace' do
before do
create(:cluster_kubernetes_namespace,
- cluster: cluster_project.cluster,
- project: cluster_project.project,
- cluster_project: cluster_project,
- namespace: kubernetes_namespace.namespace)
+ cluster: kubernetes_namespace.cluster,
+ namespace: 'my-namespace')
end
it { is_expected.not_to be_valid }
@@ -37,48 +29,79 @@ RSpec.describe Clusters::KubernetesNamespace, type: :model do
end
end
- describe '#set_namespace_and_service_account_to_default' do
- let(:cluster) { platform.cluster }
- let(:cluster_project) { create(:cluster_project, cluster: cluster) }
- let(:kubernetes_namespace) do
- create(:cluster_kubernetes_namespace,
- cluster: cluster_project.cluster,
- project: cluster_project.project,
- cluster_project: cluster_project)
- end
+ describe '#configure_predefined_variables' do
+ let(:kubernetes_namespace) { build(:cluster_kubernetes_namespace) }
+ let(:cluster) { kubernetes_namespace.cluster }
+ let(:platform) { kubernetes_namespace.platform_kubernetes }
- describe 'namespace' do
- let(:platform) { create(:cluster_platform_kubernetes, namespace: namespace) }
+ subject { kubernetes_namespace.configure_predefined_credentials }
- subject { kubernetes_namespace.namespace }
+ describe 'namespace' do
+ before do
+ platform.update_column(:namespace, namespace)
+ end
context 'when platform has a namespace assigned' do
let(:namespace) { 'platform-namespace' }
it 'should copy the namespace' do
- is_expected.to eq('platform-namespace')
+ subject
+
+ expect(kubernetes_namespace.namespace).to eq('platform-namespace')
end
end
context 'when platform does not have namespace assigned' do
+ let(:project) { kubernetes_namespace.project }
let(:namespace) { nil }
+ let(:project_slug) { "#{project.path}-#{project.id}" }
- it 'should set default namespace' do
- project_slug = "#{cluster_project.project.path}-#{cluster_project.project_id}"
+ it 'should fallback to project namespace' do
+ subject
- is_expected.to eq(project_slug)
+ expect(kubernetes_namespace.namespace).to eq(project_slug)
end
end
end
describe 'service_account_name' do
- let(:platform) { create(:cluster_platform_kubernetes) }
-
- subject { kubernetes_namespace.service_account_name }
+ let(:service_account_name) { "#{kubernetes_namespace.namespace}-service-account" }
it 'should set a service account name based on namespace' do
- is_expected.to eq("#{kubernetes_namespace.namespace}-service-account")
+ subject
+
+ expect(kubernetes_namespace.service_account_name).to eq(service_account_name)
end
end
end
+
+ describe '#predefined_variables' do
+ let(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, cluster: cluster, service_account_token: token) }
+ let(:cluster) { create(:cluster, :project, platform_kubernetes: platform) }
+ let(:platform) { create(:cluster_platform_kubernetes, api_url: api_url, ca_cert: ca_pem, token: token) }
+
+ let(:api_url) { 'https://kube.domain.com' }
+ let(:ca_pem) { 'CA PEM DATA' }
+ let(:token) { 'token' }
+
+ let(:kubeconfig) do
+ config_file = expand_fixture_path('config/kubeconfig.yml')
+ config = YAML.safe_load(File.read(config_file))
+ config.dig('users', 0, 'user')['token'] = token
+ config.dig('contexts', 0, 'context')['namespace'] = kubernetes_namespace.namespace
+ config.dig('clusters', 0, 'cluster')['certificate-authority-data'] =
+ Base64.strict_encode64(ca_pem)
+
+ YAML.dump(config)
+ end
+
+ it 'sets the variables' do
+ expect(kubernetes_namespace.predefined_variables).to include(
+ { key: 'KUBE_SERVICE_ACCOUNT', value: kubernetes_namespace.service_account_name, public: true },
+ { key: 'KUBE_NAMESPACE', value: kubernetes_namespace.namespace, public: true },
+ { key: 'KUBE_TOKEN', value: kubernetes_namespace.service_account_token, public: false },
+ { key: 'KUBECONFIG', value: kubeconfig, public: false, file: true }
+ )
+ end
+ end
end
diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb
index e13eb554add..2bcccc8184a 100644
--- a/spec/models/clusters/platforms/kubernetes_spec.rb
+++ b/spec/models/clusters/platforms/kubernetes_spec.rb
@@ -124,9 +124,17 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
end
describe '#kubeclient' do
+ let(:cluster) { create(:cluster, :project) }
+ let(:kubernetes) { build(:cluster_platform_kubernetes, :configured, namespace: 'a-namespace', cluster: cluster) }
+
subject { kubernetes.kubeclient }
- let(:kubernetes) { build(:cluster_platform_kubernetes, :configured, namespace: 'a-namespace') }
+ before do
+ create(:cluster_kubernetes_namespace,
+ cluster: kubernetes.cluster,
+ cluster_project: kubernetes.cluster.cluster_project,
+ project: kubernetes.cluster.cluster_project.project)
+ end
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::KubeClient) }
end
@@ -186,29 +194,14 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
describe '#predefined_variables' do
let!(:cluster) { create(:cluster, :project, platform_kubernetes: kubernetes) }
- let(:kubernetes) { create(:cluster_platform_kubernetes, api_url: api_url, ca_cert: ca_pem, token: token) }
+ let(:kubernetes) { create(:cluster_platform_kubernetes, api_url: api_url, ca_cert: ca_pem) }
let(:api_url) { 'https://kube.domain.com' }
let(:ca_pem) { 'CA PEM DATA' }
- let(:token) { 'token' }
-
- let(:kubeconfig) do
- config_file = expand_fixture_path('config/kubeconfig.yml')
- config = YAML.load(File.read(config_file))
- config.dig('users', 0, 'user')['token'] = token
- config.dig('contexts', 0, 'context')['namespace'] = namespace
- config.dig('clusters', 0, 'cluster')['certificate-authority-data'] =
- Base64.strict_encode64(ca_pem)
-
- YAML.dump(config)
- end
shared_examples 'setting variables' do
it 'sets the variables' do
- expect(kubernetes.predefined_variables).to include(
+ expect(kubernetes.predefined_variables(project: cluster.project)).to include(
{ key: 'KUBE_URL', value: api_url, public: true },
- { key: 'KUBE_TOKEN', value: token, public: false },
- { key: 'KUBE_NAMESPACE', value: namespace, public: true },
- { key: 'KUBECONFIG', value: kubeconfig, public: false, file: true },
{ key: 'KUBE_CA_PEM', value: ca_pem, public: true },
{ key: 'KUBE_CA_PEM_FILE', value: ca_pem, public: true, file: true }
)
@@ -229,13 +222,6 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
let(:namespace) { kubernetes.actual_namespace }
it_behaves_like 'setting variables'
-
- it 'sets the KUBE_NAMESPACE' do
- kube_namespace = kubernetes.predefined_variables.find { |h| h[:key] == 'KUBE_NAMESPACE' }
-
- expect(kube_namespace).not_to be_nil
- expect(kube_namespace[:value]).to match(/\A#{Gitlab::PathRegex::PATH_REGEX_STR}-\d+\z/)
- end
end
end
@@ -319,4 +305,27 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
it { is_expected.to include(pods: []) }
end
end
+
+ describe '#update_kubernetes_namespace' do
+ let(:cluster) { create(:cluster, :provided_by_gcp) }
+ let(:platform) { cluster.platform }
+
+ context 'when namespace is updated' do
+ it 'should call ConfigureWorker' do
+ expect(ClusterPlatformConfigureWorker).to receive(:perform_async).with(cluster.id).once
+
+ platform.namespace = 'new-namespace'
+ platform.save
+ end
+ end
+
+ context 'when namespace is not updated' do
+ it 'should not call ConfigureWorker' do
+ expect(ClusterPlatformConfigureWorker).not_to receive(:perform_async)
+
+ platform.username = "new-username"
+ platform.save
+ end
+ end
+ end
end
diff --git a/spec/models/concerns/awardable_spec.rb b/spec/models/concerns/awardable_spec.rb
index 69083bdc125..debc02fa51f 100644
--- a/spec/models/concerns/awardable_spec.rb
+++ b/spec/models/concerns/awardable_spec.rb
@@ -24,13 +24,29 @@ describe Awardable do
end
end
- describe ".awarded" do
+ describe "#awarded" do
it "filters by user and emoji name" do
expect(Issue.awarded(award_emoji.user, "thumbsup")).to be_empty
expect(Issue.awarded(award_emoji.user, "thumbsdown")).to eq [issue]
expect(Issue.awarded(award_emoji2.user, "thumbsup")).to eq [issue2]
expect(Issue.awarded(award_emoji2.user, "thumbsdown")).to be_empty
end
+
+ it "filters by user and any emoji" do
+ issue3 = create(:issue)
+ create(:award_emoji, awardable: issue3, name: "star", user: award_emoji.user)
+ create(:award_emoji, awardable: issue3, name: "star", user: award_emoji2.user)
+
+ expect(Issue.awarded(award_emoji.user)).to eq [issue, issue3]
+ expect(Issue.awarded(award_emoji2.user)).to eq [issue2, issue3]
+ end
+ end
+
+ describe "#not_awarded" do
+ it "returns issues not awarded by user" do
+ expect(Issue.not_awarded(award_emoji.user)).to eq [issue2]
+ expect(Issue.not_awarded(award_emoji2.user)).to eq [issue]
+ end
end
end
diff --git a/spec/models/concerns/blob_language_from_git_attributes_spec.rb b/spec/models/concerns/blob_language_from_git_attributes_spec.rb
new file mode 100644
index 00000000000..7f05073b08e
--- /dev/null
+++ b/spec/models/concerns/blob_language_from_git_attributes_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe BlobLanguageFromGitAttributes do
+ include FakeBlobHelpers
+
+ let(:project) { build(:project, :repository) }
+
+ describe '#language_from_gitattributes' do
+ subject(:blob) { fake_blob(path: 'file.md') }
+
+ it 'returns return value from gitattribute' do
+ expect(blob.project.repository).to receive(:gitattribute).with(blob.path, 'gitlab-language').and_return('erb?parent=json')
+
+ expect(blob.language_from_gitattributes).to eq('erb?parent=json')
+ end
+
+ it 'returns nil if project is absent' do
+ allow(blob).to receive(:project).and_return(nil)
+
+ expect(blob.language_from_gitattributes).to eq(nil)
+ end
+ end
+end
diff --git a/spec/models/concerns/cacheable_attributes_spec.rb b/spec/models/concerns/cacheable_attributes_spec.rb
index f8c2e29fadd..827fbc9d7d5 100644
--- a/spec/models/concerns/cacheable_attributes_spec.rb
+++ b/spec/models/concerns/cacheable_attributes_spec.rb
@@ -41,7 +41,7 @@ describe CacheableAttributes do
expect(minimal_test_class.current_without_cache).to eq(minimal_test_class.last)
end
- it 'can be overriden' do
+ it 'can be overridden' do
minimal_test_class.define_singleton_method(:current_without_cache) do
first
end
@@ -64,7 +64,7 @@ describe CacheableAttributes do
context 'with defaults defined' do
include_context 'with defaults'
- it 'can be overriden' do
+ it 'can be overridden' do
expect(minimal_test_class.defaults).to eq({ foo: 'a', bar: 'b', baz: 'c' })
end
end
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index ec6374f3963..a4bf3e2350a 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -519,7 +519,7 @@ describe Issuable do
end
end
- context 'substracting time' do
+ context 'subtracting time' do
before do
spend_time(1800)
end
@@ -530,7 +530,7 @@ describe Issuable do
expect(issue.total_time_spent).to eq(900)
end
- context 'when time to substract exceeds the total time spent' do
+ context 'when time to subtract exceeds the total time spent' do
it 'raise a validation error' do
Timecop.travel(1.minute.from_now) do
expect do
diff --git a/spec/models/concerns/redactable_spec.rb b/spec/models/concerns/redactable_spec.rb
new file mode 100644
index 00000000000..7d320edd492
--- /dev/null
+++ b/spec/models/concerns/redactable_spec.rb
@@ -0,0 +1,69 @@
+require 'spec_helper'
+
+describe Redactable do
+ shared_examples 'model with redactable field' do
+ it 'redacts unsubscribe token' do
+ model[field] = 'some text /sent_notifications/00000000000000000000000000000000/unsubscribe more text'
+
+ model.save!
+
+ expect(model[field]).to eq 'some text /sent_notifications/REDACTED/unsubscribe more text'
+ end
+
+ it 'ignores not hexadecimal tokens' do
+ text = 'some text /sent_notifications/token/unsubscribe more text'
+ model[field] = text
+
+ model.save!
+
+ expect(model[field]).to eq text
+ end
+
+ it 'ignores not matching texts' do
+ text = 'some text /sent_notifications/.*/unsubscribe more text'
+ model[field] = text
+
+ model.save!
+
+ expect(model[field]).to eq text
+ end
+
+ it 'redacts the field when saving the model before creating markdown cache' do
+ model[field] = 'some text /sent_notifications/00000000000000000000000000000000/unsubscribe more text'
+
+ model.save!
+
+ expected = 'some text /sent_notifications/REDACTED/unsubscribe more text'
+ expect(model[field]).to eq expected
+ expect(model["#{field}_html"]).to eq "<p dir=\"auto\">#{expected}</p>"
+ end
+ end
+
+ context 'when model is an issue' do
+ it_behaves_like 'model with redactable field' do
+ let(:model) { create(:issue) }
+ let(:field) { :description }
+ end
+ end
+
+ context 'when model is a merge request' do
+ it_behaves_like 'model with redactable field' do
+ let(:model) { create(:merge_request) }
+ let(:field) { :description }
+ end
+ end
+
+ context 'when model is a note' do
+ it_behaves_like 'model with redactable field' do
+ let(:model) { create(:note) }
+ let(:field) { :note }
+ end
+ end
+
+ context 'when model is a snippet' do
+ it_behaves_like 'model with redactable field' do
+ let(:model) { create(:snippet) }
+ let(:field) { :description }
+ end
+ end
+end
diff --git a/spec/models/concerns/token_authenticatable_spec.rb b/spec/models/concerns/token_authenticatable_spec.rb
index 9b804429138..782687516ae 100644
--- a/spec/models/concerns/token_authenticatable_spec.rb
+++ b/spec/models/concerns/token_authenticatable_spec.rb
@@ -2,8 +2,6 @@ require 'spec_helper'
shared_examples 'TokenAuthenticatable' do
describe 'dynamically defined methods' do
- it { expect(described_class).to be_private_method_defined(:generate_token) }
- it { expect(described_class).to be_private_method_defined(:write_new_token) }
it { expect(described_class).to respond_to("find_by_#{token_field}") }
it { is_expected.to respond_to("ensure_#{token_field}") }
it { is_expected.to respond_to("set_#{token_field}") }
@@ -66,13 +64,275 @@ describe ApplicationSetting, 'TokenAuthenticatable' do
end
describe 'multiple token fields' do
- before do
+ before(:all) do
described_class.send(:add_authentication_token_field, :yet_another_token)
end
- describe '.token_fields' do
- subject { described_class.authentication_token_fields }
- it { is_expected.to include(:runners_registration_token, :yet_another_token) }
+ it { is_expected.to respond_to(:ensure_runners_registration_token) }
+ it { is_expected.to respond_to(:ensure_yet_another_token) }
+ end
+
+ describe 'setting same token field multiple times' do
+ subject { described_class.send(:add_authentication_token_field, :runners_registration_token) }
+
+ it 'raises error' do
+ expect {subject}.to raise_error(ArgumentError)
+ end
+ end
+end
+
+describe PersonalAccessToken, 'TokenAuthenticatable' do
+ let(:personal_access_token_name) { 'test-pat-01' }
+ let(:token_value) { 'token' }
+ let(:user) { create(:user) }
+ let(:personal_access_token) do
+ described_class.new(name: personal_access_token_name,
+ user_id: user.id,
+ scopes: [:api],
+ token: token,
+ token_digest: token_digest)
+ end
+
+ before do
+ allow(Devise).to receive(:friendly_token).and_return(token_value)
+ end
+
+ describe '.find_by_token' do
+ subject { PersonalAccessToken.find_by_token(token_value) }
+
+ before do
+ personal_access_token.save
+ end
+
+ context 'token_digest already exists' do
+ let(:token) { nil }
+ let(:token_digest) { Gitlab::CryptoHelper.sha256(token_value) }
+
+ it 'finds the token' do
+ expect(subject).not_to be_nil
+ expect(subject.name).to eql(personal_access_token_name)
+ end
+ end
+
+ context 'token_digest does not exist' do
+ let(:token) { token_value }
+ let(:token_digest) { nil }
+
+ it 'finds the token' do
+ expect(subject).not_to be_nil
+ expect(subject.name).to eql(personal_access_token_name)
+ end
+ end
+ end
+
+ describe '#set_token' do
+ let(:new_token_value) { 'new-token' }
+ subject { personal_access_token.set_token(new_token_value) }
+
+ context 'token_digest already exists' do
+ let(:token) { nil }
+ let(:token_digest) { Gitlab::CryptoHelper.sha256(token_value) }
+
+ it 'overwrites token_digest' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(new_token_value)
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(new_token_value))
+ end
+ end
+
+ context 'token_digest does not exist but token does' do
+ let(:token) { token_value }
+ let(:token_digest) { nil }
+
+ it 'creates new token_digest and clears token' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(new_token_value)
+ expect(personal_access_token.token_digest).to eql(Gitlab::CryptoHelper.sha256(new_token_value))
+ end
+ end
+
+ context 'token_digest does not exist, nor token' do
+ let(:token) { nil }
+ let(:token_digest) { nil }
+
+ it 'creates new token_digest' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(new_token_value)
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(new_token_value))
+ end
+ end
+ end
+
+ describe '#ensure_token' do
+ subject { personal_access_token.ensure_token }
+
+ context 'token_digest already exists' do
+ let(:token) { nil }
+ let(:token_digest) { Gitlab::CryptoHelper.sha256(token_value) }
+
+ it 'does not change token fields' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to be_nil
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
+ end
+ end
+
+ context 'token_digest does not exist but token does' do
+ let(:token) { token_value }
+ let(:token_digest) { nil }
+
+ it 'does not change token fields' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to eql(token_value)
+ expect(personal_access_token.token).to eql(token_value)
+ expect(personal_access_token.token_digest).to be_nil
+ end
+ end
+
+ context 'token_digest does not exist, nor token' do
+ let(:token) { nil }
+ let(:token_digest) { nil }
+
+ it 'creates token_digest' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(token_value)
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
+ end
+ end
+ end
+
+ describe '#ensure_token!' do
+ subject { personal_access_token.ensure_token! }
+
+ context 'token_digest already exists' do
+ let(:token) { nil }
+ let(:token_digest) { Gitlab::CryptoHelper.sha256(token_value) }
+
+ it 'does not change token fields' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to be_nil
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
+ end
+ end
+
+ context 'token_digest does not exist but token does' do
+ let(:token) { token_value }
+ let(:token_digest) { nil }
+
+ it 'does not change token fields' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to eql(token_value)
+ expect(personal_access_token.token).to eql(token_value)
+ expect(personal_access_token.token_digest).to be_nil
+ end
+ end
+
+ context 'token_digest does not exist, nor token' do
+ let(:token) { nil }
+ let(:token_digest) { nil }
+
+ it 'creates token_digest' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(token_value)
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
+ end
+ end
+ end
+
+ describe '#reset_token!' do
+ subject { personal_access_token.reset_token! }
+
+ context 'token_digest already exists' do
+ let(:token) { nil }
+ let(:token_digest) { Gitlab::CryptoHelper.sha256('old-token') }
+
+ it 'creates new token_digest' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(token_value)
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
+ end
+ end
+
+ context 'token_digest does not exist but token does' do
+ let(:token) { 'old-token' }
+ let(:token_digest) { nil }
+
+ it 'creates new token_digest and clears token' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(token_value)
+ expect(personal_access_token.token_digest).to eql(Gitlab::CryptoHelper.sha256(token_value))
+ end
+ end
+
+ context 'token_digest does not exist, nor token' do
+ let(:token) { nil }
+ let(:token_digest) { nil }
+
+ it 'creates new token_digest' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(token_value)
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
+ end
+ end
+
+ context 'token_digest exists and newly generated token would be the same' do
+ let(:token) { nil }
+ let(:token_digest) { Gitlab::CryptoHelper.sha256('old-token') }
+
+ before do
+ personal_access_token.save
+ allow(Devise).to receive(:friendly_token).and_return(
+ 'old-token', token_value, 'boom!')
+ end
+
+ it 'regenerates a new token_digest' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(token_value)
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
+ end
+ end
+
+ context 'token exists and newly generated token would be the same' do
+ let(:token) { 'old-token' }
+ let(:token_digest) { nil }
+
+ before do
+ personal_access_token.save
+ allow(Devise).to receive(:friendly_token).and_return(
+ 'old-token', token_value, 'boom!')
+ end
+
+ it 'regenerates a new token_digest' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(token_value)
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
+ end
end
end
end
diff --git a/spec/models/environment_status_spec.rb b/spec/models/environment_status_spec.rb
index f2eb263c98c..e7805d52d75 100644
--- a/spec/models/environment_status_spec.rb
+++ b/spec/models/environment_status_spec.rb
@@ -5,13 +5,15 @@ describe EnvironmentStatus do
let(:environment) { deployment.environment}
let(:project) { deployment.project }
let(:merge_request) { create(:merge_request, :deployed_review_app, deployment: deployment) }
+ let(:sha) { deployment.sha }
- subject(:environment_status) { described_class.new(environment, merge_request) }
+ subject(:environment_status) { described_class.new(environment, merge_request, sha) }
it { is_expected.to delegate_method(:id).to(:environment) }
it { is_expected.to delegate_method(:name).to(:environment) }
it { is_expected.to delegate_method(:project).to(:environment) }
it { is_expected.to delegate_method(:deployed_at).to(:deployment).as(:created_at) }
+ it { is_expected.to delegate_method(:status).to(:deployment) }
describe '#project' do
subject { environment_status.project }
@@ -58,4 +60,32 @@ describe EnvironmentStatus do
)
end
end
+
+ describe '.for_merge_request' do
+ let(:admin) { create(:admin) }
+ let(:pipeline) { create(:ci_pipeline, sha: sha) }
+
+ it 'is based on merge_request.head_pipeline' do
+ expect(merge_request).to receive(:head_pipeline).and_return(pipeline)
+ expect(merge_request).not_to receive(:merge_pipeline)
+
+ described_class.for_merge_request(merge_request, admin)
+ end
+ end
+
+ describe '.after_merge_request' do
+ let(:admin) { create(:admin) }
+ let(:pipeline) { create(:ci_pipeline, sha: sha) }
+
+ before do
+ merge_request.mark_as_merged!
+ end
+
+ it 'is based on merge_request.merge_pipeline' do
+ expect(merge_request).to receive(:merge_pipeline).and_return(pipeline)
+ expect(merge_request).not_to receive(:head_pipeline)
+
+ described_class.after_merge_request(merge_request, admin)
+ end
+ end
end
diff --git a/spec/models/global_milestone_spec.rb b/spec/models/global_milestone_spec.rb
index ab58f5c5021..b6355455c1d 100644
--- a/spec/models/global_milestone_spec.rb
+++ b/spec/models/global_milestone_spec.rb
@@ -92,41 +92,6 @@ describe GlobalMilestone do
end
end
- describe '.states_count' do
- context 'when the projects have milestones' do
- before do
- create(:closed_milestone, title: 'Active Group Milestone', project: project3)
- create(:active_milestone, title: 'Active Group Milestone', project: project1)
- create(:active_milestone, title: 'Active Group Milestone', project: project2)
- create(:closed_milestone, title: 'Closed Group Milestone', project: project1)
- create(:closed_milestone, title: 'Closed Group Milestone', project: project2)
- create(:closed_milestone, title: 'Closed Group Milestone', project: project3)
- end
-
- it 'returns the quantity of global milestones in each possible state' do
- expected_count = { opened: 1, closed: 2, all: 2 }
-
- count = described_class.states_count(Project.all)
-
- expect(count).to eq(expected_count)
- end
- end
-
- context 'when the projects do not have milestones' do
- before do
- project1
- end
-
- it 'returns 0 as the quantity of global milestones in each state' do
- expected_count = { opened: 0, closed: 0, all: 0 }
-
- count = described_class.states_count(Project.all)
-
- expect(count).to eq(expected_count)
- end
- end
- end
-
describe '#initialize' do
let(:milestone1_project1) { create(:milestone, title: "Milestone v1.2", project: project1) }
let(:milestone1_project2) { create(:milestone, title: "Milestone v1.2", project: project2) }
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 1bf8f89e126..ada00f03928 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -19,6 +19,8 @@ describe Group do
it { is_expected.to have_one(:chat_team) }
it { is_expected.to have_many(:custom_attributes).class_name('GroupCustomAttribute') }
it { is_expected.to have_many(:badges).class_name('GroupBadge') }
+ it { is_expected.to have_many(:cluster_groups).class_name('Clusters::Group') }
+ it { is_expected.to have_many(:clusters).class_name('Clusters::Cluster') }
describe '#members & #requesters' do
let(:requester) { create(:user) }
@@ -651,10 +653,10 @@ describe Group do
end
end
- describe '#secret_variables_for' do
+ describe '#ci_variables_for' do
let(:project) { create(:project, group: group) }
- let!(:secret_variable) do
+ let!(:ci_variable) do
create(:ci_group_variable, value: 'secret', group: group)
end
@@ -662,11 +664,11 @@ describe Group do
create(:ci_group_variable, :protected, value: 'protected', group: group)
end
- subject { group.secret_variables_for('ref', project) }
+ subject { group.ci_variables_for('ref', project) }
shared_examples 'ref is protected' do
it 'contains all the variables' do
- is_expected.to contain_exactly(secret_variable, protected_variable)
+ is_expected.to contain_exactly(ci_variable, protected_variable)
end
end
@@ -676,8 +678,8 @@ describe Group do
default_branch_protection: Gitlab::Access::PROTECTION_NONE)
end
- it 'contains only the secret variables' do
- is_expected.to contain_exactly(secret_variable)
+ it 'contains only the CI variables' do
+ is_expected.to contain_exactly(ci_variable)
end
end
@@ -710,9 +712,9 @@ describe Group do
end
it 'returns all variables belong to the group and parent groups' do
- expected_array1 = [protected_variable, secret_variable]
+ expected_array1 = [protected_variable, ci_variable]
expected_array2 = [variable_child, variable_child_2, variable_child_3]
- got_array = group_child_3.secret_variables_for('ref', project).to_a
+ got_array = group_child_3.ci_variables_for('ref', project).to_a
expect(got_array.shift(2)).to contain_exactly(*expected_array1)
expect(got_array).to eq(expected_array2)
diff --git a/spec/models/lfs_object_spec.rb b/spec/models/lfs_object_spec.rb
index 6e35511e848..3f929710862 100644
--- a/spec/models/lfs_object_spec.rb
+++ b/spec/models/lfs_object_spec.rb
@@ -2,19 +2,13 @@ require 'spec_helper'
describe LfsObject do
describe '#local_store?' do
- it 'returns true when file_store is nil' do
- subject.file_store = nil
-
- expect(subject.local_store?).to eq true
- end
-
it 'returns true when file_store is equal to LfsObjectUploader::Store::LOCAL' do
subject.file_store = LfsObjectUploader::Store::LOCAL
expect(subject.local_store?).to eq true
end
- it 'returns false whe file_store is equal to LfsObjectUploader::Store::REMOTE' do
+ it 'returns false when file_store is equal to LfsObjectUploader::Store::REMOTE' do
subject.file_store = LfsObjectUploader::Store::REMOTE
expect(subject.local_store?).to eq false
@@ -83,19 +77,6 @@ describe LfsObject do
describe 'file is being stored' do
let(:lfs_object) { create(:lfs_object, :with_file) }
- context 'when object has nil store' do
- before do
- lfs_object.update_column(:file_store, nil)
- lfs_object.reload
- end
-
- it 'is stored locally' do
- expect(lfs_object.file_store).to be(nil)
- expect(lfs_object.file).to be_file_storage
- expect(lfs_object.file.object_store).to eq(ObjectStorage::Store::LOCAL)
- end
- end
-
context 'when existing object has local store' do
it 'is stored locally' do
expect(lfs_object.file_store).to be(ObjectStorage::Store::LOCAL)
diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb
index 90cce826b6c..47e8f04e728 100644
--- a/spec/models/merge_request_diff_spec.rb
+++ b/spec/models/merge_request_diff_spec.rb
@@ -52,9 +52,9 @@ describe MergeRequestDiff do
context 'when it was not cleaned by the system' do
it 'returns persisted diffs' do
- expect(diff).to receive(:load_diffs)
+ expect(diff).to receive(:load_diffs).and_call_original
- diff.diffs
+ diff.diffs.diff_files
end
end
@@ -76,19 +76,19 @@ describe MergeRequestDiff do
end
it 'returns persisted diffs if cannot compare with diff refs' do
- expect(diff).to receive(:load_diffs)
+ expect(diff).to receive(:load_diffs).and_call_original
diff.update!(head_commit_sha: 'invalid-sha')
- diff.diffs
+ diff.diffs.diff_files
end
it 'returns persisted diffs if diff refs does not exist' do
- expect(diff).to receive(:load_diffs)
+ expect(diff).to receive(:load_diffs).and_call_original
diff.update!(start_commit_sha: nil, base_commit_sha: nil)
- diff.diffs
+ diff.diffs.diff_files
end
end
end
@@ -211,4 +211,25 @@ describe MergeRequestDiff do
expect(diff_with_commits.commits_count).to eq(29)
end
end
+
+ describe '#commits_by_shas' do
+ let(:commit_shas) { diff_with_commits.commit_shas }
+
+ it 'returns empty if no SHAs were provided' do
+ expect(diff_with_commits.commits_by_shas([])).to be_empty
+ end
+
+ it 'returns one SHA' do
+ commits = diff_with_commits.commits_by_shas([commit_shas.first, Gitlab::Git::BLANK_SHA])
+
+ expect(commits.count).to eq(1)
+ end
+
+ it 'returns all matching SHAs' do
+ commits = diff_with_commits.commits_by_shas(commit_shas)
+
+ expect(commits.count).to eq(commit_shas.count)
+ expect(commits.map(&:sha)).to match_array(commit_shas)
+ end
+ end
end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 666d7e69f89..2eb5e39ccfd 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -13,6 +13,20 @@ describe MergeRequest do
it { is_expected.to belong_to(:merge_user).class_name("User") }
it { is_expected.to belong_to(:assignee) }
it { is_expected.to have_many(:merge_request_diffs) }
+
+ context 'for forks' do
+ let!(:project) { create(:project) }
+ let!(:fork) { fork_project(project) }
+ let!(:merge_request) { create(:merge_request, target_project: project, source_project: fork) }
+
+ it 'does not load another project due to inverse relationship' do
+ expect(project.merge_requests.first.target_project.object_id).to eq(project.object_id)
+ end
+
+ it 'finds the associated merge request' do
+ expect(project.merge_requests.find(merge_request.id)).to eq(merge_request)
+ end
+ end
end
describe '#squash_in_progress?' do
@@ -538,9 +552,9 @@ describe MergeRequest do
it 'delegates to the MR diffs' do
merge_request.save
- expect(merge_request.merge_request_diff).to receive(:raw_diffs).with(hash_including(options))
+ expect(merge_request.merge_request_diff).to receive(:raw_diffs).with(hash_including(options)).and_call_original
- merge_request.diffs(options)
+ merge_request.diffs(options).diff_files
end
end
@@ -1058,6 +1072,26 @@ describe MergeRequest do
end
end
+ describe '#merge_pipeline' do
+ it 'returns nil when not merged' do
+ expect(subject.merge_pipeline).to be_nil
+ end
+
+ context 'when the MR is merged' do
+ let(:sha) { subject.target_project.commit.id }
+ let(:pipeline) { create(:ci_empty_pipeline, sha: sha, ref: subject.target_branch, project: subject.target_project) }
+
+ before do
+ subject.mark_as_merged!
+ subject.update_attribute(:merge_commit_sha, pipeline.sha)
+ end
+
+ it 'returns the post-merge pipeline' do
+ expect(subject.merge_pipeline).to eq(pipeline)
+ end
+ end
+ end
+
describe '#has_ci?' do
let(:merge_request) { build_stubbed(:merge_request) }
@@ -2577,6 +2611,32 @@ describe MergeRequest do
end
end
+ describe '#includes_any_commits?' do
+ it 'returns false' do
+ expect(subject.includes_any_commits?([Gitlab::Git::BLANK_SHA])).to be_falsey
+ end
+
+ it 'returns true' do
+ expect(subject.includes_any_commits?([subject.merge_request_diff.head_commit_sha])).to be_truthy
+ end
+
+ it 'returns true even when there is a non-existent comit' do
+ expect(subject.includes_any_commits?([Gitlab::Git::BLANK_SHA, subject.merge_request_diff.head_commit_sha])).to be_truthy
+ end
+
+ context 'unpersisted merge request' do
+ let(:new_mr) { build(:merge_request) }
+
+ it 'returns false' do
+ expect(new_mr.includes_any_commits?([Gitlab::Git::BLANK_SHA])).to be_falsey
+ end
+
+ it 'returns true' do
+ expect(new_mr.includes_any_commits?([subject.merge_request_diff.head_commit_sha])).to be_truthy
+ end
+ end
+ end
+
describe '#can_allow_collaboration?' do
let(:target_project) { create(:project, :public) }
let(:source_project) { fork_project(target_project) }
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index 27d4e622710..d11eb46159e 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -348,4 +348,41 @@ describe Milestone do
end
end
end
+
+ describe '.states_count' do
+ context 'when the projects have milestones' do
+ before do
+ project_1 = create(:project)
+ project_2 = create(:project)
+ group_1 = create(:group)
+ group_2 = create(:group)
+
+ create(:active_milestone, title: 'Active Group Milestone', project: project_1)
+ create(:closed_milestone, title: 'Closed Group Milestone', project: project_1)
+ create(:active_milestone, title: 'Active Group Milestone', project: project_2)
+ create(:closed_milestone, title: 'Closed Group Milestone', project: project_2)
+ create(:closed_milestone, title: 'Active Group Milestone', group: group_1)
+ create(:closed_milestone, title: 'Closed Group Milestone', group: group_1)
+ create(:closed_milestone, title: 'Active Group Milestone', group: group_2)
+ create(:closed_milestone, title: 'Closed Group Milestone', group: group_2)
+ end
+
+ it 'returns the quantity of milestones in each possible state' do
+ expected_count = { opened: 5, closed: 6, all: 11 }
+
+ count = described_class.states_count(Project.all, Group.all)
+ expect(count).to eq(expected_count)
+ end
+ end
+
+ context 'when the projects do not have milestones' do
+ it 'returns 0 as the quantity of global milestones in each state' do
+ expected_count = { opened: 0, closed: 0, all: 0 }
+
+ count = described_class.states_count([project])
+
+ expect(count).to eq(expected_count)
+ end
+ end
+ end
end
diff --git a/spec/models/personal_access_token_spec.rb b/spec/models/personal_access_token_spec.rb
index 2bb1c49b740..c82ab9c9e62 100644
--- a/spec/models/personal_access_token_spec.rb
+++ b/spec/models/personal_access_token_spec.rb
@@ -49,18 +49,36 @@ describe PersonalAccessToken do
describe 'Redis storage' do
let(:user_id) { 123 }
- let(:token) { 'abc000foo' }
+ let(:token) { 'KS3wegQYXBLYhQsciwsj' }
- before do
- subject.redis_store!(user_id, token)
+ context 'reading encrypted data' do
+ before do
+ subject.redis_store!(user_id, token)
+ end
+
+ it 'returns stored data' do
+ expect(subject.redis_getdel(user_id)).to eq(token)
+ end
end
- it 'returns stored data' do
- expect(subject.redis_getdel(user_id)).to eq(token)
+ context 'reading unencrypted data' do
+ before do
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.set(described_class.redis_shared_state_key(user_id),
+ token,
+ ex: PersonalAccessToken::REDIS_EXPIRY_TIME)
+ end
+ end
+
+ it 'returns stored data unmodified' do
+ expect(subject.redis_getdel(user_id)).to eq(token)
+ end
end
context 'after deletion' do
before do
+ subject.redis_store!(user_id, token)
+
expect(subject.redis_getdel(user_id)).to eq(token)
end
diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb
index 0cd712e2f40..b0fd2ceead0 100644
--- a/spec/models/project_services/hipchat_service_spec.rb
+++ b/spec/models/project_services/hipchat_service_spec.rb
@@ -387,4 +387,22 @@ describe HipchatService do
end
end
end
+
+ context 'with UrlBlocker' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:hipchat) { described_class.new(project: project) }
+ let(:push_sample_data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
+
+ describe '#execute' do
+ before do
+ hipchat.server = 'http://localhost:9123'
+ end
+
+ it 'raises UrlBlocker for localhost' do
+ expect(Gitlab::UrlBlocker).to receive(:validate!).and_call_original
+ expect { hipchat.execute(push_sample_data) }.to raise_error(Gitlab::HTTP::BlockedUrlError)
+ end
+ end
+ end
end
diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb
index 68ab9fd08ec..9c27357ffaf 100644
--- a/spec/models/project_services/kubernetes_service_spec.rb
+++ b/spec/models/project_services/kubernetes_service_spec.rb
@@ -253,7 +253,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
end
end
- describe '#predefined_variables' do
+ describe '#predefined_variable' do
let(:kubeconfig) do
config_file = expand_fixture_path('config/kubeconfig.yml')
config = YAML.load(File.read(config_file))
@@ -274,7 +274,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
shared_examples 'setting variables' do
it 'sets the variables' do
- expect(subject.predefined_variables).to include(
+ expect(subject.predefined_variables(project: project)).to include(
{ key: 'KUBE_URL', value: 'https://kube.domain.com', public: true },
{ key: 'KUBE_TOKEN', value: 'token', public: false },
{ key: 'KUBE_NAMESPACE', value: namespace, public: true },
@@ -301,7 +301,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
it_behaves_like 'setting variables'
it 'sets the KUBE_NAMESPACE' do
- kube_namespace = subject.predefined_variables.find { |h| h[:key] == 'KUBE_NAMESPACE' }
+ kube_namespace = subject.predefined_variables(project: project).find { |h| h[:key] == 'KUBE_NAMESPACE' }
expect(kube_namespace).not_to be_nil
expect(kube_namespace[:value]).to match(/\A#{Gitlab::PathRegex::PATH_REGEX_STR}-\d+\z/)
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 62a38c66d99..d059854214f 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -88,6 +88,10 @@ describe Project do
it { is_expected.to have_many(:project_deploy_tokens) }
it { is_expected.to have_many(:deploy_tokens).through(:project_deploy_tokens) }
+ it 'has an inverse relationship with merge requests' do
+ expect(described_class.reflect_on_association(:merge_requests).has_inverse?).to eq(:target_project)
+ end
+
context 'after initialized' do
it "has a project_feature" do
expect(described_class.new.project_feature).to be_present
@@ -2401,12 +2405,24 @@ describe Project do
it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
end
- context 'when user configured kubernetes from CI/CD > Clusters' do
+ context 'when user configured kubernetes from CI/CD > Clusters and KubernetesNamespace migration has not been executed' do
let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:project) { cluster.project }
it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
end
+
+ context 'when user configured kubernetes from CI/CD > Clusters and KubernetesNamespace migration has been executed' do
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace) }
+ let!(:cluster) { kubernetes_namespace.cluster }
+ let(:project) { kubernetes_namespace.project }
+
+ it 'should return token from kubernetes namespace' do
+ expect(project.deployment_variables).to include(
+ { key: 'KUBE_TOKEN', value: kubernetes_namespace.service_account_token, public: false }
+ )
+ end
+ end
end
end
@@ -2432,10 +2448,10 @@ describe Project do
end
end
- describe '#secret_variables_for' do
+ describe '#ci_variables_for' do
let(:project) { create(:project) }
- let!(:secret_variable) do
+ let!(:ci_variable) do
create(:ci_variable, value: 'secret', project: project)
end
@@ -2443,7 +2459,7 @@ describe Project do
create(:ci_variable, :protected, value: 'protected', project: project)
end
- subject { project.reload.secret_variables_for(ref: 'ref') }
+ subject { project.reload.ci_variables_for(ref: 'ref') }
before do
stub_application_setting(
@@ -2452,13 +2468,13 @@ describe Project do
shared_examples 'ref is protected' do
it 'contains all the variables' do
- is_expected.to contain_exactly(secret_variable, protected_variable)
+ is_expected.to contain_exactly(ci_variable, protected_variable)
end
end
context 'when the ref is not protected' do
- it 'contains only the secret variables' do
- is_expected.to contain_exactly(secret_variable)
+ it 'contains only the CI variables' do
+ is_expected.to contain_exactly(ci_variable)
end
end
@@ -2746,7 +2762,7 @@ describe Project do
.to raise_error(ActiveRecord::RecordNotSaved, error_message)
end
- it 'updates the project succesfully' do
+ it 'updates the project successfully' do
merge_request = create(:merge_request, target_project: project, source_project: project)
expect { project.append_or_update_attribute(:merge_requests, [merge_request]) }
@@ -3314,7 +3330,7 @@ describe Project do
end
end
- context 'when explicitely enabled' do
+ context 'when explicitly enabled' do
context 'when domain is empty' do
before do
create(:project_auto_devops, project: project, domain: nil)
diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb
index f38fc191943..cc5e34782ec 100644
--- a/spec/models/project_wiki_spec.rb
+++ b/spec/models/project_wiki_spec.rb
@@ -145,7 +145,7 @@ describe ProjectWiki do
end
it "returns nil if the page does not exist" do
- expect(subject.find_page("non-existant")).to eq(nil)
+ expect(subject.find_page("non-existent")).to eq(nil)
end
it "can find a page by slug" do
@@ -226,7 +226,7 @@ describe ProjectWiki do
end
it 'returns nil if the page does not exist' do
- expect(subject.find_file('non-existant')).to eq(nil)
+ expect(subject.find_file('non-existent')).to eq(nil)
end
it 'returns a Gitlab::Git::WikiFile instance' do
diff --git a/spec/models/upload_spec.rb b/spec/models/upload_spec.rb
index 36b8e5d304f..3c89e99abf0 100644
--- a/spec/models/upload_spec.rb
+++ b/spec/models/upload_spec.rb
@@ -91,7 +91,7 @@ describe Upload do
.to change { upload.checksum }.from(nil).to(expected)
end
- it 'sets `checksum` to nil for a non-existant file' do
+ it 'sets `checksum` to nil for a non-existent file' do
expect(upload).to receive(:exist?).and_return(false)
checksum = Digest::SHA256.file(__FILE__).hexdigest
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index b3474e74aa4..4e7c8523e65 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -730,6 +730,14 @@ describe User do
expect(user.incoming_email_token).not_to be_blank
end
+
+ it 'uses SecureRandom to generate the incoming email token' do
+ expect(SecureRandom).to receive(:hex).and_return('3b8ca303')
+
+ user = create(:user)
+
+ expect(user.incoming_email_token).to eql('gitlab')
+ end
end
describe '#ensure_user_rights_and_limits' do