summaryrefslogtreecommitdiff
path: root/spec/controllers
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-07-20 12:26:25 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-07-20 12:26:25 +0000
commita09983ae35713f5a2bbb100981116d31ce99826e (patch)
tree2ee2af7bd104d57086db360a7e6d8c9d5d43667a /spec/controllers
parent18c5ab32b738c0b6ecb4d0df3994000482f34bd8 (diff)
downloadgitlab-ce-a09983ae35713f5a2bbb100981116d31ce99826e.tar.gz
Add latest changes from gitlab-org/gitlab@13-2-stable-ee
Diffstat (limited to 'spec/controllers')
-rw-r--r--spec/controllers/admin/application_settings_controller_spec.rb7
-rw-r--r--spec/controllers/admin/clusters_controller_spec.rb33
-rw-r--r--spec/controllers/admin/jobs_controller_spec.rb32
-rw-r--r--spec/controllers/admin/services_controller_spec.rb22
-rw-r--r--spec/controllers/application_controller_spec.rb22
-rw-r--r--spec/controllers/autocomplete_controller_spec.rb50
-rw-r--r--spec/controllers/concerns/controller_with_feature_category/config_spec.rb53
-rw-r--r--spec/controllers/concerns/controller_with_feature_category_spec.rb66
-rw-r--r--spec/controllers/concerns/metrics_dashboard_spec.rb33
-rw-r--r--spec/controllers/concerns/renders_commits_spec.rb2
-rw-r--r--spec/controllers/concerns/sorting_preference_spec.rb4
-rw-r--r--spec/controllers/dashboard/projects_controller_spec.rb42
-rw-r--r--spec/controllers/dashboard/snippets_controller_spec.rb4
-rw-r--r--spec/controllers/dashboard/todos_controller_spec.rb9
-rw-r--r--spec/controllers/dashboard_controller_spec.rb8
-rw-r--r--spec/controllers/every_controller_spec.rb82
-rw-r--r--spec/controllers/groups/clusters_controller_spec.rb40
-rw-r--r--spec/controllers/groups/imports_controller_spec.rb2
-rw-r--r--spec/controllers/groups/runners_controller_spec.rb127
-rw-r--r--spec/controllers/groups/settings/ci_cd_controller_spec.rb15
-rw-r--r--spec/controllers/groups_controller_spec.rb36
-rw-r--r--spec/controllers/import/bitbucket_controller_spec.rb48
-rw-r--r--spec/controllers/import/bitbucket_server_controller_spec.rb81
-rw-r--r--spec/controllers/import/fogbugz_controller_spec.rb23
-rw-r--r--spec/controllers/import/gitlab_controller_spec.rb23
-rw-r--r--spec/controllers/instance_statistics/cohorts_controller_spec.rb7
-rw-r--r--spec/controllers/instance_statistics/dev_ops_score_controller_spec.rb13
-rw-r--r--spec/controllers/invites_controller_spec.rb37
-rw-r--r--spec/controllers/oauth/applications_controller_spec.rb16
-rw-r--r--spec/controllers/profiles/keys_controller_spec.rb65
-rw-r--r--spec/controllers/projects/clusters_controller_spec.rb42
-rw-r--r--spec/controllers/projects/cycle_analytics_controller_spec.rb7
-rw-r--r--spec/controllers/projects/deployments_controller_spec.rb46
-rw-r--r--spec/controllers/projects/discussions_controller_spec.rb3
-rw-r--r--spec/controllers/projects/environments/prometheus_api_controller_spec.rb206
-rw-r--r--spec/controllers/projects/environments_controller_spec.rb45
-rw-r--r--spec/controllers/projects/graphs_controller_spec.rb9
-rw-r--r--spec/controllers/projects/imports_controller_spec.rb171
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb39
-rw-r--r--spec/controllers/projects/jobs_controller_spec.rb103
-rw-r--r--spec/controllers/projects/logs_controller_spec.rb28
-rw-r--r--spec/controllers/projects/merge_requests/diffs_controller_spec.rb12
-rw-r--r--spec/controllers/projects/merge_requests/drafts_controller_spec.rb9
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb4
-rw-r--r--spec/controllers/projects/notes_controller_spec.rb84
-rw-r--r--spec/controllers/projects/pipelines/stages_controller_spec.rb (renamed from spec/controllers/projects/stages_controller_spec.rb)4
-rw-r--r--spec/controllers/projects/pipelines/tests_controller_spec.rb112
-rw-r--r--spec/controllers/projects/pipelines_controller_spec.rb95
-rw-r--r--spec/controllers/projects/project_members_controller_spec.rb23
-rw-r--r--spec/controllers/projects/refs_controller_spec.rb9
-rw-r--r--spec/controllers/projects/releases_controller_spec.rb11
-rw-r--r--spec/controllers/projects/service_desk_controller_spec.rb111
-rw-r--r--spec/controllers/projects/services_controller_spec.rb19
-rw-r--r--spec/controllers/projects/settings/operations_controller_spec.rb100
-rw-r--r--spec/controllers/projects/snippets/blobs_controller_spec.rb85
-rw-r--r--spec/controllers/projects/snippets_controller_spec.rb28
-rw-r--r--spec/controllers/projects/tree_controller_spec.rb28
-rw-r--r--spec/controllers/projects/wikis_controller_spec.rb2
-rw-r--r--spec/controllers/projects_controller_spec.rb91
-rw-r--r--spec/controllers/registrations/experience_levels_controller_spec.rb47
-rw-r--r--spec/controllers/search_controller_spec.rb5
-rw-r--r--spec/controllers/snippets/blobs_controller_spec.rb61
-rw-r--r--spec/controllers/snippets_controller_spec.rb6
-rw-r--r--spec/controllers/users_controller_spec.rb65
64 files changed, 1945 insertions, 767 deletions
diff --git a/spec/controllers/admin/application_settings_controller_spec.rb b/spec/controllers/admin/application_settings_controller_spec.rb
index 8ab29a72477..7b8528009d8 100644
--- a/spec/controllers/admin/application_settings_controller_spec.rb
+++ b/spec/controllers/admin/application_settings_controller_spec.rb
@@ -128,6 +128,13 @@ RSpec.describe Admin::ApplicationSettingsController do
expect(ApplicationSetting.current.repository_storages_weighted_default).to eq(75)
end
+ it "updates default_branch_name setting" do
+ put :update, params: { application_setting: { default_branch_name: "example_branch_name" } }
+
+ expect(response).to redirect_to(general_admin_application_settings_path)
+ expect(ApplicationSetting.current.default_branch_name).to eq("example_branch_name")
+ end
+
context 'external policy classification settings' do
let(:settings) do
{
diff --git a/spec/controllers/admin/clusters_controller_spec.rb b/spec/controllers/admin/clusters_controller_spec.rb
index d899e86ae5f..2e0ee671d3f 100644
--- a/spec/controllers/admin/clusters_controller_spec.rb
+++ b/spec/controllers/admin/clusters_controller_spec.rb
@@ -171,6 +171,39 @@ RSpec.describe Admin::ClustersController do
end
end
+ it_behaves_like 'GET #metrics_dashboard for dashboard', 'Cluster health' do
+ let(:cluster) { create(:cluster, :instance, :provided_by_gcp) }
+
+ let(:metrics_dashboard_req_params) do
+ {
+ id: cluster.id
+ }
+ end
+ end
+
+ describe 'GET #prometheus_proxy' do
+ let(:user) { admin }
+ let(:proxyable) do
+ create(:cluster, :instance, :provided_by_gcp)
+ end
+
+ it_behaves_like 'metrics dashboard prometheus api proxy' do
+ context 'with anonymous user' do
+ let(:prometheus_body) { nil }
+
+ before do
+ sign_out(admin)
+ end
+
+ it 'returns 404' do
+ get :prometheus_proxy, params: prometheus_proxy_params
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+ end
+
describe 'POST #create_gcp' do
let(:legacy_abac_param) { 'true' }
let(:params) do
diff --git a/spec/controllers/admin/jobs_controller_spec.rb b/spec/controllers/admin/jobs_controller_spec.rb
new file mode 100644
index 00000000000..2d1482f40d4
--- /dev/null
+++ b/spec/controllers/admin/jobs_controller_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Admin::JobsController do
+ describe 'GET #index' do
+ context 'with an authenticated admin user' do
+ it 'paginates builds without a total count', :aggregate_failures do
+ stub_const("Admin::JobsController::BUILDS_PER_PAGE", 1)
+
+ sign_in(create(:admin))
+ create_list(:ci_build, 2)
+
+ get :index
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(assigns(:builds)).to be_a(Kaminari::PaginatableWithoutCount)
+ expect(assigns(:builds).count).to be(1)
+ end
+ end
+
+ context 'without admin access' do
+ it 'returns `not_found`' do
+ sign_in(create(:user))
+
+ get :index
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+end
diff --git a/spec/controllers/admin/services_controller_spec.rb b/spec/controllers/admin/services_controller_spec.rb
index 2ad4989af4f..8e78cc75369 100644
--- a/spec/controllers/admin/services_controller_spec.rb
+++ b/spec/controllers/admin/services_controller_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Admin::ServicesController do
end
describe 'GET #edit' do
- let!(:service) do
+ let(:service) do
create(:jira_service, :template)
end
@@ -19,6 +19,26 @@ RSpec.describe Admin::ServicesController do
expect(response).to have_gitlab_http_status(:ok)
end
+
+ context 'when integration does not exists' do
+ it 'redirects to the admin application integration page' do
+ get :edit, params: { id: 'invalid' }
+
+ expect(response).to redirect_to(admin_application_settings_services_path)
+ end
+ end
+
+ context 'when instance integration exists' do
+ before do
+ create(:jira_service, :instance)
+ end
+
+ it 'redirects to the admin application integration page' do
+ get :edit, params: { id: service.id }
+
+ expect(response).to redirect_to(admin_application_settings_services_path)
+ end
+ end
end
describe "#update" do
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 4002b7aca63..aec629ba330 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -968,4 +968,26 @@ RSpec.describe ApplicationController do
end
end
end
+
+ describe 'locale' do
+ let(:user) { create(:user, preferred_language: 'uk') }
+
+ controller(described_class) do
+ def index
+ :ok
+ end
+ end
+
+ before do
+ sign_in(user)
+
+ allow(Gitlab::I18n).to receive(:with_locale).and_call_original
+ end
+
+ it "sets user's locale" do
+ expect(Gitlab::I18n).to receive(:with_locale).with('uk')
+
+ get :index
+ end
+ end
end
diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb
index aeb3f4dcb17..e7c0bc43e86 100644
--- a/spec/controllers/autocomplete_controller_spec.rb
+++ b/spec/controllers/autocomplete_controller_spec.rb
@@ -365,6 +365,56 @@ RSpec.describe AutocompleteController do
end
end
+ context 'GET deploy_keys_with_owners' do
+ let!(:deploy_key) { create(:deploy_key, user: user) }
+ let!(:deploy_keys_project) { create(:deploy_keys_project, :write_access, project: project, deploy_key: deploy_key) }
+
+ context 'unauthorized user' do
+ it 'returns a not found response' do
+ get(:deploy_keys_with_owners, params: { project_id: project.id })
+
+ expect(response).to have_gitlab_http_status(:redirect)
+ end
+ end
+
+ context 'when the user who can read the project is logged in' do
+ before do
+ sign_in(user)
+ end
+
+ it 'renders the deploy key in a json payload, with its owner' do
+ get(:deploy_keys_with_owners, params: { project_id: project.id })
+
+ expect(json_response.count).to eq(1)
+ expect(json_response.first['title']).to eq(deploy_key.title)
+ expect(json_response.first['owner']['id']).to eq(deploy_key.user.id)
+ end
+
+ context 'with an unknown project' do
+ it 'returns a not found response' do
+ get(:deploy_keys_with_owners, params: { project_id: 9999 })
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'and the user cannot read the owner of the key' do
+ before do
+ allow(Ability).to receive(:allowed?).and_call_original
+ allow(Ability).to receive(:allowed?).with(user, :read_user, deploy_key.user).and_return(false)
+ end
+
+ it 'returns a payload without owner' do
+ get(:deploy_keys_with_owners, params: { project_id: project.id })
+
+ expect(json_response.count).to eq(1)
+ expect(json_response.first['title']).to eq(deploy_key.title)
+ expect(json_response.first['owner']).to be_nil
+ end
+ end
+ end
+ end
+
context 'Get merge_request_target_branches' do
let!(:merge_request) { create(:merge_request, source_project: project, target_branch: 'feature') }
diff --git a/spec/controllers/concerns/controller_with_feature_category/config_spec.rb b/spec/controllers/concerns/controller_with_feature_category/config_spec.rb
new file mode 100644
index 00000000000..9b8ffd2baab
--- /dev/null
+++ b/spec/controllers/concerns/controller_with_feature_category/config_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require "fast_spec_helper"
+require "rspec-parameterized"
+require_relative "../../../../app/controllers/concerns/controller_with_feature_category/config"
+
+RSpec.describe ControllerWithFeatureCategory::Config do
+ describe "#matches?" do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:only_actions, :except_actions, :if_proc, :unless_proc, :test_action, :expected) do
+ nil | nil | nil | nil | "action" | true
+ [:included] | nil | nil | nil | "action" | false
+ [:included] | nil | nil | nil | "included" | true
+ nil | [:excluded] | nil | nil | "excluded" | false
+ nil | nil | true | nil | "action" | true
+ [:included] | nil | true | nil | "action" | false
+ [:included] | nil | true | nil | "included" | true
+ nil | [:excluded] | true | nil | "excluded" | false
+ nil | nil | false | nil | "action" | false
+ [:included] | nil | false | nil | "action" | false
+ [:included] | nil | false | nil | "included" | false
+ nil | [:excluded] | false | nil | "excluded" | false
+ nil | nil | nil | true | "action" | false
+ [:included] | nil | nil | true | "action" | false
+ [:included] | nil | nil | true | "included" | false
+ nil | [:excluded] | nil | true | "excluded" | false
+ nil | nil | nil | false | "action" | true
+ [:included] | nil | nil | false | "action" | false
+ [:included] | nil | nil | false | "included" | true
+ nil | [:excluded] | nil | false | "excluded" | false
+ nil | nil | true | false | "action" | true
+ [:included] | nil | true | false | "action" | false
+ [:included] | nil | true | false | "included" | true
+ nil | [:excluded] | true | false | "excluded" | false
+ nil | nil | false | true | "action" | false
+ [:included] | nil | false | true | "action" | false
+ [:included] | nil | false | true | "included" | false
+ nil | [:excluded] | false | true | "excluded" | false
+ end
+
+ with_them do
+ let(:config) do
+ if_to_proc = if_proc.nil? ? nil : -> (_) { if_proc }
+ unless_to_proc = unless_proc.nil? ? nil : -> (_) { unless_proc }
+
+ described_class.new(:category, only_actions, except_actions, if_to_proc, unless_to_proc)
+ end
+
+ specify { expect(config.matches?(test_action)).to be(expected) }
+ end
+ end
+end
diff --git a/spec/controllers/concerns/controller_with_feature_category_spec.rb b/spec/controllers/concerns/controller_with_feature_category_spec.rb
new file mode 100644
index 00000000000..e603a7d14c4
--- /dev/null
+++ b/spec/controllers/concerns/controller_with_feature_category_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require_relative "../../../app/controllers/concerns/controller_with_feature_category"
+require_relative "../../../app/controllers/concerns/controller_with_feature_category/config"
+
+RSpec.describe ControllerWithFeatureCategory do
+ describe ".feature_category_for_action" do
+ let(:base_controller) do
+ Class.new do
+ include ControllerWithFeatureCategory
+ end
+ end
+
+ let(:controller) do
+ Class.new(base_controller) do
+ feature_category :baz
+ feature_category :foo, except: %w(update edit)
+ feature_category :bar, only: %w(index show)
+ feature_category :quux, only: %w(destroy)
+ feature_category :quuz, only: %w(destroy)
+ end
+ end
+
+ let(:subclass) do
+ Class.new(controller) do
+ feature_category :qux, only: %w(index)
+ end
+ end
+
+ it "is nil when nothing was defined" do
+ expect(base_controller.feature_category_for_action("hello")).to be_nil
+ end
+
+ it "returns the expected category", :aggregate_failures do
+ expect(controller.feature_category_for_action("update")).to eq(:baz)
+ expect(controller.feature_category_for_action("hello")).to eq(:foo)
+ expect(controller.feature_category_for_action("index")).to eq(:bar)
+ end
+
+ it "returns the closest match for categories defined in subclasses" do
+ expect(subclass.feature_category_for_action("index")).to eq(:qux)
+ expect(subclass.feature_category_for_action("show")).to eq(:bar)
+ end
+
+ it "returns the last defined feature category when multiple match" do
+ expect(controller.feature_category_for_action("destroy")).to eq(:quuz)
+ end
+
+ it "raises an error when using including and excluding the same action" do
+ expect do
+ Class.new(base_controller) do
+ feature_category :hello, only: [:world], except: [:world]
+ end
+ end.to raise_error(%r(cannot configure both `only` and `except`))
+ end
+
+ it "raises an error when using unknown arguments" do
+ expect do
+ Class.new(base_controller) do
+ feature_category :hello, hello: :world
+ end
+ end.to raise_error(%r(unknown arguments))
+ end
+ end
+end
diff --git a/spec/controllers/concerns/metrics_dashboard_spec.rb b/spec/controllers/concerns/metrics_dashboard_spec.rb
index 39ddf687dca..f0c9874965e 100644
--- a/spec/controllers/concerns/metrics_dashboard_spec.rb
+++ b/spec/controllers/concerns/metrics_dashboard_spec.rb
@@ -76,6 +76,22 @@ RSpec.describe MetricsDashboard do
end
end
+ context 'when dashboard path includes encoded characters' do
+ let(:params) { { dashboard_path: 'dashboard%26copy.yml' } }
+
+ before do
+ allow(controller)
+ .to receive(:metrics_dashboard_params)
+ .and_return(params)
+ end
+
+ it 'decodes dashboard path' do
+ expect(::Gitlab::Metrics::Dashboard::Finder).to receive(:find).with(anything, anything, hash_including(dashboard_path: 'dashboard&copy.yml'))
+
+ json_response
+ end
+ end
+
context 'when parameters are provided and the list of all dashboards is required' do
before do
allow(controller).to receive(:include_all_dashboards?).and_return(true)
@@ -88,13 +104,28 @@ RSpec.describe MetricsDashboard do
context 'in all_dashboard list' do
let(:system_dashboard) { json_response['all_dashboards'].find { |dashboard| dashboard["system_dashboard"] == true } }
- let(:project_dashboard) { json_response['all_dashboards'].find { |dashboard| dashboard["system_dashboard"] == false } }
+
+ let(:project_dashboard) do
+ json_response['all_dashboards'].find do |dashboard|
+ dashboard['path'] == '.gitlab/dashboards/test.yml'
+ end
+ end
it 'includes project_blob_path only for project dashboards' do
expect(system_dashboard['project_blob_path']).to be_nil
expect(project_dashboard['project_blob_path']).to eq("/#{project.namespace.path}/#{project.name}/-/blob/master/.gitlab/dashboards/test.yml")
end
+ it 'allows editing only for project dashboards' do
+ expect(system_dashboard['can_edit']).to be(false)
+ expect(project_dashboard['can_edit']).to be(true)
+ end
+
+ it 'includes out_of_the_box_dashboard key' do
+ expect(system_dashboard['out_of_the_box_dashboard']).to be(true)
+ expect(project_dashboard['out_of_the_box_dashboard']).to be(false)
+ end
+
describe 'project permissions' do
using RSpec::Parameterized::TableSyntax
diff --git a/spec/controllers/concerns/renders_commits_spec.rb b/spec/controllers/concerns/renders_commits_spec.rb
index 0bffb39d608..7be5f75c19d 100644
--- a/spec/controllers/concerns/renders_commits_spec.rb
+++ b/spec/controllers/concerns/renders_commits_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe RendersCommits do
it 'avoids N + 1' do
stub_const("MergeRequestDiff::COMMITS_SAFE_SIZE", 5)
- control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ control_count = ActiveRecord::QueryRecorder.new do
go
end.count
diff --git a/spec/controllers/concerns/sorting_preference_spec.rb b/spec/controllers/concerns/sorting_preference_spec.rb
index 4f9506d4675..c0091e8b694 100644
--- a/spec/controllers/concerns/sorting_preference_spec.rb
+++ b/spec/controllers/concerns/sorting_preference_spec.rb
@@ -75,7 +75,7 @@ RSpec.describe SortingPreference do
it 'sets the cookie with the right values and flags' do
subject
- expect(cookies['issue_sort']).to eq(value: 'popularity', secure: false, httponly: false)
+ expect(cookies['issue_sort']).to eq(expires: nil, value: 'popularity', secure: false, httponly: false)
end
end
@@ -86,7 +86,7 @@ RSpec.describe SortingPreference do
it 'sets the cookie with the right values and flags' do
subject
- expect(cookies['issue_sort']).to eq(value: 'created_asc', secure: false, httponly: false)
+ expect(cookies['issue_sort']).to eq(expires: nil, value: 'created_asc', secure: false, httponly: false)
end
end
end
diff --git a/spec/controllers/dashboard/projects_controller_spec.rb b/spec/controllers/dashboard/projects_controller_spec.rb
index ee043fde0ff..1e1d9519f78 100644
--- a/spec/controllers/dashboard/projects_controller_spec.rb
+++ b/spec/controllers/dashboard/projects_controller_spec.rb
@@ -5,13 +5,14 @@ require 'spec_helper'
RSpec.describe Dashboard::ProjectsController do
include ExternalAuthorizationServiceHelpers
+ let_it_be(:user) { create(:user) }
+
describe '#index' do
context 'user not logged in' do
it_behaves_like 'authenticates sessionless user', :index, :atom
end
context 'user logged in' do
- let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:project2) { create(:project) }
@@ -71,8 +72,6 @@ RSpec.describe Dashboard::ProjectsController do
context 'json requests' do
render_views
- let(:user) { create(:user) }
-
before do
sign_in(user)
end
@@ -114,16 +113,14 @@ RSpec.describe Dashboard::ProjectsController do
end
context 'atom requests' do
- let(:user) { create(:user) }
-
before do
sign_in(user)
end
describe '#index' do
- context 'project pagination' do
- let(:projects) { create_list(:project, 2, creator: user) }
+ let_it_be(:projects) { create_list(:project, 2, creator: user) }
+ context 'project pagination' do
before do
allow(Kaminari.config).to receive(:default_per_page).and_return(1)
@@ -138,6 +135,37 @@ RSpec.describe Dashboard::ProjectsController do
expect(assigns(:events).count).to eq(2)
end
end
+
+ describe 'rendering' do
+ include DesignManagementTestHelpers
+ render_views
+
+ let(:project) { projects.first }
+ let!(:design_event) { create(:design_event, project: project) }
+ let!(:wiki_page_event) { create(:wiki_page_event, project: project) }
+ let!(:issue_event) { create(:closed_issue_event, project: project) }
+ let(:design) { design_event.design }
+ let(:wiki_page) { wiki_page_event.wiki_page }
+ let(:issue) { issue_event.issue }
+
+ before do
+ enable_design_management
+ project.add_developer(user)
+ end
+
+ it 'renders all kinds of event without error', :aggregate_failures do
+ get :index, format: :atom
+
+ expect(assigns(:events)).to include(design_event, wiki_page_event, issue_event)
+ expect(response).to render_template('dashboard/projects/index')
+ expect(response.body).to include(
+ "uploaded design #{design.to_reference}",
+ "created wiki page #{wiki_page.title}",
+ "joined project #{project.full_name}",
+ "closed issue #{issue.to_reference}"
+ )
+ end
+ end
end
end
end
diff --git a/spec/controllers/dashboard/snippets_controller_spec.rb b/spec/controllers/dashboard/snippets_controller_spec.rb
index 3c316d07408..d981f738e70 100644
--- a/spec/controllers/dashboard/snippets_controller_spec.rb
+++ b/spec/controllers/dashboard/snippets_controller_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Dashboard::SnippetsController do
- let(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
before do
sign_in(user)
@@ -26,5 +26,7 @@ RSpec.describe Dashboard::SnippetsController do
get :index
end
+
+ it_behaves_like 'snippets sort order'
end
end
diff --git a/spec/controllers/dashboard/todos_controller_spec.rb b/spec/controllers/dashboard/todos_controller_spec.rb
index f0aa351bee0..2e3328ae4d2 100644
--- a/spec/controllers/dashboard/todos_controller_spec.rb
+++ b/spec/controllers/dashboard/todos_controller_spec.rb
@@ -42,6 +42,15 @@ RSpec.describe Dashboard::TodosController do
expect(response).to have_gitlab_http_status(:ok)
end
+
+ context 'tracking visits' do
+ let_it_be(:authorized_project) { create(:project, :public) }
+
+ it_behaves_like 'tracking unique visits', :index do
+ let(:request_params) { { project_id: authorized_project.id } }
+ let(:target_id) { 'u_analytics_todos' }
+ end
+ end
end
context "with render_views" do
diff --git a/spec/controllers/dashboard_controller_spec.rb b/spec/controllers/dashboard_controller_spec.rb
index d27817c0a82..c838affa239 100644
--- a/spec/controllers/dashboard_controller_spec.rb
+++ b/spec/controllers/dashboard_controller_spec.rb
@@ -24,15 +24,20 @@ RSpec.describe DashboardController do
end
describe "GET activity as JSON" do
+ include DesignManagementTestHelpers
render_views
let(:user) { create(:user) }
let(:project) { create(:project, :public, issues_access_level: ProjectFeature::PRIVATE) }
+ let(:other_project) { create(:project, :public) }
before do
+ enable_design_management
create(:event, :created, project: project, target: create(:issue))
create(:wiki_page_event, :created, project: project)
create(:wiki_page_event, :updated, project: project)
+ create(:design_event, project: project)
+ create(:design_event, author: user, project: other_project)
sign_in(user)
@@ -42,12 +47,13 @@ RSpec.describe DashboardController do
context 'when user has permission to see the event' do
before do
project.add_developer(user)
+ other_project.add_developer(user)
end
it 'returns count' do
get :activity, params: { format: :json }
- expect(json_response['count']).to eq(3)
+ expect(json_response['count']).to eq(6)
end
end
diff --git a/spec/controllers/every_controller_spec.rb b/spec/controllers/every_controller_spec.rb
new file mode 100644
index 00000000000..4785ee9ed8f
--- /dev/null
+++ b/spec/controllers/every_controller_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe "Every controller" do
+ context "feature categories" do
+ let_it_be(:feature_categories) do
+ YAML.load_file(Rails.root.join('config', 'feature_categories.yml')).map(&:to_sym).to_set
+ end
+
+ let_it_be(:controller_actions) do
+ # This will return tuples of all controller actions defined in the routes
+ # Only for controllers inheriting ApplicationController
+ # Excluding controllers from gems (OAuth, Sidekiq)
+ Rails.application.routes.routes
+ .map { |route| route.required_defaults.presence }
+ .compact
+ .select { |route| route[:controller].present? && route[:action].present? }
+ .map { |route| [constantize_controller(route[:controller]), route[:action]] }
+ .reject { |route| route.first.nil? || !route.first.include?(ControllerWithFeatureCategory) }
+ end
+
+ let_it_be(:routes_without_category) do
+ controller_actions.map do |controller, action|
+ "#{controller}##{action}" unless controller.feature_category_for_action(action)
+ end.compact
+ end
+
+ it "has feature categories" do
+ pending("We'll work on defining categories for all controllers: "\
+ "https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/463")
+
+ expect(routes_without_category).to be_empty, "#{routes_without_category.first(10)} did not have a category"
+ end
+
+ it "completed controllers don't get new routes without categories" do
+ completed_controllers = [Projects::MergeRequestsController].map(&:to_s)
+
+ newly_introduced_missing_category = routes_without_category.select do |route|
+ completed_controllers.any? { |controller| route.start_with?(controller) }
+ end
+
+ expect(newly_introduced_missing_category).to be_empty
+ end
+
+ it "recognizes the feature categories" do
+ routes_unknown_category = controller_actions.map do |controller, action|
+ used_category = controller.feature_category_for_action(action)
+ next unless used_category
+ next if used_category == :not_owned
+
+ ["#{controller}##{action}", used_category] unless feature_categories.include?(used_category)
+ end.compact
+
+ expect(routes_unknown_category).to be_empty, "#{routes_unknown_category.first(10)} had an unknown category"
+ end
+
+ it "doesn't define or exclude categories on removed actions", :aggregate_failures do
+ controller_actions.group_by(&:first).each do |controller, controller_action|
+ existing_actions = controller_action.map(&:last)
+ used_actions = actions_defined_in_feature_category_config(controller)
+ non_existing_used_actions = used_actions - existing_actions
+
+ expect(non_existing_used_actions).to be_empty,
+ "#{controller} used #{non_existing_used_actions} to define feature category, but the route does not exist"
+ end
+ end
+ end
+
+ def constantize_controller(name)
+ "#{name.camelize}Controller".constantize
+ rescue NameError
+ nil # some controllers, like the omniauth ones are dynamic
+ end
+
+ def actions_defined_in_feature_category_config(controller)
+ feature_category_configs = controller.send(:class_attributes)[:feature_category_config]
+ feature_category_configs.map do |config|
+ Array(config.send(:only)) + Array(config.send(:except))
+ end.flatten.uniq.map(&:to_s)
+ end
+end
diff --git a/spec/controllers/groups/clusters_controller_spec.rb b/spec/controllers/groups/clusters_controller_spec.rb
index 6765cf0990a..1593e1290c4 100644
--- a/spec/controllers/groups/clusters_controller_spec.rb
+++ b/spec/controllers/groups/clusters_controller_spec.rb
@@ -192,6 +192,46 @@ RSpec.describe Groups::ClustersController do
end
end
+ it_behaves_like 'GET #metrics_dashboard for dashboard', 'Cluster health' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, cluster_type: :group_type, groups: [group]) }
+
+ let(:metrics_dashboard_req_params) do
+ {
+ id: cluster.id,
+ group_id: group.name
+ }
+ end
+ end
+
+ describe 'GET #prometheus_proxy' do
+ let(:proxyable) do
+ create(:cluster, :provided_by_gcp, cluster_type: :group_type, groups: [group])
+ end
+
+ it_behaves_like 'metrics dashboard prometheus api proxy' do
+ let(:proxyable_params) do
+ {
+ id: proxyable.id.to_s,
+ group_id: group.name
+ }
+ end
+
+ context 'with anonymous user' do
+ let(:prometheus_body) { nil }
+
+ before do
+ sign_out(user)
+ end
+
+ it 'returns 404' do
+ get :prometheus_proxy, params: prometheus_proxy_params
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+ end
+
describe 'POST create for new cluster' do
let(:legacy_abac_param) { 'true' }
let(:params) do
diff --git a/spec/controllers/groups/imports_controller_spec.rb b/spec/controllers/groups/imports_controller_spec.rb
index eb43a62b75b..7372c2e9575 100644
--- a/spec/controllers/groups/imports_controller_spec.rb
+++ b/spec/controllers/groups/imports_controller_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-describe Groups::ImportsController do
+RSpec.describe Groups::ImportsController do
describe 'GET #show' do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group, :private) }
diff --git a/spec/controllers/groups/runners_controller_spec.rb b/spec/controllers/groups/runners_controller_spec.rb
index 376cd569952..91ff0a53ec7 100644
--- a/spec/controllers/groups/runners_controller_spec.rb
+++ b/spec/controllers/groups/runners_controller_spec.rb
@@ -6,6 +6,9 @@ RSpec.describe Groups::RunnersController do
let(:user) { create(:user) }
let(:group) { create(:group) }
let(:runner) { create(:ci_runner, :group, groups: [group]) }
+ let(:project) { create(:project, group: group) }
+ let(:runner_project) { create(:ci_runner, :project, projects: [project]) }
+ let(:params_runner_project) { { group_id: group, id: runner_project } }
let(:params) { { group_id: group, id: runner } }
before do
@@ -24,6 +27,13 @@ RSpec.describe Groups::RunnersController do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template(:show)
end
+
+ it 'renders show with 200 status code project runner' do
+ get :show, params: { group_id: group, id: runner_project }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template(:show)
+ end
end
context 'when user is not owner' do
@@ -36,6 +46,12 @@ RSpec.describe Groups::RunnersController do
expect(response).to have_gitlab_http_status(:not_found)
end
+
+ it 'renders a 404 project runner' do
+ get :show, params: { group_id: group, id: runner_project }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
end
end
@@ -51,6 +67,13 @@ RSpec.describe Groups::RunnersController do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template(:edit)
end
+
+ it 'renders show with 200 status code project runner' do
+ get :edit, params: { group_id: group, id: runner_project }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template(:edit)
+ end
end
context 'when user is not owner' do
@@ -63,6 +86,12 @@ RSpec.describe Groups::RunnersController do
expect(response).to have_gitlab_http_status(:not_found)
end
+
+ it 'renders a 404 project runner' do
+ get :edit, params: { group_id: group, id: runner_project }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
end
end
@@ -82,6 +111,17 @@ RSpec.describe Groups::RunnersController do
expect(response).to have_gitlab_http_status(:found)
expect(runner.reload.description).to eq(new_desc)
end
+
+ it 'updates the project runner, ticks the queue, and redirects project runner' do
+ new_desc = runner_project.description.swapcase
+
+ expect do
+ post :update, params: params_runner_project.merge(runner: { description: new_desc } )
+ end.to change { runner_project.ensure_runner_queue_value }
+
+ expect(response).to have_gitlab_http_status(:found)
+ expect(runner_project.reload.description).to eq(new_desc)
+ end
end
context 'when user is not an owner' do
@@ -99,6 +139,17 @@ RSpec.describe Groups::RunnersController do
expect(response).to have_gitlab_http_status(:not_found)
expect(runner.reload.description).to eq(old_desc)
end
+
+ it 'rejects the update and responds 404 project runner' do
+ old_desc = runner_project.description
+
+ expect do
+ post :update, params: params_runner_project.merge(runner: { description: old_desc.swapcase } )
+ end.not_to change { runner_project.ensure_runner_queue_value }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(runner_project.reload.description).to eq(old_desc)
+ end
end
end
@@ -114,6 +165,31 @@ RSpec.describe Groups::RunnersController do
expect(response).to have_gitlab_http_status(:found)
expect(Ci::Runner.find_by(id: runner.id)).to be_nil
end
+
+ it 'destroys the project runner and redirects' do
+ delete :destroy, params: params_runner_project
+
+ expect(response).to have_gitlab_http_status(:found)
+ expect(Ci::Runner.find_by(id: runner_project.id)).to be_nil
+ end
+ end
+
+ context 'when user is an owner and runner in multiple projects' do
+ let(:project_2) { create(:project, group: group) }
+ let(:runner_project_2) { create(:ci_runner, :project, projects: [project, project_2]) }
+ let(:params_runner_project_2) { { group_id: group, id: runner_project_2 } }
+
+ before do
+ group.add_owner(user)
+ end
+
+ it 'does not destroy the project runner' do
+ delete :destroy, params: params_runner_project_2
+
+ expect(response).to have_gitlab_http_status(:found)
+ expect(flash[:alert]).to eq('Runner was not deleted because it is assigned to multiple projects.')
+ expect(Ci::Runner.find_by(id: runner_project_2.id)).to be_present
+ end
end
context 'when user is not an owner' do
@@ -127,6 +203,13 @@ RSpec.describe Groups::RunnersController do
expect(response).to have_gitlab_http_status(:not_found)
expect(Ci::Runner.find_by(id: runner.id)).to be_present
end
+
+ it 'responds 404 and does not destroy the project runner' do
+ delete :destroy, params: params_runner_project
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(Ci::Runner.find_by(id: runner_project.id)).to be_present
+ end
end
end
@@ -146,6 +229,17 @@ RSpec.describe Groups::RunnersController do
expect(response).to have_gitlab_http_status(:found)
expect(runner.reload.active).to eq(true)
end
+
+ it 'marks the project runner as active, ticks the queue, and redirects' do
+ runner_project.update(active: false)
+
+ expect do
+ post :resume, params: params_runner_project
+ end.to change { runner_project.ensure_runner_queue_value }
+
+ expect(response).to have_gitlab_http_status(:found)
+ expect(runner_project.reload.active).to eq(true)
+ end
end
context 'when user is not an owner' do
@@ -163,6 +257,17 @@ RSpec.describe Groups::RunnersController do
expect(response).to have_gitlab_http_status(:not_found)
expect(runner.reload.active).to eq(false)
end
+
+ it 'responds 404 and does not activate the project runner' do
+ runner_project.update(active: false)
+
+ expect do
+ post :resume, params: params_runner_project
+ end.not_to change { runner_project.ensure_runner_queue_value }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(runner_project.reload.active).to eq(false)
+ end
end
end
@@ -182,6 +287,17 @@ RSpec.describe Groups::RunnersController do
expect(response).to have_gitlab_http_status(:found)
expect(runner.reload.active).to eq(false)
end
+
+ it 'marks the project runner as inactive, ticks the queue, and redirects' do
+ runner_project.update(active: true)
+
+ expect do
+ post :pause, params: params_runner_project
+ end.to change { runner_project.ensure_runner_queue_value }
+
+ expect(response).to have_gitlab_http_status(:found)
+ expect(runner_project.reload.active).to eq(false)
+ end
end
context 'when user is not an owner' do
@@ -199,6 +315,17 @@ RSpec.describe Groups::RunnersController do
expect(response).to have_gitlab_http_status(:not_found)
expect(runner.reload.active).to eq(true)
end
+
+ it 'responds 404 and does not update the project runner or queue' do
+ runner_project.update(active: true)
+
+ expect do
+ post :pause, params: params
+ end.not_to change { runner_project.ensure_runner_queue_value }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(runner_project.reload.active).to eq(true)
+ end
end
end
end
diff --git a/spec/controllers/groups/settings/ci_cd_controller_spec.rb b/spec/controllers/groups/settings/ci_cd_controller_spec.rb
index 55c19de4aa1..f11bb66caab 100644
--- a/spec/controllers/groups/settings/ci_cd_controller_spec.rb
+++ b/spec/controllers/groups/settings/ci_cd_controller_spec.rb
@@ -5,8 +5,15 @@ require 'spec_helper'
RSpec.describe Groups::Settings::CiCdController do
include ExternalAuthorizationServiceHelpers
- let(:group) { create(:group) }
- let(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:sub_group) { create(:group, parent: group) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:project_2) { create(:project, group: sub_group) }
+ let_it_be(:runner_group) { create(:ci_runner, :group, groups: [group]) }
+ let_it_be(:runner_project_1) { create(:ci_runner, :project, projects: [project])}
+ let_it_be(:runner_project_2) { create(:ci_runner, :project, projects: [project_2])}
+ let_it_be(:runner_project_3) { create(:ci_runner, :project, projects: [project, project_2])}
before do
sign_in(user)
@@ -18,11 +25,12 @@ RSpec.describe Groups::Settings::CiCdController do
group.add_owner(user)
end
- it 'renders show with 200 status code' do
+ it 'renders show with 200 status code and correct runners' do
get :show, params: { group_id: group }
expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template(:show)
+ expect(assigns(:group_runners)).to match_array([runner_group, runner_project_1, runner_project_2, runner_project_3])
end
end
@@ -35,6 +43,7 @@ RSpec.describe Groups::Settings::CiCdController do
get :show, params: { group_id: group }
expect(response).to have_gitlab_http_status(:not_found)
+ expect(assigns(:group_runners)).to be_nil
end
end
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
index dce7105c073..469e58c94e7 100644
--- a/spec/controllers/groups_controller_spec.rb
+++ b/spec/controllers/groups_controller_spec.rb
@@ -52,8 +52,6 @@ RSpec.describe GroupsController do
expect(assigns(:events).map(&:id)).to contain_exactly(event.id)
end
end
-
- it_behaves_like 'namespace storage limit alert'
end
describe 'GET #show' do
@@ -941,7 +939,7 @@ RSpec.describe GroupsController do
allow(Gitlab::ApplicationRateLimiter)
.to receive(:increment)
- .and_return(Gitlab::ApplicationRateLimiter.rate_limits[:group_export][:threshold] + 1)
+ .and_return(Gitlab::ApplicationRateLimiter.rate_limits[:group_export][:threshold].call + 1)
end
it 'throttles the endpoint' do
@@ -1015,7 +1013,7 @@ RSpec.describe GroupsController do
allow(Gitlab::ApplicationRateLimiter)
.to receive(:increment)
- .and_return(Gitlab::ApplicationRateLimiter.rate_limits[:group_download_export][:threshold] + 1)
+ .and_return(Gitlab::ApplicationRateLimiter.rate_limits[:group_download_export][:threshold].call + 1)
end
it 'throttles the endpoint' do
@@ -1138,6 +1136,36 @@ RSpec.describe GroupsController do
it_behaves_like 'disabled when using an external authorization service'
end
+ describe "GET #activity as JSON" do
+ include DesignManagementTestHelpers
+ render_views
+
+ let(:project) { create(:project, :public, group: group) }
+ let(:other_project) { create(:project, :public, group: group) }
+
+ def get_activity
+ get :activity, params: { format: :json, id: group.to_param }
+ end
+
+ before do
+ enable_design_management
+ issue = create(:issue, project: project)
+ create(:event, :created, project: project, target: issue)
+ create(:design_event, project: project)
+ create(:design_event, project: other_project)
+
+ sign_in(user)
+
+ request.cookies[:event_filter] = 'all'
+ end
+
+ it 'returns count' do
+ get_activity
+
+ expect(json_response['count']).to eq(3)
+ end
+ end
+
describe 'GET #issues' do
subject { get :issues, params: { id: group.to_param } }
diff --git a/spec/controllers/import/bitbucket_controller_spec.rb b/spec/controllers/import/bitbucket_controller_spec.rb
index ec38a635c2d..0427715d1ac 100644
--- a/spec/controllers/import/bitbucket_controller_spec.rb
+++ b/spec/controllers/import/bitbucket_controller_spec.rb
@@ -58,12 +58,12 @@ RSpec.describe Import::BitbucketController do
before do
@repo = double(name: 'vim', slug: 'vim', owner: 'asd', full_name: 'asd/vim', clone_url: 'http://test.host/demo/url.git', 'valid?' => true)
@invalid_repo = double(name: 'mercurialrepo', slug: 'mercurialrepo', owner: 'asd', full_name: 'asd/mercurialrepo', clone_url: 'http://test.host/demo/mercurialrepo.git', 'valid?' => false)
+ allow(controller).to receive(:provider_url).and_return('http://demobitbucket.org')
assign_session_tokens
- stub_feature_flags(new_import_ui: false)
end
- it_behaves_like 'import controller with new_import_ui feature flag' do
+ it_behaves_like 'import controller status' do
before do
allow(controller).to receive(:provider_url).and_return('http://demobitbucket.org')
end
@@ -75,44 +75,16 @@ RSpec.describe Import::BitbucketController do
let(:client_repos_field) { :repos }
end
- context 'with new_import_ui feature flag enabled' do
- before do
- stub_feature_flags(new_import_ui: true)
- allow(controller).to receive(:provider_url).and_return('http://demobitbucket.org')
- end
-
- it 'returns invalid repos' do
- allow_any_instance_of(Bitbucket::Client).to receive(:repos).and_return([@repo, @invalid_repo])
-
- get :status, format: :json
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['incompatible_repos'].length).to eq(1)
- expect(json_response.dig("incompatible_repos", 0, "id")).to eq(@invalid_repo.full_name)
- expect(json_response['provider_repos'].length).to eq(1)
- expect(json_response.dig("provider_repos", 0, "id")).to eq(@repo.full_name)
- end
- end
-
- it "assigns variables" do
- @project = create(:project, import_type: 'bitbucket', creator_id: user.id)
- allow_any_instance_of(Bitbucket::Client).to receive(:repos).and_return([@repo])
+ it 'returns invalid repos' do
+ allow_any_instance_of(Bitbucket::Client).to receive(:repos).and_return([@repo, @invalid_repo])
- get :status
-
- expect(assigns(:already_added_projects)).to eq([@project])
- expect(assigns(:repos)).to eq([@repo])
- expect(assigns(:incompatible_repos)).to eq([])
- end
+ get :status, format: :json
- it "does not show already added project" do
- @project = create(:project, import_type: 'bitbucket', creator_id: user.id, import_source: 'asd/vim')
- allow_any_instance_of(Bitbucket::Client).to receive(:repos).and_return([@repo])
-
- get :status
-
- expect(assigns(:already_added_projects)).to eq([@project])
- expect(assigns(:repos)).to eq([])
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['incompatible_repos'].length).to eq(1)
+ expect(json_response.dig("incompatible_repos", 0, "id")).to eq(@invalid_repo.full_name)
+ expect(json_response['provider_repos'].length).to eq(1)
+ expect(json_response.dig("provider_repos", 0, "id")).to eq(@repo.full_name)
end
context 'when filtering' do
diff --git a/spec/controllers/import/bitbucket_server_controller_spec.rb b/spec/controllers/import/bitbucket_server_controller_spec.rb
index af471b478fa..bb80de6425f 100644
--- a/spec/controllers/import/bitbucket_server_controller_spec.rb
+++ b/spec/controllers/import/bitbucket_server_controller_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Import::BitbucketServerController do
let(:user) { create(:user) }
let(:project_key) { 'test-project' }
let(:repo_slug) { 'some-repo' }
+ let(:repo_id) { "#{project_key}/#{repo_slug}" }
let(:client) { instance_double(BitbucketServer::Client) }
def assign_session_tokens
@@ -46,7 +47,7 @@ RSpec.describe Import::BitbucketServerController do
.to receive(:new).with(project_key, repo_slug, anything, project_name, user.namespace, user, anything)
.and_return(double(execute: project))
- post :create, params: { project: project_key, repository: repo_slug }, format: :json
+ post :create, params: { repo_id: repo_id }, format: :json
expect(response).to have_gitlab_http_status(:ok)
end
@@ -59,20 +60,20 @@ RSpec.describe Import::BitbucketServerController do
.to receive(:new).with(project_key, repo_slug, anything, project_name, user.namespace, user, anything)
.and_return(double(execute: project))
- post :create, params: { project: project_key, repository: repo_slug, format: :json }
+ post :create, params: { repo_id: repo_id }, format: :json
expect(response).to have_gitlab_http_status(:ok)
end
end
it 'returns an error when an invalid project key is used' do
- post :create, params: { project: 'some&project' }
+ post :create, params: { repo_id: 'some&project/repo' }
expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
it 'returns an error when an invalid repository slug is used' do
- post :create, params: { project: 'some-project', repository: 'try*this' }
+ post :create, params: { repo_id: 'some-project/try*this' }
expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
@@ -80,7 +81,7 @@ RSpec.describe Import::BitbucketServerController do
it 'returns an error when the project cannot be found' do
allow(client).to receive(:repo).with(project_key, repo_slug).and_return(nil)
- post :create, params: { project: project_key, repository: repo_slug }, format: :json
+ post :create, params: { repo_id: repo_id }, format: :json
expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
@@ -90,15 +91,15 @@ RSpec.describe Import::BitbucketServerController do
.to receive(:new).with(project_key, repo_slug, anything, project_name, user.namespace, user, anything)
.and_return(double(execute: build(:project)))
- post :create, params: { project: project_key, repository: repo_slug }, format: :json
+ post :create, params: { repo_id: repo_id }, format: :json
expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
it "returns an error when the server can't be contacted" do
- expect(client).to receive(:repo).with(project_key, repo_slug).and_raise(::BitbucketServer::Connection::ConnectionError)
+ allow(client).to receive(:repo).with(project_key, repo_slug).and_raise(::BitbucketServer::Connection::ConnectionError)
- post :create, params: { project: project_key, repository: repo_slug }, format: :json
+ post :create, params: { repo_id: repo_id }, format: :json
expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
@@ -123,7 +124,9 @@ RSpec.describe Import::BitbucketServerController do
end
it 'sets the session variables' do
- post :configure, params: { personal_access_token: token, bitbucket_username: username, bitbucket_server_url: url }
+ allow(controller).to receive(:allow_local_requests?).and_return(true)
+
+ post :configure, params: { personal_access_token: token, bitbucket_server_username: username, bitbucket_server_url: url }
expect(session[:bitbucket_server_url]).to eq(url)
expect(session[:bitbucket_server_username]).to eq(username)
@@ -145,28 +148,21 @@ RSpec.describe Import::BitbucketServerController do
@invalid_repo = double(slug: 'invalid', project_key: 'foobar', full_name: 'asd/foobar', "valid?" => false, browse_url: 'http://bad-repo', name: 'invalid')
@created_repo = double(slug: 'created', project_key: 'existing', full_name: 'group/created', "valid?" => true, browse_url: 'http://existing')
assign_session_tokens
- stub_feature_flags(new_import_ui: false)
end
- context 'with new_import_ui feature flag enabled' do
- before do
- stub_feature_flags(new_import_ui: true)
- end
-
- it 'returns invalid repos' do
- allow(client).to receive(:repos).with(filter: nil, limit: 25, page_offset: 0).and_return([@repo, @invalid_repo])
+ it 'returns invalid repos' do
+ allow(client).to receive(:repos).with(filter: nil, limit: 25, page_offset: 0).and_return([@repo, @invalid_repo])
- get :status, format: :json
+ get :status, format: :json
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['incompatible_repos'].length).to eq(1)
- expect(json_response.dig("incompatible_repos", 0, "id")).to eq(@invalid_repo.full_name)
- expect(json_response['provider_repos'].length).to eq(1)
- expect(json_response.dig("provider_repos", 0, "id")).to eq(@repo.full_name)
- end
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['incompatible_repos'].length).to eq(1)
+ expect(json_response.dig("incompatible_repos", 0, "id")).to eq(@invalid_repo.full_name)
+ expect(json_response['provider_repos'].length).to eq(1)
+ expect(json_response.dig("provider_repos", 0, "id")).to eq(@repo.full_name)
end
- it_behaves_like 'import controller with new_import_ui feature flag' do
+ it_behaves_like 'import controller status' do
let(:repo) { @repo }
let(:repo_id) { @repo.full_name }
let(:import_source) { @repo.browse_url }
@@ -174,47 +170,14 @@ RSpec.describe Import::BitbucketServerController do
let(:client_repos_field) { :repos }
end
- it 'assigns repository categories' do
- created_project = create(:project, :import_finished, import_type: 'bitbucket_server', creator_id: user.id, import_source: @created_repo.browse_url)
-
- expect(repos).to receive(:partition).and_return([[@repo, @created_repo], [@invalid_repo]])
- expect(repos).to receive(:current_page).and_return(1)
- expect(repos).to receive(:next_page).and_return(2)
- expect(repos).to receive(:prev_page).and_return(nil)
- expect(client).to receive(:repos).and_return(repos)
-
- get :status
-
- expect(assigns(:already_added_projects)).to eq([created_project])
- expect(assigns(:repos)).to eq([@repo])
- expect(assigns(:incompatible_repos)).to eq([@invalid_repo])
- end
-
context 'when filtering' do
let(:filter) { 'test' }
it 'passes filter param to bitbucket client' do
- expect(repos).to receive(:partition).and_return([[@repo, @created_repo], [@invalid_repo]])
- expect(client).to receive(:repos).with(filter: filter, limit: 25, page_offset: 0).and_return(repos)
+ expect(client).to receive(:repos).with(filter: filter, limit: 25, page_offset: 0).and_return([@repo])
get :status, params: { filter: filter }, as: :json
end
end
end
-
- describe 'GET jobs' do
- before do
- assign_session_tokens
- end
-
- it 'returns a list of imported projects' do
- created_project = create(:project, import_type: 'bitbucket_server', creator_id: user.id)
-
- get :jobs
-
- expect(json_response.count).to eq(1)
- expect(json_response.first['id']).to eq(created_project.id)
- expect(json_response.first['import_status']).to eq('none')
- end
- end
end
diff --git a/spec/controllers/import/fogbugz_controller_spec.rb b/spec/controllers/import/fogbugz_controller_spec.rb
index aabbcb30358..376c089df78 100644
--- a/spec/controllers/import/fogbugz_controller_spec.rb
+++ b/spec/controllers/import/fogbugz_controller_spec.rb
@@ -82,36 +82,15 @@ RSpec.describe Import::FogbugzController do
before do
@repo = OpenStruct.new(id: 'demo', name: 'vim')
stub_client(valid?: true)
- stub_feature_flags(new_import_ui: false)
end
- it_behaves_like 'import controller with new_import_ui feature flag' do
+ it_behaves_like 'import controller status' do
let(:repo) { @repo }
let(:repo_id) { @repo.id }
let(:import_source) { @repo.name }
let(:provider_name) { 'fogbugz' }
let(:client_repos_field) { :repos }
end
-
- it 'assigns variables' do
- @project = create(:project, import_type: 'fogbugz', creator_id: user.id)
- stub_client(repos: [@repo])
-
- get :status
-
- expect(assigns(:already_added_projects)).to eq([@project])
- expect(assigns(:repos)).to eq([@repo])
- end
-
- it 'does not show already added project' do
- @project = create(:project, import_type: 'fogbugz', creator_id: user.id, import_source: 'vim')
- stub_client(repos: [@repo])
-
- get :status
-
- expect(assigns(:already_added_projects)).to eq([@project])
- expect(assigns(:repos)).to eq([])
- end
end
describe 'POST create' do
diff --git a/spec/controllers/import/gitlab_controller_spec.rb b/spec/controllers/import/gitlab_controller_spec.rb
index 1cd0593f762..42c4348dac2 100644
--- a/spec/controllers/import/gitlab_controller_spec.rb
+++ b/spec/controllers/import/gitlab_controller_spec.rb
@@ -36,36 +36,15 @@ RSpec.describe Import::GitlabController do
before do
@repo = OpenStruct.new(id: 1, path: 'vim', path_with_namespace: 'asd/vim', web_url: 'https://gitlab.com/asd/vim')
assign_session_token
- stub_feature_flags(new_import_ui: false)
end
- it_behaves_like 'import controller with new_import_ui feature flag' do
+ it_behaves_like 'import controller status' do
let(:repo) { @repo }
let(:repo_id) { @repo.id }
let(:import_source) { @repo.path_with_namespace }
let(:provider_name) { 'gitlab' }
let(:client_repos_field) { :projects }
end
-
- it "assigns variables" do
- @project = create(:project, import_type: 'gitlab', creator_id: user.id)
- stub_client(projects: [@repo])
-
- get :status
-
- expect(assigns(:already_added_projects)).to eq([@project])
- expect(assigns(:repos)).to eq([@repo])
- end
-
- it "does not show already added project" do
- @project = create(:project, import_type: 'gitlab', creator_id: user.id, import_source: 'asd/vim')
- stub_client(projects: [@repo])
-
- get :status
-
- expect(assigns(:already_added_projects)).to eq([@project])
- expect(assigns(:repos)).to eq([])
- end
end
describe "POST create" do
diff --git a/spec/controllers/instance_statistics/cohorts_controller_spec.rb b/spec/controllers/instance_statistics/cohorts_controller_spec.rb
index b92fcb2575c..c16ac0dced1 100644
--- a/spec/controllers/instance_statistics/cohorts_controller_spec.rb
+++ b/spec/controllers/instance_statistics/cohorts_controller_spec.rb
@@ -18,4 +18,11 @@ RSpec.describe InstanceStatistics::CohortsController do
expect(response).to have_gitlab_http_status(:not_found)
end
+
+ describe 'GET #index' do
+ it_behaves_like 'tracking unique visits', :index do
+ let(:request_params) { {} }
+ let(:target_id) { 'i_analytics_cohorts' }
+ end
+ end
end
diff --git a/spec/controllers/instance_statistics/dev_ops_score_controller_spec.rb b/spec/controllers/instance_statistics/dev_ops_score_controller_spec.rb
index d729682bef0..c9677a64eef 100644
--- a/spec/controllers/instance_statistics/dev_ops_score_controller_spec.rb
+++ b/spec/controllers/instance_statistics/dev_ops_score_controller_spec.rb
@@ -4,4 +4,17 @@ require 'spec_helper'
RSpec.describe InstanceStatistics::DevOpsScoreController do
it_behaves_like 'instance statistics availability'
+
+ describe 'GET #index' do
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ it_behaves_like 'tracking unique visits', :index do
+ let(:request_params) { {} }
+ let(:target_id) { 'i_analytics_dev_ops_score' }
+ end
+ end
end
diff --git a/spec/controllers/invites_controller_spec.rb b/spec/controllers/invites_controller_spec.rb
index f2821bb67e8..a9e4073780d 100644
--- a/spec/controllers/invites_controller_spec.rb
+++ b/spec/controllers/invites_controller_spec.rb
@@ -4,21 +4,44 @@ require 'spec_helper'
RSpec.describe InvitesController do
let(:token) { '123456' }
- let(:user) { create(:user) }
- let(:member) { create(:project_member, invite_token: token, invite_email: 'test@abc.com', user: user) }
+ let_it_be(:user) { create(:user) }
+ let(:member) { create(:project_member, :invited, invite_token: token, invite_email: user.email) }
+ let(:project_members) { member.source.users }
before do
controller.instance_variable_set(:@member, member)
sign_in(user)
end
- describe 'GET #accept' do
+ describe 'GET #show' do
+ it 'accepts user if invite email matches signed in user' do
+ expect do
+ get :show, params: { id: token }
+ end.to change { project_members.include?(user) }.from(false).to(true)
+
+ expect(response).to have_gitlab_http_status(:found)
+ expect(flash[:notice]).to include 'You have been granted'
+ end
+
+ it 'forces re-confirmation if email does not match signed in user' do
+ member.invite_email = 'bogus@email.com'
+
+ expect do
+ get :show, params: { id: token }
+ end.not_to change { project_members.include?(user) }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(flash[:notice]).to be_nil
+ end
+ end
+
+ describe 'POST #accept' do
it 'accepts user' do
- get :accept, params: { id: token }
- member.reload
+ expect do
+ post :accept, params: { id: token }
+ end.to change { project_members.include?(user) }.from(false).to(true)
expect(response).to have_gitlab_http_status(:found)
- expect(member.user).to eq(user)
expect(flash[:notice]).to include 'You have been granted'
end
end
@@ -26,8 +49,8 @@ RSpec.describe InvitesController do
describe 'GET #decline' do
it 'declines user' do
get :decline, params: { id: token }
- expect {member.reload}.to raise_error ActiveRecord::RecordNotFound
+ expect { member.reload }.to raise_error ActiveRecord::RecordNotFound
expect(response).to have_gitlab_http_status(:found)
expect(flash[:notice]).to include 'You have declined the invitation to join'
end
diff --git a/spec/controllers/oauth/applications_controller_spec.rb b/spec/controllers/oauth/applications_controller_spec.rb
index f20204b6718..38f46ee7b15 100644
--- a/spec/controllers/oauth/applications_controller_spec.rb
+++ b/spec/controllers/oauth/applications_controller_spec.rb
@@ -121,6 +121,22 @@ RSpec.describe Oauth::ApplicationsController do
end
end
+ describe 'locale' do
+ let(:user) { create(:user, preferred_language: 'uk') }
+
+ before do
+ sign_in(user)
+
+ allow(Gitlab::I18n).to receive(:with_locale).and_call_original
+ end
+
+ it "sets user's locale" do
+ expect(Gitlab::I18n).to receive(:with_locale).with('uk')
+
+ get :new
+ end
+ end
+
def disable_user_oauth
allow(Gitlab::CurrentSettings.current_application_settings).to receive(:user_oauth_applications?).and_return(false)
end
diff --git a/spec/controllers/profiles/keys_controller_spec.rb b/spec/controllers/profiles/keys_controller_spec.rb
index 258ed62262a..66f6135df1e 100644
--- a/spec/controllers/profiles/keys_controller_spec.rb
+++ b/spec/controllers/profiles/keys_controller_spec.rb
@@ -20,69 +20,4 @@ RSpec.describe Profiles::KeysController do
expect(Key.last.expires_at).to be_like_time(expires_at)
end
end
-
- describe "#get_keys" do
- describe "non existent user" do
- it "does not generally work" do
- get :get_keys, params: { username: 'not-existent' }
-
- expect(response).not_to be_successful
- end
- end
-
- describe "user with no keys" do
- it "does generally work" do
- get :get_keys, params: { username: user.username }
-
- expect(response).to be_successful
- end
-
- it "renders all keys separated with a new line" do
- get :get_keys, params: { username: user.username }
-
- expect(response.body).to eq("")
- end
-
- it "responds with text/plain content type" do
- get :get_keys, params: { username: user.username }
- expect(response.content_type).to eq("text/plain")
- end
- end
-
- describe "user with keys" do
- let!(:key) { create(:key, user: user) }
- let!(:another_key) { create(:another_key, user: user) }
- let!(:deploy_key) { create(:deploy_key, user: user) }
-
- it "does generally work" do
- get :get_keys, params: { username: user.username }
-
- expect(response).to be_successful
- end
-
- it "renders all non deploy keys separated with a new line" do
- get :get_keys, params: { username: user.username }
-
- expect(response.body).not_to eq('')
- expect(response.body).to eq(user.all_ssh_keys.join("\n"))
-
- expect(response.body).to include(key.key.sub(' dummy@gitlab.com', ''))
- expect(response.body).to include(another_key.key.sub(' dummy@gitlab.com', ''))
-
- expect(response.body).not_to include(deploy_key.key)
- end
-
- it "does not render the comment of the key" do
- get :get_keys, params: { username: user.username }
-
- expect(response.body).not_to match(/dummy@gitlab.com/)
- end
-
- it "responds with text/plain content type" do
- get :get_keys, params: { username: user.username }
-
- expect(response.content_type).to eq("text/plain")
- end
- end
- end
end
diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb
index 5645e25b741..da4faad2a39 100644
--- a/spec/controllers/projects/clusters_controller_spec.rb
+++ b/spec/controllers/projects/clusters_controller_spec.rb
@@ -200,6 +200,48 @@ RSpec.describe Projects::ClustersController do
end
end
+ describe 'GET #prometheus_proxy' do
+ let(:proxyable) do
+ create(:cluster, :provided_by_gcp, projects: [project])
+ end
+
+ it_behaves_like 'metrics dashboard prometheus api proxy' do
+ let(:proxyable_params) do
+ {
+ id: proxyable.id.to_s,
+ namespace_id: project.namespace.full_path,
+ project_id: project.name
+ }
+ end
+
+ context 'with anonymous user' do
+ let(:prometheus_body) { nil }
+
+ before do
+ sign_out(user)
+ end
+
+ it 'redirects to signin page' do
+ get :prometheus_proxy, params: prometheus_proxy_params
+
+ expect(response).to redirect_to(new_user_session_path)
+ end
+ end
+ end
+ end
+
+ it_behaves_like 'GET #metrics_dashboard for dashboard', 'Cluster health' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) }
+
+ let(:metrics_dashboard_req_params) do
+ {
+ id: cluster.id,
+ namespace_id: project.namespace.full_path,
+ project_id: project.name
+ }
+ end
+ end
+
describe 'POST create for new cluster' do
let(:legacy_abac_param) { 'true' }
let(:params) do
diff --git a/spec/controllers/projects/cycle_analytics_controller_spec.rb b/spec/controllers/projects/cycle_analytics_controller_spec.rb
index 8feb964cdde..ec853b74b9b 100644
--- a/spec/controllers/projects/cycle_analytics_controller_spec.rb
+++ b/spec/controllers/projects/cycle_analytics_controller_spec.rb
@@ -25,6 +25,13 @@ RSpec.describe Projects::CycleAnalyticsController do
end
end
+ context 'tracking visits to html page' do
+ it_behaves_like 'tracking unique visits', :show do
+ let(:request_params) { { namespace_id: project.namespace, project_id: project } }
+ let(:target_id) { 'p_analytics_valuestream' }
+ end
+ end
+
describe 'cycle analytics not set up flag' do
context 'with no data' do
it 'is true' do
diff --git a/spec/controllers/projects/deployments_controller_spec.rb b/spec/controllers/projects/deployments_controller_spec.rb
index 85dd86d91e9..c6532e83441 100644
--- a/spec/controllers/projects/deployments_controller_spec.rb
+++ b/spec/controllers/projects/deployments_controller_spec.rb
@@ -36,6 +36,52 @@ RSpec.describe Projects::DeploymentsController do
expect(response).to be_ok
expect(response).to match_response_schema('deployments')
end
+
+ context 'anonymous user' do
+ let(:anonymous_user) { create(:user) }
+
+ before do
+ sign_in(anonymous_user)
+ end
+
+ context 'project and metrics dashboard are public' do
+ before do
+ project.update!(
+ visibility_level: Gitlab::VisibilityLevel::PUBLIC,
+ project_feature_attributes: {
+ metrics_dashboard_access_level: Gitlab::VisibilityLevel::PUBLIC
+ }
+ )
+ end
+
+ it 'returns a list with deployments information' do
+ create(:deployment, :success, environment: environment)
+
+ get :index, params: deployment_params
+
+ expect(response).to be_ok
+ end
+ end
+
+ context 'project and metrics dashboard are private' do
+ before do
+ project.update!(
+ visibility_level: Gitlab::VisibilityLevel::PRIVATE,
+ project_feature_attributes: {
+ metrics_dashboard_access_level: Gitlab::VisibilityLevel::PRIVATE
+ }
+ )
+ end
+
+ it 'responds with not found' do
+ create(:deployment, :success, environment: environment)
+
+ get :index, params: deployment_params
+
+ expect(response).to be_not_found
+ end
+ end
+ end
end
describe 'GET #metrics' do
diff --git a/spec/controllers/projects/discussions_controller_spec.rb b/spec/controllers/projects/discussions_controller_spec.rb
index f2efd40afdb..f9d16e761cb 100644
--- a/spec/controllers/projects/discussions_controller_spec.rb
+++ b/spec/controllers/projects/discussions_controller_spec.rb
@@ -182,7 +182,8 @@ RSpec.describe Projects::DiscussionsController do
it "unresolves the discussion" do
delete :unresolve, params: request_params
- expect(note.reload.discussion.resolved?).to be false
+ # discussion is memoized and reload doesn't clear the memoization
+ expect(Note.find(note.id).discussion.resolved?).to be false
end
it "returns status 200" do
diff --git a/spec/controllers/projects/environments/prometheus_api_controller_spec.rb b/spec/controllers/projects/environments/prometheus_api_controller_spec.rb
index 17952aa0683..68d50cf19f0 100644
--- a/spec/controllers/projects/environments/prometheus_api_controller_spec.rb
+++ b/spec/controllers/projects/environments/prometheus_api_controller_spec.rb
@@ -3,215 +3,73 @@
require 'spec_helper'
RSpec.describe Projects::Environments::PrometheusApiController do
- let_it_be(:project) { create(:project) }
- let_it_be(:environment) { create(:environment, project: project) }
let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:proxyable) { create(:environment, project: project) }
before do
project.add_reporter(user)
sign_in(user)
end
- describe 'GET #proxy' do
- let(:prometheus_proxy_service) { instance_double(Prometheus::ProxyService) }
-
- let(:expected_params) do
- ActionController::Parameters.new(
- environment_params(
- proxy_path: 'query',
- controller: 'projects/environments/prometheus_api',
- action: 'proxy'
- )
- ).permit!
- end
-
- context 'with valid requests' do
- before do
- allow(Prometheus::ProxyService).to receive(:new)
- .with(environment, 'GET', 'query', expected_params)
- .and_return(prometheus_proxy_service)
-
- allow(prometheus_proxy_service).to receive(:execute)
- .and_return(service_result)
+ describe 'GET #prometheus_proxy' do
+ it_behaves_like 'metrics dashboard prometheus api proxy' do
+ let(:proxyable_params) do
+ {
+ id: proxyable.id.to_s,
+ namespace_id: project.namespace.full_path,
+ project_id: project.name
+ }
end
- context 'with success result' do
- let(:service_result) { { status: :success, body: prometheus_body } }
+ context 'with variables' do
let(:prometheus_body) { '{"status":"success"}' }
- let(:prometheus_json_body) { Gitlab::Json.parse(prometheus_body) }
+ let(:pod_name) { "pod1" }
- it 'returns prometheus response' do
- get :proxy, params: environment_params
-
- expect(Prometheus::ProxyService).to have_received(:new)
- .with(environment, 'GET', 'query', expected_params)
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response).to eq(prometheus_json_body)
+ before do
+ expected_params[:query] = %{up{pod_name="#{pod_name}"}}
+ expected_params[:variables] = { 'pod_name' => pod_name }
end
- context 'with format string' do
- before do
- expected_params[:query] = %{up{environment="#{environment.slug}"}}
- end
-
- it 'replaces variables with values' do
- get :proxy, params: environment_params.merge(query: 'up{environment="{{ci_environment_slug}}"}')
-
- expect(Prometheus::ProxyService).to have_received(:new)
- .with(environment, 'GET', 'query', expected_params)
- end
-
- context 'with nil query' do
- let(:params_without_query) do
- environment_params.except(:query)
- end
-
- before do
- expected_params.delete(:query)
- end
-
- it 'does not raise error' do
- get :proxy, params: params_without_query
+ it 'replaces variables with values' do
+ get :prometheus_proxy, params: prometheus_proxy_params.merge(
+ query: 'up{pod_name="{{pod_name}}"}', variables: { 'pod_name' => pod_name }
+ )
- expect(Prometheus::ProxyService).to have_received(:new)
- .with(environment, 'GET', 'query', expected_params)
- end
- end
+ expect(response).to have_gitlab_http_status(:success)
+ expect(Prometheus::ProxyService).to have_received(:new)
+ .with(proxyable, 'GET', 'query', expected_params)
end
- context 'with variables' do
- let(:pod_name) { "pod1" }
-
- before do
- expected_params[:query] = %{up{pod_name="#{pod_name}"}}
- expected_params[:variables] = { 'pod_name' => pod_name }
- end
-
- it 'replaces variables with values' do
- get :proxy, params: environment_params.merge(
- query: 'up{pod_name="{{pod_name}}"}', variables: { 'pod_name' => pod_name }
+ context 'with invalid variables' do
+ let(:params_with_invalid_variables) do
+ prometheus_proxy_params.merge(
+ query: 'up{pod_name="{{pod_name}}"}', variables: ['a']
)
-
- expect(response).to have_gitlab_http_status(:success)
- expect(Prometheus::ProxyService).to have_received(:new)
- .with(environment, 'GET', 'query', expected_params)
- end
-
- context 'with invalid variables' do
- let(:params_with_invalid_variables) do
- environment_params.merge(
- query: 'up{pod_name="{{pod_name}}"}', variables: ['a']
- )
- end
-
- it 'returns 400' do
- get :proxy, params: params_with_invalid_variables
-
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(Prometheus::ProxyService).not_to receive(:new)
- end
- end
- end
- end
-
- context 'with nil result' do
- let(:service_result) { nil }
-
- it 'returns 204 no_content' do
- get :proxy, params: environment_params
-
- expect(json_response['status']).to eq(_('processing'))
- expect(json_response['message']).to eq(_('Not ready yet. Try again later.'))
- expect(response).to have_gitlab_http_status(:no_content)
- end
- end
-
- context 'with 404 result' do
- let(:service_result) { { http_status: 404, status: :success, body: '{"body": "value"}' } }
-
- it 'returns body' do
- get :proxy, params: environment_params
-
- expect(response).to have_gitlab_http_status(:not_found)
- expect(json_response['body']).to eq('value')
- end
- end
-
- context 'with error result' do
- context 'with http_status' do
- let(:service_result) do
- { http_status: :service_unavailable, status: :error, message: 'error message' }
- end
-
- it 'sets the http response status code' do
- get :proxy, params: environment_params
-
- expect(response).to have_gitlab_http_status(:service_unavailable)
- expect(json_response['status']).to eq('error')
- expect(json_response['message']).to eq('error message')
end
- end
-
- context 'without http_status' do
- let(:service_result) { { status: :error, message: 'error message' } }
- it 'returns bad_request' do
- get :proxy, params: environment_params
+ it 'returns 400' do
+ get :prometheus_proxy, params: params_with_invalid_variables
expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['status']).to eq('error')
- expect(json_response['message']).to eq('error message')
+ expect(Prometheus::ProxyService).not_to receive(:new)
end
end
end
- end
- context 'with inappropriate requests' do
context 'with anonymous user' do
+ let(:prometheus_body) { nil }
+
before do
sign_out(user)
end
it 'redirects to signin page' do
- get :proxy, params: environment_params
+ get :prometheus_proxy, params: prometheus_proxy_params
expect(response).to redirect_to(new_user_session_path)
end
end
-
- context 'without correct permissions' do
- before do
- project.team.truncate
- end
-
- it 'returns 404' do
- get :proxy, params: environment_params
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
end
-
- context 'with invalid environment id' do
- let(:other_environment) { create(:environment) }
-
- it 'returns 404' do
- get :proxy, params: environment_params(id: other_environment.id)
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
-
- private
-
- def environment_params(params = {})
- {
- id: environment.id.to_s,
- namespace_id: project.namespace.full_path,
- project_id: project.name,
- proxy_path: 'query',
- query: '1'
- }.merge(params)
end
end
diff --git a/spec/controllers/projects/environments_controller_spec.rb b/spec/controllers/projects/environments_controller_spec.rb
index cca4b597f4c..85ec1f7396d 100644
--- a/spec/controllers/projects/environments_controller_spec.rb
+++ b/spec/controllers/projects/environments_controller_spec.rb
@@ -546,28 +546,20 @@ RSpec.describe Projects::EnvironmentsController do
end
describe 'GET #metrics_dashboard' do
- shared_examples_for 'correctly formatted response' do |status_code|
- it 'returns a json object with the correct keys' do
- get :metrics_dashboard, params: environment_params(dashboard_params)
-
- # Exlcude `all_dashboards` to handle separately.
- found_keys = json_response.keys - ['all_dashboards']
-
- expect(response).to have_gitlab_http_status(status_code)
- expect(found_keys).to contain_exactly(*expected_keys)
- end
- end
+ let(:metrics_dashboard_req_params) { environment_params(dashboard_params) }
shared_examples_for '200 response' do
- let(:expected_keys) { %w(dashboard status metrics_data) }
-
- it_behaves_like 'correctly formatted response', :ok
+ it_behaves_like 'GET #metrics_dashboard correctly formatted response' do
+ let(:expected_keys) { %w(dashboard status metrics_data) }
+ let(:status_code) { :ok }
+ end
end
shared_examples_for 'error response' do |status_code|
- let(:expected_keys) { %w(message status) }
-
- it_behaves_like 'correctly formatted response', status_code
+ it_behaves_like 'GET #metrics_dashboard correctly formatted response' do
+ let(:expected_keys) { %w(message status) }
+ let(:status_code) { status_code }
+ end
end
shared_examples_for 'includes all dashboards' do
@@ -581,29 +573,14 @@ RSpec.describe Projects::EnvironmentsController do
end
shared_examples_for 'the default dashboard' do
- it_behaves_like '200 response'
it_behaves_like 'includes all dashboards'
-
- it 'is the default dashboard' do
- get :metrics_dashboard, params: environment_params(dashboard_params)
-
- expect(json_response['dashboard']['dashboard']).to eq('Environment metrics')
- end
+ it_behaves_like 'GET #metrics_dashboard for dashboard', 'Environment metrics'
end
shared_examples_for 'the specified dashboard' do |expected_dashboard|
- it_behaves_like '200 response'
it_behaves_like 'includes all dashboards'
- it 'has the correct name' do
- get :metrics_dashboard, params: environment_params(dashboard_params)
-
- dashboard_name = json_response['dashboard']['dashboard']
-
- # 'Environment metrics' is the default dashboard.
- expect(dashboard_name).not_to eq('Environment metrics')
- expect(dashboard_name).to eq(expected_dashboard)
- end
+ it_behaves_like 'GET #metrics_dashboard for dashboard', expected_dashboard
context 'when the dashboard cannot not be processed' do
before do
diff --git a/spec/controllers/projects/graphs_controller_spec.rb b/spec/controllers/projects/graphs_controller_spec.rb
index 12cef6bea09..49def8f80b0 100644
--- a/spec/controllers/projects/graphs_controller_spec.rb
+++ b/spec/controllers/projects/graphs_controller_spec.rb
@@ -80,6 +80,15 @@ RSpec.describe Projects::GraphsController do
expect(assigns[:daily_coverage_options]).to be_nil
end
end
+
+ it_behaves_like 'tracking unique visits', :charts do
+ before do
+ sign_in(user)
+ end
+
+ let(:request_params) { { namespace_id: project.namespace.path, project_id: project.path, id: 'master' } }
+ let(:target_id) { 'p_analytics_repo' }
+ end
end
context 'when languages were previously detected' do
diff --git a/spec/controllers/projects/imports_controller_spec.rb b/spec/controllers/projects/imports_controller_spec.rb
index 29cfd1c352e..029b4210f19 100644
--- a/spec/controllers/projects/imports_controller_spec.rb
+++ b/spec/controllers/projects/imports_controller_spec.rb
@@ -8,33 +8,15 @@ RSpec.describe Projects::ImportsController do
before do
sign_in(user)
- project.add_maintainer(user)
end
describe 'GET #show' do
- context 'when repository does not exists' do
- it 'renders template' do
- get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
-
- expect(response).to render_template :show
- end
-
- it 'sets flash.now if params is present' do
- get :show, params: { namespace_id: project.namespace.to_param, project_id: project, continue: { to: '/', notice_now: 'Started' } }
-
- expect(flash.now[:notice]).to eq 'Started'
+ context 'when the user has maintainer rights' do
+ before do
+ project.add_maintainer(user)
end
- end
-
- context 'when repository exists' do
- let(:project) { create(:project_empty_repo, import_url: 'https://github.com/vim/vim.git') }
- let(:import_state) { project.import_state }
-
- context 'when import is in progress' do
- before do
- import_state.update(status: :started)
- end
+ context 'when repository does not exists' do
it 'renders template' do
get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
@@ -42,82 +24,138 @@ RSpec.describe Projects::ImportsController do
end
it 'sets flash.now if params is present' do
- get :show, params: { namespace_id: project.namespace.to_param, project_id: project, continue: { to: '/', notice_now: 'In progress' } }
+ get :show, params: { namespace_id: project.namespace.to_param, project_id: project, continue: { to: '/', notice_now: 'Started' } }
- expect(flash.now[:notice]).to eq 'In progress'
+ expect(flash.now[:notice]).to eq 'Started'
end
end
- context 'when import failed' do
- before do
- import_state.update(status: :failed)
- end
+ context 'when repository exists' do
+ let(:project) { create(:project_empty_repo, import_url: 'https://github.com/vim/vim.git') }
+ let(:import_state) { project.import_state }
- it 'redirects to new_namespace_project_import_path' do
- get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
+ context 'when import is in progress' do
+ before do
+ import_state.update(status: :started)
+ end
- expect(response).to redirect_to new_project_import_path(project)
- end
- end
+ it 'renders template' do
+ get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
- context 'when import finished' do
- before do
- import_state.update(status: :finished)
+ expect(response).to render_template :show
+ end
+
+ it 'sets flash.now if params is present' do
+ get :show, params: { namespace_id: project.namespace.to_param, project_id: project, continue: { to: '/', notice_now: 'In progress' } }
+
+ expect(flash.now[:notice]).to eq 'In progress'
+ end
end
- context 'when project is a fork' do
- it 'redirects to namespace_project_path' do
- allow_any_instance_of(Project).to receive(:forked?).and_return(true)
+ context 'when import failed' do
+ before do
+ import_state.update(status: :failed)
+ end
+ it 'redirects to new_namespace_project_import_path' do
get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
- expect(flash[:notice]).to eq 'The project was successfully forked.'
- expect(response).to redirect_to project_path(project)
+ expect(response).to redirect_to new_project_import_path(project)
end
end
- context 'when project is external' do
- it 'redirects to namespace_project_path' do
- get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
+ context 'when import finished' do
+ before do
+ import_state.update(status: :finished)
+ end
- expect(flash[:notice]).to eq 'The project was successfully imported.'
- expect(response).to redirect_to project_path(project)
+ context 'when project is a fork' do
+ it 'redirects to namespace_project_path' do
+ allow_any_instance_of(Project).to receive(:forked?).and_return(true)
+
+ get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
+
+ expect(flash[:notice]).to eq 'The project was successfully forked.'
+ expect(response).to redirect_to project_path(project)
+ end
end
- end
- context 'when continue params is present' do
- let(:params) do
- {
- to: project_path(project),
- notice: 'Finished'
- }
+ context 'when project is external' do
+ it 'redirects to namespace_project_path' do
+ get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
+
+ expect(flash[:notice]).to eq 'The project was successfully imported.'
+ expect(response).to redirect_to project_path(project)
+ end
end
- it 'redirects to internal params[:to]' do
- get :show, params: { namespace_id: project.namespace.to_param, project_id: project, continue: params }
+ context 'when continue params is present' do
+ let(:params) do
+ {
+ to: project_path(project),
+ notice: 'Finished'
+ }
+ end
+
+ it 'redirects to internal params[:to]' do
+ get :show, params: { namespace_id: project.namespace.to_param, project_id: project, continue: params }
+
+ expect(flash[:notice]).to eq params[:notice]
+ expect(response).to redirect_to params[:to]
+ end
- expect(flash[:notice]).to eq params[:notice]
- expect(response).to redirect_to params[:to]
+ it 'does not redirect to external params[:to]' do
+ params[:to] = "//google.com"
+
+ get :show, params: { namespace_id: project.namespace.to_param, project_id: project, continue: params }
+ expect(response).not_to redirect_to params[:to]
+ end
end
+ end
- it 'does not redirect to external params[:to]' do
- params[:to] = "//google.com"
+ context 'when import never happened' do
+ before do
+ import_state.update(status: :none)
+ end
- get :show, params: { namespace_id: project.namespace.to_param, project_id: project, continue: params }
- expect(response).not_to redirect_to params[:to]
+ it 'redirects to namespace_project_path' do
+ get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
+
+ expect(response).to redirect_to project_path(project)
end
end
end
+ end
+
+ context 'when project is in group' do
+ let(:project) { create(:project_empty_repo, import_url: 'https://github.com/vim/vim.git', namespace: group) }
+
+ context 'when user has developer access to group and import is in progress' do
+ let(:import_state) { project.import_state }
- context 'when import never happened' do
before do
- import_state.update(status: :none)
+ group.add_developer(user)
+ import_state.update!(status: :started)
end
- it 'redirects to namespace_project_path' do
- get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
+ context 'when group allows developers to create projects' do
+ let(:group) { create(:group, project_creation_level: Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS) }
- expect(response).to redirect_to project_path(project)
+ it 'renders template' do
+ get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
+
+ expect(response).to render_template :show
+ end
+ end
+
+ context 'when group prohibits developers to create projects' do
+ let(:group) { create(:group, project_creation_level: Gitlab::Access::MAINTAINER_PROJECT_ACCESS) }
+
+ it 'returns 404 response' do
+ get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
end
end
end
@@ -128,6 +166,7 @@ RSpec.describe Projects::ImportsController do
let(:project) { create(:project) }
before do
+ project.add_maintainer(user)
allow(RepositoryImportWorker).to receive(:perform_async)
post :create, params: { project: params, namespace_id: project.namespace.to_param, project_id: project }
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index bcd1a53bd47..f9580c79390 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -237,7 +237,7 @@ RSpec.describe Projects::IssuesController do
context 'external issue tracker' do
let!(:service) do
- create(:custom_issue_tracker_service, project: project, title: 'Custom Issue Tracker', new_issue_url: 'http://test.com')
+ create(:custom_issue_tracker_service, project: project, new_issue_url: 'http://test.com')
end
before do
@@ -1564,6 +1564,43 @@ RSpec.describe Projects::IssuesController do
end
end
+ describe 'GET service_desk' do
+ let_it_be(:project) { create(:project_empty_repo, :public) }
+ let_it_be(:support_bot) { User.support_bot }
+ let_it_be(:other_user) { create(:user) }
+ let_it_be(:service_desk_issue_1) { create(:issue, project: project, author: support_bot) }
+ let_it_be(:service_desk_issue_2) { create(:issue, project: project, author: support_bot, assignees: [other_user]) }
+ let_it_be(:other_user_issue) { create(:issue, project: project, author: other_user) }
+
+ def get_service_desk(extra_params = {})
+ get :service_desk, params: extra_params.merge(namespace_id: project.namespace, project_id: project)
+ end
+
+ it 'adds an author filter for the support bot user' do
+ get_service_desk
+
+ expect(assigns(:issues)).to contain_exactly(service_desk_issue_1, service_desk_issue_2)
+ end
+
+ it 'does not allow any other author to be set' do
+ get_service_desk(author_username: other_user.username)
+
+ expect(assigns(:issues)).to contain_exactly(service_desk_issue_1, service_desk_issue_2)
+ end
+
+ it 'supports other filters' do
+ get_service_desk(assignee_username: other_user.username)
+
+ expect(assigns(:issues)).to contain_exactly(service_desk_issue_2)
+ end
+
+ it 'allows an assignee to be specified by id' do
+ get_service_desk(assignee_id: other_user.id)
+
+ expect(assigns(:users)).to contain_exactly(other_user, support_bot)
+ end
+ end
+
describe 'GET #discussions' do
let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb
index 44dcb0caab2..818b1c30b37 100644
--- a/spec/controllers/projects/jobs_controller_spec.rb
+++ b/spec/controllers/projects/jobs_controller_spec.rb
@@ -646,109 +646,6 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
end
- describe 'GET legacy trace.json' do
- before do
- stub_feature_flags(job_log_json: false)
- get_trace
- end
-
- context 'when job has a trace artifact' do
- let(:job) { create(:ci_build, :trace_artifact, pipeline: pipeline) }
-
- it 'returns a trace' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['id']).to eq job.id
- expect(json_response['status']).to eq job.status
- expect(json_response['state']).to be_present
- expect(json_response['append']).not_to be_nil
- expect(json_response['truncated']).not_to be_nil
- expect(json_response['size']).to be_present
- expect(json_response['total']).to be_present
- expect(json_response['html']).to eq(job.trace.html)
- end
- end
-
- context 'when job has a trace' do
- let(:job) { create(:ci_build, :trace_live, pipeline: pipeline) }
-
- it 'returns a trace' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['id']).to eq job.id
- expect(json_response['status']).to eq job.status
- expect(json_response['html']).to eq('<span>BUILD TRACE</span>')
- end
- end
-
- context 'when job has no traces' do
- let(:job) { create(:ci_build, pipeline: pipeline) }
-
- it 'returns no traces' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['id']).to eq job.id
- expect(json_response['status']).to eq job.status
- expect(json_response['html']).to be_nil
- end
- end
-
- context 'when job has a trace with ANSI sequence and Unicode' do
- let(:job) { create(:ci_build, :unicode_trace_live, pipeline: pipeline) }
-
- it 'returns a trace with Unicode' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['id']).to eq job.id
- expect(json_response['status']).to eq job.status
- expect(json_response['html']).to include("ヾ(´༎ຶД༎ຶ`)ノ")
- end
- end
-
- context 'when trace artifact is in ObjectStorage' do
- let(:url) { 'http://object-storage/trace' }
- let(:file_path) { expand_fixture_path('trace/sample_trace') }
- let!(:job) { create(:ci_build, :success, :trace_artifact, pipeline: pipeline) }
-
- before do
- allow_any_instance_of(JobArtifactUploader).to receive(:file_storage?) { false }
- allow_any_instance_of(JobArtifactUploader).to receive(:url) { url }
- allow_any_instance_of(JobArtifactUploader).to receive(:size) { File.size(file_path) }
- end
-
- context 'when there are no network issues' do
- before do
- stub_remote_url_206(url, file_path)
-
- get_trace
- end
-
- it 'returns a trace' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['id']).to eq job.id
- expect(json_response['status']).to eq job.status
- expect(json_response['html']).to eq(job.trace.html)
- end
- end
-
- context 'when there is a network issue' do
- before do
- stub_remote_url_500(url)
- end
-
- it 'returns a trace' do
- expect { get_trace }.to raise_error(Gitlab::HttpIO::FailedToGetChunkError)
- end
- end
- end
-
- def get_trace
- get :trace,
- params: {
- namespace_id: project.namespace,
- project_id: project,
- id: job.id
- },
- format: :json
- end
- end
-
describe 'GET status.json' do
let(:job) { create(:ci_build, pipeline: pipeline) }
let(:status) { job.detailed_status(double('user')) }
diff --git a/spec/controllers/projects/logs_controller_spec.rb b/spec/controllers/projects/logs_controller_spec.rb
index 1eb5a6fcc12..0f34e536064 100644
--- a/spec/controllers/projects/logs_controller_spec.rb
+++ b/spec/controllers/projects/logs_controller_spec.rb
@@ -104,6 +104,34 @@ RSpec.describe Projects::LogsController do
expect(response.headers['Poll-Interval']).to eq('3000')
end
+ context 'with gitlab managed apps logs' do
+ it 'uses cluster finder services to select cluster', :aggregate_failures do
+ cluster_list = [cluster]
+ service_params = { params: ActionController::Parameters.new(pod_name: pod_name).permit! }
+ request_params = {
+ namespace_id: project.namespace,
+ project_id: project,
+ cluster_id: cluster.id,
+ pod_name: pod_name,
+ format: :json
+ }
+
+ expect_next_instance_of(ClusterAncestorsFinder, project, user) do |finder|
+ expect(finder).to receive(:execute).and_return(cluster_list)
+ expect(cluster_list).to receive(:find).and_call_original
+ end
+
+ expect_next_instance_of(service, cluster, Gitlab::Kubernetes::Helm::NAMESPACE, service_params) do |instance|
+ expect(instance).to receive(:execute).and_return(service_result)
+ end
+
+ get endpoint, params: request_params
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(json_response).to eq(service_result_json)
+ end
+ end
+
context 'when service is processing' do
let(:service_result) { nil }
diff --git a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
index 02b4c2d1da9..217447c2ad6 100644
--- a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
@@ -91,6 +91,17 @@ RSpec.describe Projects::MergeRequests::DiffsController do
end
end
+ shared_examples "diff note on-demand position creation" do
+ it "updates diff discussion positions" do
+ service = double("service")
+
+ expect(Discussions::CaptureDiffNotePositionsService).to receive(:new).with(merge_request).and_return(service)
+ expect(service).to receive(:execute)
+
+ go
+ end
+ end
+
let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
@@ -146,6 +157,7 @@ RSpec.describe Projects::MergeRequests::DiffsController do
it_behaves_like 'persisted preferred diff view cookie'
it_behaves_like 'cached diff collection'
+ it_behaves_like 'diff note on-demand position creation'
end
describe 'GET diffs_metadata' do
diff --git a/spec/controllers/projects/merge_requests/drafts_controller_spec.rb b/spec/controllers/projects/merge_requests/drafts_controller_spec.rb
index 7d74e872d29..af39d4dec72 100644
--- a/spec/controllers/projects/merge_requests/drafts_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/drafts_controller_spec.rb
@@ -331,8 +331,10 @@ RSpec.describe Projects::MergeRequests::DraftsController do
notes = merge_request.notes.reload
expect(notes.pluck(:note)).to include(*drafts.map(&:note))
- expect(note.discussion.notes.last.note).to eq(draft_reply.note)
- expect(diff_note.discussion.notes.last.note).to eq(diff_draft_reply.note)
+
+ # discussion is memoized and reload doesn't clear the memoization
+ expect(Note.find(note.id).discussion.notes.last.note).to eq(draft_reply.note)
+ expect(Note.find(diff_note.id).discussion.notes.last.note).to eq(diff_draft_reply.note)
end
it 'can publish just a single draft note' do
@@ -376,7 +378,8 @@ RSpec.describe Projects::MergeRequests::DraftsController do
post :publish, params: params
- discussion = note.discussion
+ # discussion is memoized and reload doesn't clear the memoization
+ discussion = Note.find(note.id).discussion
expect(discussion.notes.last.note).to eq(draft_reply.note)
expect(discussion.resolved?).to eq(false)
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 382593fd7cb..4327e0bbb7a 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -442,7 +442,7 @@ RSpec.describe Projects::MergeRequestsController do
merge_request.update(squash: false)
merge_with_sha(squash: '1')
- expect(merge_request.reload.squash).to be_truthy
+ expect(merge_request.reload.squash_on_merge?).to be_truthy
end
end
@@ -451,7 +451,7 @@ RSpec.describe Projects::MergeRequestsController do
merge_request.update(squash: true)
merge_with_sha(squash: '0')
- expect(merge_request.reload.squash).to be_falsey
+ expect(merge_request.reload.squash_on_merge?).to be_falsey
end
end
diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb
index b3a83723189..9728fad417e 100644
--- a/spec/controllers/projects/notes_controller_spec.rb
+++ b/spec/controllers/projects/notes_controller_spec.rb
@@ -38,9 +38,9 @@ RSpec.describe Projects::NotesController do
end
it 'passes last_fetched_at from headers to NotesFinder and MergeIntoNotesService' do
- last_fetched_at = 3.hours.ago.to_i
+ last_fetched_at = Time.zone.at(3.hours.ago.to_i) # remove nanoseconds
- request.headers['X-Last-Fetched-At'] = last_fetched_at
+ request.headers['X-Last-Fetched-At'] = microseconds(last_fetched_at)
expect(NotesFinder).to receive(:new)
.with(anything, hash_including(last_fetched_at: last_fetched_at))
@@ -84,6 +84,81 @@ RSpec.describe Projects::NotesController do
end
end
+ context 'for multiple pages of notes', :aggregate_failures do
+ # 3 pages worth: 1 normal page, 1 oversized due to clashing updated_at,
+ # and a final, short page
+ let!(:page_1) { create_list(:note, 2, noteable: issue, project: project, updated_at: 3.days.ago) }
+ let!(:page_2) { create_list(:note, 3, noteable: issue, project: project, updated_at: 2.days.ago) }
+ let!(:page_3) { create_list(:note, 2, noteable: issue, project: project, updated_at: 1.day.ago) }
+
+ # Include a resource event in the middle page as well
+ let!(:resource_event) { create(:resource_state_event, issue: issue, user: user, created_at: 2.days.ago) }
+
+ let(:page_1_boundary) { microseconds(page_1.last.updated_at + NotesFinder::FETCH_OVERLAP) }
+ let(:page_2_boundary) { microseconds(page_2.last.updated_at + NotesFinder::FETCH_OVERLAP) }
+
+ around do |example|
+ Timecop.freeze do
+ example.run
+ end
+ end
+
+ before do
+ stub_const('Gitlab::UpdatedNotesPaginator::LIMIT', 2)
+ end
+
+ context 'feature flag enabled' do
+ before do
+ stub_feature_flags(paginated_notes: true)
+ end
+
+ it 'returns the first page of notes' do
+ get :index, params: request_params
+
+ expect(json_response['notes'].count).to eq(page_1.count)
+ expect(json_response['more']).to be_truthy
+ expect(json_response['last_fetched_at']).to eq(page_1_boundary)
+ expect(response.headers['Poll-Interval'].to_i).to eq(1)
+ end
+
+ it 'returns the second page of notes' do
+ request.headers['X-Last-Fetched-At'] = page_1_boundary
+
+ get :index, params: request_params
+
+ expect(json_response['notes'].count).to eq(page_2.count + 1) # resource event
+ expect(json_response['more']).to be_truthy
+ expect(json_response['last_fetched_at']).to eq(page_2_boundary)
+ expect(response.headers['Poll-Interval'].to_i).to eq(1)
+ end
+
+ it 'returns the final page of notes' do
+ request.headers['X-Last-Fetched-At'] = page_2_boundary
+
+ get :index, params: request_params
+
+ expect(json_response['notes'].count).to eq(page_3.count)
+ expect(json_response['more']).to be_falsy
+ expect(json_response['last_fetched_at']).to eq(microseconds(Time.zone.now))
+ expect(response.headers['Poll-Interval'].to_i).to be > 1
+ end
+ end
+
+ context 'feature flag disabled' do
+ before do
+ stub_feature_flags(paginated_notes: false)
+ end
+
+ it 'returns all notes' do
+ get :index, params: request_params
+
+ expect(json_response['notes'].count).to eq((page_1 + page_2 + page_3).size + 1)
+ expect(json_response['more']).to be_falsy
+ expect(json_response['last_fetched_at']).to eq(microseconds(Time.zone.now))
+ end
+ end
+ end
+
context 'for a discussion note' do
let(:project) { create(:project, :repository) }
let!(:note) { create(:discussion_note_on_merge_request, project: project) }
@@ -870,4 +945,9 @@ RSpec.describe Projects::NotesController do
end
end
end
+
+ # Convert a time to an integer number of microseconds
+ def microseconds(time)
+ (time.to_i * 1_000_000) + time.usec
+ end
end
diff --git a/spec/controllers/projects/stages_controller_spec.rb b/spec/controllers/projects/pipelines/stages_controller_spec.rb
index dcf8607ae18..6e8c08d95a1 100644
--- a/spec/controllers/projects/stages_controller_spec.rb
+++ b/spec/controllers/projects/pipelines/stages_controller_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Projects::StagesController do
+RSpec.describe Projects::Pipelines::StagesController do
let(:user) { create(:user) }
let(:project) { create(:project, :repository) }
@@ -60,7 +60,7 @@ RSpec.describe Projects::StagesController do
post :play_manual, params: {
namespace_id: project.namespace,
project_id: project,
- id: pipeline.id,
+ pipeline_id: pipeline.id,
stage_name: stage_name
}, format: :json
end
diff --git a/spec/controllers/projects/pipelines/tests_controller_spec.rb b/spec/controllers/projects/pipelines/tests_controller_spec.rb
new file mode 100644
index 00000000000..e2abd1238c5
--- /dev/null
+++ b/spec/controllers/projects/pipelines/tests_controller_spec.rb
@@ -0,0 +1,112 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::Pipelines::TestsController do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :public, :repository) }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+
+ before do
+ sign_in(user)
+ end
+
+ describe 'GET #summary.json' do
+ context 'when pipeline has build report results' do
+ let(:pipeline) { create(:ci_pipeline, :with_report_results, project: project) }
+
+ it 'renders test report summary data' do
+ get_tests_summary_json
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['total_count']).to eq(2)
+ end
+ end
+
+ context 'when pipeline does not have build report results' do
+ it 'renders test report summary data' do
+ get_tests_summary_json
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['total_count']).to eq(0)
+ end
+ end
+
+ context 'when feature is disabled' do
+ before do
+ stub_feature_flags(build_report_summary: false)
+ end
+
+ it 'returns 404' do
+ get_tests_summary_json
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(response.body).to be_empty
+ end
+ end
+ end
+
+ describe 'GET #show.json' do
+ context 'when pipeline has build report results' do
+ let(:pipeline) { create(:ci_pipeline, :with_report_results, project: project) }
+ let(:suite_name) { 'test' }
+ let(:build_ids) { pipeline.latest_builds.pluck(:id) }
+
+ it 'renders test suite data' do
+ get_tests_show_json(build_ids)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['name']).to eq('test')
+ end
+ end
+
+ context 'when pipeline does not have build report results' do
+ let(:pipeline) { create(:ci_empty_pipeline) }
+ let(:suite_name) { 'test' }
+
+ it 'renders 404' do
+ get_tests_show_json([])
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(response.body).to be_empty
+ end
+ end
+
+ context 'when feature is disabled' do
+ let(:suite_name) { 'test' }
+
+ before do
+ stub_feature_flags(build_report_summary: false)
+ end
+
+ it 'returns 404' do
+ get_tests_show_json([])
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(response.body).to be_empty
+ end
+ end
+ end
+
+ def get_tests_summary_json
+ get :summary,
+ params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ pipeline_id: pipeline.id
+ },
+ format: :json
+ end
+
+ def get_tests_show_json(build_ids)
+ get :show,
+ params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ pipeline_id: pipeline.id,
+ suite_name: suite_name,
+ build_ids: build_ids
+ },
+ format: :json
+ end
+end
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb
index ca09d2b1428..872f0e97b09 100644
--- a/spec/controllers/projects/pipelines_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_controller_spec.rb
@@ -37,16 +37,13 @@ RSpec.describe Projects::PipelinesController do
expect(json_response).to include('pipelines')
expect(json_response['pipelines'].count).to eq 6
expect(json_response['count']['all']).to eq '6'
- expect(json_response['count']['running']).to eq '2'
- expect(json_response['count']['pending']).to eq '1'
- expect(json_response['count']['finished']).to eq '3'
json_response.dig('pipelines', 0, 'details', 'stages').tap do |stages|
expect(stages.count).to eq 3
end
end
- it 'does not execute N+1 queries' do
+ it 'executes N+1 queries' do
get_pipelines_index_json
control_count = ActiveRecord::QueryRecorder.new do
@@ -56,10 +53,31 @@ RSpec.describe Projects::PipelinesController do
create_all_pipeline_types
# There appears to be one extra query for Pipelines#has_warnings? for some reason
- expect { get_pipelines_index_json }.not_to exceed_query_limit(control_count + 1)
+ expect { get_pipelines_index_json }.not_to exceed_query_limit(control_count + 7)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['pipelines'].count).to eq 12
end
+
+ context 'with build_report_summary turned off' do
+ before do
+ stub_feature_flags(build_report_summary: false)
+ end
+
+ it 'does not execute N+1 queries' do
+ get_pipelines_index_json
+
+ control_count = ActiveRecord::QueryRecorder.new do
+ get_pipelines_index_json
+ end.count
+
+ create_all_pipeline_types
+
+ # There appears to be one extra query for Pipelines#has_warnings? for some reason
+ expect { get_pipelines_index_json }.not_to exceed_query_limit(control_count + 1)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['pipelines'].count).to eq 12
+ end
+ end
end
it 'does not include coverage data for the pipelines' do
@@ -77,9 +95,9 @@ RSpec.describe Projects::PipelinesController do
expect(::Gitlab::GitalyClient).to receive(:allow_ref_name_caching).and_call_original
- # ListCommitsByOid, RepositoryExists, HasLocalBranches
+ # ListCommitsByOid, RepositoryExists, HasLocalBranches, ListCommitsByRefNames
expect { get_pipelines_index_json }
- .to change { Gitlab::GitalyClient.get_request_count }.by(3)
+ .to change { Gitlab::GitalyClient.get_request_count }.by(4)
end
end
@@ -101,23 +119,27 @@ RSpec.describe Projects::PipelinesController do
end
end
- context 'filter by scope' do
- it 'returns matched pipelines' do
- get_pipelines_index_json(scope: 'running')
+ context 'when user tries to access legacy scope via URL' do
+ it 'redirects to all pipelines with that status instead' do
+ get_pipelines_index_html(scope: 'running')
- check_pipeline_response(returned: 2, all: 6, running: 2, pending: 1, finished: 3)
+ expect(response).to redirect_to(project_pipelines_path(project, status: 'running', format: :html))
end
+ end
+ context 'filter by scope' do
context 'scope is branches or tags' do
before do
create(:ci_pipeline, :failed, project: project, ref: 'v1.0.0', tag: true)
+ create(:ci_pipeline, :failed, project: project, ref: 'master', tag: false)
+ create(:ci_pipeline, :failed, project: project, ref: 'feature', tag: false)
end
context 'when scope is branches' do
it 'returns matched pipelines' do
get_pipelines_index_json(scope: 'branches')
- check_pipeline_response(returned: 1, all: 7, running: 2, pending: 1, finished: 4)
+ check_pipeline_response(returned: 2, all: 9)
end
end
@@ -125,7 +147,7 @@ RSpec.describe Projects::PipelinesController do
it 'returns matched pipelines' do
get_pipelines_index_json(scope: 'tags')
- check_pipeline_response(returned: 1, all: 7, running: 2, pending: 1, finished: 4)
+ check_pipeline_response(returned: 1, all: 9)
end
end
end
@@ -138,7 +160,7 @@ RSpec.describe Projects::PipelinesController do
it 'returns matched pipelines' do
get_pipelines_index_json(username: user.username)
- check_pipeline_response(returned: 1, all: 1, running: 1, pending: 0, finished: 0)
+ check_pipeline_response(returned: 1, all: 1)
end
end
@@ -146,7 +168,7 @@ RSpec.describe Projects::PipelinesController do
it 'returns empty' do
get_pipelines_index_json(username: 'invalid-username')
- check_pipeline_response(returned: 0, all: 0, running: 0, pending: 0, finished: 0)
+ check_pipeline_response(returned: 0, all: 0)
end
end
end
@@ -158,7 +180,7 @@ RSpec.describe Projects::PipelinesController do
it 'returns matched pipelines' do
get_pipelines_index_json(ref: 'branch-1')
- check_pipeline_response(returned: 1, all: 1, running: 1, pending: 0, finished: 0)
+ check_pipeline_response(returned: 1, all: 1)
end
end
@@ -166,7 +188,7 @@ RSpec.describe Projects::PipelinesController do
it 'returns empty list' do
get_pipelines_index_json(ref: 'invalid-ref')
- check_pipeline_response(returned: 0, all: 0, running: 0, pending: 0, finished: 0)
+ check_pipeline_response(returned: 0, all: 0)
end
end
end
@@ -176,15 +198,7 @@ RSpec.describe Projects::PipelinesController do
it 'returns matched pipelines' do
get_pipelines_index_json(status: 'success')
- check_pipeline_response(returned: 1, all: 1, running: 0, pending: 0, finished: 1)
- end
-
- context 'when filter by unrelated scope' do
- it 'returns empty list' do
- get_pipelines_index_json(status: 'success', scope: 'running')
-
- check_pipeline_response(returned: 0, all: 1, running: 0, pending: 0, finished: 1)
- end
+ check_pipeline_response(returned: 1, all: 1)
end
end
@@ -192,7 +206,7 @@ RSpec.describe Projects::PipelinesController do
it 'returns empty list' do
get_pipelines_index_json(status: 'manual')
- check_pipeline_response(returned: 0, all: 0, running: 0, pending: 0, finished: 0)
+ check_pipeline_response(returned: 0, all: 0)
end
end
@@ -200,11 +214,19 @@ RSpec.describe Projects::PipelinesController do
it 'returns all list' do
get_pipelines_index_json(status: 'invalid-status')
- check_pipeline_response(returned: 6, all: 6, running: 2, pending: 1, finished: 3)
+ check_pipeline_response(returned: 6, all: 6)
end
end
end
+ def get_pipelines_index_html(params = {})
+ get :index, params: {
+ namespace_id: project.namespace,
+ project_id: project
+ }.merge(params),
+ format: :html
+ end
+
def get_pipelines_index_json(params = {})
get :index, params: {
namespace_id: project.namespace,
@@ -234,7 +256,8 @@ RSpec.describe Projects::PipelinesController do
user = create(:user)
pipeline = create(:ci_empty_pipeline, status: status,
project: project,
- sha: sha,
+ sha: sha.id,
+ ref: sha.id.first(8),
user: user,
merge_request: merge_request)
@@ -260,15 +283,12 @@ RSpec.describe Projects::PipelinesController do
)
end
- def check_pipeline_response(returned:, all:, running:, pending:, finished:)
+ def check_pipeline_response(returned:, all:)
aggregate_failures do
expect(response).to match_response_schema('pipeline')
expect(json_response['pipelines'].count).to eq returned
expect(json_response['count']['all'].to_i).to eq all
- expect(json_response['count']['running'].to_i).to eq running
- expect(json_response['count']['pending'].to_i).to eq pending
- expect(json_response['count']['finished'].to_i).to eq finished
end
end
end
@@ -689,6 +709,15 @@ RSpec.describe Projects::PipelinesController do
end
end
+ describe 'GET #charts' do
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+
+ it_behaves_like 'tracking unique visits', :charts do
+ let(:request_params) { { namespace_id: project.namespace, project_id: project, id: pipeline.id } }
+ let(:target_id) { 'p_analytics_pipelines' }
+ end
+ end
+
describe 'POST create' do
let(:project) { create(:project, :public, :repository) }
diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb
index 7457e4c5023..40a220d57a7 100644
--- a/spec/controllers/projects/project_members_controller_spec.rb
+++ b/spec/controllers/projects/project_members_controller_spec.rb
@@ -106,6 +106,29 @@ RSpec.describe Projects::ProjectMembersController do
expect(response).to redirect_to(project_project_members_path(project))
end
end
+
+ context 'adding project bot' do
+ let_it_be(:project_bot) { create(:user, :project_bot) }
+
+ before do
+ project.add_maintainer(user)
+
+ unrelated_project = create(:project)
+ unrelated_project.add_maintainer(project_bot)
+ end
+
+ it 'returns error' do
+ post :create, params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ user_ids: project_bot.id,
+ access_level: Gitlab::Access::GUEST
+ }
+
+ expect(flash[:alert]).to include('project bots cannot be added to other groups / projects')
+ expect(response).to redirect_to(project_project_members_path(project))
+ end
+ end
end
describe 'PUT update' do
diff --git a/spec/controllers/projects/refs_controller_spec.rb b/spec/controllers/projects/refs_controller_spec.rb
index a6a4aff7ce9..d10351feb9e 100644
--- a/spec/controllers/projects/refs_controller_spec.rb
+++ b/spec/controllers/projects/refs_controller_spec.rb
@@ -41,19 +41,12 @@ RSpec.describe Projects::RefsController do
expect { xhr_get }.not_to raise_error
end
- it 'renders 404 for non-JS requests' do
+ it 'renders 404 for HTML requests' do
xhr_get
expect(response).to be_not_found
end
- it 'renders JS' do
- expect(::Gitlab::GitalyClient).to receive(:allow_ref_name_caching).and_call_original
-
- xhr_get(:js)
- expect(response).to be_successful
- end
-
context 'when json is requested' do
it 'renders JSON' do
expect(::Gitlab::GitalyClient).to receive(:allow_ref_name_caching).and_call_original
diff --git a/spec/controllers/projects/releases_controller_spec.rb b/spec/controllers/projects/releases_controller_spec.rb
index 96c38c1b726..45beccfeef5 100644
--- a/spec/controllers/projects/releases_controller_spec.rb
+++ b/spec/controllers/projects/releases_controller_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Projects::ReleasesController do
+ include AccessMatchersForController
+
let!(:project) { create(:project, :repository, :public) }
let_it_be(:private_project) { create(:project, :repository, :private) }
let_it_be(:developer) { create(:user) }
@@ -118,6 +120,15 @@ RSpec.describe Projects::ReleasesController do
end
end
+ describe 'GET #new' do
+ let(:request) do
+ get :new, params: { namespace_id: project.namespace, project_id: project }
+ end
+
+ it { expect { request }.to be_denied_for(:reporter).of(project) }
+ it { expect { request }.to be_allowed_for(:developer).of(project) }
+ end
+
describe 'GET #edit' do
subject do
get :edit, params: { namespace_id: project.namespace, project_id: project, tag: tag }
diff --git a/spec/controllers/projects/service_desk_controller_spec.rb b/spec/controllers/projects/service_desk_controller_spec.rb
new file mode 100644
index 00000000000..1c4d6665414
--- /dev/null
+++ b/spec/controllers/projects/service_desk_controller_spec.rb
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::ServiceDeskController do
+ let_it_be(:project) do
+ create(:project, :private, :custom_repo, service_desk_enabled: true,
+ files: { '.gitlab/issue_templates/service_desk.md' => 'template' })
+ end
+
+ let_it_be(:user) { create(:user) }
+
+ before do
+ allow(Gitlab::IncomingEmail).to receive(:enabled?) { true }
+ allow(Gitlab::IncomingEmail).to receive(:supports_wildcard?) { true }
+
+ project.add_maintainer(user)
+ sign_in(user)
+ end
+
+ describe 'GET service desk properties' do
+ it 'returns service_desk JSON data' do
+ get :show, params: { namespace_id: project.namespace.to_param, project_id: project }, format: :json
+
+ expect(json_response["service_desk_address"]).to match(/\A[^@]+@[^@]+\z/)
+ expect(json_response["service_desk_enabled"]).to be_truthy
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ context 'when user is not project maintainer' do
+ let(:guest) { create(:user) }
+
+ it 'renders 404' do
+ project.add_guest(guest)
+ sign_in(guest)
+
+ get :show, params: { namespace_id: project.namespace.to_param, project_id: project }, format: :json
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when issue template is present' do
+ it 'returns template_file_missing as false' do
+ create(:service_desk_setting, project: project, issue_template_key: 'service_desk')
+
+ get :show, params: { namespace_id: project.namespace.to_param, project_id: project }, format: :json
+
+ response_hash = Gitlab::Json.parse(response.body)
+ expect(response_hash['template_file_missing']).to eq(false)
+ end
+ end
+
+ context 'when issue template file becomes outdated' do
+ it 'returns template_file_missing as true' do
+ service = ServiceDeskSetting.new(project_id: project.id, issue_template_key: 'deleted')
+ service.save!(validate: false)
+
+ get :show, params: { namespace_id: project.namespace.to_param, project_id: project }, format: :json
+
+ expect(json_response['template_file_missing']).to eq(true)
+ end
+ end
+ end
+
+ describe 'PUT service desk properties' do
+ it 'toggles services desk incoming email' do
+ project.update!(service_desk_enabled: false)
+
+ put :update, params: { namespace_id: project.namespace.to_param,
+ project_id: project,
+ service_desk_enabled: true }, format: :json
+
+ expect(json_response["service_desk_address"]).to be_present
+ expect(json_response["service_desk_enabled"]).to be_truthy
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'sets issue_template_key' do
+ put :update, params: { namespace_id: project.namespace.to_param,
+ project_id: project,
+ issue_template_key: 'service_desk' }, format: :json
+
+ settings = project.service_desk_setting
+ expect(settings).to be_present
+ expect(settings.issue_template_key).to eq('service_desk')
+ expect(json_response['template_file_missing']).to eq(false)
+ expect(json_response['issue_template_key']).to eq('service_desk')
+ end
+
+ it 'returns an error when update of service desk settings fails' do
+ put :update, params: { namespace_id: project.namespace.to_param,
+ project_id: project,
+ issue_template_key: 'invalid key' }, format: :json
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ expect(json_response['message']).to eq('Issue template key is empty or does not exist')
+ end
+
+ context 'when user cannot admin the project' do
+ let(:other_user) { create(:user) }
+
+ it 'renders 404' do
+ sign_in(other_user)
+ put :update, params: { namespace_id: project.namespace.to_param, project_id: project, service_desk_enabled: true }, format: :json
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+end
diff --git a/spec/controllers/projects/services_controller_spec.rb b/spec/controllers/projects/services_controller_spec.rb
index 04c74dfdefe..e8a23dcfafb 100644
--- a/spec/controllers/projects/services_controller_spec.rb
+++ b/spec/controllers/projects/services_controller_spec.rb
@@ -137,7 +137,7 @@ RSpec.describe Projects::ServicesController do
let(:params) { project_params(service: service_params) }
let(:message) { 'Jira activated.' }
- let(:redirect_url) { project_settings_integrations_path(project) }
+ let(:redirect_url) { edit_project_service_path(project, service) }
before do
put :update, params: params
@@ -179,6 +179,23 @@ RSpec.describe Projects::ServicesController do
it_behaves_like 'service update'
end
+
+ context 'wehn param `inherit_from_id` is set to empty string' do
+ let(:service_params) { { inherit_from_id: '' } }
+
+ it 'sets inherit_from_id to nil' do
+ expect(service.reload.inherit_from_id).to eq(nil)
+ end
+ end
+
+ context 'wehn param `inherit_from_id` is set to some value' do
+ let(:instance_service) { create(:jira_service, :instance) }
+ let(:service_params) { { inherit_from_id: instance_service.id } }
+
+ it 'sets inherit_from_id to value' do
+ expect(service.reload.inherit_from_id).to eq(instance_service.id)
+ end
+ end
end
describe 'as JSON' do
diff --git a/spec/controllers/projects/settings/operations_controller_spec.rb b/spec/controllers/projects/settings/operations_controller_spec.rb
index 6b440e910ad..d4f3c5d0c9b 100644
--- a/spec/controllers/projects/settings/operations_controller_spec.rb
+++ b/spec/controllers/projects/settings/operations_controller_spec.rb
@@ -151,7 +151,8 @@ RSpec.describe Projects::Settings::OperationsController do
incident_management_setting_attributes: {
create_issue: 'false',
send_email: 'false',
- issue_template_key: 'some-other-template'
+ issue_template_key: 'some-other-template',
+ pagerduty_active: 'true'
}
}
end
@@ -159,7 +160,6 @@ RSpec.describe Projects::Settings::OperationsController do
it_behaves_like 'PATCHable'
context 'updating each incident management setting' do
- let(:project) { create(:project) }
let(:new_incident_management_settings) { {} }
before do
@@ -185,6 +185,98 @@ RSpec.describe Projects::Settings::OperationsController do
it_behaves_like 'a gitlab tracking event', { issue_template_key: nil }, 'disabled_issue_template_on_alerts'
it_behaves_like 'a gitlab tracking event', { send_email: '1' }, 'enabled_sending_emails'
it_behaves_like 'a gitlab tracking event', { send_email: '0' }, 'disabled_sending_emails'
+ it_behaves_like 'a gitlab tracking event', { pagerduty_active: '1' }, 'enabled_pagerduty_webhook'
+ it_behaves_like 'a gitlab tracking event', { pagerduty_active: '0' }, 'disabled_pagerduty_webhook'
+ end
+ end
+
+ describe 'POST #reset_pagerduty_token' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ context 'with existing incident management setting has active PagerDuty webhook' do
+ let!(:incident_management_setting) do
+ create(:project_incident_management_setting, project: project, pagerduty_active: true)
+ end
+
+ let!(:old_token) { incident_management_setting.pagerduty_token }
+
+ it 'returns newly reset token' do
+ reset_pagerduty_token
+
+ new_token = incident_management_setting.reload.pagerduty_token
+ new_webhook_url = project_incidents_pagerduty_url(project, token: new_token)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['pagerduty_webhook_url']).to eq(new_webhook_url)
+ expect(json_response['pagerduty_token']).to eq(new_token)
+ expect(old_token).not_to eq(new_token)
+ end
+ end
+
+ context 'without existing incident management setting' do
+ it 'does not reset a token' do
+ reset_pagerduty_token
+
+ new_webhook_url = project_incidents_pagerduty_url(project, token: nil)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['pagerduty_webhook_url']).to eq(new_webhook_url)
+ expect(project.incident_management_setting.pagerduty_token).to be_nil
+ end
+ end
+
+ context 'when update fails' do
+ let(:operations_update_service) { spy(:operations_update_service) }
+ let(:pagerduty_token_params) do
+ { incident_management_setting_attributes: { regenerate_token: true } }
+ end
+
+ before do
+ expect(::Projects::Operations::UpdateService)
+ .to receive(:new).with(project, user, pagerduty_token_params)
+ .and_return(operations_update_service)
+ expect(operations_update_service).to receive(:execute)
+ .and_return(status: :error)
+ end
+
+ it 'returns unprocessable_entity' do
+ reset_pagerduty_token
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ expect(json_response).to be_empty
+ end
+ end
+
+ context 'with insufficient permissions' do
+ before do
+ project.add_reporter(user)
+ end
+
+ it 'returns 404' do
+ reset_pagerduty_token
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'as an anonymous user' do
+ before do
+ sign_out(user)
+ end
+
+ it 'returns a redirect' do
+ reset_pagerduty_token
+
+ expect(response).to have_gitlab_http_status(:redirect)
+ end
+ end
+
+ private
+
+ def reset_pagerduty_token
+ post :reset_pagerduty_token, params: project_params(project), format: :json
end
end
end
@@ -296,9 +388,7 @@ RSpec.describe Projects::Settings::OperationsController do
end
end
- describe 'POST reset_alerting_token' do
- let(:project) { create(:project) }
-
+ describe 'POST #reset_alerting_token' do
before do
project.add_maintainer(user)
end
diff --git a/spec/controllers/projects/snippets/blobs_controller_spec.rb b/spec/controllers/projects/snippets/blobs_controller_spec.rb
new file mode 100644
index 00000000000..ca656705e07
--- /dev/null
+++ b/spec/controllers/projects/snippets/blobs_controller_spec.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::Snippets::BlobsController do
+ using RSpec::Parameterized::TableSyntax
+ include SnippetHelpers
+
+ let_it_be(:author) { create(:user) }
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:other_user) { create(:user) }
+
+ let(:visibility) { :public }
+ let(:project_visibility) { :public }
+ let(:project) { create(:project, project_visibility) }
+ let(:snippet) { create(:project_snippet, visibility, :repository, project: project, author: author) }
+
+ before do
+ project.add_maintainer(author)
+ project.add_developer(developer)
+ end
+
+ describe 'GET #raw' do
+ let(:filepath) { 'file1' }
+ let(:ref) { TestEnv::BRANCH_SHA['snippet/single-file'] }
+ let(:inline) { nil }
+
+ subject do
+ get(:raw,
+ params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ snippet_id: snippet,
+ path: filepath,
+ ref: ref,
+ inline: inline
+ })
+ end
+
+ context 'with a snippet without a repository' do
+ let(:snippet) { create(:project_snippet, visibility, project: project, author: author) }
+
+ it_behaves_like 'raw snippet without repository', :not_found
+ end
+
+ where(:project_visibility_level, :snippet_visibility_level, :user, :status) do
+ :public | :public | :author | :ok
+ :public | :public | :developer | :ok
+ :public | :public | :other_user | :ok
+ :public | :public | nil | :ok
+
+ :public | :private | :author | :ok
+ :public | :private | :developer | :ok
+ :public | :private | :other_user | :not_found
+ :public | :private | nil | :not_found
+
+ :private | :public | :author | :ok
+ :private | :public | :developer | :ok
+ :private | :public | :other_user | :not_found
+ :private | :public | nil | :redirect
+
+ :private | :private | :author | :ok
+ :private | :private | :developer | :ok
+ :private | :private | :other_user | :not_found
+ :private | :private | nil | :redirect
+ end
+
+ with_them do
+ let(:visibility) { snippet_visibility_level }
+ let(:project_visibility) { project_visibility_level }
+
+ before do
+ sign_in_as(user)
+
+ subject
+ end
+
+ it 'responds with correct status' do
+ expect(response).to have_gitlab_http_status(status)
+ end
+ end
+
+ it_behaves_like 'raw snippet blob'
+ end
+end
diff --git a/spec/controllers/projects/snippets_controller_spec.rb b/spec/controllers/projects/snippets_controller_spec.rb
index 8bbfaa8d327..6fcb24da3cd 100644
--- a/spec/controllers/projects/snippets_controller_spec.rb
+++ b/spec/controllers/projects/snippets_controller_spec.rb
@@ -15,14 +15,18 @@ RSpec.describe Projects::SnippetsController do
end
describe 'GET #index' do
+ let(:base_params) do
+ {
+ namespace_id: project.namespace,
+ project_id: project
+ }
+ end
+
+ subject { get :index, params: base_params }
+
it_behaves_like 'paginated collection' do
let(:collection) { project.snippets }
- let(:params) do
- {
- namespace_id: project.namespace,
- project_id: project
- }
- end
+ let(:params) { base_params }
before do
create(:project_snippet, :public, project: project, author: user)
@@ -35,7 +39,11 @@ RSpec.describe Projects::SnippetsController do
.to receive(:new).with(nil, project: project)
.and_return(service)
- get :index, params: { namespace_id: project.namespace, project_id: project }
+ subject
+ end
+
+ it_behaves_like 'snippets sort order' do
+ let(:params) { base_params }
end
context 'when the project snippet is private' do
@@ -43,7 +51,7 @@ RSpec.describe Projects::SnippetsController do
context 'when anonymous' do
it 'does not include the private snippet' do
- get :index, params: { namespace_id: project.namespace, project_id: project }
+ subject
expect(assigns(:snippets)).not_to include(project_snippet)
expect(response).to have_gitlab_http_status(:ok)
@@ -56,7 +64,7 @@ RSpec.describe Projects::SnippetsController do
end
it 'renders the snippet' do
- get :index, params: { namespace_id: project.namespace, project_id: project }
+ subject
expect(assigns(:snippets)).to include(project_snippet)
expect(response).to have_gitlab_http_status(:ok)
@@ -69,7 +77,7 @@ RSpec.describe Projects::SnippetsController do
end
it 'renders the snippet' do
- get :index, params: { namespace_id: project.namespace, project_id: project }
+ subject
expect(assigns(:snippets)).to include(project_snippet)
expect(response).to have_gitlab_http_status(:ok)
diff --git a/spec/controllers/projects/tree_controller_spec.rb b/spec/controllers/projects/tree_controller_spec.rb
index f6ec04d4dd7..8e4e275bdbe 100644
--- a/spec/controllers/projects/tree_controller_spec.rb
+++ b/spec/controllers/projects/tree_controller_spec.rb
@@ -89,34 +89,6 @@ RSpec.describe Projects::TreeController do
end
end
- describe "GET show" do
- context 'lfs_blob_ids instance variable' do
- let(:id) { 'master' }
-
- context 'with vue tree view enabled' do
- before do
- get(:show, params: { namespace_id: project.namespace.to_param, project_id: project, id: id })
- end
-
- it 'is not set' do
- expect(assigns[:lfs_blob_ids]).to be_nil
- end
- end
-
- context 'with vue tree view disabled' do
- before do
- stub_feature_flags(vue_file_list: false)
-
- get(:show, params: { namespace_id: project.namespace.to_param, project_id: project, id: id })
- end
-
- it 'is set' do
- expect(assigns[:lfs_blob_ids]).not_to be_nil
- end
- end
- end
- end
-
describe 'GET show with whitespace in ref' do
render_views
diff --git a/spec/controllers/projects/wikis_controller_spec.rb b/spec/controllers/projects/wikis_controller_spec.rb
index 4e58822b613..7243588681d 100644
--- a/spec/controllers/projects/wikis_controller_spec.rb
+++ b/spec/controllers/projects/wikis_controller_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Projects::WikisController do
it_behaves_like 'wiki controller actions' do
- let(:container) { create(:project, :public, :repository, namespace: user.namespace) }
+ let(:container) { create(:project, :public, namespace: user.namespace) }
let(:routing_params) { { namespace_id: container.namespace, project_id: container } }
end
end
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index 8aae9ef85be..e59493827ba 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe ProjectsController do
include ExternalAuthorizationServiceHelpers
include ProjectForksHelper
- let(:project) { create(:project) }
+ let(:project) { create(:project, service_desk_enabled: false) }
let(:public_project) { create(:project, :public) }
let(:user) { create(:user) }
let(:jpg) { fixture_file_upload('spec/fixtures/rails_sample.jpg', 'image/jpg') }
@@ -86,11 +86,13 @@ RSpec.describe ProjectsController do
end
describe "GET #activity as JSON" do
+ include DesignManagementTestHelpers
render_views
let(:project) { create(:project, :public, issues_access_level: ProjectFeature::PRIVATE) }
before do
+ enable_design_management
create(:event, :created, project: project, target: create(:issue))
sign_in(user)
@@ -103,11 +105,32 @@ RSpec.describe ProjectsController do
project.add_developer(user)
end
- it 'returns count' do
+ def get_activity(project)
get :activity, params: { namespace_id: project.namespace, id: project, format: :json }
+ end
+
+ it 'returns count' do
+ get_activity(project)
expect(json_response['count']).to eq(1)
end
+
+ context 'design events are visible' do
+ include DesignManagementTestHelpers
+ let(:other_project) { create(:project, namespace: user.namespace) }
+
+ before do
+ enable_design_management
+ create(:design_event, project: project)
+ request.cookies[:event_filter] = EventFilter::DESIGNS
+ end
+
+ it 'returns correct count' do
+ get_activity(project)
+
+ expect(json_response['count']).to eq(1)
+ end
+ end
end
context 'when user has no permission to see the event' do
@@ -350,45 +373,6 @@ RSpec.describe ProjectsController do
.not_to exceed_query_limit(2).for_query(expected_query)
end
end
-
- context 'lfs_blob_ids instance variable' do
- let(:project) { create(:project, :public, :repository) }
-
- before do
- sign_in(user)
- end
-
- context 'with vue tree view enabled' do
- before do
- get :show, params: { namespace_id: project.namespace, id: project }
- end
-
- it 'is not set' do
- expect(assigns[:lfs_blob_ids]).to be_nil
- end
- end
-
- context 'with vue tree view disabled' do
- before do
- stub_feature_flags(vue_file_list: false)
-
- get :show, params: { namespace_id: project.namespace, id: project }
- end
-
- it 'is set' do
- expect(assigns[:lfs_blob_ids]).not_to be_nil
- end
- end
- end
-
- context 'namespace storage limit' do
- let_it_be(:project) { create(:project, :public, :repository ) }
- let(:namespace) { project.namespace }
-
- subject { get :show, params: { namespace_id: namespace, id: project } }
-
- it_behaves_like 'namespace storage limit alert'
- end
end
describe 'GET edit' do
@@ -1192,7 +1176,7 @@ RSpec.describe ProjectsController do
before do
allow(Gitlab::ApplicationRateLimiter)
.to receive(:increment)
- .and_return(Gitlab::ApplicationRateLimiter.rate_limits["project_#{action}".to_sym][:threshold] + 1)
+ .and_return(Gitlab::ApplicationRateLimiter.rate_limits["project_#{action}".to_sym][:threshold].call + 1)
end
it 'prevents requesting project export' do
@@ -1259,7 +1243,7 @@ RSpec.describe ProjectsController do
before do
allow(Gitlab::ApplicationRateLimiter)
.to receive(:increment)
- .and_return(Gitlab::ApplicationRateLimiter.rate_limits[:project_download_export][:threshold] + 1)
+ .and_return(Gitlab::ApplicationRateLimiter.rate_limits[:project_download_export][:threshold].call + 1)
end
it 'prevents requesting project export' do
@@ -1400,6 +1384,27 @@ RSpec.describe ProjectsController do
end
end
+ it 'updates Service Desk attributes' do
+ project.add_maintainer(user)
+ sign_in(user)
+ allow(Gitlab::IncomingEmail).to receive(:enabled?) { true }
+ allow(Gitlab::IncomingEmail).to receive(:supports_wildcard?) { true }
+ params = {
+ service_desk_enabled: true
+ }
+
+ put :update,
+ params: {
+ namespace_id: project.namespace,
+ id: project,
+ project: params
+ }
+ project.reload
+
+ expect(response).to have_gitlab_http_status(:found)
+ expect(project.service_desk_enabled).to eq(true)
+ end
+
def project_moved_message(redirect_route, project)
"Project '#{redirect_route.path}' was moved to '#{project.full_path}'. Please update any links and bookmarks that may still have the old path."
end
diff --git a/spec/controllers/registrations/experience_levels_controller_spec.rb b/spec/controllers/registrations/experience_levels_controller_spec.rb
index 1fc728f5de8..5a217a3a684 100644
--- a/spec/controllers/registrations/experience_levels_controller_spec.rb
+++ b/spec/controllers/registrations/experience_levels_controller_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-describe Registrations::ExperienceLevelsController do
+RSpec.describe Registrations::ExperienceLevelsController do
let_it_be(:namespace) { create(:group, path: 'group-path' ) }
let_it_be(:user) { create(:user) }
@@ -99,34 +99,51 @@ describe Registrations::ExperienceLevelsController do
end
describe 'applying the chosen level' do
- context "when an 'onboarding_issues_settings' cookie does not exist" do
- let(:params) { super().merge(experience_level: :novice) }
-
- it 'does not change the cookie' do
- expect { subject }.not_to change { cookies[:onboarding_issues_settings] }
- end
- end
-
- context "when an 'onboarding_issues_settings' cookie does exist" do
+ context 'when a "Learn GitLab" project is available' do
before do
- request.cookies[:onboarding_issues_settings] = '{}'
+ allow_next_instance_of(LearnGitlab) do |learn_gitlab|
+ allow(learn_gitlab).to receive(:available?).and_return(true)
+ allow(learn_gitlab).to receive(:label).and_return(double(id: 1))
+ end
end
context 'when novice' do
let(:params) { super().merge(experience_level: :novice) }
- it "adds a 'hideAdvanced' setting to the cookie" do
- expect { subject }.to change { Gitlab::Json.parse(cookies[:onboarding_issues_settings])['hideAdvanced'] }.from(nil).to(true)
+ it 'adds a BoardLabel' do
+ expect_next_instance_of(Boards::UpdateService) do |service|
+ expect(service).to receive(:execute)
+ end
+
+ subject
end
end
context 'when experienced' do
let(:params) { super().merge(experience_level: :experienced) }
- it 'does not change the cookie' do
- expect { subject }.not_to change { cookies[:onboarding_issues_settings] }
+ it 'does not add a BoardLabel' do
+ expect(Boards::UpdateService).not_to receive(:new)
+
+ subject
+ end
+ end
+ end
+
+ context 'when no "Learn GitLab" project exists' do
+ let(:params) { super().merge(experience_level: :novice) }
+
+ before do
+ allow_next_instance_of(LearnGitlab) do |learn_gitlab|
+ allow(learn_gitlab).to receive(:available?).and_return(false)
end
end
+
+ it 'does not add a BoardLabel' do
+ expect(Boards::UpdateService).not_to receive(:new)
+
+ subject
+ end
end
end
end
diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb
index bae6bd07b67..0849fb00e73 100644
--- a/spec/controllers/search_controller_spec.rb
+++ b/spec/controllers/search_controller_spec.rb
@@ -211,4 +211,9 @@ RSpec.describe SearchController do
end.to raise_error(ActionController::ParameterMissing)
end
end
+
+ describe 'GET #autocomplete' do
+ it_behaves_like 'when the user cannot read cross project', :autocomplete, { term: 'hello' }
+ it_behaves_like 'with external authorization service enabled', :autocomplete, { term: 'hello' }
+ end
end
diff --git a/spec/controllers/snippets/blobs_controller_spec.rb b/spec/controllers/snippets/blobs_controller_spec.rb
new file mode 100644
index 00000000000..b9f58587a58
--- /dev/null
+++ b/spec/controllers/snippets/blobs_controller_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Snippets::BlobsController do
+ using RSpec::Parameterized::TableSyntax
+ include SnippetHelpers
+
+ describe 'GET #raw' do
+ let_it_be(:author) { create(:user) }
+ let_it_be(:other_user) { create(:user) }
+
+ let(:visibility) { :public }
+ let(:snippet) { create(:personal_snippet, visibility, :repository, author: author) }
+ let(:filepath) { 'file1' }
+ let(:ref) { TestEnv::BRANCH_SHA['snippet/single-file'] }
+ let(:inline) { nil }
+
+ subject do
+ get(:raw,
+ params: {
+ snippet_id: snippet,
+ path: filepath,
+ ref: ref,
+ inline: inline
+ })
+ end
+
+ where(:snippet_visibility_level, :user, :status) do
+ :public | :author | :ok
+ :public | :other_user | :ok
+ :public | nil | :ok
+
+ :private | :author | :ok
+ :private | :other_user | :not_found
+ :private | nil | :redirect
+ end
+
+ with_them do
+ let(:visibility) { snippet_visibility_level }
+
+ before do
+ sign_in_as(user)
+
+ subject
+ end
+
+ it 'responds with correct status' do
+ expect(response).to have_gitlab_http_status(status)
+ end
+ end
+
+ it_behaves_like 'raw snippet blob'
+
+ context 'with a snippet without a repository' do
+ let(:snippet) { create(:personal_snippet, visibility, author: author) }
+
+ it_behaves_like 'raw snippet without repository', :redirect
+ end
+ end
+end
diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb
index 70df1faf7dd..92370b3381a 100644
--- a/spec/controllers/snippets_controller_spec.rb
+++ b/spec/controllers/snippets_controller_spec.rb
@@ -6,6 +6,8 @@ RSpec.describe SnippetsController do
let_it_be(:user) { create(:user) }
describe 'GET #index' do
+ let(:base_params) { { username: user.username } }
+
context 'when username parameter is present' do
it_behaves_like 'paginated collection' do
let(:collection) { Snippet.all }
@@ -38,6 +40,10 @@ RSpec.describe SnippetsController do
expect(response).to redirect_to(dashboard_snippets_path)
end
end
+
+ it_behaves_like 'snippets sort order' do
+ let(:params) { base_params }
+ end
end
describe 'GET #new' do
diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb
index bec4b24484a..99c3b82bd0d 100644
--- a/spec/controllers/users_controller_spec.rb
+++ b/spec/controllers/users_controller_spec.rb
@@ -114,6 +114,71 @@ RSpec.describe UsersController do
end
end
+ describe "#ssh_keys" do
+ describe "non existent user" do
+ it "does not generally work" do
+ get :ssh_keys, params: { username: 'not-existent' }
+
+ expect(response).not_to be_successful
+ end
+ end
+
+ describe "user with no keys" do
+ it "does generally work" do
+ get :ssh_keys, params: { username: user.username }
+
+ expect(response).to be_successful
+ end
+
+ it "renders all keys separated with a new line" do
+ get :ssh_keys, params: { username: user.username }
+
+ expect(response.body).to eq("")
+ end
+
+ it "responds with text/plain content type" do
+ get :ssh_keys, params: { username: user.username }
+ expect(response.content_type).to eq("text/plain")
+ end
+ end
+
+ describe "user with keys" do
+ let!(:key) { create(:key, user: user) }
+ let!(:another_key) { create(:another_key, user: user) }
+ let!(:deploy_key) { create(:deploy_key, user: user) }
+
+ it "does generally work" do
+ get :ssh_keys, params: { username: user.username }
+
+ expect(response).to be_successful
+ end
+
+ it "renders all non deploy keys separated with a new line" do
+ get :ssh_keys, params: { username: user.username }
+
+ expect(response.body).not_to eq('')
+ expect(response.body).to eq(user.all_ssh_keys.join("\n"))
+
+ expect(response.body).to include(key.key.sub(' dummy@gitlab.com', ''))
+ expect(response.body).to include(another_key.key.sub(' dummy@gitlab.com', ''))
+
+ expect(response.body).not_to include(deploy_key.key)
+ end
+
+ it "does not render the comment of the key" do
+ get :ssh_keys, params: { username: user.username }
+
+ expect(response.body).not_to match(/dummy@gitlab.com/)
+ end
+
+ it "responds with text/plain content type" do
+ get :ssh_keys, params: { username: user.username }
+
+ expect(response.content_type).to eq("text/plain")
+ end
+ end
+ end
+
describe 'GET #calendar' do
context 'for user' do
let(:project) { create(:project) }