diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-09 00:06:38 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-09 00:06:38 +0300 |
commit | ae72d71da85732ec9ceb9723953fe6ca1df0fdf6 (patch) | |
tree | 9e1096312c5fc03a7657ae9586a6714f04ddf8ad /spec | |
parent | 759bab058520a21d87087355dc193f634176e98a (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
26 files changed, 648 insertions, 130 deletions
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 53896c7f5c7..ca39f5dd9f2 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -90,14 +90,6 @@ describe ApplicationController do let(:format) { :html } it_behaves_like 'setting gon variables' - - context 'for peek requests' do - before do - request.path = '/-/peek' - end - - it_behaves_like 'not setting gon variables' - end end context 'with json format' do @@ -105,6 +97,12 @@ describe ApplicationController do it_behaves_like 'not setting gon variables' end + + context 'with atom format' do + let(:format) { :atom } + + it_behaves_like 'not setting gon variables' + end end describe 'session expiration' do diff --git a/spec/controllers/projects/environments_controller_spec.rb b/spec/controllers/projects/environments_controller_spec.rb index 3fe5ff5feee..7bb956201fd 100644 --- a/spec/controllers/projects/environments_controller_spec.rb +++ b/spec/controllers/projects/environments_controller_spec.rb @@ -330,11 +330,11 @@ describe Projects::EnvironmentsController do expect(response).to redirect_to(environment_metrics_path(environment)) end - it 'redirects to empty page if no environment exists' do + it 'redirects to empty metrics page if no environment exists' do get :metrics_redirect, params: { namespace_id: project.namespace, project_id: project } expect(response).to be_ok - expect(response).to render_template 'empty' + expect(response).to render_template 'empty_metrics' end end diff --git a/spec/controllers/projects/error_tracking_controller_spec.rb b/spec/controllers/projects/error_tracking_controller_spec.rb index 31868f5f717..8155d6ddafe 100644 --- a/spec/controllers/projects/error_tracking_controller_spec.rb +++ b/spec/controllers/projects/error_tracking_controller_spec.rb @@ -46,17 +46,6 @@ describe Projects::ErrorTrackingController do end describe 'format json' do - shared_examples 'no data' do - it 'returns no data' do - get :index, params: project_params(format: :json) - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to match_response_schema('error_tracking/index') - expect(json_response['external_url']).to be_nil - expect(json_response['errors']).to eq([]) - end - end - let(:list_issues_service) { spy(:list_issues_service) } let(:external_url) { 'http://example.com' } @@ -66,6 +55,19 @@ describe Projects::ErrorTrackingController do .and_return(list_issues_service) end + context 'no data' do + before do + expect(list_issues_service).to receive(:execute) + .and_return(status: :error, http_status: :no_content) + end + + it 'returns no data' do + get :index, params: project_params(format: :json) + + expect(response).to have_gitlab_http_status(:no_content) + end + end + context 'service result is successful' do before do expect(list_issues_service).to receive(:execute) @@ -232,8 +234,186 @@ describe Projects::ErrorTrackingController do end end + describe 'GET #issue_details' do + let_it_be(:issue_id) { 1234 } + + let(:issue_details_service) { spy(:issue_details_service) } + + let(:permitted_params) do + ActionController::Parameters.new( + { issue_id: issue_id.to_s } + ).permit! + end + + before do + expect(ErrorTracking::IssueDetailsService) + .to receive(:new).with(project, user, permitted_params) + .and_return(issue_details_service) + end + + describe 'format json' do + context 'no data' do + before do + expect(issue_details_service).to receive(:execute) + .and_return(status: :error, http_status: :no_content) + end + + it 'returns no data' do + get :details, params: issue_params(issue_id: issue_id, format: :json) + + expect(response).to have_gitlab_http_status(:no_content) + end + end + + context 'service result is successful' do + before do + expect(issue_details_service).to receive(:execute) + .and_return(status: :success, issue: error) + end + + let(:error) { build(:detailed_error_tracking_error) } + + it 'returns an error' do + get :details, params: issue_params(issue_id: issue_id, format: :json) + + expect(response).to have_gitlab_http_status(:ok) + expect(response).to match_response_schema('error_tracking/issue_detailed') + expect(json_response['error']).to eq(error.as_json) + end + end + + context 'service result is erroneous' do + let(:error_message) { 'error message' } + + context 'without http_status' do + before do + expect(issue_details_service).to receive(:execute) + .and_return(status: :error, message: error_message) + end + + it 'returns 400 with message' do + get :details, params: issue_params(issue_id: issue_id, format: :json) + + expect(response).to have_gitlab_http_status(:bad_request) + expect(json_response['message']).to eq(error_message) + end + end + + context 'with explicit http_status' do + let(:http_status) { :no_content } + + before do + expect(issue_details_service).to receive(:execute).and_return( + status: :error, + message: error_message, + http_status: http_status + ) + end + + it 'returns http_status with message' do + get :details, params: issue_params(issue_id: issue_id, format: :json) + + expect(response).to have_gitlab_http_status(http_status) + expect(json_response['message']).to eq(error_message) + end + end + end + end + end + + describe 'GET #stack_trace' do + let_it_be(:issue_id) { 1234 } + + let(:issue_stack_trace_service) { spy(:issue_stack_trace_service) } + + let(:permitted_params) do + ActionController::Parameters.new( + { issue_id: issue_id.to_s } + ).permit! + end + + before do + expect(ErrorTracking::IssueLatestEventService) + .to receive(:new).with(project, user, permitted_params) + .and_return(issue_stack_trace_service) + end + + describe 'format json' do + context 'awaiting data' do + before do + expect(issue_stack_trace_service).to receive(:execute) + .and_return(status: :error, http_status: :no_content) + end + + it 'returns no data' do + get :stack_trace, params: issue_params(issue_id: issue_id, format: :json) + + expect(response).to have_gitlab_http_status(:no_content) + end + end + + context 'service result is successful' do + before do + expect(issue_stack_trace_service).to receive(:execute) + .and_return(status: :success, latest_event: error_event) + end + + let(:error_event) { build(:error_tracking_error_event) } + + it 'returns an error' do + get :stack_trace, params: issue_params(issue_id: issue_id, format: :json) + + expect(response).to have_gitlab_http_status(:ok) + expect(response).to match_response_schema('error_tracking/issue_stack_trace') + expect(json_response['error']).to eq(error_event.as_json) + end + end + + context 'service result is erroneous' do + let(:error_message) { 'error message' } + + context 'without http_status' do + before do + expect(issue_stack_trace_service).to receive(:execute) + .and_return(status: :error, message: error_message) + end + + it 'returns 400 with message' do + get :stack_trace, params: issue_params(issue_id: issue_id, format: :json) + + expect(response).to have_gitlab_http_status(:bad_request) + expect(json_response['message']).to eq(error_message) + end + end + + context 'with explicit http_status' do + let(:http_status) { :no_content } + + before do + expect(issue_stack_trace_service).to receive(:execute).and_return( + status: :error, + message: error_message, + http_status: http_status + ) + end + + it 'returns http_status with message' do + get :stack_trace, params: issue_params(issue_id: issue_id, format: :json) + + expect(response).to have_gitlab_http_status(http_status) + expect(json_response['message']).to eq(error_message) + end + end + end + end + end + private + def issue_params(opts = {}) + project_params.reverse_merge(opts) + end + def project_params(opts = {}) opts.reverse_merge(namespace_id: project.namespace, project_id: project) end diff --git a/spec/controllers/uploads_controller_spec.rb b/spec/controllers/uploads_controller_spec.rb index 1bcf3bb106b..f35babc1b56 100644 --- a/spec/controllers/uploads_controller_spec.rb +++ b/spec/controllers/uploads_controller_spec.rb @@ -228,10 +228,10 @@ describe UploadsController do user.block end - it "redirects to the sign in page" do + it "responds with status 401" do get :show, params: { model: "user", mounted_as: "avatar", id: user.id, filename: "dk.png" } - expect(response).to redirect_to(new_user_session_path) + expect(response).to have_gitlab_http_status(401) end end @@ -320,10 +320,10 @@ describe UploadsController do end context "when not signed in" do - it "redirects to the sign in page" do + it "responds with status 401" do get :show, params: { model: "project", mounted_as: "avatar", id: project.id, filename: "dk.png" } - expect(response).to redirect_to(new_user_session_path) + expect(response).to have_gitlab_http_status(401) end end @@ -343,10 +343,10 @@ describe UploadsController do project.add_maintainer(user) end - it "redirects to the sign in page" do + it "responds with status 401" do get :show, params: { model: "project", mounted_as: "avatar", id: project.id, filename: "dk.png" } - expect(response).to redirect_to(new_user_session_path) + expect(response).to have_gitlab_http_status(401) end end @@ -439,10 +439,10 @@ describe UploadsController do user.block end - it "redirects to the sign in page" do + it "responds with status 401" do get :show, params: { model: "group", mounted_as: "avatar", id: group.id, filename: "dk.png" } - expect(response).to redirect_to(new_user_session_path) + expect(response).to have_gitlab_http_status(401) end end @@ -526,10 +526,10 @@ describe UploadsController do end context "when not signed in" do - it "redirects to the sign in page" do + it "responds with status 401" do get :show, params: { model: "note", mounted_as: "attachment", id: note.id, filename: "dk.png" } - expect(response).to redirect_to(new_user_session_path) + expect(response).to have_gitlab_http_status(401) end end @@ -549,10 +549,10 @@ describe UploadsController do project.add_maintainer(user) end - it "redirects to the sign in page" do + it "responds with status 401" do get :show, params: { model: "note", mounted_as: "attachment", id: note.id, filename: "dk.png" } - expect(response).to redirect_to(new_user_session_path) + expect(response).to have_gitlab_http_status(401) end end diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb index d340cec8b70..e8b30868801 100644 --- a/spec/db/schema_spec.rb +++ b/spec/db/schema_spec.rb @@ -13,7 +13,7 @@ describe 'Database schema' do # EE: edit the ee/spec/db/schema_support.rb IGNORED_FK_COLUMNS = { abuse_reports: %w[reporter_id user_id], - application_settings: %w[performance_bar_allowed_group_id slack_app_id snowplow_site_id eks_account_id eks_access_key_id], + application_settings: %w[performance_bar_allowed_group_id slack_app_id snowplow_app_id eks_account_id eks_access_key_id], approvers: %w[target_id user_id], approvals: %w[user_id], approver_groups: %w[target_id], diff --git a/spec/factories/error_tracking/detailed_error.rb b/spec/factories/error_tracking/detailed_error.rb new file mode 100644 index 00000000000..cf7de2ece96 --- /dev/null +++ b/spec/factories/error_tracking/detailed_error.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :detailed_error_tracking_error, class: Gitlab::ErrorTracking::DetailedError do + id { 'id' } + title { 'title' } + type { 'error' } + user_count { 1 } + count { 2 } + first_seen { Time.now } + last_seen { Time.now } + message { 'message' } + culprit { 'culprit' } + external_url { 'http://example.com/id' } + external_base_url { 'http://example.com' } + project_id { 'project1' } + project_name { 'project name' } + project_slug { 'project_name' } + short_id { 'ID' } + status { 'unresolved' } + frequency { [] } + first_release_last_commit { '68c914da9' } + last_release_last_commit { '9ad419c86' } + first_release_short_version { 'abc123' } + last_release_short_version { 'abc123' } + + skip_create + end +end diff --git a/spec/factories/error_tracking/error_event.rb b/spec/factories/error_tracking/error_event.rb new file mode 100644 index 00000000000..44c127e7bf5 --- /dev/null +++ b/spec/factories/error_tracking/error_event.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :error_tracking_error_event, class: Gitlab::ErrorTracking::ErrorEvent do + issue_id { 'id' } + date_received { Time.now.iso8601 } + stack_trace_entries do + { + 'stacktrace' => + { + 'frames' => [{ 'file' => 'test.rb' }] + } + } + end + + skip_create + end +end diff --git a/spec/features/projects/members/member_leaves_project_spec.rb b/spec/features/projects/members/member_leaves_project_spec.rb index fb1165838c7..cb7a405e821 100644 --- a/spec/features/projects/members/member_leaves_project_spec.rb +++ b/spec/features/projects/members/member_leaves_project_spec.rb @@ -20,7 +20,7 @@ describe 'Projects > Members > Member leaves project' do expect(project.users.exists?(user.id)).to be_falsey end - it 'user leaves project by url param', :js do + it 'user leaves project by url param', :js, :quarantine do visit project_path(project, leave: 1) page.accept_confirm diff --git a/spec/fixtures/api/schemas/error_tracking/error.json b/spec/fixtures/api/schemas/error_tracking/error.json index df2c02d7d5d..3f65105681e 100644 --- a/spec/fixtures/api/schemas/error_tracking/error.json +++ b/spec/fixtures/api/schemas/error_tracking/error.json @@ -4,7 +4,14 @@ "external_url", "last_seen", "message", - "type" + "type", + "title", + "project_id", + "project_name", + "project_slug", + "short_id", + "status", + "frequency" ], "properties" : { "id": { "type": "string"}, @@ -15,7 +22,14 @@ "culprit": { "type": "string" }, "count": { "type": "integer"}, "external_url": { "type": "string" }, - "user_count": { "type": "integer"} + "user_count": { "type": "integer"}, + "title": { "type": "string"}, + "project_id": { "type": "string"}, + "project_name": { "type": "string"}, + "project_slug": { "type": "string"}, + "short_id": { "type": "string"}, + "status": { "type": "string"}, + "frequency": { "type": "array"} }, - "additionalProperties": true + "additionalProperties": false } diff --git a/spec/fixtures/api/schemas/error_tracking/error_detailed.json b/spec/fixtures/api/schemas/error_tracking/error_detailed.json new file mode 100644 index 00000000000..40d6773f0e6 --- /dev/null +++ b/spec/fixtures/api/schemas/error_tracking/error_detailed.json @@ -0,0 +1,45 @@ +{ + "type": "object", + "required" : [ + "external_url", + "external_base_url", + "last_seen", + "message", + "type", + "title", + "project_id", + "project_name", + "project_slug", + "short_id", + "status", + "frequency", + "first_release_last_commit", + "last_release_last_commit", + "first_release_short_version", + "last_release_short_version" + ], + "properties" : { + "id": { "type": "string"}, + "first_seen": { "type": "string", "format": "date-time" }, + "last_seen": { "type": "string", "format": "date-time" }, + "type": { "type": "string" }, + "message": { "type": "string" }, + "culprit": { "type": "string" }, + "count": { "type": "integer"}, + "external_url": { "type": "string" }, + "external_base_url": { "type": "string" }, + "user_count": { "type": "integer"}, + "title": { "type": "string"}, + "project_id": { "type": "string"}, + "project_name": { "type": "string"}, + "project_slug": { "type": "string"}, + "short_id": { "type": "string"}, + "status": { "type": "string"}, + "frequency": { "type": "array"}, + "first_release_last_commit": { "type": ["string", "null"] }, + "last_release_last_commit": { "type": ["string", "null"] }, + "first_release_short_version": { "type": ["string", "null"] }, + "last_release_short_version": { "type": ["string", "null"] } + }, + "additionalProperties": false +} diff --git a/spec/fixtures/api/schemas/error_tracking/error_stack_trace.json b/spec/fixtures/api/schemas/error_tracking/error_stack_trace.json new file mode 100644 index 00000000000..a684dd0496a --- /dev/null +++ b/spec/fixtures/api/schemas/error_tracking/error_stack_trace.json @@ -0,0 +1,14 @@ +{ + "type": "object", + "required": [ + "issue_id", + "stack_trace_entries", + "date_received" + ], + "properties": { + "issue_id": { "type": ["string", "integer"] }, + "stack_trace_entries": { "type": "object" }, + "date_received": { "type": "string" } + }, + "additionalProperties": false +} diff --git a/spec/fixtures/api/schemas/error_tracking/issue_detailed.json b/spec/fixtures/api/schemas/error_tracking/issue_detailed.json new file mode 100644 index 00000000000..b5adea6fc62 --- /dev/null +++ b/spec/fixtures/api/schemas/error_tracking/issue_detailed.json @@ -0,0 +1,11 @@ +{ + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { "$ref": "error_detailed.json" } + }, + "additionalProperties": false +} + diff --git a/spec/fixtures/api/schemas/error_tracking/issue_stack_trace.json b/spec/fixtures/api/schemas/error_tracking/issue_stack_trace.json new file mode 100644 index 00000000000..7ec1ae63609 --- /dev/null +++ b/spec/fixtures/api/schemas/error_tracking/issue_stack_trace.json @@ -0,0 +1,11 @@ +{ + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { "$ref": "error_stack_trace.json" } + }, + "additionalProperties": false +} + diff --git a/spec/helpers/application_settings_helper_spec.rb b/spec/helpers/application_settings_helper_spec.rb index e466150fa46..a5e8370a715 100644 --- a/spec/helpers/application_settings_helper_spec.rb +++ b/spec/helpers/application_settings_helper_spec.rb @@ -38,7 +38,7 @@ describe ApplicationSettingsHelper do it_behaves_like 'when HTTP protocol is in use', 'http' context 'with tracking parameters' do - it { expect(visible_attributes).to include(*%i(snowplow_collector_hostname snowplow_cookie_domain snowplow_enabled snowplow_site_id)) } + it { expect(visible_attributes).to include(*%i(snowplow_collector_hostname snowplow_cookie_domain snowplow_enabled snowplow_app_id)) } it { expect(visible_attributes).to include(*%i(pendo_enabled pendo_url)) } end diff --git a/spec/lib/gitlab/ci/config/entry/default_spec.rb b/spec/lib/gitlab/ci/config/entry/default_spec.rb index f09df698f68..a0856037340 100644 --- a/spec/lib/gitlab/ci/config/entry/default_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/default_spec.rb @@ -26,7 +26,7 @@ describe Gitlab::Ci::Config::Entry::Default do it 'contains the expected node names' do expect(described_class.nodes.keys) .to match_array(%i[before_script image services - after_script cache]) + after_script cache interruptible]) end end end diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb index 9fe18caf689..fe83171c57a 100644 --- a/spec/lib/gitlab/ci/config/entry/job_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb @@ -24,7 +24,7 @@ describe Gitlab::Ci::Config::Entry::Job do let(:result) do %i[before_script script stage type after_script cache image services only except rules needs variables artifacts - environment coverage retry] + environment coverage retry interruptible] end it { is_expected.to match_array result } diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb index dc7bbc519ee..5a173470dfe 100644 --- a/spec/lib/gitlab/ci/yaml_processor_spec.rb +++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb @@ -108,6 +108,25 @@ module Gitlab it { expect(subject[:interruptible]).to be_falsy } end + + it "returns interruptible when overridden for job" do + config = YAML.dump({ default: { interruptible: true }, + rspec: { script: "rspec" } }) + + config_processor = Gitlab::Ci::YamlProcessor.new(config) + + expect(config_processor.stage_builds_attributes("test").size).to eq(1) + expect(config_processor.stage_builds_attributes("test").first).to eq({ + stage: "test", + stage_idx: 2, + name: "rspec", + options: { script: ["rspec"] }, + interruptible: true, + allow_failure: false, + when: "on_success", + yaml_variables: [] + }) + end end describe 'retry entry' do diff --git a/spec/lib/gitlab/tracking_spec.rb b/spec/lib/gitlab/tracking_spec.rb index 0bb9d6c331f..dc877f20cae 100644 --- a/spec/lib/gitlab/tracking_spec.rb +++ b/spec/lib/gitlab/tracking_spec.rb @@ -8,7 +8,7 @@ describe Gitlab::Tracking do stub_application_setting(snowplow_enabled: true) stub_application_setting(snowplow_collector_hostname: 'gitfoo.com') stub_application_setting(snowplow_cookie_domain: '.gitfoo.com') - stub_application_setting(snowplow_site_id: '_abc123_') + stub_application_setting(snowplow_app_id: '_abc123_') stub_application_setting(snowplow_iglu_registry_url: 'https://example.org') end diff --git a/spec/migrations/fill_productivity_analytics_start_date_spec.rb b/spec/migrations/fill_productivity_analytics_start_date_spec.rb new file mode 100644 index 00000000000..7cbba9ef20e --- /dev/null +++ b/spec/migrations/fill_productivity_analytics_start_date_spec.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +require 'spec_helper' +require Rails.root.join('db', 'migrate', '20191004081520_fill_productivity_analytics_start_date.rb') + +describe FillProductivityAnalyticsStartDate, :migration do + let(:settings_table) { table('application_settings') } + let(:metrics_table) { table('merge_request_metrics') } + + before do + settings_table.create! + end + + context 'with NO productivity analytics data available' do + it 'sets start_date to NOW' do + expect { migrate! }.to change { + settings_table.first&.productivity_analytics_start_date + }.to(be_like_time(Time.now)) + end + end + + context 'with productivity analytics data available' do + before do + ActiveRecord::Base.transaction do + ActiveRecord::Base.connection.execute('ALTER TABLE merge_request_metrics DISABLE TRIGGER ALL') + metrics_table.create!(merged_at: Time.parse('2019-09-09'), commits_count: nil, merge_request_id: 3) + metrics_table.create!(merged_at: Time.parse('2019-10-10'), commits_count: 5, merge_request_id: 1) + metrics_table.create!(merged_at: Time.parse('2019-11-11'), commits_count: 10, merge_request_id: 2) + ActiveRecord::Base.connection.execute('ALTER TABLE merge_request_metrics ENABLE TRIGGER ALL') + end + end + + it 'set start_date to earliest merged_at value with PA data available' do + expect { migrate! }.to change { + settings_table.first&.productivity_analytics_start_date + }.to(be_like_time(Time.parse('2019-10-10'))) + end + end +end diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb index 5aba798f2c2..1b58fb1dab1 100644 --- a/spec/requests/api/settings_spec.rb +++ b/spec/requests/api/settings_spec.rb @@ -178,7 +178,7 @@ describe API::Settings, 'Settings' do snowplow_collector_hostname: "snowplow.example.com", snowplow_cookie_domain: ".example.com", snowplow_enabled: true, - snowplow_site_id: "site_id", + snowplow_app_id: "app_id", snowplow_iglu_registry_url: 'https://example.com' } end diff --git a/spec/requests/user_avatar_spec.rb b/spec/requests/user_avatar_spec.rb new file mode 100644 index 00000000000..9451674161c --- /dev/null +++ b/spec/requests/user_avatar_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Loading a user avatar' do + let(:user) { create(:user, :with_avatar) } + + context 'when logged in' do + # The exact query count will vary depending on the 2FA settings of the + # instance, group, and user. Removing those extra 2FA queries in this case + # may not be a good idea, so we just set up the ideal case. + before do + stub_application_setting(require_two_factor_authentication: true) + + login_as(create(:user, :two_factor)) + end + + # One each for: current user, avatar user, and upload record + it 'only performs three SQL queries' do + get user.avatar_url # Skip queries on first application load + + expect(response).to have_gitlab_http_status(200) + expect { get user.avatar_url }.not_to exceed_query_limit(3) + end + end + + context 'when logged out' do + # One each for avatar user and upload record + it 'only performs two SQL queries' do + get user.avatar_url # Skip queries on first application load + + expect(response).to have_gitlab_http_status(200) + expect { get user.avatar_url }.not_to exceed_query_limit(2) + end + end +end diff --git a/spec/services/error_tracking/issue_details_service_spec.rb b/spec/services/error_tracking/issue_details_service_spec.rb new file mode 100644 index 00000000000..4d5505bb5a9 --- /dev/null +++ b/spec/services/error_tracking/issue_details_service_spec.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe ErrorTracking::IssueDetailsService do + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project) } + + let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' } + let(:token) { 'test-token' } + let(:result) { subject.execute } + + let(:error_tracking_setting) do + create(:project_error_tracking_setting, api_url: sentry_url, token: token, project: project) + end + + subject { described_class.new(project, user) } + + before do + expect(project).to receive(:error_tracking_setting).at_least(:once).and_return(error_tracking_setting) + + project.add_reporter(user) + end + + describe '#execute' do + context 'with authorized user' do + context 'when issue_details returns a detailed error' do + let(:detailed_error) { build(:detailed_error_tracking_error) } + + before do + expect(error_tracking_setting) + .to receive(:issue_details).and_return(issue: detailed_error) + end + + it 'returns the detailed error' do + expect(result).to eq(status: :success, issue: detailed_error) + end + end + + include_examples 'error tracking service data not ready', :issue_details + include_examples 'error tracking service sentry error handling', :issue_details + include_examples 'error tracking service http status handling', :issue_details + end + + include_examples 'error tracking service unauthorized user' + include_examples 'error tracking service disabled' + end +end diff --git a/spec/services/error_tracking/issue_latest_event_service_spec.rb b/spec/services/error_tracking/issue_latest_event_service_spec.rb new file mode 100644 index 00000000000..cda15042814 --- /dev/null +++ b/spec/services/error_tracking/issue_latest_event_service_spec.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe ErrorTracking::IssueLatestEventService do + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project) } + + let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' } + let(:token) { 'test-token' } + let(:result) { subject.execute } + + let(:error_tracking_setting) do + create(:project_error_tracking_setting, api_url: sentry_url, token: token, project: project) + end + + subject { described_class.new(project, user) } + + before do + expect(project).to receive(:error_tracking_setting).at_least(:once).and_return(error_tracking_setting) + + project.add_reporter(user) + end + + describe '#execute' do + context 'with authorized user' do + context 'when issue_latest_event returns an error event' do + let(:error_event) { build(:error_tracking_error_event) } + + before do + expect(error_tracking_setting) + .to receive(:issue_latest_event).and_return(latest_event: error_event) + end + + it 'returns the error event' do + expect(result).to eq(status: :success, latest_event: error_event) + end + end + + include_examples 'error tracking service data not ready', :issue_latest_event + include_examples 'error tracking service sentry error handling', :issue_latest_event + include_examples 'error tracking service http status handling', :issue_latest_event + end + + include_examples 'error tracking service unauthorized user' + include_examples 'error tracking service disabled' + end +end diff --git a/spec/services/error_tracking/list_issues_service_spec.rb b/spec/services/error_tracking/list_issues_service_spec.rb index 3a8f3069911..fce790f708d 100644 --- a/spec/services/error_tracking/list_issues_service_spec.rb +++ b/spec/services/error_tracking/list_issues_service_spec.rb @@ -37,93 +37,12 @@ describe ErrorTracking::ListIssuesService do end end - context 'when list_sentry_issues returns nil' do - before do - expect(error_tracking_setting) - .to receive(:list_sentry_issues).and_return(nil) - end - - it 'result is not ready' do - expect(result).to eq( - status: :error, http_status: :no_content, message: 'Not ready. Try again later') - end - end - - context 'when list_sentry_issues returns error' do - before do - allow(error_tracking_setting) - .to receive(:list_sentry_issues) - .and_return( - error: 'Sentry response status code: 401', - error_type: ErrorTracking::ProjectErrorTrackingSetting::SENTRY_API_ERROR_TYPE_NON_20X_RESPONSE - ) - end - - it 'returns the error' do - expect(result).to eq( - status: :error, - http_status: :bad_request, - message: 'Sentry response status code: 401' - ) - end - end - - context 'when list_sentry_issues returns error with http_status' do - before do - allow(error_tracking_setting) - .to receive(:list_sentry_issues) - .and_return( - error: 'Sentry API response is missing keys. key not found: "id"', - error_type: ErrorTracking::ProjectErrorTrackingSetting::SENTRY_API_ERROR_TYPE_MISSING_KEYS - ) - end - - it 'returns the error with correct http_status' do - expect(result).to eq( - status: :error, - http_status: :internal_server_error, - message: 'Sentry API response is missing keys. key not found: "id"' - ) - end - end + include_examples 'error tracking service data not ready', :list_sentry_issues + include_examples 'error tracking service sentry error handling', :list_sentry_issues + include_examples 'error tracking service http status handling', :list_sentry_issues end - context 'with unauthorized user' do - let(:unauthorized_user) { create(:user) } - - subject { described_class.new(project, unauthorized_user) } - - it 'returns error' do - result = subject.execute - - expect(result).to include( - status: :error, - message: 'Access denied', - http_status: :unauthorized - ) - end - end - - context 'with error tracking disabled' do - before do - error_tracking_setting.enabled = false - end - - it 'raises error' do - result = subject.execute - - expect(result).to include(status: :error, message: 'Error Tracking is not enabled') - end - end - end - - describe '#sentry_external_url' do - let(:external_url) { 'https://sentrytest.gitlab.com/sentry-org/sentry-project' } - - it 'calls ErrorTracking::ProjectErrorTrackingSetting' do - expect(error_tracking_setting).to receive(:sentry_external_url).and_call_original - - subject.external_url - end + include_examples 'error tracking service unauthorized user' + include_examples 'error tracking service disabled' end end diff --git a/spec/services/error_tracking/list_projects_service_spec.rb b/spec/services/error_tracking/list_projects_service_spec.rb index a272a604184..cd4b835e097 100644 --- a/spec/services/error_tracking/list_projects_service_spec.rb +++ b/spec/services/error_tracking/list_projects_service_spec.rb @@ -127,7 +127,7 @@ describe ErrorTracking::ListProjectsService do end it 'returns error' do - expect(result).to include(status: :error, message: 'access denied') + expect(result).to include(status: :error, message: 'Access denied', http_status: :unauthorized) end end diff --git a/spec/support/shared_examples/services/error_tracking_service_shared_examples.rb b/spec/support/shared_examples/services/error_tracking_service_shared_examples.rb new file mode 100644 index 00000000000..83c6d89e560 --- /dev/null +++ b/spec/support/shared_examples/services/error_tracking_service_shared_examples.rb @@ -0,0 +1,89 @@ +# frozen_string_literal: true + +shared_examples 'error tracking service data not ready' do |service_call| + context "when #{service_call} returns nil" do + before do + expect(error_tracking_setting) + .to receive(service_call).and_return(nil) + end + + it 'result is not ready' do + expect(result).to eq( + status: :error, http_status: :no_content, message: 'Not ready. Try again later') + end + end +end + +shared_examples 'error tracking service sentry error handling' do |service_call| + context "when #{service_call} returns error" do + before do + allow(error_tracking_setting) + .to receive(service_call) + .and_return( + error: 'Sentry response status code: 401', + error_type: ErrorTracking::ProjectErrorTrackingSetting::SENTRY_API_ERROR_TYPE_NON_20X_RESPONSE + ) + end + + it 'returns the error' do + expect(result).to eq( + status: :error, + http_status: :bad_request, + message: 'Sentry response status code: 401' + ) + end + end +end + +shared_examples 'error tracking service http status handling' do |service_call| + context "when #{service_call} returns error with http_status" do + before do + allow(error_tracking_setting) + .to receive(service_call) + .and_return( + error: 'Sentry API response is missing keys. key not found: "id"', + error_type: ErrorTracking::ProjectErrorTrackingSetting::SENTRY_API_ERROR_TYPE_MISSING_KEYS + ) + end + + it 'returns the error with correct http_status' do + expect(result).to eq( + status: :error, + http_status: :internal_server_error, + message: 'Sentry API response is missing keys. key not found: "id"' + ) + end + end +end + +shared_examples 'error tracking service unauthorized user' do + context 'with unauthorized user' do + let(:unauthorized_user) { create(:user) } + + subject { described_class.new(project, unauthorized_user) } + + it 'returns error' do + result = subject.execute + + expect(result).to include( + status: :error, + message: 'Access denied', + http_status: :unauthorized + ) + end + end +end + +shared_examples 'error tracking service disabled' do + context 'with error tracking disabled' do + before do + error_tracking_setting.enabled = false + end + + it 'raises error' do + result = subject.execute + + expect(result).to include(status: :error, message: 'Error Tracking is not enabled') + end + end +end |