diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-02-18 10:34:06 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-02-18 10:34:06 +0000 |
commit | 859a6fb938bb9ee2a317c46dfa4fcc1af49608f0 (patch) | |
tree | d7f2700abe6b4ffcb2dcfc80631b2d87d0609239 /spec/serializers | |
parent | 446d496a6d000c73a304be52587cd9bbc7493136 (diff) | |
download | gitlab-ce-859a6fb938bb9ee2a317c46dfa4fcc1af49608f0.tar.gz |
Add latest changes from gitlab-org/gitlab@13-9-stable-eev13.9.0-rc42
Diffstat (limited to 'spec/serializers')
26 files changed, 520 insertions, 489 deletions
diff --git a/spec/serializers/admin/user_entity_spec.rb b/spec/serializers/admin/user_entity_spec.rb index 7db49af09c3..42efe0eec54 100644 --- a/spec/serializers/admin/user_entity_spec.rb +++ b/spec/serializers/admin/user_entity_spec.rb @@ -22,6 +22,7 @@ RSpec.describe Admin::UserEntity do :username, :last_activity_on, :avatar_url, + :note, :badges, :projects_count, :actions diff --git a/spec/serializers/admin/user_serializer_spec.rb b/spec/serializers/admin/user_serializer_spec.rb index 719a90384c6..53a9457409c 100644 --- a/spec/serializers/admin/user_serializer_spec.rb +++ b/spec/serializers/admin/user_serializer_spec.rb @@ -17,6 +17,7 @@ RSpec.describe Admin::UserSerializer do :username, :last_activity_on, :avatar_url, + :note, :badges, :projects_count, :actions diff --git a/spec/serializers/ci/codequality_mr_diff_entity_spec.rb b/spec/serializers/ci/codequality_mr_diff_entity_spec.rb new file mode 100644 index 00000000000..82708908d95 --- /dev/null +++ b/spec/serializers/ci/codequality_mr_diff_entity_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Ci::CodequalityMrDiffEntity do + let(:entity) { described_class.new(mr_diff_report) } + let(:mr_diff_report) { Gitlab::Ci::Reports::CodequalityMrDiff.new(codequality_report) } + let(:codequality_report) { Gitlab::Ci::Reports::CodequalityReports.new } + let(:degradation_1) { build(:codequality_degradation_1) } + let(:degradation_2) { build(:codequality_degradation_2) } + + describe '#as_json' do + subject(:report) { entity.as_json } + + context 'when quality report has degradations' do + before do + codequality_report.add_degradation(degradation_1) + codequality_report.add_degradation(degradation_2) + end + + it 'contains correct codequality mr diff report', :aggregate_failures do + expect(report[:files].keys).to eq(["file_a.rb"]) + expect(report[:files]["file_a.rb"].first).to include(:line, :description, :severity) + end + end + end +end diff --git a/spec/serializers/ci/codequality_mr_diff_report_serializer_spec.rb b/spec/serializers/ci/codequality_mr_diff_report_serializer_spec.rb new file mode 100644 index 00000000000..906ca36041f --- /dev/null +++ b/spec/serializers/ci/codequality_mr_diff_report_serializer_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Ci::CodequalityMrDiffReportSerializer do + let(:serializer) { described_class.new.represent(mr_diff_report) } + let(:mr_diff_report) { Gitlab::Ci::Reports::CodequalityMrDiff.new(codequality_report) } + let(:codequality_report) { Gitlab::Ci::Reports::CodequalityReports.new } + let(:degradation_1) { build(:codequality_degradation_1) } + let(:degradation_2) { build(:codequality_degradation_2) } + + describe '#to_json' do + subject { serializer.as_json } + + context 'when quality report has degradations' do + before do + codequality_report.add_degradation(degradation_1) + codequality_report.add_degradation(degradation_2) + end + + it 'matches the schema' do + expect(subject).to match_schema('entities/codequality_mr_diff_report') + end + end + + context 'when quality report has no degradations' do + it 'matches the schema' do + expect(subject).to match_schema('entities/codequality_mr_diff_report') + end + end + end +end diff --git a/spec/serializers/ci/dag_pipeline_entity_spec.rb b/spec/serializers/ci/dag_pipeline_entity_spec.rb index e1703b09f97..fdc2f5e1a04 100644 --- a/spec/serializers/ci/dag_pipeline_entity_spec.rb +++ b/spec/serializers/ci/dag_pipeline_entity_spec.rb @@ -73,11 +73,11 @@ RSpec.describe Ci::DagPipelineEntity do end end - it 'performs the smallest number of queries' do + it 'performs the smallest number of queries', :request_store do log = ActiveRecord::QueryRecorder.new { subject } - # stages, project, builds, build_needs - expect(log.count).to eq 4 + # stages, project, builds, build_needs, feature_flag + expect(log.count).to eq 5 end it 'contains all the data' do diff --git a/spec/serializers/ci/pipeline_entity_spec.rb b/spec/serializers/ci/pipeline_entity_spec.rb new file mode 100644 index 00000000000..6ce3cef5f44 --- /dev/null +++ b/spec/serializers/ci/pipeline_entity_spec.rb @@ -0,0 +1,261 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Ci::PipelineEntity do + include Gitlab::Routing + + let_it_be(:project) { create(:project) } + let_it_be(:user) { create(:user) } + let(:request) { double('request', current_user: user) } + let(:entity) { described_class.represent(pipeline, request: request) } + + describe '#as_json' do + subject { entity.as_json } + + context 'when pipeline is empty' do + let(:pipeline) { create(:ci_empty_pipeline) } + + it 'contains required fields' do + expect(subject).to include :id, :user, :path, :coverage, :source + expect(subject).to include :ref, :commit + expect(subject).to include :updated_at, :created_at + end + + it 'excludes coverage data when disabled' do + entity = described_class + .represent(pipeline, request: request, disable_coverage: true) + + expect(entity.as_json).not_to include(:coverage) + end + + it 'contains details' do + expect(subject).to include :details + expect(subject[:details]) + .to include :duration, :finished_at, :name + expect(subject[:details][:status]).to include :icon, :favicon, :text, :label, :tooltip + end + + it 'contains flags' do + expect(subject).to include :flags + expect(subject[:flags]) + .to include :stuck, :auto_devops, :yaml_errors, + :retryable, :cancelable, :merge_request + end + end + + context 'when default branch not protected' do + before do + stub_not_protect_default_branch + end + + context 'when pipeline is retryable' do + let_it_be(:pipeline) do + create(:ci_pipeline, status: :success, project: project) + end + + before do + create(:ci_build, :failed, pipeline: pipeline) + end + + it 'does not serialize stage builds' do + subject.with_indifferent_access.dig(:details, :stages, 0).tap do |stage| + expect(stage).not_to include(:groups, :latest_statuses, :retries) + end + end + + context 'user has ability to retry pipeline' do + before do + project.add_developer(user) + end + + it 'contains retry path' do + expect(subject[:retry_path]).to be_present + end + end + + context 'user does not have ability to retry pipeline' do + it 'does not contain retry path' do + expect(subject).not_to have_key(:retry_path) + end + end + end + + context 'when pipeline is cancelable' do + let_it_be(:pipeline) do + create(:ci_pipeline, status: :running, project: project) + end + + before do + create(:ci_build, :pending, pipeline: pipeline) + end + + it 'does not serialize stage builds' do + subject.with_indifferent_access.dig(:details, :stages, 0).tap do |stage| + expect(stage).not_to include(:groups, :latest_statuses, :retries) + end + end + + context 'user has ability to cancel pipeline' do + before do + project.add_developer(user) + end + + it 'contains cancel path' do + expect(subject[:cancel_path]).to be_present + end + end + + context 'user does not have ability to cancel pipeline' do + it 'does not contain cancel path' do + expect(subject).not_to have_key(:cancel_path) + end + end + end + end + + context 'delete path' do + context 'user has ability to delete pipeline' do + let(:project) { create(:project, namespace: user.namespace) } + let(:pipeline) { create(:ci_pipeline, project: project) } + + it 'contains delete path' do + expect(subject[:delete_path]).to be_present + end + end + + context 'user does not have ability to delete pipeline' do + let(:pipeline) { create(:ci_pipeline, project: project) } + + it 'does not contain delete path' do + expect(subject).not_to have_key(:delete_path) + end + end + end + + context 'when pipeline ref is empty' do + let(:pipeline) { create(:ci_empty_pipeline) } + + before do + allow(pipeline).to receive(:ref).and_return(nil) + end + + it 'does not generate branch path' do + expect(subject[:ref][:path]).to be_nil + end + end + + context 'when pipeline has a failure reason set' do + let(:pipeline) { create(:ci_empty_pipeline) } + + before do + pipeline.drop!(:config_error) + end + + it 'has a correct failure reason' do + expect(subject[:failure_reason]) + .to eq 'CI/CD YAML configuration error!' + end + end + + context 'when request has a project' do + before do + allow(request).to receive(:project).and_return(project) + end + + context 'when pipeline is detached merge request pipeline' do + let_it_be(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) } + let(:project) { merge_request.target_project } + let(:pipeline) { merge_request.pipelines_for_merge_request.first } + + it 'makes detached flag true' do + expect(subject[:flags][:detached_merge_request_pipeline]).to be_truthy + end + + it 'does not expose source sha and target sha' do + expect(subject[:source_sha]).to be_nil + expect(subject[:target_sha]).to be_nil + end + + context 'when user is a developer' do + before do + project.add_developer(user) + end + + it 'has merge request information' do + expect(subject[:merge_request][:iid]).to eq(merge_request.iid) + + expect(project_merge_request_path(project, merge_request)) + .to include(subject[:merge_request][:path]) + + expect(subject[:merge_request][:title]).to eq(merge_request.title) + + expect(subject[:merge_request][:source_branch]) + .to eq(merge_request.source_branch) + + expect(project_commits_path(project, merge_request.source_branch)) + .to include(subject[:merge_request][:source_branch_path]) + + expect(subject[:merge_request][:target_branch]) + .to eq(merge_request.target_branch) + + expect(project_commits_path(project, merge_request.target_branch)) + .to include(subject[:merge_request][:target_branch_path]) + end + end + + context 'when user is an external user' do + it 'has no merge request information' do + expect(subject[:merge_request]).to be_nil + end + end + end + + context 'when pipeline is merge request pipeline' do + let_it_be(:merge_request) { create(:merge_request, :with_merge_request_pipeline, merge_sha: 'abc') } + let(:project) { merge_request.target_project } + let(:pipeline) { merge_request.pipelines_for_merge_request.first } + + it 'makes detached flag false' do + expect(subject[:flags][:detached_merge_request_pipeline]).to be_falsy + end + + it 'makes atached flag true' do + expect(subject[:flags][:merge_request_pipeline]).to be_truthy + end + + it 'exposes source sha and target sha' do + expect(subject[:source_sha]).to be_present + expect(subject[:target_sha]).to be_present + end + + it 'exposes merge request event type' do + expect(subject[:merge_request_event_type]).to be_present + end + end + end + + context 'when pipeline has failed builds' do + let_it_be(:pipeline) { create(:ci_pipeline, user: user) } + let_it_be(:build) { create(:ci_build, :success, pipeline: pipeline) } + let_it_be(:failed_1) { create(:ci_build, :failed, pipeline: pipeline) } + let_it_be(:failed_2) { create(:ci_build, :failed, pipeline: pipeline) } + + context 'when the user can retry the pipeline' do + it 'exposes these failed builds' do + allow(entity).to receive(:can_retry?).and_return(true) + + expect(subject[:failed_builds].map { |b| b[:id] }).to contain_exactly(failed_1.id, failed_2.id) + end + end + + context 'when the user cannot retry the pipeline' do + it 'is nil' do + allow(entity).to receive(:can_retry?).and_return(false) + + expect(subject[:failed_builds]).to be_nil + end + end + end + end +end diff --git a/spec/serializers/codequality_degradation_entity_spec.rb b/spec/serializers/codequality_degradation_entity_spec.rb index fc969195e35..315f00baa72 100644 --- a/spec/serializers/codequality_degradation_entity_spec.rb +++ b/spec/serializers/codequality_degradation_entity_spec.rb @@ -10,77 +10,24 @@ RSpec.describe CodequalityDegradationEntity do context 'when codequality contains an error' do context 'when line is included in location' do - let(:codequality_degradation) do - { - "categories": [ - "Complexity" - ], - "check_name": "argument_count", - "content": { - "body": "" - }, - "description": "Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.", - "fingerprint": "15cdb5c53afd42bc22f8ca366a08d547", - "location": { - "path": "foo.rb", - "lines": { - "begin": 10, - "end": 10 - } - }, - "other_locations": [], - "remediation_points": 900000, - "severity": "major", - "type": "issue", - "engine_name": "structure" - }.with_indifferent_access - end + let(:codequality_degradation) { build(:codequality_degradation_2) } it 'contains correct codequality degradation details', :aggregate_failures do expect(subject[:description]).to eq("Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.") expect(subject[:severity]).to eq("major") - expect(subject[:file_path]).to eq("foo.rb") + expect(subject[:file_path]).to eq("file_a.rb") expect(subject[:line]).to eq(10) end end context 'when line is included in positions' do - let(:codequality_degradation) do - { - "type": "Issue", - "check_name": "Rubocop/Metrics/ParameterLists", - "description": "Avoid parameter lists longer than 5 parameters. [12/5]", - "categories": [ - "Complexity" - ], - "remediation_points": 550000, - "location": { - "path": "foo.rb", - "positions": { - "begin": { - "column": 24, - "line": 14 - }, - "end": { - "column": 49, - "line": 14 - } - } - }, - "content": { - "body": "This cop checks for methods with too many parameters.\nThe maximum number of parameters is configurable.\nKeyword arguments can optionally be excluded from the total count." - }, - "engine_name": "rubocop", - "fingerprint": "ab5f8b935886b942d621399f5a2ca16e", - "severity": "minor" - }.with_indifferent_access - end + let(:codequality_degradation) { build(:codequality_degradation_3) } it 'contains correct codequality degradation details', :aggregate_failures do expect(subject[:description]).to eq("Avoid parameter lists longer than 5 parameters. [12/5]") expect(subject[:severity]).to eq("minor") - expect(subject[:file_path]).to eq("foo.rb") - expect(subject[:line]).to eq(14) + expect(subject[:file_path]).to eq("file_b.rb") + expect(subject[:line]).to eq(10) end end end diff --git a/spec/serializers/codequality_reports_comparer_entity_spec.rb b/spec/serializers/codequality_reports_comparer_entity_spec.rb index 7a79c30cc3f..3c74c20ca19 100644 --- a/spec/serializers/codequality_reports_comparer_entity_spec.rb +++ b/spec/serializers/codequality_reports_comparer_entity_spec.rb @@ -7,62 +7,8 @@ RSpec.describe CodequalityReportsComparerEntity do let(:comparer) { Gitlab::Ci::Reports::CodequalityReportsComparer.new(base_report, head_report) } let(:base_report) { Gitlab::Ci::Reports::CodequalityReports.new } let(:head_report) { Gitlab::Ci::Reports::CodequalityReports.new } - let(:degradation_1) do - { - "categories": [ - "Complexity" - ], - "check_name": "argument_count", - "content": { - "body": "" - }, - "description": "Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.", - "fingerprint": "15cdb5c53afd42bc22f8ca366a08d547", - "location": { - "path": "foo.rb", - "lines": { - "begin": 10, - "end": 10 - } - }, - "other_locations": [], - "remediation_points": 900000, - "severity": "major", - "type": "issue", - "engine_name": "structure" - }.with_indifferent_access - end - - let(:degradation_2) do - { - "type": "Issue", - "check_name": "Rubocop/Metrics/ParameterLists", - "description": "Avoid parameter lists longer than 5 parameters. [12/5]", - "categories": [ - "Complexity" - ], - "remediation_points": 550000, - "location": { - "path": "foo.rb", - "positions": { - "begin": { - "column": 14, - "line": 10 - }, - "end": { - "column": 39, - "line": 10 - } - } - }, - "content": { - "body": "This cop checks for methods with too many parameters.\nThe maximum number of parameters is configurable.\nKeyword arguments can optionally be excluded from the total count." - }, - "engine_name": "rubocop", - "fingerprint": "ab5f8b935886b942d621399f5a2ca16e", - "severity": "minor" - }.with_indifferent_access - end + let(:degradation_1) { build(:codequality_degradation_1) } + let(:degradation_2) { build(:codequality_degradation_2) } describe '#as_json' do subject { entity.as_json } diff --git a/spec/serializers/codequality_reports_comparer_serializer_spec.rb b/spec/serializers/codequality_reports_comparer_serializer_spec.rb index 3c47bfb6adc..50c8a69737c 100644 --- a/spec/serializers/codequality_reports_comparer_serializer_spec.rb +++ b/spec/serializers/codequality_reports_comparer_serializer_spec.rb @@ -8,62 +8,8 @@ RSpec.describe CodequalityReportsComparerSerializer do let(:comparer) { Gitlab::Ci::Reports::CodequalityReportsComparer.new(base_report, head_report) } let(:base_report) { Gitlab::Ci::Reports::CodequalityReports.new } let(:head_report) { Gitlab::Ci::Reports::CodequalityReports.new } - let(:degradation_1) do - { - "categories": [ - "Complexity" - ], - "check_name": "argument_count", - "content": { - "body": "" - }, - "description": "Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.", - "fingerprint": "15cdb5c53afd42bc22f8ca366a08d547", - "location": { - "path": "foo.rb", - "lines": { - "begin": 10, - "end": 10 - } - }, - "other_locations": [], - "remediation_points": 900000, - "severity": "major", - "type": "issue", - "engine_name": "structure" - }.with_indifferent_access - end - - let(:degradation_2) do - { - "type": "Issue", - "check_name": "Rubocop/Metrics/ParameterLists", - "description": "Avoid parameter lists longer than 5 parameters. [12/5]", - "categories": [ - "Complexity" - ], - "remediation_points": 550000, - "location": { - "path": "foo.rb", - "positions": { - "begin": { - "column": 14, - "line": 10 - }, - "end": { - "column": 39, - "line": 10 - } - } - }, - "content": { - "body": "This cop checks for methods with too many parameters.\nThe maximum number of parameters is configurable.\nKeyword arguments can optionally be excluded from the total count." - }, - "engine_name": "rubocop", - "fingerprint": "ab5f8b935886b942d621399f5a2ca16e", - "severity": "minor" - }.with_indifferent_access - end + let(:degradation_1) { build(:codequality_degradation_1) } + let(:degradation_2) { build(:codequality_degradation_2) } describe '#to_json' do subject { serializer.as_json } diff --git a/spec/serializers/diff_file_metadata_entity_spec.rb b/spec/serializers/diff_file_metadata_entity_spec.rb new file mode 100644 index 00000000000..3ce1ea49677 --- /dev/null +++ b/spec/serializers/diff_file_metadata_entity_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe DiffFileMetadataEntity do + let(:merge_request) { create(:merge_request_with_diffs) } + let(:raw_diff_file) { merge_request.merge_request_diff.diffs.raw_diff_files.first } + let(:entity) { described_class.new(raw_diff_file) } + + context 'as json' do + subject { entity.as_json } + + it 'exposes the expected fields' do + expect(subject.keys).to contain_exactly( + :added_lines, + :removed_lines, + :new_path, + :old_path, + :new_file, + :deleted_file, + :submodule, + :file_identifier_hash, + :file_hash + ) + end + end +end diff --git a/spec/serializers/diffs_entity_spec.rb b/spec/serializers/diffs_entity_spec.rb index 7569493573b..a7446f14745 100644 --- a/spec/serializers/diffs_entity_spec.rb +++ b/spec/serializers/diffs_entity_spec.rb @@ -3,10 +3,11 @@ require 'spec_helper' RSpec.describe DiffsEntity do - let(:user) { create(:user) } - let(:project) { create(:project, :repository) } + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, :repository) } + let_it_be(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) } + let(:request) { EntityRequest.new(project: project, current_user: user) } - let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) } let(:merge_request_diffs) { merge_request.merge_request_diffs } let(:options) do { request: request, merge_request: merge_request, merge_request_diffs: merge_request_diffs } @@ -30,6 +31,14 @@ RSpec.describe DiffsEntity do ) end + context 'broken merge request' do + let(:merge_request) { create(:merge_request, :invalid, target_project: project, source_project: project) } + + it 'renders without errors' do + expect { subject }.not_to raise_error + end + end + context "when a commit_id is passed" do let(:commits) { merge_request.commits } let(:entity) do diff --git a/spec/serializers/group_group_link_entity_spec.rb b/spec/serializers/group_link/group_group_link_entity_spec.rb index 9affe4af381..15bcbbcb1d6 100644 --- a/spec/serializers/group_group_link_entity_spec.rb +++ b/spec/serializers/group_link/group_group_link_entity_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GroupGroupLinkEntity do +RSpec.describe GroupLink::GroupGroupLinkEntity do include_context 'group_group_link' let_it_be(:current_user) { create(:user) } @@ -13,15 +13,15 @@ RSpec.describe GroupGroupLinkEntity do end it 'matches json schema' do - expect(entity.to_json).to match_schema('entities/group_group_link') + expect(entity.to_json).to match_schema('group_link/group_group_link') end - context 'a user with :admin_group_member permissions' do + context 'when current user has `:admin_group_member` permissions' do before do allow(entity).to receive(:can?).with(current_user, :admin_group_member, shared_group).and_return(true) end - it 'sets `can_update` and `can_remove` to `true`' do + it 'exposes `can_update` and `can_remove` as `true`' do json = entity.as_json expect(json[:can_update]).to be true diff --git a/spec/serializers/group_group_link_serializer_spec.rb b/spec/serializers/group_link/group_group_link_serializer_spec.rb index 0d977ea0a9a..a4ca32dae7b 100644 --- a/spec/serializers/group_group_link_serializer_spec.rb +++ b/spec/serializers/group_link/group_group_link_serializer_spec.rb @@ -2,12 +2,12 @@ require 'spec_helper' -RSpec.describe GroupGroupLinkSerializer do +RSpec.describe GroupLink::GroupGroupLinkSerializer do include_context 'group_group_link' subject(:json) { described_class.new.represent(shared_group.shared_with_group_links).to_json } it 'matches json schema' do - expect(json).to match_schema('group_group_links') + expect(json).to match_schema('group_link/group_group_links') end end diff --git a/spec/serializers/group_link/group_link_entity_spec.rb b/spec/serializers/group_link/group_link_entity_spec.rb new file mode 100644 index 00000000000..941445feaa2 --- /dev/null +++ b/spec/serializers/group_link/group_link_entity_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GroupLink::GroupLinkEntity do + include_context 'group_group_link' + + let(:entity) { described_class.new(group_group_link) } + let(:entity_hash) { entity.as_json } + + it 'matches json schema' do + expect(entity.to_json).to match_schema('group_link/group_link') + end + + it 'correctly exposes `valid_roles`' do + expect(entity_hash[:valid_roles]).to include(Gitlab::Access.options_with_owner) + end + + it 'correctly exposes `shared_with_group.avatar_url`' do + avatar_url = 'https://gitlab.com/uploads/-/system/group/avatar/24/foobar.png?width=40' + allow(shared_with_group).to receive(:avatar_url).with(only_path: false, size: Member::AVATAR_SIZE).and_return(avatar_url) + + expect(entity_hash[:shared_with_group][:avatar_url]).to match(avatar_url) + end +end diff --git a/spec/serializers/group_link/project_group_link_entity_spec.rb b/spec/serializers/group_link/project_group_link_entity_spec.rb new file mode 100644 index 00000000000..0bb3d06933b --- /dev/null +++ b/spec/serializers/group_link/project_group_link_entity_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GroupLink::ProjectGroupLinkEntity do + let_it_be(:current_user) { create(:user) } + let_it_be(:project_group_link) { create(:project_group_link) } + let(:entity) { described_class.new(project_group_link) } + + before do + allow(entity).to receive(:current_user).and_return(current_user) + end + + it 'matches json schema' do + expect(entity.to_json).to match_schema('group_link/project_group_link') + end + + context 'when current user has `admin_project_member` permissions' do + before do + allow(entity).to receive(:can?).with(current_user, :admin_project_member, project_group_link.project).and_return(true) + end + + it 'exposes `can_update` and `can_remove` as `true`' do + json = entity.as_json + + expect(json[:can_update]).to be true + expect(json[:can_remove]).to be true + end + end +end diff --git a/spec/serializers/group_link/project_group_link_serializer_spec.rb b/spec/serializers/group_link/project_group_link_serializer_spec.rb new file mode 100644 index 00000000000..ecd5d4d70e4 --- /dev/null +++ b/spec/serializers/group_link/project_group_link_serializer_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GroupLink::ProjectGroupLinkSerializer do + let_it_be(:project_group_links) { create_list(:project_group_link, 1) } + + subject(:json) { described_class.new.represent(project_group_links).to_json } + + it 'matches json schema' do + expect(json).to match_schema('group_link/project_group_links') + end +end diff --git a/spec/serializers/member_entity_spec.rb b/spec/serializers/member_entity_spec.rb index f34434188c1..883cb511abc 100644 --- a/spec/serializers/member_entity_spec.rb +++ b/spec/serializers/member_entity_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe MemberEntity do let_it_be(:current_user) { create(:user) } - let(:entity) { described_class.new(member, { current_user: current_user, group: group }) } + let(:entity) { described_class.new(member, { current_user: current_user, group: group, source: source }) } let(:entity_hash) { entity.as_json } shared_examples 'member.json' do @@ -40,8 +40,27 @@ RSpec.describe MemberEntity do end end + shared_examples 'is_direct_member' do + context 'when `source` is the same as `member.source`' do + let(:source) { direct_member_source } + + it 'exposes `is_direct_member` as `true`' do + expect(entity_hash[:is_direct_member]).to be(true) + end + end + + context 'when `source` is not the same as `member.source`' do + let(:source) { inherited_member_source } + + it 'exposes `is_direct_member` as `false`' do + expect(entity_hash[:is_direct_member]).to be(false) + end + end + end + context 'group member' do let(:group) { create(:group) } + let(:source) { group } let(:member) { GroupMemberPresenter.new(create(:group_member, group: group), current_user: current_user) } it_behaves_like 'member.json' @@ -52,11 +71,19 @@ RSpec.describe MemberEntity do it_behaves_like 'member.json' it_behaves_like 'invite' end + + context 'is_direct_member' do + let(:direct_member_source) { group } + let(:inherited_member_source) { create(:group) } + + it_behaves_like 'is_direct_member' + end end context 'project member' do let(:project) { create(:project) } let(:group) { project.group } + let(:source) { project } let(:member) { ProjectMemberPresenter.new(create(:project_member, project: project), current_user: current_user) } it_behaves_like 'member.json' @@ -67,5 +94,12 @@ RSpec.describe MemberEntity do it_behaves_like 'member.json' it_behaves_like 'invite' end + + context 'is_direct_member' do + let(:direct_member_source) { project } + let(:inherited_member_source) { group } + + it_behaves_like 'is_direct_member' + end end end diff --git a/spec/serializers/member_serializer_spec.rb b/spec/serializers/member_serializer_spec.rb index d3ec45fe9c4..af209c0191f 100644 --- a/spec/serializers/member_serializer_spec.rb +++ b/spec/serializers/member_serializer_spec.rb @@ -7,7 +7,7 @@ RSpec.describe MemberSerializer do let_it_be(:current_user) { create(:user) } - subject { described_class.new.represent(members, { current_user: current_user, group: group }) } + subject { described_class.new.represent(members, { current_user: current_user, group: group, source: source }) } shared_examples 'members.json' do it 'matches json schema' do @@ -17,6 +17,7 @@ RSpec.describe MemberSerializer do context 'group member' do let(:group) { create(:group) } + let(:source) { group } let(:members) { present_members(create_list(:group_member, 1, group: group)) } it_behaves_like 'members.json' @@ -24,6 +25,7 @@ RSpec.describe MemberSerializer do context 'project member' do let(:project) { create(:project) } + let(:source) { project } let(:group) { project.group } let(:members) { present_members(create_list(:project_member, 1, project: project)) } diff --git a/spec/serializers/merge_request_basic_entity_spec.rb b/spec/serializers/merge_request_basic_entity_spec.rb index 4a8bcd72d9c..7aa1f47fda5 100644 --- a/spec/serializers/merge_request_basic_entity_spec.rb +++ b/spec/serializers/merge_request_basic_entity_spec.rb @@ -20,23 +20,11 @@ RSpec.describe MergeRequestBasicEntity do let(:params) { { reviewers: [reviewer] } } let(:reviewer) { build(:user) } - context 'when merge_request_reviewers feature is disabled' do - it 'does not contain assignees attributes' do - stub_feature_flags(merge_request_reviewers: false) - - expect(subject[:reviewers]).to be_nil - end - end - - context 'when merge_request_reviewers feature is enabled' do - it 'contains reviewers attributes' do - stub_feature_flags(merge_request_reviewers: true) - - expect(subject[:reviewers].count).to be 1 - expect(subject[:reviewers].first.keys).to include( - :id, :name, :username, :state, :avatar_url, :web_url - ) - end + it 'contains reviewers attributes' do + expect(subject[:reviewers].count).to be 1 + expect(subject[:reviewers].first.keys).to include( + :id, :name, :username, :state, :avatar_url, :web_url + ) end end end diff --git a/spec/serializers/merge_request_sidebar_extras_entity_spec.rb b/spec/serializers/merge_request_sidebar_extras_entity_spec.rb index 74e9956c8a0..58f860097c2 100644 --- a/spec/serializers/merge_request_sidebar_extras_entity_spec.rb +++ b/spec/serializers/merge_request_sidebar_extras_entity_spec.rb @@ -35,23 +35,11 @@ RSpec.describe MergeRequestSidebarExtrasEntity do end describe '#reviewers' do - context 'when merge_request_reviewers feature is disabled' do - it 'does not contain reviewers attributes' do - stub_feature_flags(merge_request_reviewers: false) - - expect(entity[:reviewers]).to be_nil - end - end - - context 'when merge_request_reviewers feature is enabled' do - it 'contains reviewers attributes' do - stub_feature_flags(merge_request_reviewers: true) - - expect(entity[:reviewers].count).to be 1 - expect(entity[:reviewers].first.keys).to include( - :id, :name, :username, :state, :avatar_url, :web_url, :can_merge - ) - end + it 'contains reviewers attributes' do + expect(entity[:reviewers].count).to be 1 + expect(entity[:reviewers].first.keys).to include( + :id, :name, :username, :state, :avatar_url, :web_url, :can_merge + ) end end end diff --git a/spec/serializers/merge_request_user_entity_spec.rb b/spec/serializers/merge_request_user_entity_spec.rb index a2ad8e72845..dcd4ef6acfb 100644 --- a/spec/serializers/merge_request_user_entity_spec.rb +++ b/spec/serializers/merge_request_user_entity_spec.rb @@ -17,5 +17,23 @@ RSpec.describe MergeRequestUserEntity do it 'exposes needed attributes' do expect(subject).to include(:id, :name, :username, :state, :avatar_url, :web_url, :can_merge) end + + context 'when `status` is not preloaded' do + it 'does not expose the availability attribute' do + expect(subject).not_to include(:availability) + end + end + + context 'when `status` is preloaded' do + before do + user.create_status!(availability: :busy) + + user.status # make sure `status` is loaded + end + + it 'exposes the availibility attribute' do + expect(subject[:availability]).to eq('busy') + end + end end end diff --git a/spec/serializers/merge_request_widget_entity_spec.rb b/spec/serializers/merge_request_widget_entity_spec.rb index 42d843af596..926b33e8e1f 100644 --- a/spec/serializers/merge_request_widget_entity_spec.rb +++ b/spec/serializers/merge_request_widget_entity_spec.rb @@ -77,7 +77,7 @@ RSpec.describe MergeRequestWidgetEntity do end describe 'codequality report artifacts', :request_store do - let(:merge_base_pipeline) { create(:ci_pipeline, :with_codequality_report, project: project) } + let(:merge_base_pipeline) { create(:ci_pipeline, :with_codequality_reports, project: project) } before do project.add_developer(user) @@ -90,7 +90,7 @@ RSpec.describe MergeRequestWidgetEntity do end context 'with report artifacts' do - let(:pipeline) { create(:ci_pipeline, :with_codequality_report, project: project) } + let(:pipeline) { create(:ci_pipeline, :with_codequality_reports, project: project) } let(:generic_job_id) { pipeline.builds.first.id } let(:merge_base_job_id) { merge_base_pipeline.builds.first.id } @@ -100,7 +100,7 @@ RSpec.describe MergeRequestWidgetEntity do end context 'on pipelines for merged results' do - let(:pipeline) { create(:ci_pipeline, :merged_result_pipeline, :with_codequality_report, project: project) } + let(:pipeline) { create(:ci_pipeline, :merged_result_pipeline, :with_codequality_reports, project: project) } it 'returns URLs from the head_pipeline and merge_base_pipeline' do expect(subject[:codeclimate][:head_path]).to include("/jobs/#{generic_job_id}/artifacts/download?file_type=codequality") diff --git a/spec/serializers/paginated_diff_entity_spec.rb b/spec/serializers/paginated_diff_entity_spec.rb index 7090ce1f08d..a8ac89a8481 100644 --- a/spec/serializers/paginated_diff_entity_spec.rb +++ b/spec/serializers/paginated_diff_entity_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe PaginatedDiffEntity do let(:user) { create(:user) } let(:request) { double('request', current_user: user) } - let(:merge_request) { create(:merge_request, :with_diffs) } + let(:merge_request) { create(:merge_request) } let(:diff_batch) { merge_request.merge_request_diff.diffs_in_batch(2, 3, diff_options: nil) } let(:options) do { diff --git a/spec/serializers/pipeline_details_entity_spec.rb b/spec/serializers/pipeline_details_entity_spec.rb index 74e91cc9cdd..2f54f45866b 100644 --- a/spec/serializers/pipeline_details_entity_spec.rb +++ b/spec/serializers/pipeline_details_entity_spec.rb @@ -10,8 +10,8 @@ RSpec.describe PipelineDetailsEntity do described_class.represent(pipeline, request: request) end - it 'inherrits from PipelineEntity' do - expect(described_class).to be < PipelineEntity + it 'inherits from PipelineEntity' do + expect(described_class).to be < Ci::PipelineEntity end before do diff --git a/spec/serializers/pipeline_entity_spec.rb b/spec/serializers/pipeline_entity_spec.rb deleted file mode 100644 index d7cd13edec8..00000000000 --- a/spec/serializers/pipeline_entity_spec.rb +++ /dev/null @@ -1,264 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe PipelineEntity do - include Gitlab::Routing - - let_it_be(:project) { create(:project) } - let_it_be(:user) { create(:user) } - let(:request) { double('request') } - - before do - stub_not_protect_default_branch - - allow(request).to receive(:current_user).and_return(user) - allow(request).to receive(:project).and_return(project) - end - - let(:entity) do - described_class.represent(pipeline, request: request) - end - - describe '#as_json' do - subject { entity.as_json } - - context 'when pipeline is empty' do - let(:pipeline) { create(:ci_empty_pipeline) } - - it 'contains required fields' do - expect(subject).to include :id, :user, :path, :coverage, :source - expect(subject).to include :ref, :commit - expect(subject).to include :updated_at, :created_at - end - - it 'excludes coverage data when disabled' do - entity = described_class - .represent(pipeline, request: request, disable_coverage: true) - - expect(entity.as_json).not_to include(:coverage) - end - - it 'contains details' do - expect(subject).to include :details - expect(subject[:details]) - .to include :duration, :finished_at, :name - expect(subject[:details][:status]).to include :icon, :favicon, :text, :label, :tooltip - end - - it 'contains flags' do - expect(subject).to include :flags - expect(subject[:flags]) - .to include :stuck, :auto_devops, :yaml_errors, - :retryable, :cancelable, :merge_request - end - end - - context 'when pipeline is retryable' do - let(:project) { create(:project) } - - let(:pipeline) do - create(:ci_pipeline, status: :success, project: project) - end - - before do - create(:ci_build, :failed, pipeline: pipeline) - end - - it 'does not serialize stage builds' do - subject.with_indifferent_access.dig(:details, :stages, 0).tap do |stage| - expect(stage).not_to include(:groups, :latest_statuses, :retries) - end - end - - context 'user has ability to retry pipeline' do - before do - project.add_developer(user) - end - - it 'contains retry path' do - expect(subject[:retry_path]).to be_present - end - end - - context 'user does not have ability to retry pipeline' do - it 'does not contain retry path' do - expect(subject).not_to have_key(:retry_path) - end - end - end - - context 'when pipeline is cancelable' do - let(:project) { create(:project) } - - let(:pipeline) do - create(:ci_pipeline, status: :running, project: project) - end - - before do - create(:ci_build, :pending, pipeline: pipeline) - end - - it 'does not serialize stage builds' do - subject.with_indifferent_access.dig(:details, :stages, 0).tap do |stage| - expect(stage).not_to include(:groups, :latest_statuses, :retries) - end - end - - context 'user has ability to cancel pipeline' do - before do - project.add_developer(user) - end - - it 'contains cancel path' do - expect(subject[:cancel_path]).to be_present - end - end - - context 'user does not have ability to cancel pipeline' do - it 'does not contain cancel path' do - expect(subject).not_to have_key(:cancel_path) - end - end - end - - context 'delete path' do - context 'user has ability to delete pipeline' do - let(:project) { create(:project, namespace: user.namespace) } - let(:pipeline) { create(:ci_pipeline, project: project) } - - it 'contains delete path' do - expect(subject[:delete_path]).to be_present - end - end - - context 'user does not have ability to delete pipeline' do - let(:project) { create(:project) } - let(:pipeline) { create(:ci_pipeline, project: project) } - - it 'does not contain delete path' do - expect(subject).not_to have_key(:delete_path) - end - end - end - - context 'when pipeline ref is empty' do - let(:pipeline) { create(:ci_empty_pipeline) } - - before do - allow(pipeline).to receive(:ref).and_return(nil) - end - - it 'does not generate branch path' do - expect(subject[:ref][:path]).to be_nil - end - end - - context 'when pipeline has a failure reason set' do - let(:pipeline) { create(:ci_empty_pipeline) } - - before do - pipeline.drop!(:config_error) - end - - it 'has a correct failure reason' do - expect(subject[:failure_reason]) - .to eq 'CI/CD YAML configuration error!' - end - end - - context 'when pipeline is detached merge request pipeline' do - let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) } - let(:project) { merge_request.target_project } - let(:pipeline) { merge_request.pipelines_for_merge_request.first } - - it 'makes detached flag true' do - expect(subject[:flags][:detached_merge_request_pipeline]).to be_truthy - end - - it 'does not expose source sha and target sha' do - expect(subject[:source_sha]).to be_nil - expect(subject[:target_sha]).to be_nil - end - - context 'when user is a developer' do - before do - project.add_developer(user) - end - - it 'has merge request information' do - expect(subject[:merge_request][:iid]).to eq(merge_request.iid) - - expect(project_merge_request_path(project, merge_request)) - .to include(subject[:merge_request][:path]) - - expect(subject[:merge_request][:title]).to eq(merge_request.title) - - expect(subject[:merge_request][:source_branch]) - .to eq(merge_request.source_branch) - - expect(project_commits_path(project, merge_request.source_branch)) - .to include(subject[:merge_request][:source_branch_path]) - - expect(subject[:merge_request][:target_branch]) - .to eq(merge_request.target_branch) - - expect(project_commits_path(project, merge_request.target_branch)) - .to include(subject[:merge_request][:target_branch_path]) - end - end - - context 'when user is an external user' do - it 'has no merge request information' do - expect(subject[:merge_request]).to be_nil - end - end - end - - context 'when pipeline is merge request pipeline' do - let(:merge_request) { create(:merge_request, :with_merge_request_pipeline, merge_sha: 'abc') } - let(:project) { merge_request.target_project } - let(:pipeline) { merge_request.pipelines_for_merge_request.first } - - it 'makes detached flag false' do - expect(subject[:flags][:detached_merge_request_pipeline]).to be_falsy - end - - it 'makes atached flag true' do - expect(subject[:flags][:merge_request_pipeline]).to be_truthy - end - - it 'exposes source sha and target sha' do - expect(subject[:source_sha]).to be_present - expect(subject[:target_sha]).to be_present - end - - it 'exposes merge request event type' do - expect(subject[:merge_request_event_type]).to be_present - end - end - - context 'when pipeline has failed builds' do - let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: user) } - let_it_be(:build) { create(:ci_build, :success, pipeline: pipeline) } - let_it_be(:failed_1) { create(:ci_build, :failed, pipeline: pipeline) } - let_it_be(:failed_2) { create(:ci_build, :failed, pipeline: pipeline) } - - context 'when the user can retry the pipeline' do - it 'exposes these failed builds' do - allow(entity).to receive(:can_retry?).and_return(true) - - expect(subject[:failed_builds].map { |b| b[:id] }).to contain_exactly(failed_1.id, failed_2.id) - end - end - - context 'when the user cannot retry the pipeline' do - it 'is nil' do - allow(entity).to receive(:can_retry?).and_return(false) - - expect(subject[:failed_builds]).to be_nil - end - end - end - end -end diff --git a/spec/serializers/user_serializer_spec.rb b/spec/serializers/user_serializer_spec.rb index d54f33b6a23..f2ef1508098 100644 --- a/spec/serializers/user_serializer_spec.rb +++ b/spec/serializers/user_serializer_spec.rb @@ -9,7 +9,7 @@ RSpec.describe UserSerializer do context 'serializer with merge request context' do let(:merge_request) { create(:merge_request) } let(:project) { merge_request.project } - let(:serializer) { described_class.new(merge_request_iid: merge_request.iid) } + let(:serializer) { described_class.new(current_user: user1, merge_request_iid: merge_request.iid) } before do allow(project).to( |