summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects/clusters_controller_spec.rb2
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb84
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb2
-rw-r--r--spec/controllers/projects/pages_domains_controller_spec.rb64
-rw-r--r--spec/factories/pages_domains.rb4
-rw-r--r--spec/features/admin/admin_users_spec.rb26
-rw-r--r--spec/features/container_registry_spec.rb4
-rw-r--r--spec/features/projects/clusters/gcp_spec.rb1
-rw-r--r--spec/features/projects/pages_lets_encrypt_spec.rb153
-rw-r--r--spec/features/projects/pages_spec.rb16
-rw-r--r--spec/frontend/vue_shared/components/paginated_list_spec.js56
-rw-r--r--spec/helpers/appearances_helper_spec.rb16
-rw-r--r--spec/javascripts/jobs/components/stages_dropdown_spec.js8
-rw-r--r--spec/javascripts/notes/components/diff_with_note_spec.js13
-rw-r--r--spec/javascripts/pages/labels/components/promote_label_modal_spec.js4
-rw-r--r--spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js4
-rw-r--r--spec/javascripts/registry/components/collapsible_container_spec.js22
-rw-r--r--spec/javascripts/registry/components/table_registry_spec.js30
-rw-r--r--spec/javascripts/registry/stores/actions_spec.js24
-rw-r--r--spec/javascripts/releases/components/release_block_spec.js14
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js14
-rw-r--r--spec/lib/banzai/filter/relative_link_filter_spec.rb7
-rw-r--r--spec/lib/gitlab/bitbucket_import/importer_spec.rb27
-rw-r--r--spec/lib/gitlab/ci/ansi2html_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/trace/stream_spec.rb10
-rw-r--r--spec/lib/gitlab/highlight_spec.rb13
-rw-r--r--spec/lib/gitlab/json_cache_spec.rb68
-rw-r--r--spec/lib/gitlab/kubernetes_spec.rb24
-rw-r--r--spec/mailers/notify_spec.rb28
-rw-r--r--spec/migrations/migrate_legacy_managed_clusters_to_unmanaged_spec.rb55
-rw-r--r--spec/migrations/migrate_managed_clusters_with_no_token_to_unmanaged_spec.rb59
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb55
-rw-r--r--spec/models/concerns/deployment_platform_spec.rb53
-rw-r--r--spec/models/pages_domain_spec.rb96
-rw-r--r--spec/models/project_services/kubernetes_service_spec.rb8
-rw-r--r--spec/models/project_spec.rb4
-rw-r--r--spec/requests/api/pages_domains_spec.rb8
-rw-r--r--spec/serializers/merge_request_widget_entity_spec.rb13
-rw-r--r--spec/services/clusters/gcp/finalize_creation_service_spec.rb10
-rw-r--r--spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb56
-rw-r--r--spec/services/clusters/update_service_spec.rb1
-rw-r--r--spec/services/issues/reorder_service_spec.rb88
-rw-r--r--spec/services/issues/update_service_spec.rb16
-rw-r--r--spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb6
-rw-r--r--spec/support/helpers/kubernetes_helpers.rb24
-rw-r--r--spec/support/shared_examples/ci_trace_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/notify_shared_examples.rb14
-rw-r--r--spec/tasks/gitlab/check_rake_spec.rb9
-rw-r--r--spec/workers/cluster_provision_worker_spec.rb7
50 files changed, 979 insertions, 357 deletions
diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb
index fa49438287f..35cbab57037 100644
--- a/spec/controllers/projects/clusters_controller_spec.rb
+++ b/spec/controllers/projects/clusters_controller_spec.rb
@@ -340,7 +340,6 @@ describe Projects::ClustersController do
describe 'security' do
before do
- allow(ClusterConfigureWorker).to receive(:perform_async)
stub_kubeclient_get_namespace('https://kubernetes.example.com', namespace: 'my-namespace')
end
@@ -438,7 +437,6 @@ describe Projects::ClustersController do
end
before do
- allow(ClusterConfigureWorker).to receive(:perform_async)
stub_kubeclient_get_namespace('https://kubernetes.example.com', namespace: 'my-namespace')
end
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index 32607fc5f56..f82e3c8c7dc 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -320,6 +320,90 @@ describe Projects::IssuesController do
end
end
+ describe 'PUT #reorder' do
+ let(:group) { create(:group, projects: [project]) }
+ let!(:issue1) { create(:issue, project: project, relative_position: 10) }
+ let!(:issue2) { create(:issue, project: project, relative_position: 20) }
+ let!(:issue3) { create(:issue, project: project, relative_position: 30) }
+
+ before do
+ sign_in(user)
+ end
+
+ context 'when user has access' do
+ before do
+ project.add_developer(user)
+ end
+
+ context 'with valid params' do
+ it 'reorders issues and returns a successful 200 response' do
+ reorder_issue(issue1,
+ move_after_id: issue2.id,
+ move_before_id: issue3.id,
+ group_full_path: group.full_path)
+
+ [issue1, issue2, issue3].map(&:reload)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(issue1.relative_position)
+ .to be_between(issue2.relative_position, issue3.relative_position)
+ end
+ end
+
+ context 'with invalid params' do
+ it 'returns a unprocessable entity 422 response for invalid move ids' do
+ reorder_issue(issue1, move_after_id: 99, move_before_id: 999)
+
+ expect(response).to have_gitlab_http_status(422)
+ end
+
+ it 'returns a not found 404 response for invalid issue id' do
+ reorder_issue(object_double(issue1, iid: 999),
+ move_after_id: issue2.id,
+ move_before_id: issue3.id)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'returns a unprocessable entity 422 response for issues not in group' do
+ another_group = create(:group)
+
+ reorder_issue(issue1,
+ move_after_id: issue2.id,
+ move_before_id: issue3.id,
+ group_full_path: another_group.full_path)
+
+ expect(response).to have_gitlab_http_status(422)
+ end
+ end
+ end
+
+ context 'with unauthorized user' do
+ before do
+ project.add_guest(user)
+ end
+
+ it 'responds with 404' do
+ reorder_issue(issue1, move_after_id: issue2.id, move_before_id: issue3.id)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ def reorder_issue(issue, move_after_id: nil, move_before_id: nil, group_full_path: nil)
+ put :reorder,
+ params: {
+ namespace_id: project.namespace.to_param,
+ project_id: project,
+ id: issue.iid,
+ move_after_id: move_after_id,
+ move_before_id: move_before_id,
+ group_full_path: group_full_path
+ },
+ format: :json
+ end
+ end
+
describe 'PUT #update' do
subject do
put :update,
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 34cbf0c8723..0eca663a683 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -1001,6 +1001,8 @@ describe Projects::MergeRequestsController do
before do
project.add_developer(user)
sign_in(user)
+
+ expect(::Gitlab::GitalyClient).to receive(:allow_ref_name_caching).and_call_original
end
it 'returns 200' do
diff --git a/spec/controllers/projects/pages_domains_controller_spec.rb b/spec/controllers/projects/pages_domains_controller_spec.rb
index ff3afd51cd8..032f4f1418f 100644
--- a/spec/controllers/projects/pages_domains_controller_spec.rb
+++ b/spec/controllers/projects/pages_domains_controller_spec.rb
@@ -15,7 +15,10 @@ describe Projects::PagesDomainsController do
end
let(:pages_domain_params) do
- build(:pages_domain, domain: 'my.otherdomain.com').slice(:key, :certificate, :domain)
+ attributes_for(:pages_domain, domain: 'my.otherdomain.com').slice(:key, :certificate, :domain).tap do |params|
+ params[:user_provided_key] = params.delete(:key)
+ params[:user_provided_certificate] = params.delete(:certificate)
+ end
end
before do
@@ -84,48 +87,59 @@ describe Projects::PagesDomainsController do
controller.instance_variable_set(:@domain, pages_domain)
end
- let(:pages_domain_params) do
- attributes_for(:pages_domain).slice(:key, :certificate)
- end
-
let(:params) do
request_params.merge(id: pages_domain.domain, pages_domain: pages_domain_params)
end
- it 'updates the domain' do
- expect(pages_domain)
- .to receive(:update)
- .with(ActionController::Parameters.new(pages_domain_params).permit!)
- .and_return(true)
+ context 'with valid params' do
+ let(:pages_domain_params) do
+ attributes_for(:pages_domain, :with_trusted_chain).slice(:key, :certificate).tap do |params|
+ params[:user_provided_key] = params.delete(:key)
+ params[:user_provided_certificate] = params.delete(:certificate)
+ end
+ end
+
+ it 'updates the domain' do
+ expect do
+ patch(:update, params: params)
+ end.to change { pages_domain.reload.certificate }.to(pages_domain_params[:user_provided_certificate])
+ end
+
+ it 'redirects to the project page' do
+ patch(:update, params: params)
- patch(:update, params: params)
+ expect(flash[:notice]).to eq 'Domain was updated'
+ expect(response).to redirect_to(project_pages_path(project))
+ end
end
- it 'redirects to the project page' do
- patch(:update, params: params)
+ context 'with key parameter' do
+ before do
+ pages_domain.update!(key: nil, certificate: nil, certificate_source: 'gitlab_provided')
+ end
- expect(flash[:notice]).to eq 'Domain was updated'
- expect(response).to redirect_to(project_pages_path(project))
+ it 'marks certificate as provided by user' do
+ expect do
+ patch(:update, params: params)
+ end.to change { pages_domain.reload.certificate_source }.from('gitlab_provided').to('user_provided')
+ end
end
context 'the domain is invalid' do
- it 'renders the edit action' do
- allow(pages_domain).to receive(:update).and_return(false)
+ let(:pages_domain_params) { { user_provided_certificate: 'blabla' } }
+ it 'renders the edit action' do
patch(:update, params: params)
expect(response).to render_template('edit')
end
end
- context 'the parameters include the domain' do
- it 'renders 400 Bad Request' do
- expect(pages_domain)
- .to receive(:update)
- .with(hash_not_including(:domain))
- .and_return(true)
-
- patch(:update, params: params.deep_merge(pages_domain: { domain: 'abc' }))
+ context 'when parameters include the domain' do
+ it 'does not update domain' do
+ expect do
+ patch(:update, params: params.deep_merge(pages_domain: { domain: 'abc' }))
+ end.not_to change { pages_domain.reload.domain }
end
end
end
diff --git a/spec/factories/pages_domains.rb b/spec/factories/pages_domains.rb
index db8384877b0..8da19a37a6a 100644
--- a/spec/factories/pages_domains.rb
+++ b/spec/factories/pages_domains.rb
@@ -180,5 +180,9 @@ Iy6oRpHaCF/2obZdIdgf9rlyz0fkqyHJc9GkioSoOhJZxEV2SgAkap8yS0sX2tJ9
ZDXgrA==
-----END CERTIFICATE-----'
end
+
+ trait :letsencrypt do
+ certificate_source { :gitlab_provided }
+ end
end
end
diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb
index 29545779a34..dafec29dfcc 100644
--- a/spec/features/admin/admin_users_spec.rb
+++ b/spec/features/admin/admin_users_spec.rb
@@ -419,6 +419,32 @@ describe "Admin::Users" do
end
end
end
+
+ describe 'Email verification status' do
+ let!(:secondary_email) do
+ create :email, email: 'secondary@example.com', user: user
+ end
+
+ it 'displays the correct status for an unverified email address' do
+ user.update(confirmed_at: nil, unconfirmed_email: user.email)
+ visit admin_user_path(user)
+
+ expect(page).to have_content("#{user.email} Unverified")
+
+ expect(page).to have_content("#{secondary_email.email} Unverified")
+ end
+
+ it 'displays the correct status for a verified email address' do
+ visit admin_user_path(user)
+ expect(page).to have_content("#{user.email} Verified")
+
+ secondary_email.confirm
+ expect(secondary_email.confirmed?).to be_truthy
+
+ visit admin_user_path(user)
+ expect(page).to have_content("#{secondary_email.email} Verified")
+ end
+ end
end
describe "GET /admin/users/:id/edit" do
diff --git a/spec/features/container_registry_spec.rb b/spec/features/container_registry_spec.rb
index 6f9901815e1..21d97aba0c5 100644
--- a/spec/features/container_registry_spec.rb
+++ b/spec/features/container_registry_spec.rb
@@ -42,6 +42,8 @@ describe "Container Registry", :js do
.to receive(:delete_tags!).and_return(true)
click_on(class: 'js-remove-repo')
+ expect(find('.modal .modal-title')).to have_content 'Remove repository'
+ find('.modal .modal-footer .btn-danger').click
end
it 'user removes a specific tag from container repository' do
@@ -54,6 +56,8 @@ describe "Container Registry", :js do
.to receive(:delete).and_return(true)
click_on(class: 'js-delete-registry')
+ expect(find('.modal .modal-title')).to have_content 'Remove image'
+ find('.modal .modal-footer .btn-danger').click
end
end
diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb
index e4a3a1a8c92..974e0f84681 100644
--- a/spec/features/projects/clusters/gcp_spec.rb
+++ b/spec/features/projects/clusters/gcp_spec.rb
@@ -118,7 +118,6 @@ describe 'Gcp Cluster', :js do
context 'when user changes cluster parameters' do
before do
- allow(ClusterConfigureWorker).to receive(:perform_async)
fill_in 'cluster_platform_kubernetes_attributes_namespace', with: 'my-namespace'
page.within('#js-cluster-details') { click_button 'Save changes' }
end
diff --git a/spec/features/projects/pages_lets_encrypt_spec.rb b/spec/features/projects/pages_lets_encrypt_spec.rb
index baa217cbe58..a5f8702302c 100644
--- a/spec/features/projects/pages_lets_encrypt_spec.rb
+++ b/spec/features/projects/pages_lets_encrypt_spec.rb
@@ -2,124 +2,119 @@
require 'spec_helper'
describe "Pages with Let's Encrypt", :https_pages_enabled do
+ include LetsEncryptHelpers
+
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:role) { :maintainer }
- let(:certificate_pem) do
- <<~PEM
- -----BEGIN CERTIFICATE-----
- MIICGzCCAYSgAwIBAgIBATANBgkqhkiG9w0BAQUFADAbMRkwFwYDVQQDExB0ZXN0
- LWNlcnRpZmljYXRlMB4XDTE2MDIxMjE0MzIwMFoXDTIwMDQxMjE0MzIwMFowGzEZ
- MBcGA1UEAxMQdGVzdC1jZXJ0aWZpY2F0ZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
- gYkCgYEApL4J9L0ZxFJ1hI1LPIflAlAGvm6ZEvoT4qKU5Xf2JgU7/2geNR1qlNFa
- SvCc08Knupp5yTgmvyK/Xi09U0N82vvp4Zvr/diSc4A/RA6Mta6egLySNT438kdT
- nY2tR5feoTLwQpX0t4IMlwGQGT5h6Of2fKmDxzuwuyffcIHqLdsCAwEAAaNvMG0w
- DAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUxl9WSxBprB0z0ibJs3rXEk0+95AwCwYD
- VR0PBAQDAgXgMBEGCWCGSAGG+EIBAQQEAwIGQDAeBglghkgBhvhCAQ0EERYPeGNh
- IGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAA4GBAGC4T8SlFHK0yPSa+idGLQFQ
- joZp2JHYvNlTPkRJ/J4TcXxBTJmArcQgTIuNoBtC+0A/SwdK4MfTCUY4vNWNdese
- 5A4K65Nb7Oh1AdQieTBHNXXCdyFsva9/ScfQGEl7p55a52jOPs0StPd7g64uvjlg
- YHi2yesCrOvVXt+lgPTd
- -----END CERTIFICATE-----
- PEM
- end
+ let(:certificate_pem) { attributes_for(:pages_domain)[:certificate] }
- let(:certificate_key) do
- <<~KEY
- -----BEGIN PRIVATE KEY-----
- MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKS+CfS9GcRSdYSN
- SzyH5QJQBr5umRL6E+KilOV39iYFO/9oHjUdapTRWkrwnNPCp7qaeck4Jr8iv14t
- PVNDfNr76eGb6/3YknOAP0QOjLWunoC8kjU+N/JHU52NrUeX3qEy8EKV9LeCDJcB
- kBk+Yejn9nypg8c7sLsn33CB6i3bAgMBAAECgYA2D26w80T7WZvazYr86BNMePpd
- j2mIAqx32KZHzt/lhh40J/SRtX9+Kl0Y7nBoRR5Ja9u/HkAIxNxLiUjwg9r6cpg/
- uITEF5nMt7lAk391BuI+7VOZZGbJDsq2ulPd6lO+C8Kq/PI/e4kXcIjeH6KwQsuR
- 5vrXfBZ3sQfflaiN4QJBANBt8JY2LIGQF8o89qwUpRL5vbnKQ4IzZ5+TOl4RLR7O
- AQpJ81tGuINghO7aunctb6rrcKJrxmEH1whzComybrMCQQDKV49nOBudRBAIgG4K
- EnLzsRKISUHMZSJiYTYnablof8cKw1JaQduw7zgrUlLwnroSaAGX88+Jw1f5n2Lh
- Vlg5AkBDdUGnrDLtYBCDEQYZHblrkc7ZAeCllDOWjxUV+uMqlCv8A4Ey6omvY57C
- m6I8DkWVAQx8VPtozhvHjUw80rZHAkB55HWHAM3h13axKG0htCt7klhPsZHpx6MH
- EPjGlXIT+aW2XiPmK3ZlCDcWIenE+lmtbOpI159Wpk8BGXs/s/xBAkEAlAY3ymgx
- 63BDJEwvOb2IaP8lDDxNsXx9XJNVvQbv5n15vNsLHbjslHfAhAbxnLQ1fLhUPqSi
- nNp/xedE1YxutQ==
- -----END PRIVATE KEY-----
- KEY
- end
+ let(:certificate_key) { attributes_for(:pages_domain)[:key] }
before do
allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
+ stub_lets_encrypt_settings
+
project.add_role(user, role)
sign_in(user)
project.namespace.update(owner: user)
allow_any_instance_of(Project).to receive(:pages_deployed?) { true }
end
- context 'when the page_auto_ssl feature flag is enabled' do
- before do
- stub_feature_flags(pages_auto_ssl: true)
+ context 'when the auto SSL management is initially disabled' do
+ let(:domain) do
+ create(:pages_domain, auto_ssl_enabled: false, project: project)
end
- context 'when the auto SSL management is initially disabled' do
- let(:domain) do
- create(:pages_domain, auto_ssl_enabled: false, project: project)
- end
+ it 'enables auto SSL and dynamically updates the form accordingly', :js do
+ visit edit_project_pages_domain_path(project, domain)
- it 'enables auto SSL and dynamically updates the form accordingly', :js do
- visit edit_project_pages_domain_path(project, domain)
+ expect(domain.auto_ssl_enabled).to eq false
- expect(domain.auto_ssl_enabled).to eq false
+ expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false'
+ expect(page).to have_field 'Certificate (PEM)', type: 'textarea'
+ expect(page).to have_field 'Key (PEM)', type: 'textarea'
- expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false'
- expect(page).to have_field 'Certificate (PEM)', type: 'textarea'
- expect(page).to have_field 'Key (PEM)', type: 'textarea'
+ find('.js-auto-ssl-toggle-container .project-feature-toggle').click
- find('.js-auto-ssl-toggle-container .project-feature-toggle').click
+ expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
+ expect(page).not_to have_field 'Certificate (PEM)', type: 'textarea'
+ expect(page).not_to have_field 'Key (PEM)', type: 'textarea'
- expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
- expect(page).not_to have_field 'Certificate (PEM)', type: 'textarea'
- expect(page).not_to have_field 'Key (PEM)', type: 'textarea'
- expect(page).to have_content "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+ click_on 'Save Changes'
- click_on 'Save Changes'
+ expect(domain.reload.auto_ssl_enabled).to eq true
+ end
+ end
- expect(domain.reload.auto_ssl_enabled).to eq true
- end
+ context 'when the auto SSL management is initially enabled' do
+ let(:domain) do
+ create(:pages_domain, :letsencrypt, auto_ssl_enabled: true, project: project)
end
- context 'when the auto SSL management is initially enabled' do
- let(:domain) do
- create(:pages_domain, auto_ssl_enabled: true, project: project)
- end
+ it 'disables auto SSL and dynamically updates the form accordingly', :js do
+ visit edit_project_pages_domain_path(project, domain)
- it 'disables auto SSL and dynamically updates the form accordingly', :js do
- visit edit_project_pages_domain_path(project, domain)
+ expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
+ expect(page).not_to have_field 'Certificate (PEM)', type: 'textarea'
+ expect(page).not_to have_field 'Key (PEM)', type: 'textarea'
- expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
- expect(page).to have_field 'Certificate (PEM)', type: 'textarea', disabled: true
- expect(page).not_to have_field 'Key (PEM)', type: 'textarea'
+ find('.js-auto-ssl-toggle-container .project-feature-toggle').click
- find('.js-auto-ssl-toggle-container .project-feature-toggle').click
+ expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false'
+ expect(page).to have_field 'Certificate (PEM)', type: 'textarea'
+ expect(page).to have_field 'Key (PEM)', type: 'textarea'
- expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false'
- expect(page).to have_field 'Certificate (PEM)', type: 'textarea'
- expect(page).to have_field 'Key (PEM)', type: 'textarea'
+ fill_in 'Certificate (PEM)', with: certificate_pem
+ fill_in 'Key (PEM)', with: certificate_key
- fill_in 'Certificate (PEM)', with: certificate_pem
- fill_in 'Key (PEM)', with: certificate_key
+ click_on 'Save Changes'
- click_on 'Save Changes'
+ expect(domain.reload.auto_ssl_enabled).to eq false
+ end
+ end
- expect(domain.reload.auto_ssl_enabled).to eq false
+ shared_examples 'user sees private keys only for user provided certificate' do
+ before do
+ visit edit_project_pages_domain_path(project, domain)
+ end
+
+ shared_examples 'user do not see private key' do
+ it 'user do not see private key' do
+ expect(find_field('Key (PEM)', visible: :all, disabled: :all).value).to be_blank
+ end
+ end
+
+ context 'when auto_ssl is enabled for domain' do
+ let(:domain) { create(:pages_domain, :letsencrypt, project: project, auto_ssl_enabled: true) }
+
+ include_examples 'user do not see private key'
+ end
+
+ context 'when auto_ssl is disabled for domain' do
+ let(:domain) { create(:pages_domain, :letsencrypt, project: project) }
+
+ include_examples 'user do not see private key'
+ end
+
+ context 'when certificate is provided by user' do
+ let(:domain) { create(:pages_domain, project: project) }
+
+ it 'user sees private key' do
+ expect(find_field('Key (PEM)').value).not_to be_blank
end
end
end
- context 'when the page_auto_ssl feature flag is disabled' do
+ include_examples 'user sees private keys only for user provided certificate'
+
+ context 'when letsencrypt is disabled' do
let(:domain) do
create(:pages_domain, auto_ssl_enabled: false, project: project)
end
before do
- stub_feature_flags(pages_auto_ssl: false)
+ stub_application_setting(lets_encrypt_terms_of_service_accepted: false)
visit edit_project_pages_domain_path(project, domain)
end
@@ -127,5 +122,7 @@ describe "Pages with Let's Encrypt", :https_pages_enabled do
it "does not render the Let's Encrypt field", :js do
expect(page).not_to have_selector '.js-auto-ssl-toggle-container'
end
+
+ include_examples 'user sees private keys only for user provided certificate'
end
end
diff --git a/spec/features/projects/pages_spec.rb b/spec/features/projects/pages_spec.rb
index 9bb0ba81ef5..c4b3ddb2088 100644
--- a/spec/features/projects/pages_spec.rb
+++ b/spec/features/projects/pages_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-shared_examples 'pages domain editing' do
+shared_examples 'pages settings editing' do
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:role) { :maintainer }
@@ -321,19 +321,15 @@ shared_examples 'pages domain editing' do
end
describe 'Pages' do
- context 'when pages_auto_ssl feature flag is disabled' do
- before do
- stub_feature_flags(pages_auto_ssl: false)
- end
+ include LetsEncryptHelpers
- include_examples 'pages domain editing'
- end
+ include_examples 'pages settings editing'
- context 'when pages_auto_ssl feature flag is enabled' do
+ context 'when letsencrypt support is enabled' do
before do
- stub_feature_flags(pages_auto_ssl: true)
+ stub_lets_encrypt_settings
end
- include_examples 'pages domain editing'
+ include_examples 'pages settings editing'
end
end
diff --git a/spec/frontend/vue_shared/components/paginated_list_spec.js b/spec/frontend/vue_shared/components/paginated_list_spec.js
new file mode 100644
index 00000000000..31ac362d35f
--- /dev/null
+++ b/spec/frontend/vue_shared/components/paginated_list_spec.js
@@ -0,0 +1,56 @@
+import PaginatedList from '~/vue_shared/components/paginated_list.vue';
+import { PREV, NEXT } from '~/vue_shared/components/pagination/constants';
+import { mount } from '@vue/test-utils';
+
+describe('Pagination links component', () => {
+ let wrapper;
+ let glPaginatedList;
+
+ const template = `
+ <div class="slot" slot-scope="{ listItem }">
+ <span class="item">Item Name: {{listItem.id}}</span>
+ </div>
+ `;
+
+ const props = {
+ prevText: PREV,
+ nextText: NEXT,
+ };
+
+ beforeEach(() => {
+ wrapper = mount(PaginatedList, {
+ scopedSlots: {
+ default: template,
+ },
+ propsData: {
+ list: [{ id: 'foo' }, { id: 'bar' }],
+ props,
+ },
+ });
+
+ [glPaginatedList] = wrapper.vm.$children;
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('Paginated List Component', () => {
+ describe('props', () => {
+ // We test attrs and not props because we pass through to child component using v-bind:"$attrs"
+ it('should pass prevText to GitLab UI paginated list', () => {
+ expect(glPaginatedList.$attrs['prev-text']).toBe(props.prevText);
+ });
+ it('should pass nextText to GitLab UI paginated list', () => {
+ expect(glPaginatedList.$attrs['next-text']).toBe(props.nextText);
+ });
+ });
+
+ describe('rendering', () => {
+ it('it renders the gl-paginated-list', () => {
+ expect(wrapper.contains('ul.list-group')).toBe(true);
+ expect(wrapper.findAll('li.list-group-item').length).toBe(2);
+ });
+ });
+ });
+});
diff --git a/spec/helpers/appearances_helper_spec.rb b/spec/helpers/appearances_helper_spec.rb
index a3511e078ce..ed3e31b3c53 100644
--- a/spec/helpers/appearances_helper_spec.rb
+++ b/spec/helpers/appearances_helper_spec.rb
@@ -8,6 +8,22 @@ describe AppearancesHelper do
allow(helper).to receive(:current_user).and_return(user)
end
+ describe '.current_appearance' do
+ it 'memoizes empty appearance' do
+ expect(Appearance).to receive(:current).once
+
+ 2.times { helper.current_appearance }
+ end
+
+ it 'memoizes custom appearance' do
+ create(:appearance)
+
+ expect(Appearance).to receive(:current).once.and_call_original
+
+ 2.times { helper.current_appearance }
+ end
+ end
+
describe '#header_message' do
it 'returns nil when header message field is not set' do
create(:appearance)
diff --git a/spec/javascripts/jobs/components/stages_dropdown_spec.js b/spec/javascripts/jobs/components/stages_dropdown_spec.js
index 52bb5161123..86b7a8d7848 100644
--- a/spec/javascripts/jobs/components/stages_dropdown_spec.js
+++ b/spec/javascripts/jobs/components/stages_dropdown_spec.js
@@ -101,9 +101,7 @@ describe('Stages Dropdown', () => {
});
it(`renders the pipeline info text like "Pipeline #123 for !456 with source_branch into target_branch"`, () => {
- const expected = `Pipeline #${pipeline.id} for !${pipeline.merge_request.iid} with ${
- pipeline.merge_request.source_branch
- } into ${pipeline.merge_request.target_branch}`;
+ const expected = `Pipeline #${pipeline.id} for !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch} into ${pipeline.merge_request.target_branch}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
expect(actual).toBe(expected);
@@ -144,9 +142,7 @@ describe('Stages Dropdown', () => {
});
it(`renders the pipeline info like "Pipeline #123 for !456 with source_branch"`, () => {
- const expected = `Pipeline #${pipeline.id} for !${pipeline.merge_request.iid} with ${
- pipeline.merge_request.source_branch
- }`;
+ const expected = `Pipeline #${pipeline.id} for !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
expect(actual).toBe(expected);
diff --git a/spec/javascripts/notes/components/diff_with_note_spec.js b/spec/javascripts/notes/components/diff_with_note_spec.js
index 0752bd05904..f849fe9d8bb 100644
--- a/spec/javascripts/notes/components/diff_with_note_spec.js
+++ b/spec/javascripts/notes/components/diff_with_note_spec.js
@@ -47,6 +47,19 @@ describe('diff_with_note', () => {
vm = mountComponentWithStore(Component, { props, store });
});
+ it('removes trailing "+" char', () => {
+ const richText = vm.$el.querySelectorAll('.line_holder')[4].querySelector('.line_content')
+ .textContent[0];
+
+ expect(richText).not.toEqual('+');
+ });
+
+ it('removes trailing "-" char', () => {
+ const richText = vm.$el.querySelector('#LC13').parentNode.textContent[0];
+
+ expect(richText).not.toEqual('-');
+ });
+
it('shows text diff', () => {
expect(selectors.container).toHaveClass('text-file');
expect(selectors.diffTable).toExist();
diff --git a/spec/javascripts/pages/labels/components/promote_label_modal_spec.js b/spec/javascripts/pages/labels/components/promote_label_modal_spec.js
index 08a8362797b..75912612255 100644
--- a/spec/javascripts/pages/labels/components/promote_label_modal_spec.js
+++ b/spec/javascripts/pages/labels/components/promote_label_modal_spec.js
@@ -26,9 +26,7 @@ describe('Promote label modal', () => {
it('contains the proper description', () => {
expect(vm.text).toContain(
- `Promoting ${labelMockData.labelTitle} will make it available for all projects inside ${
- labelMockData.groupName
- }`,
+ `Promoting ${labelMockData.labelTitle} will make it available for all projects inside ${labelMockData.groupName}`,
);
});
diff --git a/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js b/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js
index 2ac73ef3024..3d25a278cef 100644
--- a/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js
+++ b/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js
@@ -24,9 +24,7 @@ describe('Promote milestone modal', () => {
it('contains the proper description', () => {
expect(vm.text).toContain(
- `Promoting ${
- milestoneMockData.milestoneTitle
- } will make it available for all projects inside ${milestoneMockData.groupName}.`,
+ `Promoting ${milestoneMockData.milestoneTitle} will make it available for all projects inside ${milestoneMockData.groupName}.`,
);
});
diff --git a/spec/javascripts/registry/components/collapsible_container_spec.js b/spec/javascripts/registry/components/collapsible_container_spec.js
index a3f7ff76dc7..9ed4b04324a 100644
--- a/spec/javascripts/registry/components/collapsible_container_spec.js
+++ b/spec/javascripts/registry/components/collapsible_container_spec.js
@@ -12,6 +12,8 @@ describe('collapsible registry container', () => {
let mock;
const Component = Vue.extend(collapsibleComponent);
+ const findDeleteBtn = () => vm.$el.querySelector('.js-remove-repo');
+
beforeEach(() => {
mock = new MockAdapter(axios);
@@ -67,7 +69,25 @@ describe('collapsible registry container', () => {
describe('delete repo', () => {
it('should be possible to delete a repo', () => {
- expect(vm.$el.querySelector('.js-remove-repo')).not.toBeNull();
+ expect(findDeleteBtn()).not.toBeNull();
+ });
+
+ describe('clicked on delete', () => {
+ beforeEach(done => {
+ findDeleteBtn().click();
+ Vue.nextTick(done);
+ });
+
+ it('should open confirmation modal', () => {
+ expect(vm.$el.querySelector('#confirm-repo-deletion-modal')).not.toBeNull();
+ });
+
+ it('should call deleteItem when confirming deletion', () => {
+ spyOn(vm, 'deleteItem').and.returnValue(Promise.resolve());
+ vm.$el.querySelector('#confirm-repo-deletion-modal .btn-danger').click();
+
+ expect(vm.deleteItem).toHaveBeenCalledWith(vm.repo);
+ });
});
});
});
diff --git a/spec/javascripts/registry/components/table_registry_spec.js b/spec/javascripts/registry/components/table_registry_spec.js
index 7f5252a7d6c..d366c67a1b9 100644
--- a/spec/javascripts/registry/components/table_registry_spec.js
+++ b/spec/javascripts/registry/components/table_registry_spec.js
@@ -3,10 +3,14 @@ import tableRegistry from '~/registry/components/table_registry.vue';
import store from '~/registry/stores';
import { repoPropsData } from '../mock_data';
+const [firstImage] = repoPropsData.list;
+
describe('table registry', () => {
let vm;
let Component;
+ const findDeleteBtn = () => vm.$el.querySelector('.js-delete-registry');
+
beforeEach(() => {
Component = Vue.extend(tableRegistry);
vm = new Component({
@@ -37,8 +41,30 @@ describe('table registry', () => {
expect(textRendered).toContain(repoPropsData.list[0].size);
});
- it('should be possible to delete a registry', () => {
- expect(vm.$el.querySelector('.table tbody tr .js-delete-registry')).toBeDefined();
+ describe('delete registry', () => {
+ it('should be possible to delete a registry', () => {
+ expect(findDeleteBtn()).toBeDefined();
+ });
+
+ describe('clicked on delete', () => {
+ beforeEach(done => {
+ findDeleteBtn().click();
+ Vue.nextTick(done);
+ });
+
+ it('should open confirmation modal and set itemToBeDeleted properly', () => {
+ expect(vm.itemToBeDeleted).toEqual(firstImage);
+ expect(vm.$el.querySelector('#confirm-image-deletion-modal')).not.toBeNull();
+ });
+
+ it('should call deleteItem and reset itemToBeDeleted when confirming deletion', () => {
+ spyOn(vm, 'deleteItem').and.returnValue(Promise.resolve());
+ vm.$el.querySelector('#confirm-image-deletion-modal .btn-danger').click();
+
+ expect(vm.deleteItem).toHaveBeenCalledWith(firstImage);
+ expect(vm.itemToBeDeleted).toBeNull();
+ });
+ });
});
describe('pagination', () => {
diff --git a/spec/javascripts/registry/stores/actions_spec.js b/spec/javascripts/registry/stores/actions_spec.js
index c9aa82dba90..0613ec8e0f1 100644
--- a/spec/javascripts/registry/stores/actions_spec.js
+++ b/spec/javascripts/registry/stores/actions_spec.js
@@ -105,4 +105,28 @@ describe('Actions Registry Store', () => {
);
});
});
+
+ describe('deleteItem', () => {
+ it('should perform DELETE request on destroyPath', done => {
+ const destroyPath = `${TEST_HOST}/mygroup/myproject/container_registry/1.json`;
+ let deleted = false;
+ mock.onDelete(destroyPath).replyOnce(() => {
+ deleted = true;
+ return [200];
+ });
+ testAction(
+ actions.deleteItem,
+ {
+ destroyPath,
+ },
+ mockedState,
+ )
+ .then(() => {
+ expect(mock.history.delete.length).toBe(1);
+ expect(deleted).toBe(true);
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
});
diff --git a/spec/javascripts/releases/components/release_block_spec.js b/spec/javascripts/releases/components/release_block_spec.js
index 36b181f24ef..e98c665f99d 100644
--- a/spec/javascripts/releases/components/release_block_spec.js
+++ b/spec/javascripts/releases/components/release_block_spec.js
@@ -78,8 +78,10 @@ describe('Release block', () => {
};
let vm;
+ const factory = props => mountComponent(Component, { release: props });
+
beforeEach(() => {
- vm = mountComponent(Component, { release });
+ vm = factory(release);
});
afterEach(() => {
@@ -149,4 +151,14 @@ describe('Release block', () => {
);
});
});
+
+ describe('with pre_release flag', () => {
+ beforeEach(() => {
+ vm = factory(Object.assign({}, release, { pre_release: true }));
+ });
+
+ it('renders pre-release badge', () => {
+ expect(vm.$el.textContent).toContain('Pre-release');
+ });
+ });
});
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
index 75017d20473..fe831094ecf 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
@@ -222,9 +222,7 @@ describe('MRWidgetPipeline', () => {
sourceBranchLink: mockCopy.source_branch_link,
});
- const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${
- pipeline.commit.short_id
- } on ${mockCopy.source_branch_link}`;
+ const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${pipeline.commit.short_id} on ${mockCopy.source_branch_link}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info-container').innerText);
@@ -247,11 +245,7 @@ describe('MRWidgetPipeline', () => {
sourceBranchLink: mockCopy.source_branch_link,
});
- const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${
- pipeline.commit.short_id
- } on !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch} into ${
- pipeline.merge_request.target_branch
- }`;
+ const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${pipeline.commit.short_id} on !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch} into ${pipeline.merge_request.target_branch}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info-container').innerText);
@@ -274,9 +268,7 @@ describe('MRWidgetPipeline', () => {
sourceBranchLink: mockCopy.source_branch_link,
});
- const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${
- pipeline.commit.short_id
- } on !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch}`;
+ const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${pipeline.commit.short_id} on !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info-container').innerText);
diff --git a/spec/lib/banzai/filter/relative_link_filter_spec.rb b/spec/lib/banzai/filter/relative_link_filter_spec.rb
index dad0a5535c0..8ff971114d6 100644
--- a/spec/lib/banzai/filter/relative_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/relative_link_filter_spec.rb
@@ -101,6 +101,13 @@ describe Banzai::Filter::RelativeLinkFilter do
.to eq "/#{project_path}/blob/#{ref}/doc/api/README.md"
end
+ it 'does not modify relative URLs in system notes' do
+ path = "#{project_path}/merge_requests/1/diffs"
+ doc = filter(link(path), system_note: true)
+
+ expect(doc.at_css('a')['href']).to eq path
+ end
+
it 'ignores absolute URLs with two leading slashes' do
doc = filter(link('//doc/api/README.md'))
expect(doc.at_css('a')['href']).to eq '//doc/api/README.md'
diff --git a/spec/lib/gitlab/bitbucket_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importer_spec.rb
index 2e90f6c7f71..35700e0b588 100644
--- a/spec/lib/gitlab/bitbucket_import/importer_spec.rb
+++ b/spec/lib/gitlab/bitbucket_import/importer_spec.rb
@@ -98,12 +98,8 @@ describe Gitlab::BitbucketImport::Importer do
describe '#import_pull_requests' do
let(:source_branch_sha) { sample.commits.last }
let(:target_branch_sha) { sample.commits.first }
-
- before do
- allow(subject).to receive(:import_wiki)
- allow(subject).to receive(:import_issues)
-
- pull_request = instance_double(
+ let(:pull_request) do
+ instance_double(
Bitbucket::Representation::PullRequest,
iid: 10,
source_branch_sha: source_branch_sha,
@@ -116,6 +112,11 @@ describe Gitlab::BitbucketImport::Importer do
author: 'other',
created_at: Time.now,
updated_at: Time.now)
+ end
+
+ before do
+ allow(subject).to receive(:import_wiki)
+ allow(subject).to receive(:import_issues)
# https://gitlab.com/gitlab-org/gitlab-test/compare/c1acaa58bbcbc3eafe538cb8274ba387047b69f8...5937ac0a7beb003549fc5fd26fc247ad
@inline_note = instance_double(
@@ -167,6 +168,20 @@ describe Gitlab::BitbucketImport::Importer do
expect(reply_note.note).to eq(@reply.note)
end
+ context 'when importing a pull request throws an exception' do
+ before do
+ allow(pull_request).to receive(:raw).and_return('hello world')
+ allow(subject.client).to receive(:pull_request_comments).and_raise(HTTParty::Error)
+ end
+
+ it 'logs an error without the backtrace' do
+ subject.execute
+
+ expect(subject.errors.count).to eq(1)
+ expect(subject.errors.first.keys).to match_array(%i(type iid errors))
+ end
+ end
+
context "when branches' sha is not found in the repository" do
let(:source_branch_sha) { 'a' * Commit::MIN_SHA_LENGTH }
let(:target_branch_sha) { 'b' * Commit::MIN_SHA_LENGTH }
diff --git a/spec/lib/gitlab/ci/ansi2html_spec.rb b/spec/lib/gitlab/ci/ansi2html_spec.rb
index 3d57ce431ab..aa4e358b148 100644
--- a/spec/lib/gitlab/ci/ansi2html_spec.rb
+++ b/spec/lib/gitlab/ci/ansi2html_spec.rb
@@ -141,11 +141,11 @@ describe Gitlab::Ci::Ansi2html do
end
it "replaces newlines with line break tags" do
- expect(convert_html("\n")).to eq('<span class=""><br/><span class=""></span></span>')
+ expect(convert_html("\n")).to eq('<span class=""></span><br/><span class=""></span>')
end
it "groups carriage returns with newlines" do
- expect(convert_html("\r\n")).to eq('<span class=""><br/><span class=""></span></span>')
+ expect(convert_html("\r\n")).to eq('<span class=""></span><br/><span class=""></span>')
end
describe "incremental update" do
@@ -193,7 +193,7 @@ describe Gitlab::Ci::Ansi2html do
let(:pre_text) { "Hello\r" }
let(:pre_html) { "<span class=\"\">Hello\r</span>" }
let(:text) { "\nWorld" }
- let(:html) { "<span class=\"\"><br/><span class=\"\">World</span></span>" }
+ let(:html) { "<span class=\"\"></span><br/><span class=\"\">World</span>" }
it_behaves_like 'stateable converter'
end
@@ -232,7 +232,7 @@ describe Gitlab::Ci::Ansi2html do
it 'prints light red' do
text = "#{section_start}\e[91mHello\e[0m\n#{section_end}"
header = %{<span class="term-fg-l-red section js-section-header section-header js-s-#{class_name(section_name)}">Hello</span>}
- line_break = %{<span class="section js-section-header section-header js-s-#{class_name(section_name)}"><br/></span>}
+ line_break = %{<span class="section js-section-header section-header js-s-#{class_name(section_name)}"></span><br/>}
line = %{<span class="section line s_#{class_name(section_name)}"></span>}
empty_line = %{<span class="section js-s-#{class_name(section_name)}"></span>}
html = "#{section_start_html}#{header}#{line_break}#{line}#{empty_line}#{section_end_html}"
diff --git a/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb b/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
index 5ac5122e800..c5bc81a2b9e 100644
--- a/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
+++ b/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
@@ -45,12 +45,6 @@ describe Gitlab::Ci::Build::Prerequisite::KubernetesNamespace do
it { is_expected.to be_truthy }
end
end
-
- context 'and cluster is project type' do
- let(:cluster) { create(:cluster, :project) }
-
- it { is_expected.to be_falsey }
- end
end
context 'and no cluster to deploy to' do
diff --git a/spec/lib/gitlab/ci/trace/stream_spec.rb b/spec/lib/gitlab/ci/trace/stream_spec.rb
index 35250632e86..0d03eef99c8 100644
--- a/spec/lib/gitlab/ci/trace/stream_spec.rb
+++ b/spec/lib/gitlab/ci/trace/stream_spec.rb
@@ -65,9 +65,9 @@ describe Gitlab::Ci::Trace::Stream, :clean_gitlab_redis_cache do
result = stream.html
expect(result).to eq(
- "<span class=\"\">ヾ(´༎ຶД༎ຶ`)ノ<br/><span class=\"\"></span></span>"\
- "<span class=\"term-fg-green\">許功蓋</span><span class=\"\"><br/>"\
- "<span class=\"\"></span></span>")
+ "<span class=\"\">ヾ(´༎ຶД༎ຶ`)ノ</span><br/><span class=\"\"></span>"\
+ "<span class=\"term-fg-green\">許功蓋</span><span class=\"\"></span><br/>"\
+ "<span class=\"\"></span>")
expect(result.encoding).to eq(Encoding.default_external)
end
end
@@ -306,8 +306,8 @@ describe Gitlab::Ci::Trace::Stream, :clean_gitlab_redis_cache do
shared_examples_for 'htmls' do
it "returns html" do
expect(stream.html).to eq(
- "<span class=\"\">12<br/><span class=\"\">34<br/>"\
- "<span class=\"\">56</span></span></span>")
+ "<span class=\"\">12</span><br/><span class=\"\">34</span><br/>"\
+ "<span class=\"\">56</span>")
end
it "returns html for last line only" do
diff --git a/spec/lib/gitlab/highlight_spec.rb b/spec/lib/gitlab/highlight_spec.rb
index fe0e9702f8a..4676db6b8d8 100644
--- a/spec/lib/gitlab/highlight_spec.rb
+++ b/spec/lib/gitlab/highlight_spec.rb
@@ -18,9 +18,10 @@ describe Gitlab::Highlight do
end
describe '#highlight' do
+ let(:plain_text_file_name) { "test.txt" }
+ let(:plain_text_content) { "plain text contents" }
let(:file_name) { 'test.lisp' }
- let(:no_context_content) { ":type \"assem\"))" }
- let(:content) { "(make-pathname :defaults name\n#{no_context_content}" }
+ let(:content) { "(make-pathname :defaults name\n:type \"assem\")" }
let(:multiline_content) do
%q(
def test(input):
@@ -32,22 +33,22 @@ describe Gitlab::Highlight do
it 'highlights' do
expected = %Q[<span id="LC1" class="line" lang="common_lisp"><span class="p">(</span><span class="nb">make-pathname</span> <span class="ss">:defaults</span> <span class="nv">name</span></span>
-<span id="LC2" class="line" lang="common_lisp"><span class="ss">:type</span> <span class="s">"assem"</span><span class="p">))</span></span>]
+<span id="LC2" class="line" lang="common_lisp"><span class="ss">:type</span> <span class="s">"assem"</span><span class="p">)</span></span>]
expect(described_class.highlight(file_name, content)).to eq(expected)
end
it 'returns plain version for unknown lexer context' do
- result = described_class.highlight(file_name, no_context_content)
+ result = described_class.highlight(plain_text_file_name, plain_text_content)
- expect(result).to eq(%[<span id="LC1" class="line" lang="">:type "assem"))</span>])
+ expect(result).to eq(%[<span id="LC1" class="line" lang="plaintext">plain text contents</span>])
end
it 'returns plain version for long content' do
stub_const('Gitlab::Highlight::MAXIMUM_TEXT_HIGHLIGHT_SIZE', 1)
result = described_class.highlight(file_name, content)
- expect(result).to eq(%[<span id="LC1" class="line" lang="">(make-pathname :defaults name</span>\n<span id="LC2" class="line" lang="">:type "assem"))</span>])
+ expect(result).to eq(%[<span id="LC1" class="line" lang="">(make-pathname :defaults name</span>\n<span id="LC2" class="line" lang="">:type "assem")</span>])
end
it 'highlights multi-line comments' do
diff --git a/spec/lib/gitlab/json_cache_spec.rb b/spec/lib/gitlab/json_cache_spec.rb
index c6a6042c65c..59160741c45 100644
--- a/spec/lib/gitlab/json_cache_spec.rb
+++ b/spec/lib/gitlab/json_cache_spec.rb
@@ -6,7 +6,7 @@ describe Gitlab::JsonCache do
let(:backend) { double('backend').as_null_object }
let(:namespace) { 'geo' }
let(:key) { 'foo' }
- let(:expanded_key) { "#{namespace}:#{key}:#{Rails.version}" }
+ let(:expanded_key) { "#{namespace}:#{key}:#{Gitlab::VERSION}:#{Rails.version}" }
set(:broadcast_message) { create(:broadcast_message) }
subject(:cache) { described_class.new(namespace: namespace, backend: backend) }
@@ -35,42 +35,68 @@ describe Gitlab::JsonCache do
describe '#cache_key' do
context 'when namespace is not defined' do
- it 'expands out the key with Rails version' do
- cache = described_class.new(cache_key_with_version: true)
+ context 'when cache_key_with_version is true' do
+ it 'expands out the key with GitLab, and Rails versions' do
+ cache = described_class.new(cache_key_with_version: true)
- cache_key = cache.cache_key(key)
+ cache_key = cache.cache_key(key)
- expect(cache_key).to eq("#{key}:#{Rails.version}")
+ expect(cache_key).to eq("#{key}:#{Gitlab::VERSION}:#{Rails.version}")
+ end
end
- end
- context 'when cache_key_with_version is true' do
- it 'expands out the key with namespace and Rails version' do
- cache = described_class.new(namespace: namespace, cache_key_with_version: true)
+ context 'when cache_key_with_version is false' do
+ it 'returns the key' do
+ cache = described_class.new(namespace: nil, cache_key_with_version: false)
- cache_key = cache.cache_key(key)
+ cache_key = cache.cache_key(key)
- expect(cache_key).to eq("#{namespace}:#{key}:#{Rails.version}")
+ expect(cache_key).to eq(key)
+ end
end
end
- context 'when cache_key_with_version is false' do
- it 'expands out the key with namespace' do
- cache = described_class.new(namespace: namespace, cache_key_with_version: false)
+ context 'when namespace is nil' do
+ context 'when cache_key_with_version is true' do
+ it 'expands out the key with GitLab, and Rails versions' do
+ cache = described_class.new(cache_key_with_version: true)
- cache_key = cache.cache_key(key)
+ cache_key = cache.cache_key(key)
- expect(cache_key).to eq("#{namespace}:#{key}")
+ expect(cache_key).to eq("#{key}:#{Gitlab::VERSION}:#{Rails.version}")
+ end
+ end
+
+ context 'when cache_key_with_version is false' do
+ it 'returns the key' do
+ cache = described_class.new(namespace: nil, cache_key_with_version: false)
+
+ cache_key = cache.cache_key(key)
+
+ expect(cache_key).to eq(key)
+ end
end
end
- context 'when namespace is nil, and cache_key_with_version is false' do
- it 'returns the key' do
- cache = described_class.new(namespace: nil, cache_key_with_version: false)
+ context 'when namespace is set' do
+ context 'when cache_key_with_version is true' do
+ it 'expands out the key with namespace and Rails version' do
+ cache = described_class.new(namespace: namespace, cache_key_with_version: true)
+
+ cache_key = cache.cache_key(key)
- cache_key = cache.cache_key(key)
+ expect(cache_key).to eq("#{namespace}:#{key}:#{Gitlab::VERSION}:#{Rails.version}")
+ end
+ end
- expect(cache_key).to eq(key)
+ context 'when cache_key_with_version is false' do
+ it 'expands out the key with namespace' do
+ cache = described_class.new(namespace: namespace, cache_key_with_version: false)
+
+ cache_key = cache.cache_key(key)
+
+ expect(cache_key).to eq("#{namespace}:#{key}")
+ end
end
end
end
diff --git a/spec/lib/gitlab/kubernetes_spec.rb b/spec/lib/gitlab/kubernetes_spec.rb
index 45369b91ed6..a7ea942960b 100644
--- a/spec/lib/gitlab/kubernetes_spec.rb
+++ b/spec/lib/gitlab/kubernetes_spec.rb
@@ -67,6 +67,30 @@ describe Gitlab::Kubernetes do
end
end
+ describe '#filter_by_legacy_label' do
+ let(:non_matching_pod) { kube_pod(environment_slug: 'production', project_slug: 'my-cool-app') }
+
+ let(:non_matching_pod_2) do
+ kube_pod(environment_slug: 'production', project_slug: 'my-cool-app').tap do |pod|
+ pod['metadata']['labels']['app'] = 'production'
+ end
+ end
+
+ let(:matching_pod) do
+ kube_pod.tap do |pod|
+ pod['metadata']['annotations'].delete('app.gitlab.com/env')
+ pod['metadata']['annotations'].delete('app.gitlab.com/app')
+ pod['metadata']['labels']['app'] = 'production'
+ end
+ end
+
+ it 'returns matching labels' do
+ items = [non_matching_pod, non_matching_pod_2, matching_pod]
+
+ expect(filter_by_legacy_label(items, 'my-cool-app', 'production')).to contain_exactly(matching_pod)
+ end
+ end
+
describe '#to_kubeconfig' do
let(:token) { 'TOKEN' }
let(:ca_pem) { 'PEM' }
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index cbbb22ad78c..11af6837dab 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -99,15 +99,9 @@ describe Notify do
end
end
- context 'when enabled email_author_in_body' do
- before do
- stub_application_setting(email_author_in_body: true)
- end
-
- it 'contains a link to note author' do
- is_expected.to have_body_text(issue.author_name)
- is_expected.to have_body_text 'created an issue:'
- end
+ it 'contains a link to issue author' do
+ is_expected.to have_body_text(issue.author_name)
+ is_expected.to have_body_text 'created an issue:'
end
end
@@ -314,15 +308,9 @@ describe Notify do
end
end
- context 'when enabled email_author_in_body' do
- before do
- stub_application_setting(email_author_in_body: true)
- end
-
- it 'contains a link to note author' do
- is_expected.to have_body_text merge_request.author_name
- is_expected.to have_body_text 'created a merge request:'
- end
+ it 'contains a link to merge request author' do
+ is_expected.to have_body_text merge_request.author_name
+ is_expected.to have_body_text 'created a merge request:'
end
end
@@ -907,7 +895,9 @@ describe Notify do
end
it 'contains an introduction' do
- is_expected.to have_body_text 'started a new discussion'
+ issuable_url = "project_#{note.noteable_type.underscore}_url"
+
+ is_expected.to have_body_text "started a new <a href=\"#{public_send(issuable_url, project, note.noteable, anchor: "note_#{note.id}")}\">discussion</a>"
end
context 'when a comment on an existing discussion' do
diff --git a/spec/migrations/migrate_legacy_managed_clusters_to_unmanaged_spec.rb b/spec/migrations/migrate_legacy_managed_clusters_to_unmanaged_spec.rb
new file mode 100644
index 00000000000..93426f1f273
--- /dev/null
+++ b/spec/migrations/migrate_legacy_managed_clusters_to_unmanaged_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20190606163724_migrate_legacy_managed_clusters_to_unmanaged.rb')
+
+describe MigrateLegacyManagedClustersToUnmanaged, :migration do
+ let(:cluster_type) { 'project_type' }
+ let(:created_at) { 1.hour.ago }
+
+ let!(:cluster) do
+ table(:clusters).create!(
+ name: 'cluster',
+ cluster_type: described_class::Cluster.cluster_types[cluster_type],
+ managed: true,
+ created_at: created_at
+ )
+ end
+
+ it 'marks the cluster as unmanaged' do
+ migrate!
+ expect(cluster.reload).not_to be_managed
+ end
+
+ context 'cluster is not project type' do
+ let(:cluster_type) { 'group_type' }
+
+ it 'does not update the cluster' do
+ migrate!
+ expect(cluster.reload).to be_managed
+ end
+ end
+
+ context 'cluster has a kubernetes namespace associated' do
+ before do
+ table(:clusters_kubernetes_namespaces).create!(
+ cluster_id: cluster.id,
+ namespace: 'namespace'
+ )
+ end
+
+ it 'does not update the cluster' do
+ migrate!
+ expect(cluster.reload).to be_managed
+ end
+ end
+
+ context 'cluster was recently created' do
+ let(:created_at) { 2.minutes.ago }
+
+ it 'does not update the cluster' do
+ migrate!
+ expect(cluster.reload).to be_managed
+ end
+ end
+end
diff --git a/spec/migrations/migrate_managed_clusters_with_no_token_to_unmanaged_spec.rb b/spec/migrations/migrate_managed_clusters_with_no_token_to_unmanaged_spec.rb
new file mode 100644
index 00000000000..b73bd16cb60
--- /dev/null
+++ b/spec/migrations/migrate_managed_clusters_with_no_token_to_unmanaged_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20190613231640_migrate_managed_clusters_with_no_token_to_unmanaged.rb')
+
+describe MigrateManagedClustersWithNoTokenToUnmanaged, :migration do
+ let(:cluster_type) { 'project_type' }
+ let(:created_at) { Date.new(2018, 11, 1).midnight }
+
+ let!(:cluster) do
+ table(:clusters).create!(
+ name: 'cluster',
+ cluster_type: described_class::Cluster.cluster_types[cluster_type],
+ managed: true,
+ created_at: created_at
+ )
+ end
+
+ let!(:kubernetes_namespace) do
+ table(:clusters_kubernetes_namespaces).create!(
+ cluster_id: cluster.id,
+ namespace: 'namespace'
+ )
+ end
+
+ it 'marks the cluster as unmanaged' do
+ migrate!
+ expect(cluster.reload).not_to be_managed
+ end
+
+ context 'cluster is not project type' do
+ let(:cluster_type) { 'group_type' }
+
+ it 'does not update the cluster' do
+ migrate!
+ expect(cluster.reload).to be_managed
+ end
+ end
+
+ context 'kubernetes namespace has a service account token' do
+ before do
+ kubernetes_namespace.update!(encrypted_service_account_token: "TOKEN")
+ end
+
+ it 'does not update the cluster' do
+ migrate!
+ expect(cluster.reload).to be_managed
+ end
+ end
+
+ context 'cluster was created after the cutoff' do
+ let(:created_at) { Date.new(2019, 1, 1).midnight }
+
+ it 'does not update the cluster' do
+ migrate!
+ expect(cluster.reload).to be_managed
+ end
+ end
+end
diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb
index 1fb3a8de808..05b3035e591 100644
--- a/spec/models/clusters/platforms/kubernetes_spec.rb
+++ b/spec/models/clusters/platforms/kubernetes_spec.rb
@@ -281,14 +281,14 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
it_behaves_like 'setting variables'
- it 'sets KUBE_TOKEN' do
- expect(subject).to include(
+ it 'does not set KUBE_TOKEN' do
+ expect(subject).not_to include(
{ key: 'KUBE_TOKEN', value: kubernetes.token, public: false, masked: true }
)
end
end
- context 'kubernetes namespace is created with no service account token' do
+ context 'kubernetes namespace is created with service account token' do
let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token, cluster: cluster) }
it_behaves_like 'setting variables'
@@ -340,32 +340,6 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
end
end
- context 'namespace is provided' do
- let(:namespace) { 'my-project' }
-
- before do
- kubernetes.namespace = namespace
- end
-
- it_behaves_like 'setting variables'
-
- it 'sets KUBE_TOKEN' do
- expect(subject).to include(
- { key: 'KUBE_TOKEN', value: kubernetes.token, public: false, masked: true }
- )
- end
- end
-
- context 'no namespace provided' do
- it_behaves_like 'setting variables'
-
- it 'sets KUBE_TOKEN' do
- expect(subject).to include(
- { key: 'KUBE_TOKEN', value: kubernetes.token, public: false, masked: true }
- )
- end
- end
-
context 'group level cluster' do
let!(:cluster) { create(:cluster, :group, platform_kubernetes: kubernetes) }
@@ -510,27 +484,4 @@ 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 'calls ConfigureWorker' do
- expect(ClusterConfigureWorker).to receive(:perform_async).with(cluster.id).once
-
- platform.namespace = 'new-namespace'
- platform.save
- end
- end
-
- context 'when namespace is not updated' do
- it 'does not call ConfigureWorker' do
- expect(ClusterConfigureWorker).not_to receive(:perform_async)
-
- platform.username = "new-username"
- platform.save
- end
- end
- end
end
diff --git a/spec/models/concerns/deployment_platform_spec.rb b/spec/models/concerns/deployment_platform_spec.rb
index 0e34d8fccf3..96465a51db2 100644
--- a/spec/models/concerns/deployment_platform_spec.rb
+++ b/spec/models/concerns/deployment_platform_spec.rb
@@ -8,40 +8,7 @@ describe DeploymentPlatform do
describe '#deployment_platform' do
subject { project.deployment_platform }
- context 'with no Kubernetes configuration on CI/CD, no Kubernetes Service and a Kubernetes template configured' do
- let!(:kubernetes_service) { create(:kubernetes_service, template: true) }
-
- it 'returns a platform kubernetes' do
- expect(subject).to be_a_kind_of(Clusters::Platforms::Kubernetes)
- end
-
- it 'creates a cluster and a platform kubernetes' do
- expect { subject }
- .to change { Clusters::Cluster.count }.by(1)
- .and change { Clusters::Platforms::Kubernetes.count }.by(1)
- end
-
- it 'includes appropriate attributes for Cluster' do
- cluster = subject.cluster
- expect(cluster.name).to eq('kubernetes-template')
- expect(cluster.project).to eq(project)
- expect(cluster.provider_type).to eq('user')
- expect(cluster.platform_type).to eq('kubernetes')
- end
-
- it 'creates a platform kubernetes' do
- expect { subject }.to change { Clusters::Platforms::Kubernetes.count }.by(1)
- end
-
- it 'copies attributes from Clusters::Platform::Kubernetes template into the new Cluster::Platforms::Kubernetes' do
- expect(subject.api_url).to eq(kubernetes_service.api_url)
- expect(subject.ca_pem).to eq(kubernetes_service.ca_pem)
- expect(subject.token).to eq(kubernetes_service.token)
- expect(subject.namespace).to eq(kubernetes_service.namespace)
- end
- end
-
- context 'with no Kubernetes configuration on CI/CD, no Kubernetes Service and no Kubernetes template configured' do
+ context 'with no Kubernetes configuration on CI/CD, no Kubernetes Service' do
it { is_expected.to be_nil }
end
@@ -126,23 +93,5 @@ describe DeploymentPlatform do
end
end
end
-
- context 'when user configured kubernetes integration from project services' do
- let!(:kubernetes_service) { create(:kubernetes_service, project: project) }
-
- it 'returns the Kubernetes service' do
- expect(subject).to eq(kubernetes_service)
- end
- end
-
- context 'when the cluster creation fails' do
- let!(:kubernetes_service) { create(:kubernetes_service, template: true) }
-
- before do
- allow_any_instance_of(Clusters::Cluster).to receive(:persisted?).and_return(false)
- end
-
- it { is_expected.to be_nil }
- end
end
end
diff --git a/spec/models/pages_domain_spec.rb b/spec/models/pages_domain_spec.rb
index fdc81359d34..4fb7b71a3c7 100644
--- a/spec/models/pages_domain_spec.rb
+++ b/spec/models/pages_domain_spec.rb
@@ -356,6 +356,102 @@ describe PagesDomain do
end
end
+ describe '#user_provided_key' do
+ subject { domain.user_provided_key }
+
+ context 'when certificate is provided by user' do
+ let(:domain) { create(:pages_domain) }
+
+ it 'returns key' do
+ is_expected.to eq(domain.key)
+ end
+ end
+
+ context 'when certificate is provided by gitlab' do
+ let(:domain) { create(:pages_domain, :letsencrypt) }
+
+ it 'returns nil' do
+ is_expected.to be_nil
+ end
+ end
+ end
+
+ describe '#user_provided_certificate' do
+ subject { domain.user_provided_certificate }
+
+ context 'when certificate is provided by user' do
+ let(:domain) { create(:pages_domain) }
+
+ it 'returns key' do
+ is_expected.to eq(domain.certificate)
+ end
+ end
+
+ context 'when certificate is provided by gitlab' do
+ let(:domain) { create(:pages_domain, :letsencrypt) }
+
+ it 'returns nil' do
+ is_expected.to be_nil
+ end
+ end
+ end
+
+ shared_examples 'certificate setter' do |attribute, setter_name, old_certificate_source, new_certificate_source|
+ let(:domain) do
+ create(:pages_domain, certificate_source: old_certificate_source)
+ end
+
+ let(:old_value) { domain.public_send(attribute) }
+
+ subject { domain.public_send(setter_name, new_value) }
+
+ context 'when value has been changed' do
+ let(:new_value) { 'new_value' }
+
+ it "assignes new value to #{attribute}" do
+ expect do
+ subject
+ end.to change { domain.public_send(attribute) }.from(old_value).to('new_value')
+ end
+
+ it 'changes certificate source' do
+ expect do
+ subject
+ end.to change { domain.certificate_source }.from(old_certificate_source).to(new_certificate_source)
+ end
+ end
+
+ context 'when value has not been not changed' do
+ let(:new_value) { old_value }
+
+ it 'does not change certificate source' do
+ expect do
+ subject
+ end.not_to change { domain.certificate_source }.from(old_certificate_source)
+ end
+ end
+ end
+
+ describe '#user_provided_key=' do
+ include_examples('certificate setter', 'key', 'user_provided_key=',
+ 'gitlab_provided', 'user_provided')
+ end
+
+ describe '#gitlab_provided_key=' do
+ include_examples('certificate setter', 'key', 'gitlab_provided_key=',
+ 'user_provided', 'gitlab_provided')
+ end
+
+ describe '#user_provided_certificate=' do
+ include_examples('certificate setter', 'certificate', 'user_provided_certificate=',
+ 'gitlab_provided', 'user_provided')
+ end
+
+ describe '#gitlab_provided_certificate=' do
+ include_examples('certificate setter', 'certificate', 'gitlab_provided_certificate=',
+ 'user_provided', 'gitlab_provided')
+ end
+
describe '.for_removal' do
subject { described_class.for_removal }
diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb
index 34ee1eafd5c..5d7d6c34e67 100644
--- a/spec/models/project_services/kubernetes_service_spec.rb
+++ b/spec/models/project_services/kubernetes_service_spec.rb
@@ -7,7 +7,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
include ReactiveCachingHelpers
let(:project) { create(:kubernetes_project) }
- let(:service) { project.deployment_platform }
+ let(:service) { create(:kubernetes_service, project: project) }
describe 'Associations' do
it { is_expected.to belong_to :project }
@@ -78,7 +78,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
it 'includes an error with a deprecation message' do
kubernetes_service.valid?
- expect(kubernetes_service.errors[:base].first).to match(/Kubernetes service integration has been deprecated/)
+ expect(kubernetes_service.errors[:base].first).to match(/Kubernetes service integration has been disabled/)
end
end
@@ -383,13 +383,13 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
let(:kubernetes_service) { create(:kubernetes_service) }
it 'indicates the service is deprecated' do
- expect(kubernetes_service.deprecation_message).to match(/Kubernetes service integration has been deprecated/)
+ expect(kubernetes_service.deprecation_message).to match(/Kubernetes service integration has been disabled/)
end
context 'if the service is not active' do
it 'returns a message' do
kubernetes_service.update_attribute(:active, false)
- expect(kubernetes_service.deprecation_message).to match(/Fields on this page are now uneditable/)
+ expect(kubernetes_service.deprecation_message).to match(/Fields on this page are not used by GitLab/)
end
end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 20b98b5eb85..cc0f5002a1e 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -2656,8 +2656,8 @@ describe Project do
let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:project) { cluster.project }
- it 'returns variables from this service' do
- expect(project.deployment_variables).to include(
+ it 'does not return variables from this service' do
+ expect(project.deployment_variables).not_to include(
{ key: 'KUBE_TOKEN', value: project.deployment_platform.token, public: false, masked: true }
)
end
diff --git a/spec/requests/api/pages_domains_spec.rb b/spec/requests/api/pages_domains_spec.rb
index 3eb68a6abb6..449032b95b7 100644
--- a/spec/requests/api/pages_domains_spec.rb
+++ b/spec/requests/api/pages_domains_spec.rb
@@ -359,6 +359,14 @@ describe API::PagesDomains do
expect(pages_domain_secure.certificate).to eq(params_secure_nokey[:certificate])
end
+ it 'updates certificate source to user_provided if is changed' do
+ pages_domain.update!(certificate_source: 'gitlab_provided')
+
+ expect do
+ put api(route_domain, user), params: params_secure
+ end.to change { pages_domain.reload.certificate_source }.from('gitlab_provided').to('user_provided')
+ end
+
it 'fails to update pages domain adding certificate without key' do
put api(route_domain, user), params: params_secure_nokey
diff --git a/spec/serializers/merge_request_widget_entity_spec.rb b/spec/serializers/merge_request_widget_entity_spec.rb
index a27c22191f4..ffbfac9b326 100644
--- a/spec/serializers/merge_request_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_widget_entity_spec.rb
@@ -32,6 +32,19 @@ describe MergeRequestWidgetEntity do
end
end
+ describe 'issues links' do
+ it 'includes issues links when requested' do
+ data = described_class.new(resource, request: request, issues_links: true).as_json
+
+ expect(data).to include(:issues_links)
+ expect(data[:issues_links]).to include(:assign_to_closing, :closing, :mentioned_but_not_closing)
+ end
+
+ it 'omits issue links by default' do
+ expect(subject).not_to include(:issues_links)
+ end
+ end
+
describe 'pipeline' do
let(:pipeline) { create(:ci_empty_pipeline, project: project, ref: resource.source_branch, sha: resource.source_branch_sha, head_pipeline_of: resource) }
diff --git a/spec/services/clusters/gcp/finalize_creation_service_spec.rb b/spec/services/clusters/gcp/finalize_creation_service_spec.rb
index 2664649df47..5f91acb8e84 100644
--- a/spec/services/clusters/gcp/finalize_creation_service_spec.rb
+++ b/spec/services/clusters/gcp/finalize_creation_service_spec.rb
@@ -19,10 +19,6 @@ describe Clusters::Gcp::FinalizeCreationService, '#execute' do
subject { described_class.new.execute(provider) }
- before do
- allow(ClusterConfigureWorker).to receive(:perform_async)
- end
-
shared_examples 'success' do
it 'configures provider and kubernetes' do
subject
@@ -42,12 +38,6 @@ describe Clusters::Gcp::FinalizeCreationService, '#execute' do
expect(platform.password).to eq(password)
expect(platform.token).to eq(token)
end
-
- it 'calls ClusterConfigureWorker in a ascync fashion' do
- expect(ClusterConfigureWorker).to receive(:perform_async).with(cluster.id)
-
- subject
- end
end
shared_examples 'error' do
diff --git a/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb b/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb
index a5806559b14..93c0dc37ade 100644
--- a/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb
+++ b/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb
@@ -17,7 +17,7 @@ describe Clusters::Gcp::Kubernetes::FetchKubernetesTokenService do
)
end
- subject { described_class.new(kubeclient, service_account_token_name, namespace).execute }
+ subject { described_class.new(kubeclient, service_account_token_name, namespace, token_retry_delay: 0).execute }
before do
stub_kubeclient_discover(api_url)
@@ -26,8 +26,7 @@ describe Clusters::Gcp::Kubernetes::FetchKubernetesTokenService do
context 'when params correct' do
let(:decoded_token) { 'xxx.token.xxx' }
let(:token) { Base64.encode64(decoded_token) }
-
- context 'when gitlab-token exists' do
+ context 'when the secret exists' do
before do
stub_kubeclient_get_secret(
api_url,
@@ -50,13 +49,62 @@ describe Clusters::Gcp::Kubernetes::FetchKubernetesTokenService do
it { expect { subject }.to raise_error(Kubeclient::HttpError) }
end
- context 'when gitlab-token does not exist' do
+ context 'when the secret does not exist on the first try' do
+ before do
+ stub_kubeclient_get_secret_not_found_then_found(
+ api_url,
+ {
+ metadata_name: service_account_token_name,
+ namespace: namespace,
+ token: token
+ }
+ )
+ end
+
+ it 'retries and finds the token' do
+ expect(subject).to eq(decoded_token)
+ end
+ end
+
+ context 'when the secret permanently does not exist' do
before do
stub_kubeclient_get_secret_error(api_url, service_account_token_name, namespace: namespace, status: 404)
end
it { is_expected.to be_nil }
end
+
+ context 'when the secret is missing a token on the first try' do
+ before do
+ stub_kubeclient_get_secret_missing_token_then_with_token(
+ api_url,
+ {
+ metadata_name: service_account_token_name,
+ namespace: namespace,
+ token: token
+ }
+ )
+ end
+
+ it 'retries and finds the token' do
+ expect(subject).to eq(decoded_token)
+ end
+ end
+
+ context 'when the secret is permanently missing a token' do
+ before do
+ stub_kubeclient_get_secret(
+ api_url,
+ {
+ metadata_name: service_account_token_name,
+ namespace: namespace,
+ token: nil
+ }
+ )
+ end
+
+ it { is_expected.to be_nil }
+ end
end
end
end
diff --git a/spec/services/clusters/update_service_spec.rb b/spec/services/clusters/update_service_spec.rb
index 21b37f88fd8..3ee45375dca 100644
--- a/spec/services/clusters/update_service_spec.rb
+++ b/spec/services/clusters/update_service_spec.rb
@@ -39,7 +39,6 @@ describe Clusters::UpdateService do
end
before do
- allow(ClusterConfigureWorker).to receive(:perform_async)
stub_kubeclient_get_namespace('https://kubernetes.example.com', namespace: 'my-namespace')
end
diff --git a/spec/services/issues/reorder_service_spec.rb b/spec/services/issues/reorder_service_spec.rb
new file mode 100644
index 00000000000..b147cdf4e64
--- /dev/null
+++ b/spec/services/issues/reorder_service_spec.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Issues::ReorderService do
+ set(:user) { create(:user) }
+ set(:project) { create(:project) }
+ set(:group) { create(:group) }
+
+ shared_examples 'issues reorder service' do
+ context 'when reordering issues' do
+ it 'returns false with no params' do
+ expect(service({}).execute(issue1)).to be_falsey
+ end
+
+ it 'returns false with both invalid params' do
+ params = { move_after_id: nil, move_before_id: 1 }
+
+ expect(service(params).execute(issue1)).to be_falsey
+ end
+
+ it 'sorts issues' do
+ params = { move_after_id: issue2.id, move_before_id: issue3.id }
+
+ service(params).execute(issue1)
+
+ expect(issue1.relative_position)
+ .to be_between(issue2.relative_position, issue3.relative_position)
+ end
+ end
+ end
+
+ describe '#execute' do
+ let(:issue1) { create(:issue, project: project, relative_position: 10) }
+ let(:issue2) { create(:issue, project: project, relative_position: 20) }
+ let(:issue3) { create(:issue, project: project, relative_position: 30) }
+
+ context 'when ordering issues in a project' do
+ let(:parent) { project }
+
+ before do
+ parent.add_developer(user)
+ end
+
+ it_behaves_like 'issues reorder service'
+ end
+
+ context 'when ordering issues in a group' do
+ let(:project) { create(:project, namespace: group) }
+
+ before do
+ group.add_developer(user)
+ end
+
+ it_behaves_like 'issues reorder service'
+
+ context 'when ordering in a group issue list' do
+ let(:params) { { move_after_id: issue2.id, move_before_id: issue3.id, group_full_path: group.full_path } }
+
+ subject { service(params) }
+
+ it 'sends the board_group_id parameter' do
+ match_params = { move_between_ids: [issue2.id, issue3.id], board_group_id: group.id }
+
+ expect(Issues::UpdateService)
+ .to receive(:new).with(project, user, match_params)
+ .and_return(double(execute: build(:issue)))
+
+ subject.execute(issue1)
+ end
+
+ it 'sorts issues' do
+ project2 = create(:project, namespace: group)
+ issue4 = create(:issue, project: project2)
+
+ subject.execute(issue4)
+
+ expect(issue4.relative_position)
+ .to be_between(issue2.relative_position, issue3.relative_position)
+ end
+ end
+ end
+ end
+
+ def service(params)
+ described_class.new(project, user, params)
+ end
+end
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index 22f5607cb9c..28fa5d12d9c 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -687,6 +687,22 @@ describe Issues::UpdateService, :mailer do
end
end
+ context 'when moving an issue ', :nested_groups do
+ it 'raises an error for invalid move ids within a project' do
+ opts = { move_between_ids: [9000, 9999] }
+
+ expect { described_class.new(issue.project, user, opts).execute(issue) }
+ .to raise_error(ActiveRecord::RecordNotFound)
+ end
+
+ it 'raises an error for invalid move ids within a group' do
+ opts = { move_between_ids: [9000, 9999], board_group_id: create(:group).id }
+
+ expect { described_class.new(issue.project, user, opts).execute(issue) }
+ .to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+
include_examples 'issuable update service' do
let(:open_issuable) { issue }
let(:closed_issuable) { create(:closed_issue, project: project) }
diff --git a/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb b/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb
index 6d7be27939c..d5f77f3354b 100644
--- a/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb
+++ b/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb
@@ -137,6 +137,12 @@ describe PagesDomains::ObtainLetsEncryptCertificateService do
expect(pages_domain.certificate).to eq(certificate)
end
+ it 'marks certificate as gitlab_provided' do
+ service.execute
+
+ expect(pages_domain.certificate_source).to eq("gitlab_provided")
+ end
+
it 'removes order from database' do
service.execute
diff --git a/spec/support/helpers/kubernetes_helpers.rb b/spec/support/helpers/kubernetes_helpers.rb
index 011c4df0fe5..3c7bcba2b42 100644
--- a/spec/support/helpers/kubernetes_helpers.rb
+++ b/spec/support/helpers/kubernetes_helpers.rb
@@ -104,6 +104,26 @@ module KubernetesHelpers
.to_return(status: [status, "Internal Server Error"])
end
+ def stub_kubeclient_get_secret_not_found_then_found(api_url, **options)
+ options[:metadata_name] ||= "default-token-1"
+ options[:namespace] ||= "default"
+
+ WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{options[:namespace]}/secrets/#{options[:metadata_name]}")
+ .to_return(status: [404, "Not Found"])
+ .then
+ .to_return(kube_response(kube_v1_secret_body(options)))
+ end
+
+ def stub_kubeclient_get_secret_missing_token_then_with_token(api_url, **options)
+ options[:metadata_name] ||= "default-token-1"
+ options[:namespace] ||= "default"
+
+ WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{options[:namespace]}/secrets/#{options[:metadata_name]}")
+ .to_return(kube_response(kube_v1_secret_body(options.merge(token: nil))))
+ .then
+ .to_return(kube_response(kube_v1_secret_body(options)))
+ end
+
def stub_kubeclient_get_service_account(api_url, name, namespace: 'default')
WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{namespace}/serviceaccounts/#{name}")
.to_return(kube_response({}))
@@ -184,11 +204,11 @@ module KubernetesHelpers
"kind" => "SecretList",
"apiVersion": "v1",
"metadata": {
- "name": options[:metadata_name] || "default-token-1",
+ "name": options.fetch(:metadata_name, "default-token-1"),
"namespace": "kube-system"
},
"data": {
- "token": options[:token] || Base64.encode64('token-sample-123')
+ "token": options.fetch(:token, Base64.encode64('token-sample-123'))
}
}
end
diff --git a/spec/support/shared_examples/ci_trace_shared_examples.rb b/spec/support/shared_examples/ci_trace_shared_examples.rb
index f985b2dcbba..7993b2870e5 100644
--- a/spec/support/shared_examples/ci_trace_shared_examples.rb
+++ b/spec/support/shared_examples/ci_trace_shared_examples.rb
@@ -5,7 +5,7 @@ shared_examples_for 'common trace features' do
end
it "returns formatted html" do
- expect(trace.html).to eq("<span class=\"\">12<br/><span class=\"\">34</span></span>")
+ expect(trace.html).to eq("<span class=\"\">12</span><br/><span class=\"\">34</span>")
end
it "returns last line of formatted html" do
diff --git a/spec/support/shared_examples/notify_shared_examples.rb b/spec/support/shared_examples/notify_shared_examples.rb
index 897c9106d77..6894a63ce42 100644
--- a/spec/support/shared_examples/notify_shared_examples.rb
+++ b/spec/support/shared_examples/notify_shared_examples.rb
@@ -281,18 +281,8 @@ shared_examples 'a note email' do
is_expected.to have_body_text note.note
end
- it 'does not contain note author' do
- is_expected.not_to have_body_text note.author_name
- end
-
- context 'when enabled email_author_in_body' do
- before do
- stub_application_setting(email_author_in_body: true)
- end
-
- it 'contains a link to note author' do
- is_expected.to have_body_text note.author_name
- end
+ it 'contains a link to note author' do
+ is_expected.to have_body_text note.author_name
end
end
diff --git a/spec/tasks/gitlab/check_rake_spec.rb b/spec/tasks/gitlab/check_rake_spec.rb
index 06525e3c771..0fcb9b269f3 100644
--- a/spec/tasks/gitlab/check_rake_spec.rb
+++ b/spec/tasks/gitlab/check_rake_spec.rb
@@ -96,6 +96,15 @@ describe 'check.rake' do
subject
end
+
+ it 'sanitizes output' do
+ user = double(dn: 'uid=fake_user1', uid: 'fake_user1')
+ allow(adapter).to receive(:users).and_return([user])
+ stub_env('SANITIZE', 'true')
+
+ expect { subject }.to output(/User output sanitized/).to_stdout
+ expect { subject }.not_to output('fake_user1').to_stdout
+ end
end
end
end
diff --git a/spec/workers/cluster_provision_worker_spec.rb b/spec/workers/cluster_provision_worker_spec.rb
index 9cc2ad12bfc..3f69962f25d 100644
--- a/spec/workers/cluster_provision_worker_spec.rb
+++ b/spec/workers/cluster_provision_worker_spec.rb
@@ -23,18 +23,11 @@ describe ClusterProvisionWorker do
described_class.new.perform(cluster.id)
end
-
- it 'configures kubernetes platform' do
- expect(ClusterConfigureWorker).to receive(:perform_async).with(cluster.id)
-
- described_class.new.perform(cluster.id)
- end
end
context 'when cluster does not exist' do
it 'does not provision a cluster' do
expect_any_instance_of(Clusters::Gcp::ProvisionService).not_to receive(:execute)
- expect(ClusterConfigureWorker).not_to receive(:perform_async)
described_class.new.perform(123)
end