diff options
Diffstat (limited to 'spec/models/project_spec.rb')
-rw-r--r-- | spec/models/project_spec.rb | 258 |
1 files changed, 127 insertions, 131 deletions
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 59a2560ca06..f2b4e9070b4 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -22,6 +22,7 @@ describe Project, models: true do it { is_expected.to have_many(:protected_branches).dependent(:destroy) } it { is_expected.to have_one(:forked_project_link).dependent(:destroy) } it { is_expected.to have_one(:slack_service).dependent(:destroy) } + it { is_expected.to have_one(:microsoft_teams_service).dependent(:destroy) } it { is_expected.to have_one(:mattermost_service).dependent(:destroy) } it { is_expected.to have_one(:pushover_service).dependent(:destroy) } it { is_expected.to have_one(:asana_service).dependent(:destroy) } @@ -57,6 +58,7 @@ describe Project, models: true do it { is_expected.to have_many(:builds) } it { is_expected.to have_many(:runner_projects) } it { is_expected.to have_many(:runners) } + it { is_expected.to have_many(:active_runners) } it { is_expected.to have_many(:variables) } it { is_expected.to have_many(:triggers) } it { is_expected.to have_many(:pages_domains) } @@ -71,6 +73,7 @@ describe Project, models: true do it { is_expected.to have_many(:notification_settings).dependent(:destroy) } it { is_expected.to have_many(:forks).through(:forked_project_links) } it { is_expected.to have_many(:uploads).dependent(:destroy) } + it { is_expected.to have_many(:pipeline_schedules).dependent(:destroy) } context 'after initialized' do it "has a project_feature" do @@ -251,6 +254,34 @@ describe Project, models: true do expect(new_project.errors.full_messages.first).to eq('The project is still being deleted. Please try again later.') end end + + describe 'path validation' do + it 'allows paths reserved on the root namespace' do + project = build(:project, path: 'api') + + expect(project).to be_valid + end + + it 'rejects paths reserved on another level' do + project = build(:project, path: 'tree') + + expect(project).not_to be_valid + end + + it 'rejects nested paths' do + parent = create(:group, :nested, path: 'environments') + project = build(:project, path: 'folders', namespace: parent) + + expect(project).not_to be_valid + end + + it 'allows a reserved group name' do + parent = create(:group) + project = build(:project, path: 'avatar', namespace: parent) + + expect(project).to be_valid + end + end end describe 'default_scope' do @@ -702,25 +733,6 @@ describe Project, models: true do end end - describe '#open_branches' do - let(:project) { create(:project, :repository) } - - before do - project.protected_branches.create(name: 'master') - end - - it { expect(project.open_branches.map(&:name)).to include('feature') } - it { expect(project.open_branches.map(&:name)).not_to include('master') } - - it "includes branches matching a protected branch wildcard" do - expect(project.open_branches.map(&:name)).to include('feature') - - create(:protected_branch, name: 'feat*', project: project) - - expect(Project.find(project.id).open_branches.map(&:name)).to include('feature') - end - end - describe '#star_count' do it 'counts stars from multiple users' do user1 = create :user @@ -798,17 +810,19 @@ describe Project, models: true do let(:project) { create(:empty_project) } - context 'When avatar file is uploaded' do - before do - project.update_columns(avatar: 'uploads/avatar.png') - allow(project.avatar).to receive(:present?) { true } - end + context 'when avatar file is uploaded' do + let(:project) { create(:empty_project, :with_avatar) } + let(:avatar_path) { "/uploads/project/avatar/#{project.id}/dk.png" } + let(:gitlab_host) { "http://#{Gitlab.config.gitlab.host}" } - let(:avatar_path) do - "/uploads/project/avatar/#{project.id}/uploads/avatar.png" - end + it 'shows correct url' do + expect(project.avatar_url).to eq(avatar_path) + expect(project.avatar_url(only_path: false)).to eq([gitlab_host, avatar_path].join) - it { should eq "http://#{Gitlab.config.gitlab.host}#{avatar_path}" } + allow(ActionController::Base).to receive(:asset_host).and_return(gitlab_host) + + expect(project.avatar_url).to eq([gitlab_host, avatar_path].join) + end end context 'When avatar file in git' do @@ -816,9 +830,7 @@ describe Project, models: true do allow(project).to receive(:avatar_in_git) { true } end - let(:avatar_path) do - "/#{project.full_path}/avatar" - end + let(:avatar_path) { "/#{project.full_path}/avatar" } it { should eq "http://#{Gitlab.config.gitlab.host}#{avatar_path}" } end @@ -961,7 +973,7 @@ describe Project, models: true do before do storages = { 'default' => { 'path' => 'tmp/tests/repositories' }, - 'picked' => { 'path' => 'tmp/tests/repositories' }, + 'picked' => { 'path' => 'tmp/tests/repositories' } } allow(Gitlab.config.repositories).to receive(:storages).and_return(storages) end @@ -1157,11 +1169,12 @@ describe Project, models: true do # Project#gitlab_shell returns a new instance of Gitlab::Shell on every # call. This makes testing a bit easier. allow(project).to receive(:gitlab_shell).and_return(gitlab_shell) - allow(project).to receive(:previous_changes).and_return('path' => ['foo']) end it 'renames a repository' do + stub_container_registry_config(enabled: false) + expect(gitlab_shell).to receive(:mv_repository). ordered. with(project.repository_storage_path, "#{project.namespace.full_path}/foo", "#{project.full_path}"). @@ -1185,10 +1198,13 @@ describe Project, models: true do project.rename_repo end - context 'container registry with tags' do + context 'container registry with images' do + let(:container_repository) { create(:container_repository) } + before do stub_container_registry_config(enabled: true) - stub_container_registry_tags('tag') + stub_container_registry_tags(repository: :any, tags: ['tag']) + project.container_repositories << container_repository end subject { project.rename_repo } @@ -1291,62 +1307,6 @@ describe Project, models: true do end end - describe '#protected_branch?' do - context 'existing project' do - let(:project) { create(:project, :repository) } - - it 'returns true when the branch matches a protected branch via direct match' do - create(:protected_branch, project: project, name: "foo") - - expect(project.protected_branch?('foo')).to eq(true) - end - - it 'returns true when the branch matches a protected branch via wildcard match' do - create(:protected_branch, project: project, name: "production/*") - - expect(project.protected_branch?('production/some-branch')).to eq(true) - end - - it 'returns false when the branch does not match a protected branch via direct match' do - expect(project.protected_branch?('foo')).to eq(false) - end - - it 'returns false when the branch does not match a protected branch via wildcard match' do - create(:protected_branch, project: project, name: "production/*") - - expect(project.protected_branch?('staging/some-branch')).to eq(false) - end - end - - context "new project" do - let(:project) { create(:empty_project) } - - it 'returns false when default_protected_branch is unprotected' do - stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_NONE) - - expect(project.protected_branch?('master')).to be false - end - - it 'returns false when default_protected_branch lets developers push' do - stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_DEV_CAN_PUSH) - - expect(project.protected_branch?('master')).to be false - end - - it 'returns true when default_branch_protection does not let developers push but let developer merge branches' do - stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_DEV_CAN_MERGE) - - expect(project.protected_branch?('master')).to be true - end - - it 'returns true when default_branch_protection is in full protection' do - stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_FULL) - - expect(project.protected_branch?('master')).to be true - end - end - end - describe '#user_can_push_to_empty_repo?' do let(:project) { create(:empty_project) } let(:user) { create(:user) } @@ -1386,38 +1346,17 @@ describe Project, models: true do end end - describe '#container_registry_path_with_namespace' do - let(:project) { create(:empty_project, path: 'PROJECT') } - - subject { project.container_registry_path_with_namespace } - - it { is_expected.not_to eq(project.path_with_namespace) } - it { is_expected.to eq(project.path_with_namespace.downcase) } - end - - describe '#container_registry_repository' do + describe '#container_registry_url' do let(:project) { create(:empty_project) } - before { stub_container_registry_config(enabled: true) } - - subject { project.container_registry_repository } - - it { is_expected.not_to be_nil } - end - - describe '#container_registry_repository_url' do - let(:project) { create(:empty_project) } - - subject { project.container_registry_repository_url } + subject { project.container_registry_url } before { stub_container_registry_config(**registry_settings) } context 'for enabled registry' do let(:registry_settings) do - { - enabled: true, - host_port: 'example.com', - } + { enabled: true, + host_port: 'example.com' } end it { is_expected.not_to be_nil } @@ -1425,9 +1364,7 @@ describe Project, models: true do context 'for disabled registry' do let(:registry_settings) do - { - enabled: false - } + { enabled: false } end it { is_expected.to be_nil } @@ -1437,28 +1374,60 @@ describe Project, models: true do describe '#has_container_registry_tags?' do let(:project) { create(:empty_project) } - subject { project.has_container_registry_tags? } - - context 'for enabled registry' do + context 'when container registry is enabled' do before { stub_container_registry_config(enabled: true) } - context 'with tags' do - before { stub_container_registry_tags('test', 'test2') } + context 'when tags are present for multi-level registries' do + before do + create(:container_repository, project: project, name: 'image') + + stub_container_registry_tags(repository: /image/, + tags: %w[latest rc1]) + end - it { is_expected.to be_truthy } + it 'should have image tags' do + expect(project).to have_container_registry_tags + end end - context 'when no tags' do - before { stub_container_registry_tags } + context 'when tags are present for root repository' do + before do + stub_container_registry_tags(repository: project.full_path, + tags: %w[latest rc1 pre1]) + end - it { is_expected.to be_falsey } + it 'should have image tags' do + expect(project).to have_container_registry_tags + end + end + + context 'when there are no tags at all' do + before do + stub_container_registry_tags(repository: :any, tags: []) + end + + it 'should not have image tags' do + expect(project).not_to have_container_registry_tags + end end end - context 'for disabled registry' do + context 'when container registry is disabled' do before { stub_container_registry_config(enabled: false) } - it { is_expected.to be_falsey } + it 'should not have image tags' do + expect(project).not_to have_container_registry_tags + end + + it 'should not check root repository tags' do + expect(project).not_to receive(:full_path) + expect(project).not_to have_container_registry_tags + end + + it 'should iterate through container repositories' do + expect(project).to receive(:container_repositories) + expect(project).not_to have_container_registry_tags + end end end @@ -1934,11 +1903,38 @@ describe Project, models: true do describe '#pipeline_status' do let(:project) { create(:project) } it 'builds a pipeline status' do - expect(project.pipeline_status).to be_a(Ci::PipelineStatus) + expect(project.pipeline_status).to be_a(Gitlab::Cache::Ci::ProjectPipelineStatus) end it 'hase a loaded pipeline status' do expect(project.pipeline_status).to be_loaded end end + + describe '#append_or_update_attribute' do + let(:project) { create(:project) } + + it 'shows full error updating an invalid MR' do + error_message = 'Failed to replace merge_requests because one or more of the new records could not be saved.'\ + ' Validate fork Source project is not a fork of the target project' + + expect { project.append_or_update_attribute(:merge_requests, [create(:merge_request)]) }. + to raise_error(ActiveRecord::RecordNotSaved, error_message) + end + + it 'updates the project succesfully' do + merge_request = create(:merge_request, target_project: project, source_project: project) + + expect { project.append_or_update_attribute(:merge_requests, [merge_request]) }. + not_to raise_error + end + end + + describe '#last_repository_updated_at' do + it 'sets to created_at upon creation' do + project = create(:empty_project, created_at: 2.hours.ago) + + expect(project.last_repository_updated_at.to_i).to eq(project.created_at.to_i) + end + end end |