diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-08-18 13:50:51 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-08-18 13:50:51 +0300 |
commit | db384e6b19af03b4c3c82a5760d83a3fd79f7982 (patch) | |
tree | 34beaef37df5f47ccbcf5729d7583aae093cffa0 /spec/requests/projects | |
parent | 54fd7b1bad233e3944434da91d257fa7f63c3996 (diff) |
Add latest changes from gitlab-org/gitlab@16-3-stable-eev16.3.0-rc42
Diffstat (limited to 'spec/requests/projects')
-rw-r--r-- | spec/requests/projects/blob_spec.rb | 87 | ||||
-rw-r--r-- | spec/requests/projects/merge_requests/creations_spec.rb | 59 | ||||
-rw-r--r-- | spec/requests/projects/merge_requests_controller_spec.rb | 40 | ||||
-rw-r--r-- | spec/requests/projects/merge_requests_discussions_spec.rb | 23 | ||||
-rw-r--r-- | spec/requests/projects/metrics/dashboards/builder_spec.rb | 123 | ||||
-rw-r--r-- | spec/requests/projects/ml/models_controller_spec.rb | 15 | ||||
-rw-r--r-- | spec/requests/projects/noteable_notes_spec.rb | 8 | ||||
-rw-r--r-- | spec/requests/projects/notes_controller_spec.rb | 27 | ||||
-rw-r--r-- | spec/requests/projects/service_desk_controller_spec.rb | 8 | ||||
-rw-r--r-- | spec/requests/projects/tracing_controller_spec.rb | 60 |
10 files changed, 191 insertions, 259 deletions
diff --git a/spec/requests/projects/blob_spec.rb b/spec/requests/projects/blob_spec.rb deleted file mode 100644 index 7d62619e76a..00000000000 --- a/spec/requests/projects/blob_spec.rb +++ /dev/null @@ -1,87 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'Blobs', feature_category: :source_code_management do - let_it_be(:project) { create(:project, :public, :repository, lfs: true) } - - describe 'GET /:namespace_id/:project_id/-/blob/:id' do - subject(:request) do - get namespace_project_blob_path(namespace_id: project.namespace, project_id: project, id: id) - end - - context 'with LFS file' do - let(:id) { 'master/files/lfs/lfs_object.iso' } - let(:object_store_host) { 'http://127.0.0.1:9000' } - let(:connect_src) do - csp = response.headers['Content-Security-Policy'] - csp.split('; ').find { |src| src.starts_with?('connect-src') } - end - - let(:gitlab_config) do - Gitlab.config.gitlab.deep_merge( - 'content_security_policy' => { - 'enabled' => content_security_policy_enabled - } - ) - end - - let(:lfs_config) do - Gitlab.config.lfs.deep_merge( - 'enabled' => lfs_enabled, - 'object_store' => { - 'remote_directory' => 'lfs-objects', - 'enabled' => true, - 'proxy_download' => proxy_download, - 'connection' => { - 'endpoint' => object_store_host, - 'path_style' => true - } - } - ) - end - - before do - stub_config_setting(gitlab_config) - stub_lfs_setting(lfs_config) - stub_lfs_object_storage(proxy_download: proxy_download) - - request - end - - describe 'directly downloading lfs file' do - let(:lfs_enabled) { true } - let(:proxy_download) { false } - let(:content_security_policy_enabled) { true } - - it { expect(response).to have_gitlab_http_status(:success) } - - it { expect(connect_src).to include(object_store_host) } - - context 'when lfs is disabled' do - let(:lfs_enabled) { false } - - it { expect(response).to have_gitlab_http_status(:success) } - - it { expect(connect_src).not_to include(object_store_host) } - end - - context 'when content_security_policy is disabled' do - let(:content_security_policy_enabled) { false } - - it { expect(response).to have_gitlab_http_status(:success) } - - it { expect(connect_src).not_to include(object_store_host) } - end - - context 'when proxy download is enabled' do - let(:proxy_download) { true } - - it { expect(response).to have_gitlab_http_status(:success) } - - it { expect(connect_src).not_to include(object_store_host) } - end - end - end - end -end diff --git a/spec/requests/projects/merge_requests/creations_spec.rb b/spec/requests/projects/merge_requests/creations_spec.rb index e8a073fef5f..8f55aa90bee 100644 --- a/spec/requests/projects/merge_requests/creations_spec.rb +++ b/spec/requests/projects/merge_requests/creations_spec.rb @@ -10,6 +10,17 @@ RSpec.describe 'merge requests creations', feature_category: :code_review_workfl let_it_be(:project) { create(:project, :repository, group: group) } let_it_be(:user) { create(:user) } + let(:get_params) do + { + namespace_id: project.namespace.to_param, + project_id: project, + merge_request: { + source_branch: 'two-commits', + target_branch: 'master' + } + } + end + before_all do group.add_developer(user) end @@ -18,16 +29,52 @@ RSpec.describe 'merge requests creations', feature_category: :code_review_workfl login_as(user) end - def get_new - get namespace_project_new_merge_request_path(namespace_id: project.namespace, project_id: project) + def get_new(params = get_params) + get namespace_project_new_merge_request_path(params) end - it 'avoids N+1 DB queries even with forked projects' do - control = ActiveRecord::QueryRecorder.new(skip_cached: false) { get_new } + describe 'GET new' do + context 'without merge_request params' do + it 'avoids N+1 DB queries even with forked projects' do + control = ActiveRecord::QueryRecorder.new(skip_cached: false) { get_new } + + 5.times { fork_project(project, user) } + + expect { get_new }.not_to exceed_query_limit(control) + end + + it 'renders branch selection screen' do + get_new(get_params.except(:merge_request)) + + expect(response).to be_successful + expect(response).to render_template(partial: '_new_compare') + end + end + + context 'with merge_request params' do + it 'renders new merge request widget template' do + get_new + + expect(response).to be_successful + expect(response).to render_template(partial: '_new_submit') + expect(response).not_to render_template(partial: '_new_compare') + end - 5.times { fork_project(project, user) } + context 'when existing merge request with same target and source branches' do + let_it_be(:existing_mr) { create(:merge_request) } - expect { get_new }.not_to exceed_query_limit(control) + it 'renders branch selection screen' do + allow_next_instance_of(MergeRequest) do |instance| + allow(instance).to receive(:existing_mrs_targeting_same_branch).and_return([existing_mr]) + end + + get_new + + expect(response).to be_successful + expect(response).to render_template(partial: '_new_compare') + end + end + end end it_behaves_like "observability csp policy", Projects::MergeRequests::CreationsController do diff --git a/spec/requests/projects/merge_requests_controller_spec.rb b/spec/requests/projects/merge_requests_controller_spec.rb index 955b6e53686..e6a281d8d59 100644 --- a/spec/requests/projects/merge_requests_controller_spec.rb +++ b/spec/requests/projects/merge_requests_controller_spec.rb @@ -132,4 +132,44 @@ RSpec.describe Projects::MergeRequestsController, feature_category: :source_code end end end + + describe 'GET #pipelines.json' do + before do + login_as(user) + end + + it 'avoids N+1 queries', :use_sql_query_cache do + create_pipeline + + # warm up + get pipelines_project_merge_request_path(project, merge_request, format: :json) + + control = ActiveRecord::QueryRecorder.new(skip_cached: false) do + get pipelines_project_merge_request_path(project, merge_request, format: :json) + end + + expect(response).to have_gitlab_http_status(:ok) + expect(Gitlab::Json.parse(response.body)['count']['all']).to eq(1) + + create_pipeline + + expect do + get pipelines_project_merge_request_path(project, merge_request, format: :json) + end.to issue_same_number_of_queries_as(control) + + expect(response).to have_gitlab_http_status(:ok) + expect(Gitlab::Json.parse(response.body)['count']['all']).to eq(2) + end + + private + + def create_pipeline + create( + :ci_pipeline, :with_job, :success, + project: merge_request.source_project, + ref: merge_request.source_branch, + sha: merge_request.diff_head_sha + ) + end + end end diff --git a/spec/requests/projects/merge_requests_discussions_spec.rb b/spec/requests/projects/merge_requests_discussions_spec.rb index 644f26af006..24b6fb2f640 100644 --- a/spec/requests/projects/merge_requests_discussions_spec.rb +++ b/spec/requests/projects/merge_requests_discussions_spec.rb @@ -27,19 +27,15 @@ RSpec.describe 'merge requests discussions', feature_category: :source_code_mana end # rubocop:enable RSpec/InstanceVariable - shared_examples 'N+1 queries' do - it 'avoids N+1 DB queries', :request_store do - send_request # warm up + it 'avoids N+1 DB queries', :request_store do + send_request # warm up - create(:diff_note_on_merge_request, noteable: merge_request, project: merge_request.project) - control = ActiveRecord::QueryRecorder.new { send_request } + create(:diff_note_on_merge_request, noteable: merge_request, project: merge_request.project) + control = ActiveRecord::QueryRecorder.new { send_request } - create(:diff_note_on_merge_request, noteable: merge_request, project: merge_request.project) + create(:diff_note_on_merge_request, noteable: merge_request, project: merge_request.project) - expect do - send_request - end.not_to exceed_query_limit(control).with_threshold(notes_metadata_threshold) - end + expect { send_request }.not_to exceed_query_limit(control) end it 'returns 200' do @@ -48,13 +44,6 @@ RSpec.describe 'merge requests discussions', feature_category: :source_code_mana expect(response).to have_gitlab_http_status(:ok) end - # https://docs.gitlab.com/ee/development/query_recorder.html#use-request-specs-instead-of-controller-specs - context 'with notes_metadata_threshold' do - let(:notes_metadata_threshold) { 1 } - - it_behaves_like 'N+1 queries' - end - it 'limits Gitaly queries', :request_store do Gitlab::GitalyClient.allow_n_plus_1_calls do create_list(:diff_note_on_merge_request, 7, noteable: merge_request, project: merge_request.project) diff --git a/spec/requests/projects/metrics/dashboards/builder_spec.rb b/spec/requests/projects/metrics/dashboards/builder_spec.rb deleted file mode 100644 index 8af2d1f1d25..00000000000 --- a/spec/requests/projects/metrics/dashboards/builder_spec.rb +++ /dev/null @@ -1,123 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'Projects::Metrics::Dashboards::BuilderController', feature_category: :metrics do - let_it_be(:project) { create(:project) } - let_it_be(:environment) { create(:environment, project: project) } - let_it_be(:user) { create(:user) } - let_it_be(:valid_panel_yml) do - <<~YML - --- - title: "Super Chart A1" - type: "area-chart" - y_label: "y_label" - weight: 1 - max_value: 1 - metrics: - - id: metric_a1 - query_range: |+ - avg( - sum( - container_memory_usage_bytes{ - container_name!="POD", - pod_name=~"^{{ci_environment_slug}}-(.*)", - namespace="{{kube_namespace}}", - user_def_variable="{{user_def_variable}}" - } - ) by (job) - ) without (job) - /1024/1024/1024 - unit: unit - label: Legend Label - YML - end - - let_it_be(:invalid_panel_yml) do - <<~YML - --- - title: "Super Chart A1" - type: "area-chart" - y_label: "y_label" - weight: 1 - max_value: 1 - YML - end - - def send_request(params = {}) - post namespace_project_metrics_dashboards_builder_path(namespace_id: project.namespace, project_id: project, format: :json, **params) - end - - describe 'POST /:namespace/:project/-/metrics/dashboards/builder' do - before do - stub_feature_flags(remove_monitor_metrics: false) - end - - context 'as anonymous user' do - it 'redirects user to sign in page' do - send_request - - expect(response).to redirect_to(new_user_session_path) - end - end - - context 'as user with guest access' do - before do - project.add_guest(user) - login_as(user) - end - - it 'returns not found' do - send_request - - expect(response).to have_gitlab_http_status(:not_found) - end - end - - context 'as logged in user' do - before do - project.add_developer(user) - login_as(user) - end - - context 'valid yaml panel is supplied' do - it 'returns success' do - send_request(panel_yaml: valid_panel_yml) - - expect(response).to have_gitlab_http_status(:ok) - expect(json_response).to include('title' => 'Super Chart A1', 'type' => 'area-chart') - end - end - - context 'invalid yaml panel is supplied' do - it 'returns unprocessable entity' do - send_request(panel_yaml: invalid_panel_yml) - - expect(response).to have_gitlab_http_status(:unprocessable_entity) - expect(json_response['message']).to eq('Each "panel" must define an array :metrics') - end - end - - context 'invalid panel_yaml is not a yaml string' do - it 'returns unprocessable entity' do - send_request(panel_yaml: 1) - - expect(response).to have_gitlab_http_status(:unprocessable_entity) - expect(json_response['message']).to eq('Invalid configuration format') - end - end - - context 'when metrics dashboard feature is unavailable' do - before do - stub_feature_flags(remove_monitor_metrics: true) - end - - it 'returns not found' do - send_request - - expect(response).to have_gitlab_http_status(:not_found) - end - end - end - end -end diff --git a/spec/requests/projects/ml/models_controller_spec.rb b/spec/requests/projects/ml/models_controller_spec.rb index d03748c8dff..8569f2396d3 100644 --- a/spec/requests/projects/ml/models_controller_spec.rb +++ b/spec/requests/projects/ml/models_controller_spec.rb @@ -5,9 +5,9 @@ require 'spec_helper' RSpec.describe Projects::Ml::ModelsController, feature_category: :mlops do let_it_be(:project) { create(:project, :repository) } let_it_be(:user) { project.first_owner } - let_it_be(:model1_a) { create(:ml_model_package, project: project) } - let_it_be(:model1_b) { create(:ml_model_package, project: project, name: model1_a.name) } - let_it_be(:model2) { create(:ml_model_package, project: project) } + let_it_be(:model1) { create(:ml_models, :with_versions, project: project) } + let_it_be(:model2) { create(:ml_models, project: project) } + let_it_be(:model_in_different_project) { create(:ml_models) } let(:model_registry_enabled) { true } @@ -36,16 +36,17 @@ RSpec.describe Projects::Ml::ModelsController, feature_category: :mlops do index_request end - it 'prepares model view using the presenter' do - expect(::Ml::ModelsIndexPresenter).to receive(:new).and_call_original - + it 'fetches the correct models' do index_request + + expect(assigns(:models)).to match_array([model1, model2]) end it 'does not perform N+1 sql queries' do control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) { list_models } - create_list(:ml_model_package, 4, project: project) + create_list(:ml_model_versions, 2, model: model1) + create_list(:ml_model_versions, 2, model: model2) expect { list_models }.not_to exceed_all_query_limit(control_count) end diff --git a/spec/requests/projects/noteable_notes_spec.rb b/spec/requests/projects/noteable_notes_spec.rb index 55540447da0..a490e059680 100644 --- a/spec/requests/projects/noteable_notes_spec.rb +++ b/spec/requests/projects/noteable_notes_spec.rb @@ -14,6 +14,8 @@ RSpec.describe 'Project noteable notes', feature_category: :team_planning do let(:response_etag) { response.headers['ETag'] } let(:stored_etag) { "W/\"#{etag_store.get(notes_path)}\"" } + let(:default_headers) { { 'X-Last-Fetched-At' => 0 } } + before do login_as(user) end @@ -21,7 +23,7 @@ RSpec.describe 'Project noteable notes', feature_category: :team_planning do it 'does not set a Gitlab::EtagCaching ETag if there is a note' do create(:note_on_merge_request, noteable: merge_request, project: merge_request.project) - get notes_path + get notes_path, headers: default_headers expect(response).to have_gitlab_http_status(:ok) @@ -31,7 +33,7 @@ RSpec.describe 'Project noteable notes', feature_category: :team_planning do end it 'sets a Gitlab::EtagCaching ETag if there is no note' do - get notes_path + get notes_path, headers: default_headers expect(response).to have_gitlab_http_status(:ok) expect(response_etag).to eq(stored_etag) @@ -68,7 +70,7 @@ RSpec.describe 'Project noteable notes', feature_category: :team_planning do ) ) - get notes_path, headers: { "if-none-match": stored_etag } + get notes_path, headers: default_headers.merge("if-none-match": stored_etag) expect(response).to have_gitlab_http_status(:not_modified) end diff --git a/spec/requests/projects/notes_controller_spec.rb b/spec/requests/projects/notes_controller_spec.rb new file mode 100644 index 00000000000..9cd8ba364ea --- /dev/null +++ b/spec/requests/projects/notes_controller_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Projects::NotesController, feature_category: :team_planning do + let_it_be(:project) { create(:project, :public) } + let_it_be(:issue) { create(:issue, project: project) } + + describe '#index' do + def get_notes + get project_noteable_notes_path(project, target_type: 'issue', target_id: issue.id, format: :json), + headers: { 'X-Last-Fetched-At': 0 } + end + + it 'does not execute N+1 queries' do + get_notes + + create(:note_on_issue, project: project, noteable: issue) + + control = ActiveRecord::QueryRecorder.new { get_notes } + + create(:note_on_issue, project: project, noteable: issue) + + expect { get_notes }.not_to exceed_query_limit(control) + end + end +end diff --git a/spec/requests/projects/service_desk_controller_spec.rb b/spec/requests/projects/service_desk_controller_spec.rb index 54fe176e244..05e48c2c5c7 100644 --- a/spec/requests/projects/service_desk_controller_spec.rb +++ b/spec/requests/projects/service_desk_controller_spec.rb @@ -71,7 +71,7 @@ RSpec.describe Projects::ServiceDeskController, feature_category: :service_desk it 'toggles services desk incoming email' do project.update!(service_desk_enabled: false) - put project_service_desk_refresh_path(project, format: :json), params: { service_desk_enabled: true } + put project_service_desk_path(project, format: :json), params: { service_desk_enabled: true } expect(json_response["service_desk_address"]).to be_present expect(json_response["service_desk_enabled"]).to be_truthy @@ -79,7 +79,7 @@ RSpec.describe Projects::ServiceDeskController, feature_category: :service_desk end it 'sets issue_template_key' do - put project_service_desk_refresh_path(project, format: :json), params: { issue_template_key: 'service_desk' } + put project_service_desk_path(project, format: :json), params: { issue_template_key: 'service_desk' } settings = project.service_desk_setting expect(settings).to be_present @@ -89,7 +89,7 @@ RSpec.describe Projects::ServiceDeskController, feature_category: :service_desk end it 'returns an error when update of service desk settings fails' do - put project_service_desk_refresh_path(project, format: :json), params: { issue_template_key: 'invalid key' } + put project_service_desk_path(project, format: :json), params: { issue_template_key: 'invalid key' } expect(response).to have_gitlab_http_status(:unprocessable_entity) expect(json_response['message']).to eq('Issue template key is empty or does not exist') @@ -100,7 +100,7 @@ RSpec.describe Projects::ServiceDeskController, feature_category: :service_desk it 'renders 404' do sign_in(other_user) - put project_service_desk_refresh_path(project, format: :json), params: { service_desk_enabled: true } + put project_service_desk_path(project, format: :json), params: { service_desk_enabled: true } expect(response).to have_gitlab_http_status(:not_found) end diff --git a/spec/requests/projects/tracing_controller_spec.rb b/spec/requests/projects/tracing_controller_spec.rb index eecaa0d962a..8996ea7f8d6 100644 --- a/spec/requests/projects/tracing_controller_spec.rb +++ b/spec/requests/projects/tracing_controller_spec.rb @@ -14,14 +14,12 @@ RSpec.describe Projects::TracingController, feature_category: :tracing do response end - describe 'GET #index' do - before do - stub_feature_flags(observability_tracing: observability_tracing_ff) - sign_in(user) - end - - let(:path) { project_tracing_index_path(project) } + before do + stub_feature_flags(observability_tracing: observability_tracing_ff) + sign_in(user) + end + shared_examples 'tracing route request' do it_behaves_like 'observability csp policy' do before_all do project.add_developer(user) @@ -45,6 +43,26 @@ RSpec.describe Projects::TracingController, feature_category: :tracing do expect(subject).to have_gitlab_http_status(:ok) end + context 'when feature is disabled' do + let(:observability_tracing_ff) { false } + + it 'returns 404' do + expect(subject).to have_gitlab_http_status(:not_found) + end + end + end + end + + describe 'GET #index' do + let(:path) { project_tracing_index_path(project) } + + it_behaves_like 'tracing route request' + + describe 'html response' do + before_all do + project.add_developer(user) + end + it 'renders the js-tracing element correctly' do element = Nokogiri::HTML.parse(subject.body).at_css('#js-tracing') @@ -55,13 +73,31 @@ RSpec.describe Projects::TracingController, feature_category: :tracing do }.to_json expect(element.attributes['data-view-model'].value).to eq(expected_view_model) end + end + end - context 'when feature is disabled' do - let(:observability_tracing_ff) { false } + describe 'GET #show' do + let(:path) { project_tracing_path(project, id: "test-trace-id") } - it 'returns 404' do - expect(subject).to have_gitlab_http_status(:not_found) - end + it_behaves_like 'tracing route request' + + describe 'html response' do + before_all do + project.add_developer(user) + end + + it 'renders the js-tracing element correctly' do + element = Nokogiri::HTML.parse(subject.body).at_css('#js-tracing-details') + + expected_view_model = { + tracingIndexUrl: project_tracing_index_path(project), + traceId: 'test-trace-id', + tracingUrl: Gitlab::Observability.tracing_url(project), + provisioningUrl: Gitlab::Observability.provisioning_url(project), + oauthUrl: Gitlab::Observability.oauth_url + }.to_json + + expect(element.attributes['data-view-model'].value).to eq(expected_view_model) end end end |