diff options
Diffstat (limited to 'spec/models')
24 files changed, 894 insertions, 84 deletions
diff --git a/spec/models/application_setting/term_spec.rb b/spec/models/application_setting/term_spec.rb index 1eddf3c56ff..aa49594f4d1 100644 --- a/spec/models/application_setting/term_spec.rb +++ b/spec/models/application_setting/term_spec.rb @@ -12,4 +12,41 @@ describe ApplicationSetting::Term do expect(described_class.latest).to eq(terms) end end + + describe '#accepted_by_user?' do + let(:user) { create(:user) } + let(:term) { create(:term) } + + it 'is true when the user accepted the terms' do + accept_terms(term, user) + + expect(term.accepted_by_user?(user)).to be(true) + end + + it 'is false when the user declined the terms' do + decline_terms(term, user) + + expect(term.accepted_by_user?(user)).to be(false) + end + + it 'does not cause a query when the user accepted the current terms' do + accept_terms(term, user) + + expect { term.accepted_by_user?(user) }.not_to exceed_query_limit(0) + end + + it 'returns false if the currently accepted terms are different' do + accept_terms(create(:term), user) + + expect(term.accepted_by_user?(user)).to be(false) + end + + def accept_terms(term, user) + Users::RespondToTermsService.new(user, term).execute(accepted: true) + end + + def decline_terms(term, user) + Users::RespondToTermsService.new(user, term).execute(accepted: false) + end + end end diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 968267a6d24..3e6656e0f12 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -110,10 +110,9 @@ describe ApplicationSetting do # Upgraded databases will have this sort of content context 'repository_storages is a String, not an Array' do before do - setting.__send__(:raw_write_attribute, :repository_storages, 'default') + described_class.where(id: setting.id).update_all(repository_storages: 'default') end - it { expect(setting.repository_storages_before_type_cast).to eq('default') } it { expect(setting.repository_storages).to eq(['default']) } end diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 66c9708b4cf..51b9b518117 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -116,6 +116,26 @@ describe Ci::Build do end end + describe '.with_live_trace' do + subject { described_class.with_live_trace } + + context 'when build has live trace' do + let!(:build) { create(:ci_build, :success, :trace_live) } + + it 'selects the build' do + is_expected.to eq([build]) + end + end + + context 'when build does not have live trace' do + let!(:build) { create(:ci_build, :success, :trace_artifact) } + + it 'does not select the build' do + is_expected.to be_empty + end + end + end + describe '#actionize' do context 'when build is a created' do before do @@ -1528,7 +1548,9 @@ describe Ci::Build do let(:predefined_variables) do [ { key: 'CI_PIPELINE_ID', value: pipeline.id.to_s, public: true }, + { key: 'CI_PIPELINE_URL', value: project.web_url + "/pipelines/#{pipeline.id}", public: true }, { key: 'CI_JOB_ID', value: build.id.to_s, public: true }, + { key: 'CI_JOB_URL', value: project.web_url + "/-/jobs/#{build.id}", public: true }, { key: 'CI_JOB_TOKEN', value: build.token, public: false }, { key: 'CI_BUILD_ID', value: build.id.to_s, public: true }, { key: 'CI_BUILD_TOKEN', value: build.token, public: false }, @@ -2151,6 +2173,7 @@ describe Ci::Build do it 'does not return prohibited variables' do keys = %w[CI_JOB_ID + CI_JOB_URL CI_JOB_TOKEN CI_BUILD_ID CI_BUILD_TOKEN @@ -2506,4 +2529,76 @@ describe Ci::Build do end end end + + describe 'pages deployments' do + set(:build) { create(:ci_build, project: project, user: user) } + + context 'when job is "pages"' do + before do + build.name = 'pages' + end + + context 'when pages are enabled' do + before do + allow(Gitlab.config.pages).to receive_messages(enabled: true) + end + + it 'is marked as pages generator' do + expect(build).to be_pages_generator + end + + context 'job succeeds' do + it "calls pages worker" do + expect(PagesWorker).to receive(:perform_async).with(:deploy, build.id) + + build.success! + end + end + + context 'job fails' do + it "does not call pages worker" do + expect(PagesWorker).not_to receive(:perform_async) + + build.drop! + end + end + end + + context 'when pages are disabled' do + before do + allow(Gitlab.config.pages).to receive_messages(enabled: false) + end + + it 'is not marked as pages generator' do + expect(build).not_to be_pages_generator + end + + context 'job succeeds' do + it "does not call pages worker" do + expect(PagesWorker).not_to receive(:perform_async) + + build.success! + end + end + end + end + + context 'when job is not "pages"' do + before do + build.name = 'other-job' + end + + it 'is not marked as pages generator' do + expect(build).not_to be_pages_generator + end + + context 'job succeeds' do + it "does not call pages worker" do + expect(PagesWorker).not_to receive(:perform_async) + + build.success + end + end + end + end end diff --git a/spec/models/ci/build_trace_chunk_spec.rb b/spec/models/ci/build_trace_chunk_spec.rb index cbcf1e55979..b5a6d959ccb 100644 --- a/spec/models/ci/build_trace_chunk_spec.rb +++ b/spec/models/ci/build_trace_chunk_spec.rb @@ -54,14 +54,6 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do it { is_expected.to eq('Sample data in db') } end - - context 'when data_store is others' do - before do - build_trace_chunk.send(:write_attribute, :data_store, -1) - end - - it { expect { subject }.to raise_error('Unsupported data store') } - end end describe '#set_data' do diff --git a/spec/models/ci/group_spec.rb b/spec/models/ci/group_spec.rb index 51123e73fe6..838fa63cb1f 100644 --- a/spec/models/ci/group_spec.rb +++ b/spec/models/ci/group_spec.rb @@ -41,4 +41,55 @@ describe Ci::Group do end end end + + describe '.fabricate' do + let(:pipeline) { create(:ci_empty_pipeline) } + let(:stage) { create(:ci_stage_entity, pipeline: pipeline) } + + before do + create_build(:ci_build, name: 'rspec 0 2') + create_build(:ci_build, name: 'rspec 0 1') + create_build(:ci_build, name: 'spinach 0 1') + create_build(:commit_status, name: 'aaaaa') + end + + it 'returns an array of three groups' do + expect(stage.groups).to be_a Array + expect(stage.groups).to all(be_a described_class) + expect(stage.groups.size).to eq 3 + end + + it 'returns groups with correctly ordered statuses' do + expect(stage.groups.first.jobs.map(&:name)) + .to eq ['aaaaa'] + expect(stage.groups.second.jobs.map(&:name)) + .to eq ['rspec 0 1', 'rspec 0 2'] + expect(stage.groups.third.jobs.map(&:name)) + .to eq ['spinach 0 1'] + end + + it 'returns groups with correct names' do + expect(stage.groups.map(&:name)) + .to eq %w[aaaaa rspec spinach] + end + + context 'when a name is nil on legacy pipelines' do + before do + pipeline.builds.first.update_attribute(:name, nil) + end + + it 'returns an array of three groups' do + expect(stage.groups.map(&:name)) + .to eq ['', 'aaaaa', 'rspec', 'spinach'] + end + end + + def create_build(type, status: 'success', **opts) + create(type, pipeline: pipeline, + stage: stage.name, + status: status, + stage_id: stage.id, + **opts) + end + end end diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb index a3e119cbc27..efddd4e7662 100644 --- a/spec/models/ci/job_artifact_spec.rb +++ b/spec/models/ci/job_artifact_spec.rb @@ -76,12 +76,12 @@ describe Ci::JobArtifact do context 'updating the artifact file' do it 'updates the artifact size' do - artifact.update!(file: fixture_file_upload(File.join(Rails.root, 'spec/fixtures/dk.png'))) + artifact.update!(file: fixture_file_upload('spec/fixtures/dk.png')) expect(artifact.size).to eq(1062) end it 'updates the project statistics' do - expect { artifact.update!(file: fixture_file_upload(File.join(Rails.root, 'spec/fixtures/dk.png'))) } + expect { artifact.update!(file: fixture_file_upload('spec/fixtures/dk.png')) } .to change { artifact.project.statistics.reload.build_artifacts_size } .by(1062 - 106365) end diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 24692ebb9a3..a41657b53b7 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -194,7 +194,7 @@ describe Ci::Pipeline, :mailer do it 'does contains persisted variables' do keys = subject.map { |variable| variable[:key] } - expect(keys).to eq %w[CI_PIPELINE_ID] + expect(keys).to eq %w[CI_PIPELINE_ID CI_PIPELINE_URL] end end end @@ -537,6 +537,87 @@ describe Ci::Pipeline, :mailer do end end end + + describe '#stages' do + before do + create(:ci_stage_entity, project: project, + pipeline: pipeline, + name: 'build') + end + + it 'returns persisted stages' do + expect(pipeline.stages).not_to be_empty + expect(pipeline.stages).to all(be_persisted) + end + end + + describe '#ordered_stages' do + before do + create(:ci_stage_entity, project: project, + pipeline: pipeline, + position: 4, + name: 'deploy') + + create(:ci_build, project: project, + pipeline: pipeline, + stage: 'test', + stage_idx: 3, + name: 'test') + + create(:ci_build, project: project, + pipeline: pipeline, + stage: 'build', + stage_idx: 2, + name: 'build') + + create(:ci_stage_entity, project: project, + pipeline: pipeline, + position: 1, + name: 'sanity') + + create(:ci_stage_entity, project: project, + pipeline: pipeline, + position: 5, + name: 'cleanup') + end + + subject { pipeline.ordered_stages } + + context 'when using legacy stages' do + before do + stub_feature_flags(ci_pipeline_persisted_stages: false) + end + + it 'returns legacy stages in valid order' do + expect(subject.map(&:name)).to eq %w[build test] + end + end + + context 'when using persisted stages' do + before do + stub_feature_flags(ci_pipeline_persisted_stages: true) + end + + context 'when pipelines is not complete' do + it 'still returns legacy stages' do + expect(subject).to all(be_a Ci::LegacyStage) + expect(subject.map(&:name)).to eq %w[build test] + end + end + + context 'when pipeline is complete' do + before do + pipeline.succeed! + end + + it 'returns stages in valid order' do + expect(subject).to all(be_a Ci::Stage) + expect(subject.map(&:name)) + .to eq %w[sanity build test deploy cleanup] + end + end + end + end end describe 'state machine' do @@ -1181,6 +1262,43 @@ describe Ci::Pipeline, :mailer do end end + describe '#update_status' do + context 'when pipeline is empty' do + it 'updates does not change pipeline status' do + expect(pipeline.statuses.latest.status).to be_nil + + expect { pipeline.update_status } + .to change { pipeline.reload.status }.to 'skipped' + end + end + + context 'when updating status to pending' do + before do + allow(pipeline) + .to receive_message_chain(:statuses, :latest, :status) + .and_return(:running) + end + + it 'updates pipeline status to running' do + expect { pipeline.update_status } + .to change { pipeline.reload.status }.to 'running' + end + end + + context 'when statuses status was not recognized' do + before do + allow(pipeline) + .to receive(:latest_builds_status) + .and_return(:unknown) + end + + it 'raises an exception' do + expect { pipeline.update_status } + .to raise_error(HasStatus::UnknownStatusError) + end + end + end + describe '#detailed_status' do subject { pipeline.detailed_status(user) } diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb index 0f072aa1719..f6433234573 100644 --- a/spec/models/ci/runner_spec.rb +++ b/spec/models/ci/runner_spec.rb @@ -549,7 +549,7 @@ describe Ci::Runner do end describe '#update_cached_info' do - let(:runner) { create(:ci_runner) } + let(:runner) { create(:ci_runner, :project) } subject { runner.update_cached_info(architecture: '18-bit') } @@ -570,17 +570,22 @@ describe Ci::Runner do runner.contacted_at = 2.hours.ago end - it 'updates database' do - expect_redis_update + context 'with invalid runner' do + before do + runner.projects = [] + end + + it 'still updates redis cache and database' do + expect(runner).to be_invalid - expect { subject }.to change { runner.reload.read_attribute(:contacted_at) } - .and change { runner.reload.read_attribute(:architecture) } + expect_redis_update + does_db_update + end end - it 'updates cache' do + it 'updates redis cache and database' do expect_redis_update - - subject + does_db_update end end @@ -590,6 +595,11 @@ describe Ci::Runner do expect(redis).to receive(:set).with(redis_key, anything, any_args) end end + + def does_db_update + expect { subject }.to change { runner.reload.read_attribute(:contacted_at) } + .and change { runner.reload.read_attribute(:architecture) } + end end describe '#destroy' do diff --git a/spec/models/ci/stage_spec.rb b/spec/models/ci/stage_spec.rb index a00db1d2bfc..22a4556c10c 100644 --- a/spec/models/ci/stage_spec.rb +++ b/spec/models/ci/stage_spec.rb @@ -65,7 +65,31 @@ describe Ci::Stage, :models do end end - context 'when stage is skipped' do + context 'when stage has only created builds' do + let(:stage) { create(:ci_stage_entity, status: :created) } + + before do + create(:ci_build, :created, stage_id: stage.id) + end + + it 'updates status to skipped' do + expect(stage.reload.status).to eq 'created' + end + end + + context 'when stage is skipped because of skipped builds' do + before do + create(:ci_build, :skipped, stage_id: stage.id) + end + + it 'updates status to skipped' do + expect { stage.update_status } + .to change { stage.reload.status } + .to 'skipped' + end + end + + context 'when stage is skipped because is empty' do it 'updates status to skipped' do expect { stage.update_status } .to change { stage.reload.status } @@ -86,9 +110,85 @@ describe Ci::Stage, :models do expect(stage.reload).to be_failed end end + + context 'when statuses status was not recognized' do + before do + allow(stage) + .to receive_message_chain(:statuses, :latest, :status) + .and_return(:unknown) + end + + it 'raises an exception' do + expect { stage.update_status } + .to raise_error(HasStatus::UnknownStatusError) + end + end + end + + describe '#detailed_status' do + using RSpec::Parameterized::TableSyntax + + let(:user) { create(:user) } + let(:stage) { create(:ci_stage_entity, status: :created) } + subject { stage.detailed_status(user) } + + where(:statuses, :label) do + %w[created] | :created + %w[success] | :passed + %w[pending] | :pending + %w[skipped] | :skipped + %w[canceled] | :canceled + %w[success failed] | :failed + %w[running pending] | :running + end + + with_them do + before do + statuses.each do |status| + create(:commit_status, project: stage.project, + pipeline: stage.pipeline, + stage_id: stage.id, + status: status) + + stage.update_status + end + end + + it 'has a correct label' do + expect(subject.label).to eq label.to_s + end + end + + context 'when stage has warnings' do + before do + create(:ci_build, project: stage.project, + pipeline: stage.pipeline, + stage_id: stage.id, + status: :failed, + allow_failure: true) + + stage.update_status + end + + it 'is passed with warnings' do + expect(subject.label).to eq 'passed with warnings' + end + end end - describe '#index' do + describe '#groups' do + before do + create(:ci_build, stage_id: stage.id, name: 'rspec 0 1') + create(:ci_build, stage_id: stage.id, name: 'rspec 0 2') + end + + it 'groups stage builds by name' do + expect(stage.groups).to be_one + expect(stage.groups.first.name).to eq 'rspec' + end + end + + describe '#position' do context 'when stage has been imported and does not have position index set' do before do stage.update_column(:position, nil) @@ -119,4 +219,42 @@ describe Ci::Stage, :models do end end end + + context 'when stage has warnings' do + before do + create(:ci_build, :failed, :allowed_to_fail, stage_id: stage.id) + end + + describe '#has_warnings?' do + it 'returns true' do + expect(stage).to have_warnings + end + end + + describe '#number_of_warnings' do + it 'returns a lazy stage warnings counter' do + lazy_queries = ActiveRecord::QueryRecorder.new do + stage.number_of_warnings + end + + synced_queries = ActiveRecord::QueryRecorder.new do + stage.number_of_warnings.to_i + end + + expect(lazy_queries.count).to eq 0 + expect(synced_queries.count).to eq 1 + + expect(stage.number_of_warnings.inspect).to include 'BatchLoader' + expect(stage.number_of_warnings).to eq 1 + end + end + end + + context 'when stage does not have warnings' do + describe '#has_warnings?' do + it 'returns false' do + expect(stage).not_to have_warnings + end + end + end end diff --git a/spec/models/concerns/cache_markdown_field_spec.rb b/spec/models/concerns/cache_markdown_field_spec.rb index b3797c1fb46..2d75422ee68 100644 --- a/spec/models/concerns/cache_markdown_field_spec.rb +++ b/spec/models/concerns/cache_markdown_field_spec.rb @@ -156,7 +156,7 @@ describe CacheMarkdownField do end it { expect(thing.foo_html).to eq(updated_html) } - it { expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_REDCARPET_VERSION) } + it { expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_COMMONMARK_VERSION) } end describe '#cached_html_up_to_date?' do @@ -234,7 +234,7 @@ describe CacheMarkdownField do it 'returns default version when version is nil' do thing.cached_markdown_version = nil - is_expected.to eq(CacheMarkdownField::CACHE_REDCARPET_VERSION) + is_expected.to eq(CacheMarkdownField::CACHE_COMMONMARK_VERSION) end end @@ -261,7 +261,7 @@ describe CacheMarkdownField do thing.cached_markdown_version = nil thing.refresh_markdown_cache - expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_REDCARPET_VERSION) + expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_COMMONMARK_VERSION) end end @@ -346,7 +346,7 @@ describe CacheMarkdownField do expect(thing.foo_html).to eq(updated_html) expect(thing.baz_html).to eq(updated_html) - expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_REDCARPET_VERSION) + expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_COMMONMARK_VERSION) end end @@ -366,7 +366,7 @@ describe CacheMarkdownField do expect(thing.foo_html).to eq(updated_html) expect(thing.baz_html).to eq(updated_html) - expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_REDCARPET_VERSION) + expect(thing.cached_markdown_version).to eq(CacheMarkdownField::CACHE_COMMONMARK_VERSION) end end end diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index f83b52e8975..9fe1186a8c9 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -67,6 +67,30 @@ describe Group do end end + describe '#notification_settings', :nested_groups do + let(:user) { create(:user) } + let(:group) { create(:group) } + let(:sub_group) { create(:group, parent_id: group.id) } + + before do + group.add_developer(user) + sub_group.add_developer(user) + end + + it 'also gets notification settings from parent groups' do + expect(sub_group.notification_settings.size).to eq(2) + expect(sub_group.notification_settings).to include(group.notification_settings.first) + end + + context 'when sub group is deleted' do + it 'does not delete parent notification settings' do + expect do + sub_group.destroy + end.to change { NotificationSetting.count }.by(-1) + end + end + end + describe '#visibility_level_allowed_by_parent' do let(:parent) { create(:group, :internal) } let(:sub_group) { build(:group, parent_id: parent.id) } @@ -240,7 +264,7 @@ describe Group do it "is false if avatar is html page" do group.update_attribute(:avatar, 'uploads/avatar.html') - expect(group.avatar_type).to eq(["file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff"]) + expect(group.avatar_type).to eq(["file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico"]) end end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 65cc9372cbe..3f028b3bd5c 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -16,7 +16,11 @@ describe MergeRequest do describe '#squash_in_progress?' do shared_examples 'checking whether a squash is in progress' do - let(:repo_path) { subject.source_project.repository.path } + let(:repo_path) do + Gitlab::GitalyClient::StorageSettings.allow_disk_access do + subject.source_project.repository.path + end + end let(:squash_path) { File.join(repo_path, "gitlab-worktree", "squash-#{subject.id}") } before do @@ -2197,7 +2201,11 @@ describe MergeRequest do describe '#rebase_in_progress?' do shared_examples 'checking whether a rebase is in progress' do - let(:repo_path) { subject.source_project.repository.path } + let(:repo_path) do + Gitlab::GitalyClient::StorageSettings.allow_disk_access do + subject.source_project.repository.path + end + end let(:rebase_path) { File.join(repo_path, "gitlab-worktree", "rebase-#{subject.id}") } before do @@ -2237,25 +2245,25 @@ describe MergeRequest do end end - describe '#allow_maintainer_to_push' do + describe '#allow_collaboration' do let(:merge_request) do - build(:merge_request, source_branch: 'fixes', allow_maintainer_to_push: true) + build(:merge_request, source_branch: 'fixes', allow_collaboration: true) end it 'is false when pushing by a maintainer is not possible' do - expect(merge_request).to receive(:maintainer_push_possible?) { false } + expect(merge_request).to receive(:collaborative_push_possible?) { false } - expect(merge_request.allow_maintainer_to_push).to be_falsy + expect(merge_request.allow_collaboration).to be_falsy end it 'is true when pushing by a maintainer is possible' do - expect(merge_request).to receive(:maintainer_push_possible?) { true } + expect(merge_request).to receive(:collaborative_push_possible?) { true } - expect(merge_request.allow_maintainer_to_push).to be_truthy + expect(merge_request.allow_collaboration).to be_truthy end end - describe '#maintainer_push_possible?' do + describe '#collaborative_push_possible?' do let(:merge_request) do build(:merge_request, source_branch: 'fixes') end @@ -2267,14 +2275,14 @@ describe MergeRequest do it 'does not allow maintainer to push if the source project is the same as the target' do merge_request.target_project = merge_request.source_project = create(:project, :public) - expect(merge_request.maintainer_push_possible?).to be_falsy + expect(merge_request.collaborative_push_possible?).to be_falsy end it 'allows maintainer to push when both source and target are public' do merge_request.target_project = build(:project, :public) merge_request.source_project = build(:project, :public) - expect(merge_request.maintainer_push_possible?).to be_truthy + expect(merge_request.collaborative_push_possible?).to be_truthy end it 'is not available for protected branches' do @@ -2285,11 +2293,11 @@ describe MergeRequest do .with(merge_request.source_project, 'fixes') .and_return(true) - expect(merge_request.maintainer_push_possible?).to be_falsy + expect(merge_request.collaborative_push_possible?).to be_falsy end end - describe '#can_allow_maintainer_to_push?' do + describe '#can_allow_collaboration?' do let(:target_project) { create(:project, :public) } let(:source_project) { fork_project(target_project) } let(:merge_request) do @@ -2301,17 +2309,17 @@ describe MergeRequest do let(:user) { create(:user) } before do - allow(merge_request).to receive(:maintainer_push_possible?) { true } + allow(merge_request).to receive(:collaborative_push_possible?) { true } end it 'is false if the user does not have push access to the source project' do - expect(merge_request.can_allow_maintainer_to_push?(user)).to be_falsy + expect(merge_request.can_allow_collaboration?(user)).to be_falsy end it 'is true when the user has push access to the source project' do source_project.add_developer(user) - expect(merge_request.can_allow_maintainer_to_push?(user)).to be_truthy + expect(merge_request.can_allow_collaboration?(user)).to be_truthy end end diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index 6f702d8d95e..18b01c3e6b7 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -301,12 +301,18 @@ describe Namespace do end def project_rugged(project) - project.repository.rugged + Gitlab::GitalyClient::StorageSettings.allow_disk_access do + project.repository.rugged + end end end describe '#rm_dir', 'callback' do - let(:repository_storage_path) { Gitlab.config.repositories.storages.default.legacy_disk_path } + let(:repository_storage_path) do + Gitlab::GitalyClient::StorageSettings.allow_disk_access do + Gitlab.config.repositories.storages.default.legacy_disk_path + end + end let(:path_in_dir) { File.join(repository_storage_path, namespace.full_path) } let(:deleted_path) { namespace.full_path.gsub(namespace.path, "#{namespace.full_path}+#{namespace.id}+deleted") } let(:deleted_path_in_dir) { File.join(repository_storage_path, deleted_path) } diff --git a/spec/models/notification_recipient_spec.rb b/spec/models/notification_recipient_spec.rb index eda0e1da835..13fe47799ed 100644 --- a/spec/models/notification_recipient_spec.rb +++ b/spec/models/notification_recipient_spec.rb @@ -13,4 +13,48 @@ describe NotificationRecipient do expect(recipient.has_access?).to be_falsy end + + context '#notification_setting' do + context 'for child groups', :nested_groups do + let!(:moved_group) { create(:group) } + let(:group) { create(:group) } + let(:sub_group_1) { create(:group, parent: group) } + let(:sub_group_2) { create(:group, parent: sub_group_1) } + let(:project) { create(:project, namespace: moved_group) } + + before do + sub_group_2.add_owner(user) + moved_group.add_owner(user) + Groups::TransferService.new(moved_group, user).execute(sub_group_2) + + moved_group.reload + end + + context 'when notification setting is global' do + before do + user.notification_settings_for(group).global! + user.notification_settings_for(sub_group_1).mention! + user.notification_settings_for(sub_group_2).global! + user.notification_settings_for(moved_group).global! + end + + it 'considers notification setting from the first parent without global setting' do + expect(subject.notification_setting.source).to eq(sub_group_1) + end + end + + context 'when notification setting is not global' do + before do + user.notification_settings_for(group).global! + user.notification_settings_for(sub_group_1).mention! + user.notification_settings_for(sub_group_2).watch! + user.notification_settings_for(moved_group).disabled! + end + + it 'considers notification setting from lowest group member in hierarchy' do + expect(subject.notification_setting.source).to eq(moved_group) + end + end + end + end end diff --git a/spec/models/project_auto_devops_spec.rb b/spec/models/project_auto_devops_spec.rb index 7545c0797e9..749b2094787 100644 --- a/spec/models/project_auto_devops_spec.rb +++ b/spec/models/project_auto_devops_spec.rb @@ -5,6 +5,8 @@ describe ProjectAutoDevops do it { is_expected.to belong_to(:project) } + it { is_expected.to define_enum_for(:deploy_strategy) } + it { is_expected.to respond_to(:created_at) } it { is_expected.to respond_to(:updated_at) } @@ -67,8 +69,127 @@ describe ProjectAutoDevops do end end + context 'when deploy_strategy is manual' do + let(:domain) { 'example.com' } + + before do + auto_devops.deploy_strategy = 'manual' + end + + it do + expect(auto_devops.predefined_variables.map { |var| var[:key] }) + .to include("STAGING_ENABLED", "INCREMENTAL_ROLLOUT_ENABLED") + end + end + + context 'when deploy_strategy is continuous' do + let(:domain) { 'example.com' } + + before do + auto_devops.deploy_strategy = 'continuous' + end + + it do + expect(auto_devops.predefined_variables.map { |var| var[:key] }) + .not_to include("STAGING_ENABLED", "INCREMENTAL_ROLLOUT_ENABLED") + end + end + def domain_variable { key: 'AUTO_DEVOPS_DOMAIN', value: 'example.com', public: true } end end + + describe '#set_gitlab_deploy_token' do + let(:auto_devops) { build(:project_auto_devops, project: project) } + + context 'when the project is public' do + let(:project) { create(:project, :repository, :public) } + + it 'should not create a gitlab deploy token' do + expect do + auto_devops.save + end.not_to change { DeployToken.count } + end + end + + context 'when the project is internal' do + let(:project) { create(:project, :repository, :internal) } + + it 'should create a gitlab deploy token' do + expect do + auto_devops.save + end.to change { DeployToken.count }.by(1) + end + end + + context 'when the project is private' do + let(:project) { create(:project, :repository, :private) } + + it 'should create a gitlab deploy token' do + expect do + auto_devops.save + end.to change { DeployToken.count }.by(1) + end + end + + context 'when autodevops is enabled at project level' do + let(:project) { create(:project, :repository, :internal) } + let(:auto_devops) { build(:project_auto_devops, project: project) } + + it 'should create a deploy token' do + expect do + auto_devops.save + end.to change { DeployToken.count }.by(1) + end + end + + context 'when autodevops is enabled at instancel level' do + let(:project) { create(:project, :repository, :internal) } + let(:auto_devops) { build(:project_auto_devops, :disabled, project: project) } + + it 'should create a deploy token' do + allow(Gitlab::CurrentSettings).to receive(:auto_devops_enabled?).and_return(true) + + expect do + auto_devops.save + end.to change { DeployToken.count }.by(1) + end + end + + context 'when autodevops is disabled' do + let(:project) { create(:project, :repository, :internal) } + let(:auto_devops) { build(:project_auto_devops, :disabled, project: project) } + + it 'should not create a deploy token' do + expect do + auto_devops.save + end.not_to change { DeployToken.count } + end + end + + context 'when the project already has an active gitlab-deploy-token' do + let(:project) { create(:project, :repository, :internal) } + let!(:deploy_token) { create(:deploy_token, :gitlab_deploy_token, projects: [project]) } + let(:auto_devops) { build(:project_auto_devops, project: project) } + + it 'should not create a deploy token' do + expect do + auto_devops.save + end.not_to change { DeployToken.count } + end + end + + context 'when the project already has a revoked gitlab-deploy-token' do + let(:project) { create(:project, :repository, :internal) } + let!(:deploy_token) { create(:deploy_token, :gitlab_deploy_token, :expired, projects: [project]) } + let(:auto_devops) { build(:project_auto_devops, project: project) } + + it 'should not create a deploy token' do + expect do + auto_devops.save + end.not_to change { DeployToken.count } + end + end + end end diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index 54ef0be67ff..6c637533c6b 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' describe JiraService do include Gitlab::Routing + include AssetsHelpers describe '#options' do let(:service) do @@ -164,6 +165,8 @@ describe JiraService do it "creates Remote Link reference in JIRA for comment" do @jira_service.close_issue(merge_request, ExternalIssue.new("JIRA-123", project)) + favicon_path = "http://localhost/assets/#{find_asset('favicon.png').digest_path}" + # Creates comment expect(WebMock).to have_requested(:post, @comment_url) # Creates Remote Link in JIRA issue fields @@ -173,7 +176,7 @@ describe JiraService do object: { url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/commit/#{merge_request.diff_head_sha}", title: "GitLab: Solved by commit #{merge_request.diff_head_sha}.", - icon: { title: "GitLab", url16x16: "http://localhost/favicon.ico" }, + icon: { title: "GitLab", url16x16: favicon_path }, status: { resolved: true } } ) @@ -464,4 +467,18 @@ describe JiraService do end end end + + describe 'favicon urls', :request_store do + it 'includes the standard favicon' do + props = described_class.new.send(:build_remote_link_props, url: 'http://example.com', title: 'title') + expect(props[:object][:icon][:url16x16]).to match %r{^http://localhost/assets/favicon(?:-\h+).png$} + end + + it 'includes returns the custom favicon' do + create :appearance, favicon: fixture_file_upload('spec/fixtures/dk.png') + + props = described_class.new.send(:build_remote_link_props, url: 'http://example.com', title: 'title') + expect(props[:object][:icon][:url16x16]).to match %r{^http://localhost/uploads/-/system/appearance/favicon/\d+/dk.png$} + end + end end diff --git a/spec/models/project_services/microsoft_teams_service_spec.rb b/spec/models/project_services/microsoft_teams_service_spec.rb index 8d9ee96227f..3351c6280b4 100644 --- a/spec/models/project_services/microsoft_teams_service_spec.rb +++ b/spec/models/project_services/microsoft_teams_service_spec.rb @@ -225,10 +225,15 @@ describe MicrosoftTeamsService do it 'calls Microsoft Teams API for pipeline events' do data = Gitlab::DataBuilder::Pipeline.build(pipeline) + data[:markdown] = true chat_service.execute(data) - expect(WebMock).to have_requested(:post, webhook_url).once + message = ChatMessage::PipelineMessage.new(data) + + expect(WebMock).to have_requested(:post, webhook_url) + .with(body: hash_including({ summary: message.summary })) + .once end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 9a76452a808..a2f8fac2f38 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -238,20 +238,27 @@ describe Project do expect(project2.import_data).to be_nil end - it "does not allow blocked import_url localhost" do + it "does not allow import_url pointing to localhost" do project2 = build(:project, import_url: 'http://localhost:9000/t.git') expect(project2).to be_invalid expect(project2.errors[:import_url].first).to include('Requests to localhost are not allowed') end - it "does not allow blocked import_url port" do + it "does not allow import_url with invalid ports" do project2 = build(:project, import_url: 'http://github.com:25/t.git') expect(project2).to be_invalid expect(project2.errors[:import_url].first).to include('Only allowed ports are 22, 80, 443') end + it "does not allow import_url with invalid user" do + project2 = build(:project, import_url: 'http://$user:password@github.com/t.git') + + expect(project2).to be_invalid + expect(project2.errors[:import_url].first).to include('Username needs to start with an alphanumeric character') + end + describe 'project pending deletion' do let!(:project_pending_deletion) do create(:project, @@ -960,7 +967,7 @@ describe Project do it 'is false if avatar is html page' do project.update_attribute(:avatar, 'uploads/avatar.html') - expect(project.avatar_type).to eq(['file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff']) + expect(project.avatar_type).to eq(['file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico']) end end @@ -1693,6 +1700,31 @@ describe Project do end end + describe '#human_import_status_name' do + context 'when import_state exists' do + it 'returns the humanized status name' do + project = create(:project) + create(:import_state, :started, project: project) + + expect(project.human_import_status_name).to eq("started") + end + end + + context 'when import_state was not created yet' do + let(:project) { create(:project, :import_started) } + + it 'ensures import_state is created and returns humanized status name' do + expect do + project.human_import_status_name + end.to change { ProjectImportState.count }.from(0).to(1) + end + + it 'returns humanized status name' do + expect(project.human_import_status_name).to eq("started") + end + end + end + describe 'Project import job' do let(:project) { create(:project, import_url: generate(:url)) } @@ -1701,7 +1733,11 @@ describe Project do .with(project.repository_storage, project.disk_path, project.import_url) .and_return(true) - expect_any_instance_of(Repository).to receive(:after_import) + # Works around https://github.com/rspec/rspec-mocks/issues/910 + allow(described_class).to receive(:find).with(project.id).and_return(project) + expect(project.repository).to receive(:after_import) + .and_call_original + expect(project.wiki.repository).to receive(:after_import) .and_call_original end @@ -2303,6 +2339,22 @@ describe Project do end end + describe '#any_lfs_file_locks?', :request_store do + set(:project) { create(:project) } + + it 'returns false when there are no LFS file locks' do + expect(project.any_lfs_file_locks?).to be_falsey + end + + it 'returns a cached true when there are LFS file locks' do + create(:lfs_file_lock, project: project) + + expect(project.lfs_file_locks).to receive(:any?).once.and_call_original + + 2.times { expect(project.any_lfs_file_locks?).to be_truthy } + end + end + describe '#protected_for?' do let(:project) { create(:project) } @@ -2907,7 +2959,7 @@ describe Project do project.rename_repo - expect(project.repository.rugged.config['gitlab.fullpath']).to eq(project.full_path) + expect(rugged_config['gitlab.fullpath']).to eq(project.full_path) end end @@ -3068,7 +3120,7 @@ describe Project do it 'updates project full path in .git/config' do project.rename_repo - expect(project.repository.rugged.config['gitlab.fullpath']).to eq(project.full_path) + expect(rugged_config['gitlab.fullpath']).to eq(project.full_path) end end @@ -3366,10 +3418,11 @@ describe Project do end describe '#after_import' do - let(:project) { build(:project) } + let(:project) { create(:project) } it 'runs the correct hooks' do expect(project.repository).to receive(:after_import) + expect(project.wiki.repository).to receive(:after_import) expect(project).to receive(:import_finish) expect(project).to receive(:update_project_counter_caches) expect(project).to receive(:remove_import_jid) @@ -3488,13 +3541,13 @@ describe Project do it 'writes full path in .git/config when key is missing' do project.write_repository_config - expect(project.repository.rugged.config['gitlab.fullpath']).to eq project.full_path + expect(rugged_config['gitlab.fullpath']).to eq project.full_path end it 'updates full path in .git/config when key is present' do project.write_repository_config(gl_full_path: 'old/path') - expect { project.write_repository_config }.to change { project.repository.rugged.config['gitlab.fullpath'] }.from('old/path').to(project.full_path) + expect { project.write_repository_config }.to change { rugged_config['gitlab.fullpath'] }.from('old/path').to(project.full_path) end it 'does not raise an error with an empty repository' do @@ -3583,7 +3636,7 @@ describe Project do target_branch: 'target-branch', source_project: project, source_branch: 'awesome-feature-1', - allow_maintainer_to_push: true + allow_collaboration: true ) end @@ -3620,9 +3673,14 @@ describe Project do end end - describe '#branch_allows_maintainer_push?' do + describe '#branch_allows_collaboration_push?' do it 'allows access if the user can merge the merge request' do - expect(project.branch_allows_maintainer_push?(user, 'awesome-feature-1')) + expect(project.branch_allows_collaboration?(user, 'awesome-feature-1')) + .to be_truthy + end + + it 'allows access when there are merge requests open but no branch name is given' do + expect(project.branch_allows_collaboration?(user, nil)) .to be_truthy end @@ -3630,7 +3688,7 @@ describe Project do guest = create(:user) target_project.add_guest(guest) - expect(project.branch_allows_maintainer_push?(guest, 'awesome-feature-1')) + expect(project.branch_allows_collaboration?(guest, 'awesome-feature-1')) .to be_falsy end @@ -3640,31 +3698,31 @@ describe Project do target_branch: 'target-branch', source_project: project, source_branch: 'rejected-feature-1', - allow_maintainer_to_push: true) + allow_collaboration: true) - expect(project.branch_allows_maintainer_push?(user, 'rejected-feature-1')) + expect(project.branch_allows_collaboration?(user, 'rejected-feature-1')) .to be_falsy end it 'does not allow access if the user cannot merge the merge request' do create(:protected_branch, :masters_can_push, project: target_project, name: 'target-branch') - expect(project.branch_allows_maintainer_push?(user, 'awesome-feature-1')) + expect(project.branch_allows_collaboration?(user, 'awesome-feature-1')) .to be_falsy end it 'caches the result' do - control = ActiveRecord::QueryRecorder.new { project.branch_allows_maintainer_push?(user, 'awesome-feature-1') } + control = ActiveRecord::QueryRecorder.new { project.branch_allows_collaboration?(user, 'awesome-feature-1') } - expect { 3.times { project.branch_allows_maintainer_push?(user, 'awesome-feature-1') } } + expect { 3.times { project.branch_allows_collaboration?(user, 'awesome-feature-1') } } .not_to exceed_query_limit(control) end context 'when the requeststore is active', :request_store do it 'only queries per project across instances' do - control = ActiveRecord::QueryRecorder.new { project.branch_allows_maintainer_push?(user, 'awesome-feature-1') } + control = ActiveRecord::QueryRecorder.new { project.branch_allows_collaboration?(user, 'awesome-feature-1') } - expect { 2.times { described_class.find(project.id).branch_allows_maintainer_push?(user, 'awesome-feature-1') } } + expect { 2.times { described_class.find(project.id).branch_allows_collaboration?(user, 'awesome-feature-1') } } .not_to exceed_query_limit(control).with_threshold(2) end end @@ -3775,4 +3833,10 @@ describe Project do let(:uploader_class) { AttachmentUploader } end end + + def rugged_config + Gitlab::GitalyClient::StorageSettings.allow_disk_access do + project.repository.rugged.config + end + end end diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb index e07c522800a..9978f3e9566 100644 --- a/spec/models/project_team_spec.rb +++ b/spec/models/project_team_spec.rb @@ -179,14 +179,14 @@ describe ProjectTeam do end describe "#human_max_access" do - it 'returns Master role' do + it 'returns Maintainer role' do user = create(:user) group = create(:group) project = create(:project, namespace: group) group.add_master(user) - expect(project.team.human_max_access(user.id)).to eq 'Master' + expect(project.team.human_max_access(user.id)).to eq 'Maintainer' end it 'returns Owner role' do diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb index f1142832f1a..a3c20b3b3c1 100644 --- a/spec/models/project_wiki_spec.rb +++ b/spec/models/project_wiki_spec.rb @@ -188,7 +188,11 @@ describe ProjectWiki do before do subject.wiki # Make sure the wiki repo exists - BareRepoOperations.new(subject.repository.path_to_repo).commit_file(image, 'image.png') + repo_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do + subject.repository.path_to_repo + end + + BareRepoOperations.new(repo_path).commit_file(image, 'image.png') end it 'returns the latest version of the file if it exists' do diff --git a/spec/models/remote_mirror_spec.rb b/spec/models/remote_mirror_spec.rb index 1d94abe4195..3597b080021 100644 --- a/spec/models/remote_mirror_spec.rb +++ b/spec/models/remote_mirror_spec.rb @@ -15,6 +15,13 @@ describe RemoteMirror do expect(remote_mirror).not_to be_valid end + + it 'does not allow url with an invalid user' do + remote_mirror = build(:remote_mirror, url: 'http://$user:password@invalid.invalid') + + expect(remote_mirror).to be_invalid + expect(remote_mirror.errors[:url].first).to include('Username needs to start with an alphanumeric character') + end end end @@ -67,7 +74,9 @@ describe RemoteMirror do mirror.update_attribute(:url, 'http://foo:baz@test.com') - config = repo.raw_repository.rugged.config + config = Gitlab::GitalyClient::StorageSettings.allow_disk_access do + repo.raw_repository.rugged.config + end expect(config["remote.#{mirror.remote_name}.url"]).to eq('http://foo:baz@test.com') end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 0ccf55bd895..b6df048d4ca 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -136,7 +136,10 @@ describe Repository do before do options = { message: 'test tag message\n', tagger: { name: 'John Smith', email: 'john@gmail.com' } } - repository.rugged.tags.create(annotated_tag_name, 'a48e4fc218069f68ef2e769dd8dfea3991362175', options) + + Gitlab::GitalyClient::StorageSettings.allow_disk_access do + repository.rugged.tags.create(annotated_tag_name, 'a48e4fc218069f68ef2e769dd8dfea3991362175', options) + end double_first = double(committed_date: Time.now - 1.second) double_last = double(committed_date: Time.now) @@ -1048,6 +1051,13 @@ describe Repository do let(:target_project) { project } let(:target_repository) { target_project.repository } + around do |example| + # TODO Gitlab::Git::OperationService will be moved to gitaly-ruby and disappear from this repo + Gitlab::GitalyClient::StorageSettings.allow_disk_access do + example.run + end + end + context 'when pre hooks were successful' do before do service = Gitlab::Git::HooksService.new @@ -1185,7 +1195,7 @@ describe Repository do Gitlab::Git::OperationService.new(git_user, repository.raw_repository).with_branch('feature') do new_rev end - end.to raise_error(Gitlab::Git::HooksService::PreReceiveError) + end.to raise_error(Gitlab::Git::PreReceiveError) end end @@ -1309,6 +1319,13 @@ describe Repository do end describe '#update_autocrlf_option' do + around do |example| + # TODO Gitlab::Git::OperationService will be moved to gitaly-ruby and disappear from this repo + Gitlab::GitalyClient::StorageSettings.allow_disk_access do + example.run + end + end + describe 'when autocrlf is not already set to :input' do before do repository.raw_repository.autocrlf = true @@ -1802,7 +1819,9 @@ describe Repository do expect(repository.branch_count).to be_an(Integer) # NOTE: Until rugged goes away, make sure rugged and gitaly are in sync - rugged_count = repository.raw_repository.rugged.branches.count + rugged_count = Gitlab::GitalyClient::StorageSettings.allow_disk_access do + repository.raw_repository.rugged.branches.count + end expect(repository.branch_count).to eq(rugged_count) end @@ -1813,7 +1832,9 @@ describe Repository do expect(repository.tag_count).to be_an(Integer) # NOTE: Until rugged goes away, make sure rugged and gitaly are in sync - rugged_count = repository.raw_repository.rugged.tags.count + rugged_count = Gitlab::GitalyClient::StorageSettings.allow_disk_access do + repository.raw_repository.rugged.tags.count + end expect(repository.tag_count).to eq(rugged_count) end @@ -1917,13 +1938,13 @@ describe Repository do context 'when pre hooks failed' do before do allow_any_instance_of(Gitlab::GitalyClient::OperationService) - .to receive(:user_delete_branch).and_raise(Gitlab::Git::HooksService::PreReceiveError) + .to receive(:user_delete_branch).and_raise(Gitlab::Git::PreReceiveError) end it 'gets an error and does not delete the branch' do expect do repository.rm_branch(user, 'feature') - end.to raise_error(Gitlab::Git::HooksService::PreReceiveError) + end.to raise_error(Gitlab::Git::PreReceiveError) expect(repository.find_branch('feature')).not_to be_nil end @@ -1959,7 +1980,7 @@ describe Repository do expect do repository.rm_branch(user, 'feature') - end.to raise_error(Gitlab::Git::HooksService::PreReceiveError) + end.to raise_error(Gitlab::Git::PreReceiveError) end it 'does not delete the branch' do @@ -1967,7 +1988,7 @@ describe Repository do expect do repository.rm_branch(user, 'feature') - end.to raise_error(Gitlab::Git::HooksService::PreReceiveError) + end.to raise_error(Gitlab::Git::PreReceiveError) expect(repository.find_branch('feature')).not_to be_nil end end @@ -2073,7 +2094,10 @@ describe Repository do it "attempting to call keep_around on truncated ref does not fail" do repository.keep_around(sample_commit.id) ref = repository.send(:keep_around_ref_name, sample_commit.id) - path = File.join(repository.path, ref) + + path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do + File.join(repository.path, ref) + end # Corrupt the reference File.truncate(path, 0) @@ -2088,6 +2112,13 @@ describe Repository do end describe '#update_ref' do + around do |example| + # TODO Gitlab::Git::OperationService will be moved to gitaly-ruby and disappear from this repo + Gitlab::GitalyClient::StorageSettings.allow_disk_access do + example.run + end + end + it 'can create a ref' do Gitlab::Git::OperationService.new(nil, repository.raw_repository).send(:update_ref, 'refs/heads/foobar', 'refs/heads/master', Gitlab::Git::BLANK_SHA) @@ -2372,7 +2403,9 @@ describe Repository do end def create_remote_branch(remote_name, branch_name, target) - rugged = repository.rugged + rugged = Gitlab::GitalyClient::StorageSettings.allow_disk_access do + repository.rugged + end rugged.references.create("refs/remotes/#{remote_name}/#{branch_name}", target.id) end @@ -2410,6 +2443,32 @@ describe Repository do end end + describe '#archive_metadata' do + let(:ref) { 'master' } + let(:storage_path) { '/tmp' } + + let(:prefix) { [project.path, ref].join('-') } + let(:filename) { prefix + '.tar.gz' } + + subject(:result) { repository.archive_metadata(ref, storage_path, append_sha: false) } + + context 'with hashed storage disabled' do + let(:project) { create(:project, :repository, :legacy_storage) } + + it 'uses the project path to generate the filename' do + expect(result['ArchivePrefix']).to eq(prefix) + expect(File.basename(result['ArchivePath'])).to eq(filename) + end + end + + context 'with hashed storage enabled' do + it 'uses the project path to generate the filename' do + expect(result['ArchivePrefix']).to eq(prefix) + expect(File.basename(result['ArchivePath'])).to eq(filename) + end + end + end + describe 'commit cache' do set(:project) { create(:project, :repository) } diff --git a/spec/models/term_agreement_spec.rb b/spec/models/term_agreement_spec.rb index a59bf119692..950dfa09a6a 100644 --- a/spec/models/term_agreement_spec.rb +++ b/spec/models/term_agreement_spec.rb @@ -5,4 +5,13 @@ describe TermAgreement do it { is_expected.to validate_presence_of(:term) } it { is_expected.to validate_presence_of(:user) } end + + describe '.accepted' do + it 'only includes accepted terms' do + accepted = create(:term_agreement, :accepted) + create(:term_agreement, :declined) + + expect(described_class.accepted).to contain_exactly(accepted) + end + end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 09dfeae6377..097144d04ce 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1260,7 +1260,7 @@ describe User do it 'is false if avatar is html page' do user.update_attribute(:avatar, 'uploads/avatar.html') - expect(user.avatar_type).to eq(['file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff']) + expect(user.avatar_type).to eq(['file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico']) end end |