diff options
Diffstat (limited to 'spec/models/project_spec.rb')
-rw-r--r-- | spec/models/project_spec.rb | 225 |
1 files changed, 182 insertions, 43 deletions
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 63333b7af1f..f50b4aea411 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -143,6 +143,10 @@ describe Project, models: true do it { is_expected.to validate_length_of(:description).is_at_most(2000) } + it { is_expected.to validate_length_of(:ci_config_path).is_at_most(255) } + it { is_expected.to allow_value('').for(:ci_config_path) } + it { is_expected.not_to allow_value('test/../foo').for(:ci_config_path) } + it { is_expected.to validate_presence_of(:creator) } it { is_expected.to validate_presence_of(:namespace) } @@ -284,15 +288,6 @@ describe Project, models: true do end end - describe 'default_scope' do - it 'excludes projects pending deletion from the results' do - project = create(:empty_project) - create(:empty_project, pending_delete: true) - - expect(Project.all).to eq [project] - end - end - describe 'project token' do it 'sets an random token if none provided' do project = FactoryGirl.create :empty_project, runners_token: '' @@ -832,13 +827,13 @@ describe Project, models: true do let(:avatar_path) { "/#{project.full_path}/avatar" } - it { should eq "http://#{Gitlab.config.gitlab.host}#{avatar_path}" } + it { is_expected.to eq "http://#{Gitlab.config.gitlab.host}#{avatar_path}" } end context 'when git repo is empty' do let(:project) { create(:empty_project) } - it { should eq nil } + it { is_expected.to eq nil } end end @@ -1179,6 +1174,16 @@ describe Project, models: true do expect(relation.search(project.namespace.name)).to eq([project]) end + + describe 'with pending_delete project' do + let(:pending_delete_project) { create(:empty_project, pending_delete: true) } + + it 'shows pending deletion project' do + search_result = described_class.search(pending_delete_project.name) + + expect(search_result).to eq([pending_delete_project]) + end + end end describe '#rename_repo' do @@ -1195,26 +1200,28 @@ describe Project, models: true do 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}"). - and_return(true) + expect(gitlab_shell).to receive(:mv_repository) + .ordered + .with(project.repository_storage_path, "#{project.namespace.full_path}/foo", "#{project.full_path}") + .and_return(true) - expect(gitlab_shell).to receive(:mv_repository). - ordered. - with(project.repository_storage_path, "#{project.namespace.full_path}/foo.wiki", "#{project.full_path}.wiki"). - and_return(true) + expect(gitlab_shell).to receive(:mv_repository) + .ordered + .with(project.repository_storage_path, "#{project.namespace.full_path}/foo.wiki", "#{project.full_path}.wiki") + .and_return(true) - expect_any_instance_of(SystemHooksService). - to receive(:execute_hooks_for). - with(project, :rename) + expect_any_instance_of(SystemHooksService) + .to receive(:execute_hooks_for) + .with(project, :rename) - expect_any_instance_of(Gitlab::UploadsTransfer). - to receive(:rename_project). - with('foo', project.path, project.namespace.full_path) + expect_any_instance_of(Gitlab::UploadsTransfer) + .to receive(:rename_project) + .with('foo', project.path, project.namespace.full_path) expect(project).to receive(:expire_caches_before_rename) + expect(project).to receive(:expires_full_path_cache) + project.rename_repo end @@ -1239,13 +1246,13 @@ describe Project, models: true do let(:wiki) { double(:wiki, exists?: true) } it 'expires the caches of the repository and wiki' do - allow(Repository).to receive(:new). - with('foo', project). - and_return(repo) + allow(Repository).to receive(:new) + .with('foo', project) + .and_return(repo) - allow(Repository).to receive(:new). - with('foo.wiki', project). - and_return(wiki) + allow(Repository).to receive(:new) + .with('foo.wiki', project) + .and_return(wiki) expect(repo).to receive(:before_delete) expect(wiki).to receive(:before_delete) @@ -1296,9 +1303,9 @@ describe Project, models: true do context 'using a regular repository' do it 'creates the repository' do - expect(shell).to receive(:add_repository). - with(project.repository_storage_path, project.path_with_namespace). - and_return(true) + expect(shell).to receive(:add_repository) + .with(project.repository_storage_path, project.path_with_namespace) + .and_return(true) expect(project.repository).to receive(:after_create) @@ -1306,9 +1313,9 @@ describe Project, models: true do end it 'adds an error if the repository could not be created' do - expect(shell).to receive(:add_repository). - with(project.repository_storage_path, project.path_with_namespace). - and_return(false) + expect(shell).to receive(:add_repository) + .with(project.repository_storage_path, project.path_with_namespace) + .and_return(false) expect(project.repository).not_to receive(:after_create) @@ -1327,6 +1334,50 @@ describe Project, models: true do end end + describe '#ensure_repository' do + let(:project) { create(:project, :repository) } + let(:shell) { Gitlab::Shell.new } + + before do + allow(project).to receive(:gitlab_shell).and_return(shell) + end + + it 'creates the repository if it not exist' do + allow(project).to receive(:repository_exists?) + .and_return(false) + + allow(shell).to receive(:add_repository) + .with(project.repository_storage_path, project.path_with_namespace) + .and_return(true) + + expect(project).to receive(:create_repository).with(force: true) + + project.ensure_repository + end + + it 'does not create the repository if it exists' do + allow(project).to receive(:repository_exists?) + .and_return(true) + + expect(project).not_to receive(:create_repository) + + project.ensure_repository + end + + it 'creates the repository if it is a fork' do + expect(project).to receive(:forked?).and_return(true) + + allow(project).to receive(:repository_exists?) + .and_return(false) + + expect(shell).to receive(:add_repository) + .with(project.repository_storage_path, project.path_with_namespace) + .and_return(true) + + project.ensure_repository + end + end + describe '#user_can_push_to_empty_repo?' do let(:project) { create(:empty_project) } let(:user) { create(:user) } @@ -1457,6 +1508,28 @@ describe Project, models: true do end end + describe '#ci_config_path=' do + let(:project) { create(:empty_project) } + + it 'sets nil' do + project.update!(ci_config_path: nil) + + expect(project.ci_config_path).to be_nil + end + + it 'sets a string' do + project.update!(ci_config_path: 'foo/.gitlab_ci.yml') + + expect(project.ci_config_path).to eq('foo/.gitlab_ci.yml') + end + + it 'sets a string but removes all leading slashes and null characters' do + project.update!(ci_config_path: "///f\0oo/\0/.gitlab_ci.yml") + + expect(project.ci_config_path).to eq('foo//.gitlab_ci.yml') + end + end + describe 'Project import job' do let(:project) { create(:empty_project, import_url: generate(:url)) } @@ -1478,6 +1551,40 @@ describe Project, models: true do end end + describe 'project import state transitions' do + context 'state transition: [:started] => [:finished]' do + let(:housekeeping_service) { spy } + + before do + allow(Projects::HousekeepingService).to receive(:new) { housekeeping_service } + end + + it 'performs housekeeping when an import of a fresh project is completed' do + project = create(:project_empty_repo, :import_started, import_type: :github) + + project.import_finish + + expect(housekeeping_service).to have_received(:execute) + end + + it 'does not perform housekeeping when project repository does not exist' do + project = create(:empty_project, :import_started, import_type: :github) + + project.import_finish + + expect(housekeeping_service).not_to have_received(:execute) + end + + it 'does not perform housekeeping when project does not have a valid import type' do + project = create(:empty_project, :import_started, import_type: nil) + + project.import_finish + + expect(housekeeping_service).not_to have_received(:execute) + end + end + end + describe '#latest_successful_builds_for' do def create_pipeline(status = 'success') create(:ci_pipeline, project: project, @@ -1564,8 +1671,8 @@ describe Project, models: true do let(:project) { forked_project_link.forked_to_project } it 'schedules a RepositoryForkWorker job' do - expect(RepositoryForkWorker).to receive(:perform_async). - with(project.id, forked_from_project.repository_storage_path, + expect(RepositoryForkWorker).to receive(:perform_async) + .with(project.id, forked_from_project.repository_storage_path, forked_from_project.path_with_namespace, project.namespace.full_path) project.add_import_job @@ -2041,15 +2148,15 @@ describe Project, models: true 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) + 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 + expect { project.append_or_update_attribute(:merge_requests, [merge_request]) } + .not_to raise_error end end @@ -2060,4 +2167,36 @@ describe Project, models: true do expect(project.last_repository_updated_at.to_i).to eq(project.created_at.to_i) end end + + describe '.public_or_visible_to_user' do + let!(:user) { create(:user) } + + let!(:private_project) do + create(:empty_project, :private, creator: user, namespace: user.namespace) + end + + let!(:public_project) { create(:empty_project, :public) } + + context 'with a user' do + let(:projects) do + Project.all.public_or_visible_to_user(user) + end + + it 'includes projects the user has access to' do + expect(projects).to include(private_project) + end + + it 'includes projects the user can see' do + expect(projects).to include(public_project) + end + end + + context 'without a user' do + it 'only includes public projects' do + projects = Project.all.public_or_visible_to_user + + expect(projects).to eq([public_project]) + end + end + end end |