2014-09-02 18:07:02 +05:30
require 'spec_helper'
2017-09-10 17:25:29 +05:30
describe Project do
2018-03-27 19:54:05 +05:30
include ProjectForksHelper
2018-12-05 23:21:45 +05:30
include GitHelpers
2018-03-27 19:54:05 +05:30
2019-02-15 15:39:39 +05:30
it_behaves_like 'having unique enum values'
2015-09-11 14:41:01 +05:30
describe 'associations' do
2015-04-26 12:48:37 +05:30
it { is_expected . to belong_to ( :group ) }
it { is_expected . to belong_to ( :namespace ) }
it { is_expected . to belong_to ( :creator ) . class_name ( 'User' ) }
2018-12-13 13:39:08 +05:30
it { is_expected . to belong_to ( :pool_repository ) }
2015-04-26 12:48:37 +05:30
it { is_expected . to have_many ( :users ) }
2016-09-29 09:46:39 +05:30
it { is_expected . to have_many ( :services ) }
2017-09-10 17:25:29 +05:30
it { is_expected . to have_many ( :events ) }
it { is_expected . to have_many ( :merge_requests ) }
it { is_expected . to have_many ( :issues ) }
it { is_expected . to have_many ( :milestones ) }
it { is_expected . to have_many ( :project_members ) . dependent ( :delete_all ) }
2016-08-24 12:49:21 +05:30
it { is_expected . to have_many ( :users ) . through ( :project_members ) }
2017-09-10 17:25:29 +05:30
it { is_expected . to have_many ( :requesters ) . dependent ( :delete_all ) }
it { is_expected . to have_many ( :notes ) }
it { is_expected . to have_many ( :snippets ) . class_name ( 'ProjectSnippet' ) }
it { is_expected . to have_many ( :deploy_keys_projects ) }
2015-04-26 12:48:37 +05:30
it { is_expected . to have_many ( :deploy_keys ) }
2017-09-10 17:25:29 +05:30
it { is_expected . to have_many ( :hooks ) }
it { is_expected . to have_many ( :protected_branches ) }
it { is_expected . to have_one ( :slack_service ) }
it { is_expected . to have_one ( :microsoft_teams_service ) }
it { is_expected . to have_one ( :mattermost_service ) }
2018-11-18 11:00:15 +05:30
it { is_expected . to have_one ( :hangouts_chat_service ) }
2018-03-17 18:26:18 +05:30
it { is_expected . to have_one ( :packagist_service ) }
2017-09-10 17:25:29 +05:30
it { is_expected . to have_one ( :pushover_service ) }
it { is_expected . to have_one ( :asana_service ) }
it { is_expected . to have_many ( :boards ) }
it { is_expected . to have_one ( :campfire_service ) }
2019-02-15 15:39:39 +05:30
it { is_expected . to have_one ( :discord_service ) }
2017-09-10 17:25:29 +05:30
it { is_expected . to have_one ( :drone_ci_service ) }
it { is_expected . to have_one ( :emails_on_push_service ) }
it { is_expected . to have_one ( :pipelines_email_service ) }
it { is_expected . to have_one ( :irker_service ) }
it { is_expected . to have_one ( :pivotaltracker_service ) }
it { is_expected . to have_one ( :hipchat_service ) }
it { is_expected . to have_one ( :flowdock_service ) }
it { is_expected . to have_one ( :assembla_service ) }
it { is_expected . to have_one ( :slack_slash_commands_service ) }
it { is_expected . to have_one ( :mattermost_slash_commands_service ) }
it { is_expected . to have_one ( :buildkite_service ) }
it { is_expected . to have_one ( :bamboo_service ) }
it { is_expected . to have_one ( :teamcity_service ) }
it { is_expected . to have_one ( :jira_service ) }
it { is_expected . to have_one ( :redmine_service ) }
it { is_expected . to have_one ( :custom_issue_tracker_service ) }
it { is_expected . to have_one ( :bugzilla_service ) }
it { is_expected . to have_one ( :gitlab_issue_tracker_service ) }
it { is_expected . to have_one ( :external_wiki_service ) }
it { is_expected . to have_one ( :project_feature ) }
2019-02-15 15:39:39 +05:30
it { is_expected . to have_one ( :project_repository ) }
2017-09-10 17:25:29 +05:30
it { is_expected . to have_one ( :statistics ) . class_name ( 'ProjectStatistics' ) }
it { is_expected . to have_one ( :import_data ) . class_name ( 'ProjectImportData' ) }
2016-09-29 09:46:39 +05:30
it { is_expected . to have_one ( :last_event ) . class_name ( 'Event' ) }
2018-12-13 13:39:08 +05:30
it { is_expected . to have_one ( :forked_from_project ) . through ( :fork_network_member ) }
2018-03-17 18:26:18 +05:30
it { is_expected . to have_one ( :auto_devops ) . class_name ( 'ProjectAutoDevops' ) }
2019-02-15 15:39:39 +05:30
it { is_expected . to have_one ( :error_tracking_setting ) . class_name ( 'ErrorTracking::ProjectErrorTrackingSetting' ) }
2015-12-23 02:04:40 +05:30
it { is_expected . to have_many ( :commit_statuses ) }
2019-02-15 15:39:39 +05:30
it { is_expected . to have_many ( :ci_pipelines ) }
2015-12-23 02:04:40 +05:30
it { is_expected . to have_many ( :builds ) }
2018-03-17 18:26:18 +05:30
it { is_expected . to have_many ( :build_trace_section_names ) }
2015-12-23 02:04:40 +05:30
it { is_expected . to have_many ( :runner_projects ) }
it { is_expected . to have_many ( :runners ) }
it { is_expected . to have_many ( :variables ) }
it { is_expected . to have_many ( :triggers ) }
2017-08-17 22:00:37 +05:30
it { is_expected . to have_many ( :pages_domains ) }
2017-09-10 17:25:29 +05:30
it { is_expected . to have_many ( :labels ) . class_name ( 'ProjectLabel' ) }
it { is_expected . to have_many ( :users_star_projects ) }
2018-11-18 11:00:15 +05:30
it { is_expected . to have_many ( :repository_languages ) }
2017-09-10 17:25:29 +05:30
it { is_expected . to have_many ( :environments ) }
it { is_expected . to have_many ( :deployments ) }
it { is_expected . to have_many ( :todos ) }
it { is_expected . to have_many ( :releases ) }
it { is_expected . to have_many ( :lfs_objects_projects ) }
it { is_expected . to have_many ( :project_group_links ) }
it { is_expected . to have_many ( :notification_settings ) . dependent ( :delete_all ) }
2018-12-13 13:39:08 +05:30
it { is_expected . to have_many ( :forked_to_members ) . class_name ( 'ForkNetworkMember' ) }
it { is_expected . to have_many ( :forks ) . through ( :forked_to_members ) }
2018-11-08 19:23:39 +05:30
it { is_expected . to have_many ( :uploads ) }
2017-09-10 17:25:29 +05:30
it { is_expected . to have_many ( :pipeline_schedules ) }
2018-03-17 18:26:18 +05:30
it { is_expected . to have_many ( :members_and_requesters ) }
it { is_expected . to have_many ( :clusters ) }
2019-02-15 15:39:39 +05:30
it { is_expected . to have_many ( :kubernetes_namespaces ) }
2018-03-17 18:26:18 +05:30
it { is_expected . to have_many ( :custom_attributes ) . class_name ( 'ProjectCustomAttribute' ) }
2018-03-27 19:54:05 +05:30
it { is_expected . to have_many ( :project_badges ) . class_name ( 'ProjectBadge' ) }
2018-03-17 18:26:18 +05:30
it { is_expected . to have_many ( :lfs_file_locks ) }
2018-05-09 12:01:36 +05:30
it { is_expected . to have_many ( :project_deploy_tokens ) }
it { is_expected . to have_many ( :deploy_tokens ) . through ( :project_deploy_tokens ) }
2016-08-24 12:49:21 +05:30
2018-12-13 13:39:08 +05:30
it 'has an inverse relationship with merge requests' do
expect ( described_class . reflect_on_association ( :merge_requests ) . has_inverse? ) . to eq ( :target_project )
end
2016-11-24 13:41:30 +05:30
context 'after initialized' do
it " has a project_feature " do
2017-09-10 17:25:29 +05:30
expect ( described_class . new . project_feature ) . to be_present
2016-11-03 12:29:30 +05:30
end
end
2018-10-15 14:42:47 +05:30
context 'when creating a new project' do
it 'automatically creates a CI/CD settings row' do
project = create ( :project )
expect ( project . ci_cd_settings ) . to be_an_instance_of ( ProjectCiCdSetting )
expect ( project . ci_cd_settings ) . to be_persisted
end
end
context 'updating cd_cd_settings' do
it 'does not raise an error' do
project = create ( :project )
expect { project . update ( ci_cd_settings : nil ) } . not_to raise_exception
end
end
2016-08-24 12:49:21 +05:30
describe '#members & #requesters' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project , :public , :access_requestable ) }
2016-08-24 12:49:21 +05:30
let ( :requester ) { create ( :user ) }
let ( :developer ) { create ( :user ) }
before do
project . request_access ( requester )
2018-03-17 18:26:18 +05:30
project . add_developer ( developer )
2016-08-24 12:49:21 +05:30
end
2018-03-17 18:26:18 +05:30
it_behaves_like 'members and requesters associations' do
let ( :namespace ) { project }
2016-08-24 12:49:21 +05:30
end
end
2016-11-03 12:29:30 +05:30
describe '#boards' do
it 'raises an error when attempting to add more than one board to the project' do
subject . boards . build
expect { subject . boards . build } . to raise_error ( Project :: BoardLimitExceeded , 'Number of permitted boards exceeded' )
expect ( subject . boards . size ) . to eq 1
end
end
2019-02-15 15:39:39 +05:30
describe 'ci_pipelines association' do
it 'returns only pipelines from ci_sources' do
expect ( Ci :: Pipeline ) . to receive ( :ci_sources ) . and_call_original
subject . ci_pipelines
end
end
2014-09-02 18:07:02 +05:30
end
2015-09-11 14:41:01 +05:30
describe 'modules' do
subject { described_class }
it { is_expected . to include_module ( Gitlab :: ConfigHelper ) }
it { is_expected . to include_module ( Gitlab :: ShellAdapter ) }
it { is_expected . to include_module ( Gitlab :: VisibilityLevel ) }
it { is_expected . to include_module ( Referable ) }
it { is_expected . to include_module ( Sortable ) }
2014-09-02 18:07:02 +05:30
end
2019-02-15 15:39:39 +05:30
describe '.missing_kubernetes_namespace' do
let! ( :project ) { create ( :project ) }
let! ( :cluster ) { create ( :cluster , :provided_by_user , :group ) }
let ( :kubernetes_namespaces ) { project . kubernetes_namespaces }
subject { described_class . missing_kubernetes_namespace ( kubernetes_namespaces ) }
it { is_expected . to contain_exactly ( project ) }
context 'kubernetes namespace exists' do
before do
create ( :cluster_kubernetes_namespace , project : project , cluster : cluster )
end
it { is_expected . to be_empty }
end
end
2015-09-11 14:41:01 +05:30
describe 'validation' do
2017-09-10 17:25:29 +05:30
let! ( :project ) { create ( :project ) }
2014-09-02 18:07:02 +05:30
2015-04-26 12:48:37 +05:30
it { is_expected . to validate_presence_of ( :name ) }
it { is_expected . to validate_uniqueness_of ( :name ) . scoped_to ( :namespace_id ) }
2017-08-17 22:00:37 +05:30
it { is_expected . to validate_length_of ( :name ) . is_at_most ( 255 ) }
2015-04-26 12:48:37 +05:30
it { is_expected . to validate_presence_of ( :path ) }
2017-08-17 22:00:37 +05:30
it { is_expected . to validate_length_of ( :path ) . is_at_most ( 255 ) }
it { is_expected . to validate_length_of ( :description ) . is_at_most ( 2000 ) }
2017-09-10 17:25:29 +05:30
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 ) }
2018-03-17 18:26:18 +05:30
it { is_expected . not_to allow_value ( '/test/foo' ) . for ( :ci_config_path ) }
2015-04-26 12:48:37 +05:30
it { is_expected . to validate_presence_of ( :creator ) }
it { is_expected . to validate_presence_of ( :namespace ) }
2016-08-24 12:49:21 +05:30
it { is_expected . to validate_presence_of ( :repository_storage ) }
2014-09-02 18:07:02 +05:30
2018-11-18 11:00:15 +05:30
it 'validates build timeout constraints' do
is_expected . to validate_numericality_of ( :build_timeout )
. only_integer
. is_greater_than_or_equal_to ( 10 . minutes )
. is_less_than ( 1 . month )
. with_message ( 'needs to be beetween 10 minutes and 1 month' )
end
2016-09-13 17:45:13 +05:30
it 'does not allow new projects beyond user limits' do
2017-09-10 17:25:29 +05:30
project2 = build ( :project )
2019-03-02 22:35:43 +05:30
allow ( project2 )
. to receive ( :creator )
. and_return (
double ( can_create_project? : false , projects_limit : 0 ) . as_null_object
)
2015-04-26 12:48:37 +05:30
expect ( project2 ) . not_to be_valid
2014-09-02 18:07:02 +05:30
end
2016-08-24 12:49:21 +05:30
describe 'wiki path conflict' do
context " when the new path has been used by the wiki of other Project " do
2016-09-13 17:45:13 +05:30
it 'has an error on the name attribute' do
2017-09-10 17:25:29 +05:30
new_project = build_stubbed ( :project , namespace_id : project . namespace_id , path : " #{ project . path } .wiki " )
2016-08-24 12:49:21 +05:30
expect ( new_project ) . not_to be_valid
expect ( new_project . errors [ :name ] . first ) . to eq ( 'has already been taken' )
end
end
context " when the new wiki path has been used by the path of other Project " do
2016-09-13 17:45:13 +05:30
it 'has an error on the name attribute' do
2017-09-10 17:25:29 +05:30
project_with_wiki_suffix = create ( :project , path : 'foo.wiki' )
new_project = build_stubbed ( :project , namespace_id : project_with_wiki_suffix . namespace_id , path : 'foo' )
2016-08-24 12:49:21 +05:30
expect ( new_project ) . not_to be_valid
expect ( new_project . errors [ :name ] . first ) . to eq ( 'has already been taken' )
end
end
end
2017-09-10 17:25:29 +05:30
context 'repository storages inclusion' do
let ( :project2 ) { build ( :project , repository_storage : 'missing' ) }
2016-08-24 12:49:21 +05:30
before do
2017-08-17 22:00:37 +05:30
storages = { 'custom' = > { 'path' = > 'tmp/tests/custom_repositories' } }
2016-08-24 12:49:21 +05:30
allow ( Gitlab . config . repositories ) . to receive ( :storages ) . and_return ( storages )
end
2016-09-13 17:45:13 +05:30
it " does not allow repository storages that don't match a label in the configuration " do
2016-08-24 12:49:21 +05:30
expect ( project2 ) . not_to be_valid
expect ( project2 . errors [ :repository_storage ] . first ) . to match ( / is not included in the list / )
end
end
2018-11-29 20:51:05 +05:30
describe 'import_url' do
it 'does not allow an invalid URI as import_url' do
2018-12-13 13:39:08 +05:30
project = build ( :project , import_url : 'invalid://' )
2016-08-24 12:49:21 +05:30
2018-12-13 13:39:08 +05:30
expect ( project ) . not_to be_valid
end
it 'does allow a SSH URI as import_url for persisted projects' do
project = create ( :project )
project . import_url = 'ssh://test@gitlab.com/project.git'
expect ( project ) . to be_valid
end
it 'does not allow a SSH URI as import_url for new projects' do
project = build ( :project , import_url : 'ssh://test@gitlab.com/project.git' )
expect ( project ) . not_to be_valid
2018-11-29 20:51:05 +05:30
end
2016-08-24 12:49:21 +05:30
2018-11-29 20:51:05 +05:30
it 'does allow a valid URI as import_url' do
2018-12-13 13:39:08 +05:30
project = build ( :project , import_url : 'http://gitlab.com/project.git' )
2016-08-24 12:49:21 +05:30
2018-12-13 13:39:08 +05:30
expect ( project ) . to be_valid
2018-11-29 20:51:05 +05:30
end
2016-08-24 12:49:21 +05:30
2018-11-29 20:51:05 +05:30
it 'allows an empty URI' do
2018-12-13 13:39:08 +05:30
project = build ( :project , import_url : '' )
2016-08-24 12:49:21 +05:30
2018-12-13 13:39:08 +05:30
expect ( project ) . to be_valid
2018-11-29 20:51:05 +05:30
end
2016-08-24 12:49:21 +05:30
2018-11-29 20:51:05 +05:30
it 'does not produce import data on an empty URI' do
2018-12-13 13:39:08 +05:30
project = build ( :project , import_url : '' )
2016-08-24 12:49:21 +05:30
2018-12-13 13:39:08 +05:30
expect ( project . import_data ) . to be_nil
2018-11-29 20:51:05 +05:30
end
2016-08-24 12:49:21 +05:30
2018-11-29 20:51:05 +05:30
it 'does not produce import data on an invalid URI' do
2018-12-13 13:39:08 +05:30
project = build ( :project , import_url : 'test://' )
2016-08-24 12:49:21 +05:30
2018-12-13 13:39:08 +05:30
expect ( project . import_data ) . to be_nil
2018-11-29 20:51:05 +05:30
end
2017-08-17 22:00:37 +05:30
2018-11-29 20:51:05 +05:30
it " does not allow import_url pointing to localhost " do
2018-12-13 13:39:08 +05:30
project = build ( :project , import_url : 'http://localhost:9000/t.git' )
expect ( project ) . to be_invalid
expect ( project . errors [ :import_url ] . first ) . to include ( 'Requests to localhost are not allowed' )
end
2017-08-17 22:00:37 +05:30
2019-01-03 12:48:30 +05:30
it 'does not allow import_url pointing to the local network' do
project = build ( :project , import_url : 'https://192.168.1.1' )
expect ( project ) . to be_invalid
expect ( project . errors [ :import_url ] . first ) . to include ( 'Requests to the local network are not allowed' )
end
2018-12-13 13:39:08 +05:30
it " does not allow import_url with invalid ports for new projects " do
project = build ( :project , import_url : 'http://github.com:25/t.git' )
expect ( project ) . to be_invalid
expect ( project . errors [ :import_url ] . first ) . to include ( 'Only allowed ports are 80, 443' )
2018-11-29 20:51:05 +05:30
end
2017-08-17 22:00:37 +05:30
2018-12-13 13:39:08 +05:30
it " does not allow import_url with invalid ports for persisted projects " do
project = create ( :project )
project . import_url = 'http://github.com:25/t.git'
2017-08-17 22:00:37 +05:30
2018-12-13 13:39:08 +05:30
expect ( project ) . to be_invalid
expect ( project . errors [ :import_url ] . first ) . to include ( 'Only allowed ports are 22, 80, 443' )
2018-11-29 20:51:05 +05:30
end
it " does not allow import_url with invalid user " do
2018-12-13 13:39:08 +05:30
project = build ( :project , import_url : 'http://$user:password@github.com/t.git' )
2017-08-17 22:00:37 +05:30
2018-12-13 13:39:08 +05:30
expect ( project ) . to be_invalid
expect ( project . errors [ :import_url ] . first ) . to include ( 'Username needs to start with an alphanumeric character' )
2018-11-29 20:51:05 +05:30
end
2018-11-08 19:23:39 +05:30
2018-11-29 20:51:05 +05:30
include_context 'invalid urls'
it 'does not allow urls with CR or LF characters' do
project = build ( :project )
aggregate_failures do
urls_with_CRLF . each do | url |
project . import_url = url
expect ( project ) . not_to be_valid
expect ( project . errors . full_messages . first ) . to match ( / is blocked: URI is invalid / )
end
end
end
2018-11-08 19:23:39 +05:30
end
2017-08-17 22:00:37 +05:30
describe 'project pending deletion' do
let! ( :project_pending_deletion ) do
2017-09-10 17:25:29 +05:30
create ( :project ,
2017-08-17 22:00:37 +05:30
pending_delete : true )
end
let ( :new_project ) do
2017-09-10 17:25:29 +05:30
build ( :project ,
2017-08-17 22:00:37 +05:30
name : project_pending_deletion . name ,
namespace : project_pending_deletion . namespace )
end
before do
new_project . validate
end
it 'contains errors related to the project being deleted' 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
2018-03-17 18:26:18 +05:30
it 'allows a path ending in a period' do
project = build ( :project , path : 'foo.' )
expect ( project ) . to be_valid
end
2017-08-17 22:00:37 +05:30
end
2014-09-02 18:07:02 +05:30
end
2016-04-02 18:10:28 +05:30
2019-02-15 15:39:39 +05:30
describe '#all_pipelines' do
2019-02-02 18:00:53 +05:30
let ( :project ) { create ( :project ) }
before do
create ( :ci_pipeline , project : project , ref : 'master' , source : :web )
create ( :ci_pipeline , project : project , ref : 'master' , source : :external )
end
it 'has all pipelines' do
2019-02-15 15:39:39 +05:30
expect ( project . all_pipelines . size ) . to eq ( 2 )
2019-02-02 18:00:53 +05:30
end
context 'when builds are disabled' do
before do
project . project_feature . update_attribute ( :builds_access_level , ProjectFeature :: DISABLED )
end
it 'should return .external pipelines' do
2019-02-15 15:39:39 +05:30
expect ( project . all_pipelines ) . to all ( have_attributes ( source : 'external' ) )
expect ( project . all_pipelines . size ) . to eq ( 1 )
2019-02-02 18:00:53 +05:30
end
end
end
2015-12-23 02:04:40 +05:30
describe 'project token' do
2016-09-13 17:45:13 +05:30
it 'sets an random token if none provided' do
2018-11-08 19:23:39 +05:30
project = FactoryBot . create ( :project , runners_token : '' )
2015-12-23 02:04:40 +05:30
expect ( project . runners_token ) . not_to eq ( '' )
end
2016-09-29 09:46:39 +05:30
it 'does not set an random token if one provided' do
2018-11-08 19:23:39 +05:30
project = FactoryBot . create ( :project , runners_token : 'my-token' )
2015-12-23 02:04:40 +05:30
expect ( project . runners_token ) . to eq ( 'my-token' )
end
end
2014-09-02 18:07:02 +05:30
2015-04-26 12:48:37 +05:30
describe 'Respond to' do
it { is_expected . to respond_to ( :url_to_repo ) }
it { is_expected . to respond_to ( :repo_exists? ) }
it { is_expected . to respond_to ( :execute_hooks ) }
it { is_expected . to respond_to ( :owner ) }
it { is_expected . to respond_to ( :path_with_namespace ) }
2017-09-10 17:25:29 +05:30
it { is_expected . to respond_to ( :full_path ) }
2014-09-02 18:07:02 +05:30
end
2017-08-17 22:00:37 +05:30
describe 'delegation' do
2018-11-18 11:00:15 +05:30
[ :add_guest , :add_reporter , :add_developer , :add_maintainer , :add_user , :add_users ] . each do | method |
2017-09-10 17:25:29 +05:30
it { is_expected . to delegate_method ( method ) . to ( :team ) }
end
it { is_expected . to delegate_method ( :members ) . to ( :team ) . with_prefix ( true ) }
it { is_expected . to delegate_method ( :name ) . to ( :owner ) . with_prefix ( true ) . with_arguments ( allow_nil : true ) }
2019-02-15 15:39:39 +05:30
it { is_expected . to delegate_method ( :group_clusters_enabled? ) . to ( :group ) . with_arguments ( allow_nil : true ) }
it { is_expected . to delegate_method ( :root_ancestor ) . to ( :namespace ) . with_arguments ( allow_nil : true ) }
2016-06-16 23:09:34 +05:30
end
2018-11-20 20:47:30 +05:30
describe '#to_reference_with_postfix' do
it 'returns the full path with reference_postfix' do
namespace = create ( :namespace , path : 'sample-namespace' )
project = create ( :project , path : 'sample-project' , namespace : namespace )
expect ( project . to_reference_with_postfix ) . to eq 'sample-namespace/sample-project>'
end
end
2015-09-11 14:41:01 +05:30
describe '#to_reference' do
2017-08-17 22:00:37 +05:30
let ( :owner ) { create ( :user , name : 'Gitlab' ) }
let ( :namespace ) { create ( :namespace , path : 'sample-namespace' , owner : owner ) }
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project , path : 'sample-project' , namespace : namespace ) }
2018-10-15 14:42:47 +05:30
let ( :group ) { create ( :group , name : 'Group' , path : 'sample-group' ) }
2015-09-11 14:41:01 +05:30
2017-08-17 22:00:37 +05:30
context 'when nil argument' do
it 'returns nil' do
expect ( project . to_reference ) . to be_nil
end
end
context 'when full is true' do
it 'returns complete path to the project' do
expect ( project . to_reference ( full : true ) ) . to eq 'sample-namespace/sample-project'
expect ( project . to_reference ( project , full : true ) ) . to eq 'sample-namespace/sample-project'
expect ( project . to_reference ( group , full : true ) ) . to eq 'sample-namespace/sample-project'
end
end
context 'when same project argument' do
it 'returns nil' do
expect ( project . to_reference ( project ) ) . to be_nil
end
end
context 'when cross namespace project argument' do
2017-09-10 17:25:29 +05:30
let ( :another_namespace_project ) { create ( :project , name : 'another-project' ) }
2017-08-17 22:00:37 +05:30
it 'returns complete path to the project' do
expect ( project . to_reference ( another_namespace_project ) ) . to eq 'sample-namespace/sample-project'
end
end
context 'when same namespace / cross-project argument' do
2017-09-10 17:25:29 +05:30
let ( :another_project ) { create ( :project , namespace : namespace ) }
2017-08-17 22:00:37 +05:30
it 'returns path to the project' do
expect ( project . to_reference ( another_project ) ) . to eq 'sample-project'
end
end
context 'when different namespace / cross-project argument' do
let ( :another_namespace ) { create ( :namespace , path : 'another-namespace' , owner : owner ) }
2017-09-10 17:25:29 +05:30
let ( :another_project ) { create ( :project , path : 'another-project' , namespace : another_namespace ) }
2017-08-17 22:00:37 +05:30
it 'returns full path to the project' do
expect ( project . to_reference ( another_project ) ) . to eq 'sample-namespace/sample-project'
end
end
context 'when argument is a namespace' do
context 'with same project path' do
it 'returns path to the project' do
expect ( project . to_reference ( namespace ) ) . to eq 'sample-project'
end
end
context 'with different project path' do
it 'returns full path to the project' do
expect ( project . to_reference ( group ) ) . to eq 'sample-namespace/sample-project'
end
end
end
end
describe '#to_human_reference' do
let ( :owner ) { create ( :user , name : 'Gitlab' ) }
let ( :namespace ) { create ( :namespace , name : 'Sample namespace' , owner : owner ) }
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project , name : 'Sample project' , namespace : namespace ) }
2017-08-17 22:00:37 +05:30
context 'when nil argument' do
it 'returns nil' do
expect ( project . to_human_reference ) . to be_nil
end
end
context 'when same project argument' do
it 'returns nil' do
expect ( project . to_human_reference ( project ) ) . to be_nil
end
end
context 'when cross namespace project argument' do
2017-09-10 17:25:29 +05:30
let ( :another_namespace_project ) { create ( :project , name : 'another-project' ) }
2017-08-17 22:00:37 +05:30
it 'returns complete name with namespace of the project' do
expect ( project . to_human_reference ( another_namespace_project ) ) . to eq 'Gitlab / Sample project'
end
end
context 'when same namespace / cross-project argument' do
2017-09-10 17:25:29 +05:30
let ( :another_project ) { create ( :project , namespace : namespace ) }
2017-08-17 22:00:37 +05:30
it 'returns name of the project' do
expect ( project . to_human_reference ( another_project ) ) . to eq 'Sample project'
end
2015-09-11 14:41:01 +05:30
end
end
2018-03-17 18:26:18 +05:30
describe '#merge_method' do
using RSpec :: Parameterized :: TableSyntax
2016-08-24 12:49:21 +05:30
2018-03-17 18:26:18 +05:30
where ( :ff , :rebase , :method ) do
true | true | :ff
true | false | :ff
false | true | :rebase_merge
false | false | :merge
2016-08-24 12:49:21 +05:30
end
2018-03-17 18:26:18 +05:30
with_them do
let ( :project ) { build ( :project , merge_requests_rebase_enabled : rebase , merge_requests_ff_only_enabled : ff ) }
subject { project . merge_method }
it { is_expected . to eq ( method ) }
2016-08-24 12:49:21 +05:30
end
2018-03-17 18:26:18 +05:30
end
2016-09-13 17:45:13 +05:30
it 'returns valid url to repo' do
2017-09-10 17:25:29 +05:30
project = described_class . new ( path : 'somewhere' )
2015-04-26 12:48:37 +05:30
expect ( project . url_to_repo ) . to eq ( Gitlab . config . gitlab_shell . ssh_path_prefix + 'somewhere.git' )
2014-09-02 18:07:02 +05:30
end
2015-09-11 14:41:01 +05:30
describe " # web_url " do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project , path : " somewhere " ) }
2015-09-11 14:41:01 +05:30
it 'returns the full web URL for this repo' do
2017-08-17 22:00:37 +05:30
expect ( project . web_url ) . to eq ( " #{ Gitlab . config . gitlab . url } / #{ project . namespace . full_path } /somewhere " )
2015-09-11 14:41:01 +05:30
end
2014-09-02 18:07:02 +05:30
end
2018-11-08 19:23:39 +05:30
describe " # readme_url " do
context 'with a non-existing repository' do
2018-12-13 13:39:08 +05:30
let ( :project ) { create ( :project ) }
2018-11-08 19:23:39 +05:30
2018-12-13 13:39:08 +05:30
it 'returns nil' do
2018-11-08 19:23:39 +05:30
expect ( project . readme_url ) . to be_nil
end
end
context 'with an existing repository' do
context 'when no README exists' do
2018-12-13 13:39:08 +05:30
let ( :project ) { create ( :project , :empty_repo ) }
2018-11-08 19:23:39 +05:30
2018-12-13 13:39:08 +05:30
it 'returns nil' do
2018-11-08 19:23:39 +05:30
expect ( project . readme_url ) . to be_nil
end
end
context 'when a README exists' do
2018-12-13 13:39:08 +05:30
let ( :project ) { create ( :project , :repository ) }
2018-11-08 19:23:39 +05:30
it 'returns the README' do
2018-12-13 13:39:08 +05:30
expect ( project . readme_url ) . to eq ( " #{ project . web_url } /blob/master/README.md " )
2018-11-08 19:23:39 +05:30
end
end
end
end
2018-03-17 18:26:18 +05:30
describe " # new_issuable_address " do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project , path : " somewhere " ) }
2016-09-13 17:45:13 +05:30
let ( :user ) { create ( :user ) }
context 'incoming email enabled' do
before do
stub_incoming_email_setting ( enabled : true , address : " p+%{key}@gl.ab " )
end
it 'returns the address to create a new issue' do
2019-02-15 15:39:39 +05:30
address = " p+ #{ project . full_path_slug } - #{ project . project_id } - #{ user . incoming_email_token } -issue@gl.ab "
2016-09-13 17:45:13 +05:30
2018-03-17 18:26:18 +05:30
expect ( project . new_issuable_address ( user , 'issue' ) ) . to eq ( address )
end
it 'returns the address to create a new merge request' do
2019-02-15 15:39:39 +05:30
address = " p+ #{ project . full_path_slug } - #{ project . project_id } - #{ user . incoming_email_token } -merge-request@gl.ab "
2018-03-17 18:26:18 +05:30
expect ( project . new_issuable_address ( user , 'merge_request' ) ) . to eq ( address )
2016-09-13 17:45:13 +05:30
end
2019-02-15 15:39:39 +05:30
it 'returns nil with invalid address type' do
expect ( project . new_issuable_address ( user , 'invalid_param' ) ) . to be_nil
end
2016-09-13 17:45:13 +05:30
end
context 'incoming email disabled' do
before do
stub_incoming_email_setting ( enabled : false )
end
it 'returns nil' do
2018-03-17 18:26:18 +05:30
expect ( project . new_issuable_address ( user , 'issue' ) ) . to be_nil
end
it 'returns nil' do
expect ( project . new_issuable_address ( user , 'merge_request' ) ) . to be_nil
2016-09-13 17:45:13 +05:30
end
end
end
2015-04-26 12:48:37 +05:30
describe 'last_activity methods' do
2016-11-03 12:29:30 +05:30
let ( :timestamp ) { 2 . hours . ago }
# last_activity_at gets set to created_at upon creation
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project , created_at : timestamp , updated_at : timestamp ) }
2014-09-02 18:07:02 +05:30
2015-04-26 12:48:37 +05:30
describe 'last_activity' do
2016-09-13 17:45:13 +05:30
it 'alias last_activity to last_event' do
2017-09-10 17:25:29 +05:30
last_event = create ( :event , :closed , project : project )
2016-09-29 09:46:39 +05:30
2015-04-26 12:48:37 +05:30
expect ( project . last_activity ) . to eq ( last_event )
2014-09-02 18:07:02 +05:30
end
end
describe 'last_activity_date' do
it 'returns the creation date of the project\'s last event if present' do
2017-09-10 17:25:29 +05:30
new_event = create ( :event , :closed , project : project , created_at : Time . now )
2016-09-29 09:46:39 +05:30
2016-11-03 12:29:30 +05:30
project . reload
2016-09-29 09:46:39 +05:30
expect ( project . last_activity_at . to_i ) . to eq ( new_event . created_at . to_i )
2014-09-02 18:07:02 +05:30
end
it 'returns the project\'s last update date if it has no events' do
2015-04-26 12:48:37 +05:30
expect ( project . last_activity_date ) . to eq ( project . updated_at )
2014-09-02 18:07:02 +05:30
end
2018-03-27 19:54:05 +05:30
it 'returns the most recent timestamp' do
2018-11-18 11:00:15 +05:30
project . update ( updated_at : nil ,
last_activity_at : timestamp ,
last_repository_updated_at : timestamp - 1 . hour )
2018-03-27 19:54:05 +05:30
2018-11-08 19:23:39 +05:30
expect ( project . last_activity_date ) . to be_like_time ( timestamp )
2018-03-27 19:54:05 +05:30
2018-11-18 11:00:15 +05:30
project . update ( updated_at : timestamp ,
last_activity_at : timestamp - 1 . hour ,
last_repository_updated_at : nil )
2018-03-27 19:54:05 +05:30
2018-11-08 19:23:39 +05:30
expect ( project . last_activity_date ) . to be_like_time ( timestamp )
2018-03-27 19:54:05 +05:30
end
2014-09-02 18:07:02 +05:30
end
end
2015-09-11 14:41:01 +05:30
describe '#get_issue' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2015-12-23 02:04:40 +05:30
let! ( :issue ) { create ( :issue , project : project ) }
2017-01-15 13:20:01 +05:30
let ( :user ) { create ( :user ) }
before do
2018-03-17 18:26:18 +05:30
project . add_developer ( user )
2017-01-15 13:20:01 +05:30
end
2015-09-11 14:41:01 +05:30
context 'with default issues tracker' do
it 'returns an issue' do
2017-01-15 13:20:01 +05:30
expect ( project . get_issue ( issue . iid , user ) ) . to eq issue
2015-09-11 14:41:01 +05:30
end
2015-12-23 02:04:40 +05:30
it 'returns count of open issues' do
expect ( project . open_issues_count ) . to eq ( 1 )
end
2015-09-11 14:41:01 +05:30
it 'returns nil when no issue found' do
2017-01-15 13:20:01 +05:30
expect ( project . get_issue ( 999 , user ) ) . to be_nil
end
it " returns nil when user doesn't have access " do
user = create ( :user )
expect ( project . get_issue ( issue . iid , user ) ) . to eq nil
2015-09-11 14:41:01 +05:30
end
end
context 'with external issues tracker' do
2017-09-10 17:25:29 +05:30
let! ( :internal_issue ) { create ( :issue , project : project ) }
2015-09-11 14:41:01 +05:30
before do
2017-09-10 17:25:29 +05:30
allow ( project ) . to receive ( :external_issue_tracker ) . and_return ( true )
2015-09-11 14:41:01 +05:30
end
2017-09-10 17:25:29 +05:30
context 'when internal issues are enabled' do
it 'returns interlan issue' do
issue = project . get_issue ( internal_issue . iid , user )
expect ( issue ) . to be_kind_of ( Issue )
expect ( issue . iid ) . to eq ( internal_issue . iid )
expect ( issue . project ) . to eq ( project )
end
it 'returns an ExternalIssue when internal issue does not exists' do
issue = project . get_issue ( 'FOO-1234' , user )
expect ( issue ) . to be_kind_of ( ExternalIssue )
expect ( issue . iid ) . to eq ( 'FOO-1234' )
expect ( issue . project ) . to eq ( project )
end
end
context 'when internal issues are disabled' do
before do
project . issues_enabled = false
project . save!
end
it 'returns always an External issues' do
issue = project . get_issue ( internal_issue . iid , user )
expect ( issue ) . to be_kind_of ( ExternalIssue )
expect ( issue . iid ) . to eq ( internal_issue . iid . to_s )
expect ( issue . project ) . to eq ( project )
end
it 'returns an ExternalIssue when internal issue does not exists' do
issue = project . get_issue ( 'FOO-1234' , user )
expect ( issue ) . to be_kind_of ( ExternalIssue )
expect ( issue . iid ) . to eq ( 'FOO-1234' )
expect ( issue . project ) . to eq ( project )
end
2015-09-11 14:41:01 +05:30
end
end
end
describe '#issue_exists?' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2015-09-11 14:41:01 +05:30
it 'is truthy when issue exists' do
expect ( project ) . to receive ( :get_issue ) . and_return ( double )
expect ( project . issue_exists? ( 1 ) ) . to be_truthy
end
it 'is falsey when issue does not exist' do
expect ( project ) . to receive ( :get_issue ) . and_return ( nil )
expect ( project . issue_exists? ( 1 ) ) . to be_falsey
end
end
2016-08-24 12:49:21 +05:30
describe '#to_param' do
2014-09-02 18:07:02 +05:30
context 'with namespace' do
before do
2018-11-08 19:23:39 +05:30
@group = create ( :group , name : 'gitlab' )
2017-09-10 17:25:29 +05:30
@project = create ( :project , name : 'gitlabhq' , namespace : @group )
2014-09-02 18:07:02 +05:30
end
2015-04-26 12:48:37 +05:30
it { expect ( @project . to_param ) . to eq ( 'gitlabhq' ) }
2014-09-02 18:07:02 +05:30
end
2016-09-13 17:45:13 +05:30
context 'with invalid path' do
it 'returns previous path to keep project suitable for use in URLs when persisted' do
2017-09-10 17:25:29 +05:30
project = create ( :project , path : 'gitlab' )
2016-09-13 17:45:13 +05:30
project . path = 'foo&bar'
expect ( project ) . not_to be_valid
expect ( project . to_param ) . to eq 'gitlab'
end
it 'returns current path when new record' do
2017-09-10 17:25:29 +05:30
project = build ( :project , path : 'gitlab' )
2016-09-13 17:45:13 +05:30
project . path = 'foo&bar'
expect ( project ) . not_to be_valid
expect ( project . to_param ) . to eq 'foo&bar'
end
end
2014-09-02 18:07:02 +05:30
end
2016-08-24 12:49:21 +05:30
describe '#repository' do
2017-08-17 22:00:37 +05:30
let ( :project ) { create ( :project , :repository ) }
2014-09-02 18:07:02 +05:30
2016-08-24 12:49:21 +05:30
it 'returns valid repo' do
2015-04-26 12:48:37 +05:30
expect ( project . repository ) . to be_kind_of ( Repository )
2014-09-02 18:07:02 +05:30
end
end
2016-08-24 12:49:21 +05:30
describe '#default_issues_tracker?' do
2016-09-13 17:45:13 +05:30
it " is true if used internal tracker " do
2017-09-10 17:25:29 +05:30
project = build ( :project )
2017-08-17 22:00:37 +05:30
2015-04-26 12:48:37 +05:30
expect ( project . default_issues_tracker? ) . to be_truthy
2014-09-02 18:07:02 +05:30
end
2016-09-13 17:45:13 +05:30
it " is false if used other tracker " do
2017-08-17 22:00:37 +05:30
# NOTE: The current nature of this factory requires persistence
project = create ( :redmine_project )
expect ( project . default_issues_tracker? ) . to be_falsey
2014-09-02 18:07:02 +05:30
end
end
2018-03-17 18:26:18 +05:30
describe '#empty_repo?' do
context 'when the repo does not exist' do
let ( :project ) { build_stubbed ( :project ) }
it 'returns true' do
expect ( project . empty_repo? ) . to be ( true )
end
end
context 'when the repo exists' do
let ( :project ) { create ( :project , :repository ) }
let ( :empty_project ) { create ( :project , :empty_repo ) }
it { expect ( empty_project . empty_repo? ) . to be ( true ) }
it { expect ( project . empty_repo? ) . to be ( false ) }
end
end
2016-08-24 12:49:21 +05:30
describe '#external_issue_tracker' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2014-09-02 18:07:02 +05:30
let ( :ext_project ) { create ( :redmine_project ) }
2016-06-16 23:09:34 +05:30
context 'on existing projects with no value for has_external_issue_tracker' do
2018-03-17 18:26:18 +05:30
before do
2016-06-16 23:09:34 +05:30
project . update_column ( :has_external_issue_tracker , nil )
ext_project . update_column ( :has_external_issue_tracker , nil )
end
it 'updates the has_external_issue_tracker boolean' do
expect do
project . external_issue_tracker
end . to change { project . reload . has_external_issue_tracker } . to ( false )
expect do
ext_project . external_issue_tracker
end . to change { ext_project . reload . has_external_issue_tracker } . to ( true )
end
end
it 'returns nil and does not query services when there is no external issue tracker' do
expect ( project ) . not_to receive ( :services )
expect ( project . external_issue_tracker ) . to eq ( nil )
end
it 'retrieves external_issue_tracker querying services and cache it when there is external issue tracker' do
ext_project . reload # Factory returns a project with changed attributes
expect ( ext_project ) . to receive ( :services ) . once . and_call_original
2 . times { expect ( ext_project . external_issue_tracker ) . to be_a_kind_of ( RedmineService ) }
2014-09-02 18:07:02 +05:30
end
2016-06-16 23:09:34 +05:30
end
2016-08-24 12:49:21 +05:30
describe '#cache_has_external_issue_tracker' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project , has_external_issue_tracker : nil ) }
2016-06-16 23:09:34 +05:30
it 'stores true if there is any external_issue_tracker' do
services = double ( :service , external_issue_trackers : [ RedmineService . new ] )
expect ( project ) . to receive ( :services ) . and_return ( services )
2014-09-02 18:07:02 +05:30
2016-06-16 23:09:34 +05:30
expect do
project . cache_has_external_issue_tracker
end . to change { project . has_external_issue_tracker } . to ( true )
2014-09-02 18:07:02 +05:30
end
2016-06-16 23:09:34 +05:30
it 'stores false if there is no external_issue_tracker' do
services = double ( :service , external_issue_trackers : [ ] )
expect ( project ) . to receive ( :services ) . and_return ( services )
2014-09-02 18:07:02 +05:30
2016-06-16 23:09:34 +05:30
expect do
project . cache_has_external_issue_tracker
end . to change { project . has_external_issue_tracker } . to ( false )
2014-09-02 18:07:02 +05:30
end
2018-03-17 18:26:18 +05:30
it 'does not cache data when in a read-only GitLab instance' do
allow ( Gitlab :: Database ) . to receive ( :read_only? ) { true }
expect do
project . cache_has_external_issue_tracker
end . not_to change { project . has_external_issue_tracker }
end
end
describe '#cache_has_external_wiki' do
let ( :project ) { create ( :project , has_external_wiki : nil ) }
it 'stores true if there is any external_wikis' do
services = double ( :service , external_wikis : [ ExternalWikiService . new ] )
expect ( project ) . to receive ( :services ) . and_return ( services )
expect do
project . cache_has_external_wiki
end . to change { project . has_external_wiki } . to ( true )
end
it 'stores false if there is no external_wikis' do
services = double ( :service , external_wikis : [ ] )
expect ( project ) . to receive ( :services ) . and_return ( services )
expect do
project . cache_has_external_wiki
end . to change { project . has_external_wiki } . to ( false )
end
it 'does not cache data when in a read-only GitLab instance' do
allow ( Gitlab :: Database ) . to receive ( :read_only? ) { true }
expect do
project . cache_has_external_wiki
end . not_to change { project . has_external_wiki }
end
2014-09-02 18:07:02 +05:30
end
2016-09-29 09:46:39 +05:30
describe '#has_wiki?' do
2017-09-10 17:25:29 +05:30
let ( :no_wiki_project ) { create ( :project , :wiki_disabled , has_external_wiki : false ) }
let ( :wiki_enabled_project ) { create ( :project ) }
let ( :external_wiki_project ) { create ( :project , has_external_wiki : true ) }
2016-09-29 09:46:39 +05:30
it 'returns true if project is wiki enabled or has external wiki' do
expect ( wiki_enabled_project ) . to have_wiki
expect ( external_wiki_project ) . to have_wiki
expect ( no_wiki_project ) . not_to have_wiki
end
end
2016-08-24 12:49:21 +05:30
describe '#external_wiki' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2016-08-24 12:49:21 +05:30
context 'with an active external wiki' do
before do
create ( :service , project : project , type : 'ExternalWikiService' , active : true )
project . external_wiki
end
it 'sets :has_external_wiki as true' do
expect ( project . has_external_wiki ) . to be ( true )
end
it 'sets :has_external_wiki as false if an external wiki service is destroyed later' do
expect ( project . has_external_wiki ) . to be ( true )
project . services . external_wikis . first . destroy
expect ( project . has_external_wiki ) . to be ( false )
end
end
context 'with an inactive external wiki' do
before do
create ( :service , project : project , type : 'ExternalWikiService' , active : false )
end
it 'sets :has_external_wiki as false' do
expect ( project . has_external_wiki ) . to be ( false )
end
end
context 'with no external wiki' do
before do
project . external_wiki
end
it 'sets :has_external_wiki as false' do
expect ( project . has_external_wiki ) . to be ( false )
end
it 'sets :has_external_wiki as true if an external wiki service is created later' do
expect ( project . has_external_wiki ) . to be ( false )
create ( :service , project : project , type : 'ExternalWikiService' , active : true )
expect ( project . has_external_wiki ) . to be ( true )
end
end
end
2014-09-02 18:07:02 +05:30
describe '#star_count' do
it 'counts stars from multiple users' do
2018-11-08 19:23:39 +05:30
user1 = create ( :user )
user2 = create ( :user )
2017-09-10 17:25:29 +05:30
project = create ( :project , :public )
2014-09-02 18:07:02 +05:30
expect ( project . star_count ) . to eq ( 0 )
user1 . toggle_star ( project )
expect ( project . reload . star_count ) . to eq ( 1 )
user2 . toggle_star ( project )
project . reload
expect ( project . reload . star_count ) . to eq ( 2 )
user1 . toggle_star ( project )
project . reload
expect ( project . reload . star_count ) . to eq ( 1 )
user2 . toggle_star ( project )
project . reload
expect ( project . reload . star_count ) . to eq ( 0 )
end
it 'counts stars on the right project' do
2018-11-08 19:23:39 +05:30
user = create ( :user )
2017-09-10 17:25:29 +05:30
project1 = create ( :project , :public )
project2 = create ( :project , :public )
2014-09-02 18:07:02 +05:30
expect ( project1 . star_count ) . to eq ( 0 )
expect ( project2 . star_count ) . to eq ( 0 )
user . toggle_star ( project1 )
project1 . reload
project2 . reload
expect ( project1 . star_count ) . to eq ( 1 )
expect ( project2 . star_count ) . to eq ( 0 )
user . toggle_star ( project1 )
project1 . reload
project2 . reload
expect ( project1 . star_count ) . to eq ( 0 )
expect ( project2 . star_count ) . to eq ( 0 )
user . toggle_star ( project2 )
project1 . reload
project2 . reload
expect ( project1 . star_count ) . to eq ( 0 )
expect ( project2 . star_count ) . to eq ( 1 )
user . toggle_star ( project2 )
project1 . reload
project2 . reload
expect ( project1 . star_count ) . to eq ( 0 )
expect ( project2 . star_count ) . to eq ( 0 )
end
end
2015-04-26 12:48:37 +05:30
2016-08-24 12:49:21 +05:30
describe '#avatar_type' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2015-04-26 12:48:37 +05:30
2016-09-13 17:45:13 +05:30
it 'is true if avatar is image' do
2015-04-26 12:48:37 +05:30
project . update_attribute ( :avatar , 'uploads/avatar.png' )
expect ( project . avatar_type ) . to be_truthy
end
2016-09-13 17:45:13 +05:30
it 'is false if avatar is html page' do
2015-04-26 12:48:37 +05:30
project . update_attribute ( :avatar , 'uploads/avatar.html' )
2018-11-08 19:23:39 +05:30
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' ] )
2015-04-26 12:48:37 +05:30
end
end
2016-08-24 12:49:21 +05:30
describe '#avatar_url' do
2015-04-26 12:48:37 +05:30
subject { project . avatar_url }
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2015-04-26 12:48:37 +05:30
2017-08-17 22:00:37 +05:30
context 'when avatar file is uploaded' do
2018-03-17 18:26:18 +05:30
let ( :project ) { create ( :project , :public , :with_avatar ) }
2015-04-26 12:48:37 +05:30
2017-09-10 17:25:29 +05:30
it 'shows correct url' do
2018-03-17 18:26:18 +05:30
expect ( project . avatar_url ) . to eq ( project . avatar . url )
expect ( project . avatar_url ( only_path : false ) ) . to eq ( [ Gitlab . config . gitlab . url , project . avatar . url ] . join )
2017-09-10 17:25:29 +05:30
end
2015-04-26 12:48:37 +05:30
end
2018-03-17 18:26:18 +05:30
context 'when avatar file in git' do
2015-04-26 12:48:37 +05:30
before do
allow ( project ) . to receive ( :avatar_in_git ) { true }
end
2017-08-17 22:00:37 +05:30
let ( :avatar_path ) { " / #{ project . full_path } /avatar " }
2015-04-26 12:48:37 +05:30
2017-09-10 17:25:29 +05:30
it { is_expected . to eq " http:// #{ Gitlab . config . gitlab . host } #{ avatar_path } " }
2015-04-26 12:48:37 +05:30
end
2016-06-02 11:05:42 +05:30
context 'when git repo is empty' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2016-06-02 11:05:42 +05:30
2017-09-10 17:25:29 +05:30
it { is_expected . to eq nil }
2016-06-02 11:05:42 +05:30
end
2015-04-26 12:48:37 +05:30
end
2015-10-24 18:46:33 +05:30
2016-09-29 09:46:39 +05:30
describe '#pipeline_for' do
2017-08-17 22:00:37 +05:30
let ( :project ) { create ( :project , :repository ) }
2019-03-02 22:35:43 +05:30
let! ( :pipeline ) { create_pipeline ( project ) }
2015-10-24 18:46:33 +05:30
2016-09-29 09:46:39 +05:30
shared_examples 'giving the correct pipeline' do
it { is_expected . to eq ( pipeline ) }
2016-06-02 11:05:42 +05:30
2016-09-29 09:46:39 +05:30
context 'return latest' do
2019-03-02 22:35:43 +05:30
let! ( :pipeline2 ) { create_pipeline ( project ) }
2016-06-02 11:05:42 +05:30
2016-09-29 09:46:39 +05:30
it { is_expected . to eq ( pipeline2 ) }
2016-06-02 11:05:42 +05:30
end
2016-09-29 09:46:39 +05:30
end
context 'with explicit sha' do
subject { project . pipeline_for ( 'master' , pipeline . sha ) }
it_behaves_like 'giving the correct pipeline'
end
context 'with implicit sha' do
subject { project . pipeline_for ( 'master' ) }
2016-06-02 11:05:42 +05:30
2016-09-29 09:46:39 +05:30
it_behaves_like 'giving the correct pipeline'
end
2015-10-24 18:46:33 +05:30
end
2016-08-24 12:49:21 +05:30
describe '#builds_enabled' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2015-10-24 18:46:33 +05:30
2015-11-26 14:37:03 +05:30
subject { project . builds_enabled }
it { expect ( project . builds_enabled? ) . to be_truthy }
2015-10-24 18:46:33 +05:30
end
2018-12-05 23:21:45 +05:30
describe '.sort_by_attribute' do
it 'reorders the input relation by start count desc' do
project1 = create ( :project , star_count : 2 )
project2 = create ( :project , star_count : 1 )
project3 = create ( :project )
projects = described_class . sort_by_attribute ( :stars_desc )
expect ( projects ) . to eq ( [ project1 , project2 , project3 ] )
end
end
2017-08-17 22:00:37 +05:30
describe '.with_shared_runners' do
2017-09-10 17:25:29 +05:30
subject { described_class . with_shared_runners }
2017-08-17 22:00:37 +05:30
context 'when shared runners are enabled for project' do
2017-09-10 17:25:29 +05:30
let! ( :project ) { create ( :project , shared_runners_enabled : true ) }
2017-08-17 22:00:37 +05:30
it " returns a project " do
is_expected . to eq ( [ project ] )
end
end
context 'when shared runners are disabled for project' do
2017-09-10 17:25:29 +05:30
let! ( :project ) { create ( :project , shared_runners_enabled : false ) }
2017-08-17 22:00:37 +05:30
it " returns an empty array " do
is_expected . to be_empty
end
end
end
2017-09-10 17:25:29 +05:30
describe '.cached_count' , :use_clean_rails_memory_store_caching do
2016-08-24 12:49:21 +05:30
let ( :group ) { create ( :group , :public ) }
2017-09-10 17:25:29 +05:30
let! ( :project1 ) { create ( :project , :public , group : group ) }
let! ( :project2 ) { create ( :project , :public , group : group ) }
2016-08-24 12:49:21 +05:30
it 'returns total project count' do
2017-09-10 17:25:29 +05:30
expect ( described_class ) . to receive ( :count ) . once . and_call_original
2016-08-24 12:49:21 +05:30
3 . times do
2017-09-10 17:25:29 +05:30
expect ( described_class . cached_count ) . to eq ( 2 )
2016-08-24 12:49:21 +05:30
end
end
end
2015-10-24 18:46:33 +05:30
describe '.trending' do
2016-06-02 11:05:42 +05:30
let ( :group ) { create ( :group , :public ) }
2017-09-10 17:25:29 +05:30
let ( :project1 ) { create ( :project , :public , group : group ) }
let ( :project2 ) { create ( :project , :public , group : group ) }
2015-10-24 18:46:33 +05:30
before do
2 . times do
create ( :note_on_commit , project : project1 )
end
create ( :note_on_commit , project : project2 )
2016-11-03 12:29:30 +05:30
TrendingProject . refresh!
2015-10-24 18:46:33 +05:30
end
2016-11-03 12:29:30 +05:30
subject { described_class . trending . to_a }
2015-10-24 18:46:33 +05:30
2016-11-03 12:29:30 +05:30
it 'sorts projects by the amount of notes in descending order' do
expect ( subject ) . to eq ( [ project1 , project2 ] )
end
2015-10-24 18:46:33 +05:30
2016-11-03 12:29:30 +05:30
it 'does not take system notes into account' do
10 . times do
create ( :note_on_commit , project : project2 , system : true )
2015-10-24 18:46:33 +05:30
end
2016-11-03 12:29:30 +05:30
expect ( described_class . trending . to_a ) . to eq ( [ project1 , project2 ] )
2015-10-24 18:46:33 +05:30
end
end
2015-11-26 14:37:03 +05:30
2017-09-10 17:25:29 +05:30
describe '.starred_by' do
it 'returns only projects starred by the given user' do
user1 = create ( :user )
user2 = create ( :user )
project1 = create ( :project )
project2 = create ( :project )
create ( :project )
user1 . toggle_star ( project1 )
user2 . toggle_star ( project2 )
expect ( described_class . starred_by ( user1 ) ) . to contain_exactly ( project1 )
end
end
2015-11-26 14:37:03 +05:30
describe '.visible_to_user' do
2017-09-10 17:25:29 +05:30
let! ( :project ) { create ( :project , :private ) }
2015-11-26 14:37:03 +05:30
let! ( :user ) { create ( :user ) }
subject { described_class . visible_to_user ( user ) }
describe 'when a user has access to a project' do
before do
2018-11-18 11:00:15 +05:30
project . add_user ( user , Gitlab :: Access :: MAINTAINER )
2015-11-26 14:37:03 +05:30
end
it { is_expected . to eq ( [ project ] ) }
end
describe 'when a user does not have access to any projects' do
it { is_expected . to eq ( [ ] ) }
end
end
2015-12-23 02:04:40 +05:30
2016-08-24 12:49:21 +05:30
context 'repository storage by default' do
2018-10-15 14:42:47 +05:30
let ( :project ) { build ( :project ) }
2016-08-24 12:49:21 +05:30
before do
2016-11-24 13:41:30 +05:30
storages = {
2018-05-09 12:01:36 +05:30
'default' = > Gitlab :: GitalyClient :: StorageSettings . new ( 'path' = > 'tmp/tests/repositories' ) ,
'picked' = > Gitlab :: GitalyClient :: StorageSettings . new ( 'path' = > 'tmp/tests/repositories' )
2016-11-24 13:41:30 +05:30
}
2016-08-24 12:49:21 +05:30
allow ( Gitlab . config . repositories ) . to receive ( :storages ) . and_return ( storages )
end
2016-11-24 13:41:30 +05:30
it 'picks storage from ApplicationSetting' do
expect_any_instance_of ( ApplicationSetting ) . to receive ( :pick_repository_storage ) . and_return ( 'picked' )
expect ( project . repository_storage ) . to eq ( 'picked' )
end
2016-08-24 12:49:21 +05:30
end
2015-12-23 02:04:40 +05:30
context 'shared runners by default' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2015-12-23 02:04:40 +05:30
subject { project . shared_runners_enabled }
context 'are enabled' do
2017-09-10 17:25:29 +05:30
before do
stub_application_setting ( shared_runners_enabled : true )
end
2015-12-23 02:04:40 +05:30
it { is_expected . to be_truthy }
end
context 'are disabled' do
2017-09-10 17:25:29 +05:30
before do
stub_application_setting ( shared_runners_enabled : false )
end
2015-12-23 02:04:40 +05:30
it { is_expected . to be_falsey }
end
end
2018-10-15 14:42:47 +05:30
describe '#any_runners?' do
context 'shared runners' do
2018-11-08 19:23:39 +05:30
let ( :project ) { create ( :project , shared_runners_enabled : shared_runners_enabled ) }
let ( :specific_runner ) { create ( :ci_runner , :project , projects : [ project ] ) }
let ( :shared_runner ) { create ( :ci_runner , :instance ) }
2015-12-23 02:04:40 +05:30
2018-10-15 14:42:47 +05:30
context 'for shared runners disabled' do
let ( :shared_runners_enabled ) { false }
2016-04-02 18:10:28 +05:30
2018-10-15 14:42:47 +05:30
it 'has no runners available' do
expect ( project . any_runners? ) . to be_falsey
end
2016-04-02 18:10:28 +05:30
2018-10-15 14:42:47 +05:30
it 'has a specific runner' do
2018-11-08 19:23:39 +05:30
specific_runner
2018-10-15 14:42:47 +05:30
expect ( project . any_runners? ) . to be_truthy
end
it 'has a shared runner, but they are prohibited to use' do
shared_runner
expect ( project . any_runners? ) . to be_falsey
end
it 'checks the presence of specific runner' do
2018-11-08 19:23:39 +05:30
specific_runner
2018-10-15 14:42:47 +05:30
expect ( project . any_runners? { | runner | runner == specific_runner } ) . to be_truthy
end
2016-04-02 18:10:28 +05:30
2018-10-15 14:42:47 +05:30
it 'returns false if match cannot be found' do
2018-11-08 19:23:39 +05:30
specific_runner
2018-10-15 14:42:47 +05:30
expect ( project . any_runners? { false } ) . to be_falsey
end
2015-12-23 02:04:40 +05:30
end
2016-04-02 18:10:28 +05:30
2018-10-15 14:42:47 +05:30
context 'for shared runners enabled' do
let ( :shared_runners_enabled ) { true }
it 'has a shared runner' do
shared_runner
expect ( project . any_runners? ) . to be_truthy
end
it 'checks the presence of shared runner' do
shared_runner
expect ( project . any_runners? { | runner | runner == shared_runner } ) . to be_truthy
end
it 'returns false if match cannot be found' do
shared_runner
expect ( project . any_runners? { false } ) . to be_falsey
end
2015-12-23 02:04:40 +05:30
end
end
2016-04-02 18:10:28 +05:30
2018-10-15 14:42:47 +05:30
context 'group runners' do
2018-11-08 19:23:39 +05:30
let ( :project ) { create ( :project , group_runners_enabled : group_runners_enabled ) }
let ( :group ) { create ( :group , projects : [ project ] ) }
let ( :group_runner ) { create ( :ci_runner , :group , groups : [ group ] ) }
2018-10-15 14:42:47 +05:30
context 'for group runners disabled' do
let ( :group_runners_enabled ) { false }
2016-04-02 18:10:28 +05:30
2018-10-15 14:42:47 +05:30
it 'has no runners available' do
expect ( project . any_runners? ) . to be_falsey
end
it 'has a group runner, but they are prohibited to use' do
group_runner
expect ( project . any_runners? ) . to be_falsey
end
2015-12-23 02:04:40 +05:30
end
2018-10-15 14:42:47 +05:30
context 'for group runners enabled' do
let ( :group_runners_enabled ) { true }
it 'has a group runner' do
group_runner
expect ( project . any_runners? ) . to be_truthy
end
it 'checks the presence of group runner' do
group_runner
expect ( project . any_runners? { | runner | runner == group_runner } ) . to be_truthy
end
it 'returns false if match cannot be found' do
group_runner
expect ( project . any_runners? { false } ) . to be_falsey
end
2015-12-23 02:04:40 +05:30
end
end
end
2016-01-14 18:37:52 +05:30
2017-08-17 22:00:37 +05:30
describe '#shared_runners' do
2018-11-08 19:23:39 +05:30
let! ( :runner ) { create ( :ci_runner , :instance ) }
2017-08-17 22:00:37 +05:30
subject { project . shared_runners }
context 'when shared runners are enabled for project' do
2017-09-10 17:25:29 +05:30
let! ( :project ) { create ( :project , shared_runners_enabled : true ) }
2017-08-17 22:00:37 +05:30
it " returns a list of shared runners " do
is_expected . to eq ( [ runner ] )
end
end
context 'when shared runners are disabled for project' do
2017-09-10 17:25:29 +05:30
let! ( :project ) { create ( :project , shared_runners_enabled : false ) }
2017-08-17 22:00:37 +05:30
it " returns a empty list " do
is_expected . to be_empty
end
end
end
2019-03-02 22:35:43 +05:30
describe '#visibility_level' do
let ( :project ) { build ( :project ) }
subject { project . visibility_level }
context 'by default' do
it { is_expected . to eq ( Gitlab :: VisibilityLevel :: PRIVATE ) }
end
context 'when set to INTERNAL in application settings' do
before do
stub_application_setting ( default_project_visibility : Gitlab :: VisibilityLevel :: INTERNAL )
end
it { is_expected . to eq ( Gitlab :: VisibilityLevel :: INTERNAL ) }
end
end
2016-01-14 18:37:52 +05:30
describe '#visibility_level_allowed?' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project , :internal ) }
2016-01-14 18:37:52 +05:30
context 'when checking on non-forked project' do
it { expect ( project . visibility_level_allowed? ( Gitlab :: VisibilityLevel :: PRIVATE ) ) . to be_truthy }
it { expect ( project . visibility_level_allowed? ( Gitlab :: VisibilityLevel :: INTERNAL ) ) . to be_truthy }
it { expect ( project . visibility_level_allowed? ( Gitlab :: VisibilityLevel :: PUBLIC ) ) . to be_truthy }
end
context 'when checking on forked project' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project , :internal ) }
2018-12-13 13:39:08 +05:30
let ( :forked_project ) { fork_project ( project ) }
2016-01-14 18:37:52 +05:30
it { expect ( forked_project . visibility_level_allowed? ( Gitlab :: VisibilityLevel :: PRIVATE ) ) . to be_truthy }
it { expect ( forked_project . visibility_level_allowed? ( Gitlab :: VisibilityLevel :: INTERNAL ) ) . to be_truthy }
it { expect ( forked_project . visibility_level_allowed? ( Gitlab :: VisibilityLevel :: PUBLIC ) ) . to be_falsey }
end
2016-06-02 11:05:42 +05:30
end
2017-08-17 22:00:37 +05:30
describe '#pages_deployed?' do
2018-11-08 19:23:39 +05:30
let ( :project ) { create ( :project ) }
2017-08-17 22:00:37 +05:30
subject { project . pages_deployed? }
context 'if public folder does exist' do
2017-09-10 17:25:29 +05:30
before do
allow ( Dir ) . to receive ( :exist? ) . with ( project . public_pages_path ) . and_return ( true )
end
2017-08-17 22:00:37 +05:30
it { is_expected . to be_truthy }
end
context " if public folder doesn't exist " do
it { is_expected . to be_falsey }
end
end
2017-09-10 17:25:29 +05:30
describe '#pages_url' do
2018-11-08 19:23:39 +05:30
let ( :group ) { create ( :group , name : group_name ) }
let ( :project ) { create ( :project , namespace : group , name : project_name ) }
2017-09-10 17:25:29 +05:30
let ( :domain ) { 'Example.com' }
subject { project . pages_url }
before do
allow ( Settings . pages ) . to receive ( :host ) . and_return ( domain )
allow ( Gitlab . config . pages ) . to receive ( :url ) . and_return ( 'http://example.com' )
end
context 'group page' do
let ( :group_name ) { 'Group' }
let ( :project_name ) { 'group.example.com' }
it { is_expected . to eq ( " http://group.example.com " ) }
end
context 'project page' do
let ( :group_name ) { 'Group' }
let ( :project_name ) { 'Project' }
it { is_expected . to eq ( " http://group.example.com/project " ) }
end
end
2018-05-09 12:01:36 +05:30
describe '#pages_group_url' do
2018-11-08 19:23:39 +05:30
let ( :group ) { create ( :group , name : group_name ) }
let ( :project ) { create ( :project , namespace : group , name : project_name ) }
2018-05-09 12:01:36 +05:30
let ( :domain ) { 'Example.com' }
let ( :port ) { 1234 }
subject { project . pages_group_url }
before do
allow ( Settings . pages ) . to receive ( :host ) . and_return ( domain )
allow ( Gitlab . config . pages ) . to receive ( :url ) . and_return ( " http://example.com: #{ port } " )
end
context 'group page' do
let ( :group_name ) { 'Group' }
let ( :project_name ) { 'group.example.com' }
it { is_expected . to eq ( " http://group.example.com: #{ port } " ) }
end
context 'project page' do
let ( :group_name ) { 'Group' }
let ( :project_name ) { 'Project' }
it { is_expected . to eq ( " http://group.example.com: #{ port } " ) }
end
end
2016-06-02 11:05:42 +05:30
describe '.search' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project , description : 'kitten mittens' ) }
2016-06-02 11:05:42 +05:30
it 'returns projects with a matching name' do
expect ( described_class . search ( project . name ) ) . to eq ( [ project ] )
end
it 'returns projects with a partially matching name' do
expect ( described_class . search ( project . name [ 0 .. 2 ] ) ) . to eq ( [ project ] )
end
it 'returns projects with a matching name regardless of the casing' do
expect ( described_class . search ( project . name . upcase ) ) . to eq ( [ project ] )
end
it 'returns projects with a matching description' do
expect ( described_class . search ( project . description ) ) . to eq ( [ project ] )
end
it 'returns projects with a partially matching description' do
expect ( described_class . search ( 'kitten' ) ) . to eq ( [ project ] )
end
it 'returns projects with a matching description regardless of the casing' do
expect ( described_class . search ( 'KITTEN' ) ) . to eq ( [ project ] )
end
it 'returns projects with a matching path' do
expect ( described_class . search ( project . path ) ) . to eq ( [ project ] )
end
2016-01-14 18:37:52 +05:30
2016-06-02 11:05:42 +05:30
it 'returns projects with a partially matching path' do
expect ( described_class . search ( project . path [ 0 .. 2 ] ) ) . to eq ( [ project ] )
end
it 'returns projects with a matching path regardless of the casing' do
expect ( described_class . search ( project . path . upcase ) ) . to eq ( [ project ] )
end
2017-09-10 17:25:29 +05:30
describe 'with pending_delete project' do
let ( :pending_delete_project ) { create ( :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
2016-01-14 18:37:52 +05:30
end
2016-04-02 18:10:28 +05:30
2018-11-20 20:47:30 +05:30
describe '.optionally_search' do
let ( :project ) { create ( :project ) }
it 'searches for projects matching the query if one is given' do
relation = described_class . optionally_search ( project . name )
expect ( relation ) . to eq ( [ project ] )
end
it 'returns the current relation if no search query is given' do
relation = described_class . where ( id : project . id )
expect ( relation . optionally_search ) . to eq ( relation )
end
end
describe '.paginate_in_descending_order_using_id' do
let! ( :project1 ) { create ( :project ) }
let! ( :project2 ) { create ( :project ) }
it 'orders the relation in descending order' do
expect ( described_class . paginate_in_descending_order_using_id )
. to eq ( [ project2 , project1 ] )
end
it 'applies a limit to the relation' do
expect ( described_class . paginate_in_descending_order_using_id ( limit : 1 ) )
. to eq ( [ project2 ] )
end
it 'limits projects by and ID when given' do
expect ( described_class . paginate_in_descending_order_using_id ( before : project2 . id ) )
. to eq ( [ project1 ] )
end
end
describe '.including_namespace_and_owner' do
it 'eager loads the namespace and namespace owner' do
create ( :project )
row = described_class . eager_load_namespace_and_owner . to_a . first
recorder = ActiveRecord :: QueryRecorder . new { row . namespace . owner }
expect ( recorder . count ) . to be_zero
end
end
2016-04-02 18:10:28 +05:30
describe '#expire_caches_before_rename' do
2017-08-17 22:00:37 +05:30
let ( :project ) { create ( :project , :repository ) }
2016-04-02 18:10:28 +05:30
let ( :repo ) { double ( :repo , exists? : true ) }
let ( :wiki ) { double ( :wiki , exists? : true ) }
it 'expires the caches of the repository and wiki' do
2017-09-10 17:25:29 +05:30
allow ( Repository ) . to receive ( :new )
. with ( 'foo' , project )
. and_return ( repo )
2016-04-02 18:10:28 +05:30
2017-09-10 17:25:29 +05:30
allow ( Repository ) . to receive ( :new )
. with ( 'foo.wiki' , project )
. and_return ( wiki )
2016-04-02 18:10:28 +05:30
2016-06-02 11:05:42 +05:30
expect ( repo ) . to receive ( :before_delete )
expect ( wiki ) . to receive ( :before_delete )
2016-04-02 18:10:28 +05:30
project . expire_caches_before_rename ( 'foo' )
end
end
2016-06-02 11:05:42 +05:30
describe '.search_by_title' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project , name : 'kittens' ) }
2016-06-02 11:05:42 +05:30
it 'returns projects with a matching name' do
expect ( described_class . search_by_title ( project . name ) ) . to eq ( [ project ] )
end
it 'returns projects with a partially matching name' do
expect ( described_class . search_by_title ( 'kitten' ) ) . to eq ( [ project ] )
end
it 'returns projects with a matching name regardless of the casing' do
expect ( described_class . search_by_title ( 'KITTENS' ) ) . to eq ( [ project ] )
end
end
context 'when checking projects from groups' do
let ( :private_group ) { create ( :group , visibility_level : 0 ) }
let ( :internal_group ) { create ( :group , visibility_level : 10 ) }
2018-11-08 19:23:39 +05:30
let ( :private_project ) { create ( :project , :private , group : private_group ) }
let ( :internal_project ) { create ( :project , :internal , group : internal_group ) }
2016-06-02 11:05:42 +05:30
context 'when group is private project can not be internal' do
it { expect ( private_project . visibility_level_allowed? ( Gitlab :: VisibilityLevel :: INTERNAL ) ) . to be_falsey }
end
context 'when group is internal project can not be public' do
it { expect ( internal_project . visibility_level_allowed? ( Gitlab :: VisibilityLevel :: PUBLIC ) ) . to be_falsey }
end
end
2019-02-15 15:39:39 +05:30
describe '#track_project_repository' do
shared_examples 'tracks storage location' do
context 'when a project repository entry does not exist' do
it 'creates a new entry' do
expect { project . track_project_repository } . to change ( project , :project_repository )
end
it 'tracks the project storage location' do
project . track_project_repository
expect ( project . project_repository ) . to have_attributes (
disk_path : project . disk_path ,
shard_name : project . repository_storage
)
end
end
context 'when a tracking entry exists' do
let! ( :project_repository ) { create ( :project_repository , project : project ) }
let! ( :shard ) { create ( :shard , name : 'foo' ) }
it 'does not create a new entry in the database' do
expect { project . track_project_repository } . not_to change ( project , :project_repository )
end
it 'updates the project storage location' do
allow ( project ) . to receive ( :disk_path ) . and_return ( 'fancy/new/path' )
allow ( project ) . to receive ( :repository_storage ) . and_return ( 'foo' )
project . track_project_repository
expect ( project . project_repository ) . to have_attributes (
disk_path : 'fancy/new/path' ,
shard_name : 'foo'
)
end
end
end
context 'with projects on legacy storage' do
let ( :project ) { create ( :project , :repository , :legacy_storage ) }
it_behaves_like 'tracks storage location'
end
context 'with projects on hashed storage' do
let ( :project ) { create ( :project , :repository ) }
it_behaves_like 'tracks storage location'
end
end
2016-06-02 11:05:42 +05:30
describe '#create_repository' do
2017-08-17 22:00:37 +05:30
let ( :project ) { create ( :project , :repository ) }
2016-06-02 11:05:42 +05:30
let ( :shell ) { Gitlab :: Shell . new }
before do
allow ( project ) . to receive ( :gitlab_shell ) . and_return ( shell )
end
context 'using a regular repository' do
it 'creates the repository' do
2018-05-09 12:01:36 +05:30
expect ( shell ) . to receive ( :create_repository )
2019-03-02 22:35:43 +05:30
. with ( project . repository_storage , project . disk_path , project . full_path )
2017-09-10 17:25:29 +05:30
. and_return ( true )
2016-06-02 11:05:42 +05:30
expect ( project . repository ) . to receive ( :after_create )
expect ( project . create_repository ) . to eq ( true )
end
it 'adds an error if the repository could not be created' do
2018-05-09 12:01:36 +05:30
expect ( shell ) . to receive ( :create_repository )
2019-03-02 22:35:43 +05:30
. with ( project . repository_storage , project . disk_path , project . full_path )
2017-09-10 17:25:29 +05:30
. and_return ( false )
2016-06-02 11:05:42 +05:30
expect ( project . repository ) . not_to receive ( :after_create )
expect ( project . create_repository ) . to eq ( false )
expect ( project . errors ) . not_to be_empty
end
end
context 'using a forked repository' do
it 'does nothing' do
expect ( project ) . to receive ( :forked? ) . and_return ( true )
2018-05-09 12:01:36 +05:30
expect ( shell ) . not_to receive ( :create_repository )
2016-06-02 11:05:42 +05:30
project . create_repository
end
end
end
2017-09-10 17:25:29 +05:30
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 )
2018-05-09 12:01:36 +05:30
allow ( shell ) . to receive ( :create_repository )
2019-03-02 22:35:43 +05:30
. with ( project . repository_storage , project . disk_path , project . full_path )
2017-09-10 17:25:29 +05:30
. 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 )
2018-05-09 12:01:36 +05:30
expect ( shell ) . to receive ( :create_repository )
2019-03-02 22:35:43 +05:30
. with ( project . repository_storage , project . disk_path , project . full_path )
2017-09-10 17:25:29 +05:30
. and_return ( true )
project . ensure_repository
end
end
2019-02-15 15:39:39 +05:30
describe 'handling import URL' do
it 'returns the sanitized URL' do
project = create ( :project , :import_started , import_url : 'http://user:pass@test.com' )
project . import_state . finish
expect ( project . reload . import_url ) . to eq ( 'http://test.com' )
end
end
2017-08-17 22:00:37 +05:30
describe '#container_registry_url' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2016-06-02 11:05:42 +05:30
2017-08-17 22:00:37 +05:30
subject { project . container_registry_url }
2016-06-02 11:05:42 +05:30
2017-09-10 17:25:29 +05:30
before do
stub_container_registry_config ( ** registry_settings )
end
2016-06-02 11:05:42 +05:30
context 'for enabled registry' do
let ( :registry_settings ) do
2017-08-17 22:00:37 +05:30
{ enabled : true ,
host_port : 'example.com' }
2016-06-02 11:05:42 +05:30
end
2016-06-16 23:09:34 +05:30
it { is_expected . not_to be_nil }
2016-06-02 11:05:42 +05:30
end
context 'for disabled registry' do
let ( :registry_settings ) do
2017-08-17 22:00:37 +05:30
{ enabled : false }
2016-06-02 11:05:42 +05:30
end
it { is_expected . to be_nil }
end
end
describe '#has_container_registry_tags?' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2016-06-02 11:05:42 +05:30
2017-08-17 22:00:37 +05:30
context 'when container registry is enabled' do
2017-09-10 17:25:29 +05:30
before do
stub_container_registry_config ( enabled : true )
end
2016-06-02 11:05:42 +05:30
2017-08-17 22:00:37 +05:30
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 'should have image tags' do
expect ( project ) . to have_container_registry_tags
end
end
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
2016-06-02 11:05:42 +05:30
2017-08-17 22:00:37 +05:30
it 'should have image tags' do
expect ( project ) . to have_container_registry_tags
end
2016-06-02 11:05:42 +05:30
end
2017-08-17 22:00:37 +05:30
context 'when there are no tags at all' do
before do
stub_container_registry_tags ( repository : :any , tags : [ ] )
end
2016-06-02 11:05:42 +05:30
2017-08-17 22:00:37 +05:30
it 'should not have image tags' do
expect ( project ) . not_to have_container_registry_tags
end
2016-06-02 11:05:42 +05:30
end
end
2017-08-17 22:00:37 +05:30
context 'when container registry is disabled' do
2017-09-10 17:25:29 +05:30
before do
stub_container_registry_config ( enabled : false )
end
2016-06-02 11:05:42 +05:30
2017-08-17 22:00:37 +05:30
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
2016-06-02 11:05:42 +05:30
end
end
2016-06-16 23:09:34 +05:30
2017-09-10 17:25:29 +05:30
describe '#ci_config_path=' do
let ( :project ) { create ( :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
2018-03-17 18:26:18 +05:30
it 'sets a string but removes all null characters' do
project . update! ( ci_config_path : " f \0 oo/ \0 /.gitlab_ci.yml " )
2017-09-10 17:25:29 +05:30
expect ( project . ci_config_path ) . to eq ( 'foo//.gitlab_ci.yml' )
end
end
2019-03-02 22:35:43 +05:30
describe '#latest_successful_build_for' do
2017-08-17 22:00:37 +05:30
let ( :project ) { create ( :project , :repository ) }
2019-03-02 22:35:43 +05:30
let ( :pipeline ) { create_pipeline ( project ) }
2016-08-24 12:49:21 +05:30
context 'with many builds' do
it 'gives the latest builds from latest pipeline' do
2019-03-02 22:35:43 +05:30
pipeline1 = create_pipeline ( project )
pipeline2 = create_pipeline ( project )
2016-08-24 12:49:21 +05:30
create_build ( pipeline1 , 'test' )
create_build ( pipeline1 , 'test2' )
2019-02-15 15:39:39 +05:30
build1_p2 = create_build ( pipeline2 , 'test' )
2019-03-02 22:35:43 +05:30
create_build ( pipeline2 , 'test2' )
2016-08-24 12:49:21 +05:30
2019-03-02 22:35:43 +05:30
expect ( project . latest_successful_build_for ( build1_p2 . name ) )
. to eq ( build1_p2 )
2016-08-24 12:49:21 +05:30
end
end
context 'with succeeded pipeline' do
let! ( :build ) { create_build }
context 'standalone pipeline' do
it 'returns builds for ref for default_branch' do
2019-03-02 22:35:43 +05:30
expect ( project . latest_successful_build_for ( build . name ) )
. to eq ( build )
end
2016-08-24 12:49:21 +05:30
2019-03-02 22:35:43 +05:30
it 'returns empty relation if the build cannot be found' do
expect ( project . latest_successful_build_for ( 'TAIL' ) )
. to be_nil
2016-08-24 12:49:21 +05:30
end
2019-03-02 22:35:43 +05:30
end
2016-08-24 12:49:21 +05:30
2019-03-02 22:35:43 +05:30
context 'with some pending pipeline' do
before do
create_build ( create_pipeline ( project , 'pending' ) )
end
2016-08-24 12:49:21 +05:30
2019-03-02 22:35:43 +05:30
it 'gives the latest build from latest pipeline' do
expect ( project . latest_successful_build_for ( build . name ) )
. to eq ( build )
end
end
end
context 'with pending pipeline' do
it 'returns empty relation' do
pipeline . update ( status : 'pending' )
pending_build = create_build ( pipeline )
expect ( project . latest_successful_build_for ( pending_build . name ) ) . to be_nil
end
end
end
describe '#latest_successful_build_for!' do
let ( :project ) { create ( :project , :repository ) }
let ( :pipeline ) { create_pipeline ( project ) }
context 'with many builds' do
it 'gives the latest builds from latest pipeline' do
pipeline1 = create_pipeline ( project )
pipeline2 = create_pipeline ( project )
create_build ( pipeline1 , 'test' )
create_build ( pipeline1 , 'test2' )
build1_p2 = create_build ( pipeline2 , 'test' )
create_build ( pipeline2 , 'test2' )
expect ( project . latest_successful_build_for ( build1_p2 . name ) )
. to eq ( build1_p2 )
end
end
context 'with succeeded pipeline' do
let! ( :build ) { create_build }
context 'standalone pipeline' do
it 'returns builds for ref for default_branch' do
expect ( project . latest_successful_build_for! ( build . name ) )
. to eq ( build )
2016-08-24 12:49:21 +05:30
end
2019-02-15 15:39:39 +05:30
2019-03-02 22:35:43 +05:30
it 'returns exception if the build cannot be found' do
expect { project . latest_successful_build_for! ( build . name , 'TAIL' ) }
. to raise_error ( ActiveRecord :: RecordNotFound )
2019-02-15 15:39:39 +05:30
end
2016-08-24 12:49:21 +05:30
end
context 'with some pending pipeline' do
before do
2019-03-02 22:35:43 +05:30
create_build ( create_pipeline ( project , 'pending' ) )
2016-08-24 12:49:21 +05:30
end
it 'gives the latest build from latest pipeline' do
2019-03-02 22:35:43 +05:30
expect ( project . latest_successful_build_for! ( build . name ) )
. to eq ( build )
2016-08-24 12:49:21 +05:30
end
end
end
context 'with pending pipeline' do
it 'returns empty relation' do
2019-03-02 22:35:43 +05:30
pipeline . update ( status : 'pending' )
pending_build = create_build ( pipeline )
2016-08-24 12:49:21 +05:30
2019-03-02 22:35:43 +05:30
expect { project . latest_successful_build_for! ( pending_build . name ) }
. to raise_error ( ActiveRecord :: RecordNotFound )
2016-08-24 12:49:21 +05:30
end
end
end
2019-02-15 15:39:39 +05:30
describe '#import_status' do
context 'with import_state' do
it 'returns the right status' do
project = create ( :project , :import_started )
expect ( project . import_status ) . to eq ( " started " )
end
end
context 'without import_state' do
it 'returns none' do
project = create ( :project )
expect ( project . import_status ) . to eq ( 'none' )
end
end
end
describe '#human_import_status_name' do
context 'with import_state' do
it 'returns the right human import status' do
project = create ( :project , :import_started )
expect ( project . human_import_status_name ) . to eq ( 'started' )
end
end
context 'without import_state' do
it 'returns none' do
project = create ( :project )
expect ( project . human_import_status_name ) . to eq ( 'none' )
end
end
end
2016-08-24 12:49:21 +05:30
describe '#add_import_job' do
2018-03-17 18:26:18 +05:30
let ( :import_jid ) { '123' }
2016-08-24 12:49:21 +05:30
context 'forked' do
2018-12-13 13:39:08 +05:30
let ( :forked_from_project ) { create ( :project , :repository ) }
let ( :project ) { create ( :project ) }
before do
fork_project ( forked_from_project , nil , target_project : project )
end
2016-08-24 12:49:21 +05:30
it 'schedules a RepositoryForkWorker job' do
2018-05-09 12:01:36 +05:30
expect ( RepositoryForkWorker ) . to receive ( :perform_async ) . with ( project . id ) . and_return ( import_jid )
2016-08-24 12:49:21 +05:30
2018-03-17 18:26:18 +05:30
expect ( project . add_import_job ) . to eq ( import_jid )
2016-08-24 12:49:21 +05:30
end
end
context 'not forked' do
it 'schedules a RepositoryImportWorker job' do
2017-09-10 17:25:29 +05:30
project = create ( :project , import_url : generate ( :url ) )
2018-03-17 18:26:18 +05:30
expect ( RepositoryImportWorker ) . to receive ( :perform_async ) . with ( project . id ) . and_return ( import_jid )
expect ( project . add_import_job ) . to eq ( import_jid )
2016-08-24 12:49:21 +05:30
end
end
end
2017-08-17 22:00:37 +05:30
describe '#gitlab_project_import?' do
2017-09-10 17:25:29 +05:30
subject ( :project ) { build ( :project , import_type : 'gitlab_project' ) }
2017-08-17 22:00:37 +05:30
it { expect ( project . gitlab_project_import? ) . to be true }
end
describe '#gitea_import?' do
2017-09-10 17:25:29 +05:30
subject ( :project ) { build ( :project , import_type : 'gitea' ) }
2017-08-17 22:00:37 +05:30
it { expect ( project . gitea_import? ) . to be true }
end
2018-10-15 14:42:47 +05:30
describe '#has_remote_mirror?' do
let ( :project ) { create ( :project , :remote_mirror , :import_started ) }
subject { project . has_remote_mirror? }
before do
allow_any_instance_of ( RemoteMirror ) . to receive ( :refresh_remote )
end
it 'returns true when a remote mirror is enabled' do
is_expected . to be_truthy
end
it 'returns false when remote mirror is disabled' do
2018-11-18 11:00:15 +05:30
project . remote_mirrors . first . update ( enabled : false )
2018-10-15 14:42:47 +05:30
is_expected . to be_falsy
end
end
describe '#update_remote_mirrors' do
let ( :project ) { create ( :project , :remote_mirror , :import_started ) }
delegate :update_remote_mirrors , to : :project
before do
allow_any_instance_of ( RemoteMirror ) . to receive ( :refresh_remote )
end
it 'syncs enabled remote mirror' do
expect_any_instance_of ( RemoteMirror ) . to receive ( :sync )
update_remote_mirrors
end
it 'does nothing when remote mirror is disabled globally and not overridden' do
stub_application_setting ( mirror_available : false )
project . remote_mirror_available_overridden = false
expect_any_instance_of ( RemoteMirror ) . not_to receive ( :sync )
update_remote_mirrors
end
it 'does not sync disabled remote mirrors' do
2018-11-18 11:00:15 +05:30
project . remote_mirrors . first . update ( enabled : false )
2018-10-15 14:42:47 +05:30
expect_any_instance_of ( RemoteMirror ) . not_to receive ( :sync )
update_remote_mirrors
end
end
describe '#remote_mirror_available?' do
let ( :project ) { create ( :project ) }
context 'when remote mirror global setting is enabled' do
it 'returns true' do
expect ( project . remote_mirror_available? ) . to be ( true )
end
end
context 'when remote mirror global setting is disabled' do
before do
stub_application_setting ( mirror_available : false )
end
it 'returns true when overridden' do
project . remote_mirror_available_overridden = true
expect ( project . remote_mirror_available? ) . to be ( true )
end
it 'returns false when not overridden' do
expect ( project . remote_mirror_available? ) . to be ( false )
end
end
end
2018-03-17 18:26:18 +05:30
describe '#ancestors_upto' , :nested_groups do
let ( :parent ) { create ( :group ) }
let ( :child ) { create ( :group , parent : parent ) }
let ( :child2 ) { create ( :group , parent : child ) }
let ( :project ) { create ( :project , namespace : child2 ) }
it 'returns all ancestors when no namespace is given' do
expect ( project . ancestors_upto ) . to contain_exactly ( child2 , child , parent )
end
it 'includes ancestors upto but excluding the given ancestor' do
expect ( project . ancestors_upto ( parent ) ) . to contain_exactly ( child2 , child )
end
2019-02-15 15:39:39 +05:30
describe 'with hierarchy_order' do
it 'returns ancestors ordered by descending hierarchy' do
expect ( project . ancestors_upto ( hierarchy_order : :desc ) ) . to eq ( [ parent , child , child2 ] )
end
it 'can be used with upto option' do
expect ( project . ancestors_upto ( parent , hierarchy_order : :desc ) ) . to eq ( [ child , child2 ] )
end
end
end
describe '#root_ancestor' do
let ( :project ) { create ( :project ) }
subject { project . root_ancestor }
it { is_expected . to eq ( project . namespace ) }
context 'in a group' do
let ( :group ) { create ( :group ) }
let ( :project ) { create ( :project , group : group ) }
it { is_expected . to eq ( group ) }
end
context 'in a nested group' , :nested_groups do
let ( :root ) { create ( :group ) }
let ( :child ) { create ( :group , parent : root ) }
let ( :project ) { create ( :project , group : child ) }
it { is_expected . to eq ( root ) }
end
2018-03-17 18:26:18 +05:30
end
2016-09-29 09:46:39 +05:30
describe '#lfs_enabled?' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2016-09-29 09:46:39 +05:30
shared_examples 'project overrides group' do
it 'returns true when enabled in project' do
project . update_attribute ( :lfs_enabled , true )
expect ( project . lfs_enabled? ) . to be_truthy
end
it 'returns false when disabled in project' do
project . update_attribute ( :lfs_enabled , false )
expect ( project . lfs_enabled? ) . to be_falsey
end
it 'returns the value from the namespace, when no value is set in project' do
expect ( project . lfs_enabled? ) . to eq ( project . namespace . lfs_enabled? )
end
end
context 'LFS disabled in group' do
before do
project . namespace . update_attribute ( :lfs_enabled , false )
enable_lfs
end
it_behaves_like 'project overrides group'
end
context 'LFS enabled in group' do
before do
project . namespace . update_attribute ( :lfs_enabled , true )
enable_lfs
end
it_behaves_like 'project overrides group'
end
describe 'LFS disabled globally' do
shared_examples 'it always returns false' do
it do
expect ( project . lfs_enabled? ) . to be_falsey
expect ( project . namespace . lfs_enabled? ) . to be_falsey
end
end
context 'when no values are set' do
it_behaves_like 'it always returns false'
end
context 'when all values are set to true' do
before do
project . namespace . update_attribute ( :lfs_enabled , true )
project . update_attribute ( :lfs_enabled , true )
end
it_behaves_like 'it always returns false'
end
end
end
2017-08-17 22:00:37 +05:30
describe '#change_head' do
let ( :project ) { create ( :project , :repository ) }
2016-08-24 12:49:21 +05:30
2018-03-17 18:26:18 +05:30
it 'returns error if branch does not exist' do
expect ( project . change_head ( 'unexisted-branch' ) ) . to be false
expect ( project . errors . size ) . to eq ( 1 )
end
2017-08-17 22:00:37 +05:30
it 'calls the before_change_head and after_change_head methods' do
2016-09-29 09:46:39 +05:30
expect ( project . repository ) . to receive ( :before_change_head )
2017-08-17 22:00:37 +05:30
expect ( project . repository ) . to receive ( :after_change_head )
2016-09-29 09:46:39 +05:30
project . change_head ( project . default_branch )
end
it 'copies the gitattributes' do
expect ( project . repository ) . to receive ( :copy_gitattributes ) . with ( project . default_branch )
project . change_head ( project . default_branch )
end
it 'reloads the default branch' do
expect ( project ) . to receive ( :reload_default_branch )
project . change_head ( project . default_branch )
end
end
2018-03-17 18:26:18 +05:30
context 'forks' do
include ProjectForksHelper
let ( :project ) { create ( :project , :public ) }
let! ( :forked_project ) { fork_project ( project ) }
describe '#fork_network' do
it 'includes a fork of the project' do
expect ( project . fork_network . projects ) . to include ( forked_project )
end
it 'includes a fork of a fork' do
other_fork = fork_project ( forked_project )
expect ( project . fork_network . projects ) . to include ( other_fork )
end
it 'includes sibling forks' do
other_fork = fork_project ( project )
expect ( forked_project . fork_network . projects ) . to include ( other_fork )
end
it 'includes the base project' do
expect ( forked_project . fork_network . projects ) . to include ( project . reload )
end
end
describe '#in_fork_network_of?' do
it 'is true for a real fork' do
expect ( forked_project . in_fork_network_of? ( project ) ) . to be_truthy
end
it 'is true for a fork of a fork' , :postgresql do
other_fork = fork_project ( forked_project )
expect ( other_fork . in_fork_network_of? ( project ) ) . to be_truthy
end
it 'is true for sibling forks' do
sibling = fork_project ( project )
expect ( sibling . in_fork_network_of? ( forked_project ) ) . to be_truthy
end
it 'is false when another project is given' do
other_project = build_stubbed ( :project )
expect ( forked_project . in_fork_network_of? ( other_project ) ) . to be_falsy
end
end
describe '#fork_source' do
let! ( :second_fork ) { fork_project ( forked_project ) }
it 'returns the direct source if it exists' do
expect ( second_fork . fork_source ) . to eq ( forked_project )
end
it 'returns the root of the fork network when the directs source was deleted' do
forked_project . destroy
expect ( second_fork . fork_source ) . to eq ( project )
end
it 'returns nil if it is the root of the fork network' do
expect ( project . fork_source ) . to be_nil
end
end
2018-12-13 13:39:08 +05:30
describe '#forks' do
it 'includes direct forks of the project' do
expect ( project . forks ) . to contain_exactly ( forked_project )
end
end
2018-03-17 18:26:18 +05:30
describe '#lfs_storage_project' do
it 'returns self for non-forks' do
expect ( project . lfs_storage_project ) . to eq project
end
it 'returns the fork network root for forks' do
second_fork = fork_project ( forked_project )
expect ( second_fork . lfs_storage_project ) . to eq project
end
it 'returns self when fork_source is nil' do
expect ( forked_project ) . to receive ( :fork_source ) . and_return ( nil )
expect ( forked_project . lfs_storage_project ) . to eq forked_project
end
end
2018-05-09 12:01:36 +05:30
describe '#all_lfs_objects' do
let ( :lfs_object ) { create ( :lfs_object ) }
before do
project . lfs_objects << lfs_object
end
it 'returns the lfs object for a project' do
expect ( project . all_lfs_objects ) . to contain_exactly ( lfs_object )
end
it 'returns the lfs object for a fork' do
expect ( forked_project . all_lfs_objects ) . to contain_exactly ( lfs_object )
end
end
2018-03-17 18:26:18 +05:30
end
2019-02-15 15:39:39 +05:30
describe '#set_repository_read_only!' do
let ( :project ) { create ( :project ) }
it 'returns true when there is no existing git transfer in progress' do
expect ( project . set_repository_read_only! ) . to be_truthy
end
it 'returns false when there is an existing git transfer in progress' do
allow ( project ) . to receive ( :git_transfer_in_progress? ) { true }
expect ( project . set_repository_read_only! ) . to be_falsey
end
end
2019-03-13 22:55:13 +05:30
describe '#set_repository_writable!' do
it 'sets repository_read_only to false' do
project = create ( :project , :read_only )
expect { project . set_repository_writable! }
. to change ( project , :repository_read_only )
. from ( true ) . to ( false )
end
end
2016-09-29 09:46:39 +05:30
describe '#pushes_since_gc' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2016-09-29 09:46:39 +05:30
after do
project . reset_pushes_since_gc
end
context 'without any pushes' do
it 'returns 0' do
expect ( project . pushes_since_gc ) . to eq ( 0 )
end
end
context 'with a number of pushes' do
it 'returns the number of pushes' do
3 . times { project . increment_pushes_since_gc }
expect ( project . pushes_since_gc ) . to eq ( 3 )
end
end
end
describe '#increment_pushes_since_gc' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2016-09-29 09:46:39 +05:30
after do
project . reset_pushes_since_gc
end
it 'increments the number of pushes since the last GC' do
3 . times { project . increment_pushes_since_gc }
expect ( project . pushes_since_gc ) . to eq ( 3 )
end
end
describe '#reset_pushes_since_gc' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2016-09-29 09:46:39 +05:30
after do
project . reset_pushes_since_gc
end
it 'resets the number of pushes since the last GC' do
3 . times { project . increment_pushes_since_gc }
project . reset_pushes_since_gc
expect ( project . pushes_since_gc ) . to eq ( 0 )
end
end
2017-08-17 22:00:37 +05:30
describe '#deployment_variables' do
context 'when project has no deployment service' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2016-09-29 09:46:39 +05:30
2017-08-17 22:00:37 +05:30
it 'returns an empty array' do
expect ( project . deployment_variables ) . to eq [ ]
end
end
context 'when project has a deployment service' do
2018-03-17 18:26:18 +05:30
shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
it 'returns variables from this service' do
expect ( project . deployment_variables ) . to include (
{ key : 'KUBE_TOKEN' , value : project . deployment_platform . token , public : false }
)
end
end
context 'when user configured kubernetes from Integration > Kubernetes' do
let ( :project ) { create ( :kubernetes_project ) }
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
end
2018-12-13 13:39:08 +05:30
context 'when user configured kubernetes from CI/CD > Clusters and KubernetesNamespace migration has not been executed' do
2018-03-17 18:26:18 +05:30
let! ( :cluster ) { create ( :cluster , :project , :provided_by_gcp ) }
let ( :project ) { cluster . project }
it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
2016-09-29 09:46:39 +05:30
end
2018-12-13 13:39:08 +05:30
context 'when user configured kubernetes from CI/CD > Clusters and KubernetesNamespace migration has been executed' do
let! ( :kubernetes_namespace ) { create ( :cluster_kubernetes_namespace , :with_token ) }
let! ( :cluster ) { kubernetes_namespace . cluster }
let ( :project ) { kubernetes_namespace . project }
it 'should return token from kubernetes namespace' do
expect ( project . deployment_variables ) . to include (
{ key : 'KUBE_TOKEN' , value : kubernetes_namespace . service_account_token , public : false }
)
end
end
2017-08-17 22:00:37 +05:30
end
end
2016-09-29 09:46:39 +05:30
2018-11-08 19:23:39 +05:30
describe '#default_environment' do
let ( :project ) { create ( :project ) }
it 'returns production environment when it exists' do
production = create ( :environment , name : " production " , project : project )
create ( :environment , name : 'staging' , project : project )
expect ( project . default_environment ) . to eq ( production )
end
it 'returns first environment when no production environment exists' do
create ( :environment , name : 'staging' , project : project )
create ( :environment , name : 'foo' , project : project )
expect ( project . default_environment ) . to eq ( project . environments . first )
end
it 'returns nil when no available environment exists' do
expect ( project . default_environment ) . to be_nil
end
end
2018-12-13 13:39:08 +05:30
describe '#ci_variables_for' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2018-12-13 13:39:08 +05:30
let! ( :ci_variable ) do
2017-09-10 17:25:29 +05:30
create ( :ci_variable , value : 'secret' , project : project )
end
let! ( :protected_variable ) do
create ( :ci_variable , :protected , value : 'protected' , project : project )
end
2018-12-13 13:39:08 +05:30
subject { project . reload . ci_variables_for ( ref : 'ref' ) }
2017-09-10 17:25:29 +05:30
before do
stub_application_setting (
default_branch_protection : Gitlab :: Access :: PROTECTION_NONE )
end
shared_examples 'ref is protected' do
it 'contains all the variables' do
2018-12-13 13:39:08 +05:30
is_expected . to contain_exactly ( ci_variable , protected_variable )
2017-09-10 17:25:29 +05:30
end
end
context 'when the ref is not protected' do
2019-01-03 12:48:30 +05:30
before do
allow ( project ) . to receive ( :protected_for? ) . with ( 'ref' ) . and_return ( false )
end
2018-12-13 13:39:08 +05:30
it 'contains only the CI variables' do
is_expected . to contain_exactly ( ci_variable )
2017-09-10 17:25:29 +05:30
end
end
context 'when the ref is a protected branch' do
before do
2018-03-17 18:26:18 +05:30
allow ( project ) . to receive ( :protected_for? ) . with ( 'ref' ) . and_return ( true )
2017-09-10 17:25:29 +05:30
end
it_behaves_like 'ref is protected'
end
context 'when the ref is a protected tag' do
before do
2018-03-17 18:26:18 +05:30
allow ( project ) . to receive ( :protected_for? ) . with ( 'ref' ) . and_return ( true )
2017-09-10 17:25:29 +05:30
end
it_behaves_like 'ref is protected'
end
end
2018-11-08 19:23:39 +05:30
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
2017-09-10 17:25:29 +05:30
describe '#protected_for?' do
2019-01-03 12:48:30 +05:30
let ( :project ) { create ( :project , :repository ) }
2017-09-10 17:25:29 +05:30
2019-01-03 12:48:30 +05:30
subject { project . protected_for? ( ref ) }
2017-09-10 17:25:29 +05:30
2019-01-03 12:48:30 +05:30
shared_examples 'ref is not protected' do
2017-09-10 17:25:29 +05:30
before do
stub_application_setting (
default_branch_protection : Gitlab :: Access :: PROTECTION_NONE )
end
it 'returns false' do
2019-01-03 12:48:30 +05:30
is_expected . to be false
2017-09-10 17:25:29 +05:30
end
end
2019-01-03 12:48:30 +05:30
shared_examples 'ref is protected branch' do
2017-09-10 17:25:29 +05:30
before do
2019-01-03 12:48:30 +05:30
create ( :protected_branch , name : 'master' , project : project )
2017-09-10 17:25:29 +05:30
end
it 'returns true' do
2019-01-03 12:48:30 +05:30
is_expected . to be true
2017-09-10 17:25:29 +05:30
end
end
2019-01-03 12:48:30 +05:30
shared_examples 'ref is protected tag' do
2017-09-10 17:25:29 +05:30
before do
2019-01-03 12:48:30 +05:30
create ( :protected_tag , name : 'v1.0.0' , project : project )
2017-09-10 17:25:29 +05:30
end
it 'returns true' do
2019-01-03 12:48:30 +05:30
is_expected . to be true
end
end
context 'when ref is nil' do
let ( :ref ) { nil }
it 'returns false' do
is_expected . to be false
end
end
context 'when ref is ref name' do
context 'when ref is ambiguous' do
let ( :ref ) { 'ref' }
before do
project . repository . add_branch ( project . creator , 'ref' , 'master' )
project . repository . add_tag ( project . creator , 'ref' , 'master' )
end
it 'raises an error' do
expect { subject } . to raise_error ( Repository :: AmbiguousRefError )
end
end
context 'when the ref is not protected' do
let ( :ref ) { 'master' }
it_behaves_like 'ref is not protected'
end
context 'when the ref is a protected branch' do
let ( :ref ) { 'master' }
it_behaves_like 'ref is protected branch'
end
context 'when the ref is a protected tag' do
let ( :ref ) { 'v1.0.0' }
it_behaves_like 'ref is protected tag'
end
context 'when ref does not exist' do
let ( :ref ) { 'something' }
it 'returns false' do
is_expected . to be false
end
end
end
context 'when ref is full ref' do
context 'when the ref is not protected' do
let ( :ref ) { 'refs/heads/master' }
it_behaves_like 'ref is not protected'
end
context 'when the ref is a protected branch' do
let ( :ref ) { 'refs/heads/master' }
it_behaves_like 'ref is protected branch'
end
context 'when the ref is a protected tag' do
let ( :ref ) { 'refs/tags/v1.0.0' }
it_behaves_like 'ref is protected tag'
end
context 'when branch ref name is a full tag ref' do
let ( :ref ) { 'refs/tags/something' }
before do
project . repository . add_branch ( project . creator , ref , 'master' )
end
context 'when ref is not protected' do
it 'returns false' do
is_expected . to be false
end
end
context 'when ref is a protected branch' do
before do
create ( :protected_branch , name : 'refs/tags/something' , project : project )
end
it 'returns true' do
is_expected . to be true
end
end
end
context 'when ref does not exist' do
let ( :ref ) { 'refs/heads/something' }
it 'returns false' do
is_expected . to be false
end
2017-09-10 17:25:29 +05:30
end
end
end
2017-08-17 22:00:37 +05:30
describe '#update_project_statistics' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2017-08-17 22:00:37 +05:30
it " is called after creation " do
expect ( project . statistics ) . to be_a ProjectStatistics
expect ( project . statistics ) . to be_persisted
end
it " copies the namespace_id " do
expect ( project . statistics . namespace_id ) . to eq project . namespace_id
end
it " updates the namespace_id when changed " do
namespace = create ( :namespace )
project . update ( namespace : namespace )
expect ( project . statistics . namespace_id ) . to eq namespace . id
end
end
describe 'inside_path' do
2017-09-10 17:25:29 +05:30
let! ( :project1 ) { create ( :project , namespace : create ( :namespace , path : 'name_pace' ) ) }
let! ( :project2 ) { create ( :project ) }
let! ( :project3 ) { create ( :project , namespace : create ( :namespace , path : 'namespace' ) ) }
2017-08-17 22:00:37 +05:30
let! ( :path ) { project1 . namespace . full_path }
it 'returns correct project' do
2017-09-10 17:25:29 +05:30
expect ( described_class . inside_path ( path ) ) . to eq ( [ project1 ] )
2017-08-17 22:00:37 +05:30
end
end
describe '#route_map_for' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project , :repository ) }
2017-08-17 22:00:37 +05:30
let ( :route_map ) do
<<-MAP.strip_heredoc
- source : / source / ( . * ) /
public : '\\1'
MAP
end
before do
project . repository . create_file ( User . last , '.gitlab/route-map.yml' , route_map , message : 'Add .gitlab/route-map.yml' , branch_name : 'master' )
end
context 'when there is a .gitlab/route-map.yml at the commit' do
context 'when the route map is valid' do
it 'returns a route map' do
map = project . route_map_for ( project . commit . sha )
expect ( map ) . to be_a_kind_of ( Gitlab :: RouteMap )
end
2016-09-29 09:46:39 +05:30
end
2017-08-17 22:00:37 +05:30
context 'when the route map is invalid' do
let ( :route_map ) { 'INVALID' }
it 'returns nil' do
expect ( project . route_map_for ( project . commit . sha ) ) . to be_nil
end
2016-09-29 09:46:39 +05:30
end
2017-08-17 22:00:37 +05:30
end
2016-09-29 09:46:39 +05:30
2017-08-17 22:00:37 +05:30
context 'when there is no .gitlab/route-map.yml at the commit' do
it 'returns nil' do
expect ( project . route_map_for ( project . commit . parent . sha ) ) . to be_nil
2016-09-29 09:46:39 +05:30
end
end
2017-08-17 22:00:37 +05:30
end
2016-09-29 09:46:39 +05:30
2017-08-17 22:00:37 +05:30
describe '#public_path_for_source_path' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project , :repository ) }
2017-08-17 22:00:37 +05:30
let ( :route_map ) do
Gitlab :: RouteMap . new ( <<-MAP.strip_heredoc)
- source : / source / ( . * ) /
public : '\\1'
MAP
end
let ( :sha ) { project . commit . id }
context 'when there is a route map' do
2016-09-29 09:46:39 +05:30
before do
2017-08-17 22:00:37 +05:30
allow ( project ) . to receive ( :route_map_for ) . with ( sha ) . and_return ( route_map )
2016-09-29 09:46:39 +05:30
end
2017-08-17 22:00:37 +05:30
context 'when the source path is mapped' do
it 'returns the public path' do
expect ( project . public_path_for_source_path ( 'source/file.html' , sha ) ) . to eq ( 'file.html' )
end
2016-09-29 09:46:39 +05:30
end
2017-08-17 22:00:37 +05:30
context 'when the source path is not mapped' do
it 'returns nil' do
expect ( project . public_path_for_source_path ( 'file.html' , sha ) ) . to be_nil
end
2016-09-29 09:46:39 +05:30
end
2017-08-17 22:00:37 +05:30
end
2016-09-29 09:46:39 +05:30
2017-08-17 22:00:37 +05:30
context 'when there is no route map' do
before do
allow ( project ) . to receive ( :route_map_for ) . with ( sha ) . and_return ( nil )
end
it 'returns nil' do
expect ( project . public_path_for_source_path ( 'source/file.html' , sha ) ) . to be_nil
2016-09-29 09:46:39 +05:30
end
end
end
2017-08-17 22:00:37 +05:30
describe '#parent' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2017-08-17 22:00:37 +05:30
it { expect ( project . parent ) . to eq ( project . namespace ) }
end
2018-03-17 18:26:18 +05:30
describe '#parent_id' do
let ( :project ) { create ( :project ) }
it { expect ( project . parent_id ) . to eq ( project . namespace_id ) }
end
2017-08-17 22:00:37 +05:30
describe '#parent_changed?' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
before do
project . namespace_id = 7
end
2017-08-17 22:00:37 +05:30
it { expect ( project . parent_changed? ) . to be_truthy }
end
2016-09-29 09:46:39 +05:30
def enable_lfs
allow ( Gitlab . config . lfs ) . to receive ( :enabled ) . and_return ( true )
end
2017-08-17 22:00:37 +05:30
describe '#pages_url' do
2018-11-08 19:23:39 +05:30
let ( :group ) { create ( :group , name : 'Group' ) }
let ( :nested_group ) { create ( :group , parent : group ) }
2017-08-17 22:00:37 +05:30
let ( :domain ) { 'Example.com' }
subject { project . pages_url }
before do
allow ( Settings . pages ) . to receive ( :host ) . and_return ( domain )
allow ( Gitlab . config . pages ) . to receive ( :url ) . and_return ( 'http://example.com' )
end
context 'top-level group' do
2018-11-08 19:23:39 +05:30
let ( :project ) { create ( :project , namespace : group , name : project_name ) }
2017-08-17 22:00:37 +05:30
context 'group page' do
let ( :project_name ) { 'group.example.com' }
it { is_expected . to eq ( " http://group.example.com " ) }
end
context 'project page' do
let ( :project_name ) { 'Project' }
it { is_expected . to eq ( " http://group.example.com/project " ) }
end
end
context 'nested group' do
2018-11-08 19:23:39 +05:30
let ( :project ) { create ( :project , namespace : nested_group , name : project_name ) }
2017-08-17 22:00:37 +05:30
let ( :expected_url ) { " http://group.example.com/ #{ nested_group . path } / #{ project . path } " }
context 'group page' do
let ( :project_name ) { 'group.example.com' }
it { is_expected . to eq ( expected_url ) }
end
context 'project page' do
let ( :project_name ) { 'Project' }
it { is_expected . to eq ( expected_url ) }
end
end
end
describe '#http_url_to_repo' do
2018-11-08 19:23:39 +05:30
let ( :project ) { create ( :project ) }
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
it 'returns the url to the repo without a username' do
expect ( project . http_url_to_repo ) . to eq ( " #{ project . web_url } .git " )
expect ( project . http_url_to_repo ) . not_to include ( '@' )
2017-08-17 22:00:37 +05:30
end
end
2019-02-15 15:39:39 +05:30
describe '#lfs_http_url_to_repo' do
let ( :project ) { create ( :project ) }
it 'returns the url to the repo without a username' do
lfs_http_url_to_repo = project . lfs_http_url_to_repo ( 'operation_that_doesnt_matter' )
expect ( lfs_http_url_to_repo ) . to eq ( " #{ project . web_url } .git " )
expect ( lfs_http_url_to_repo ) . not_to include ( '@' )
end
end
2017-08-17 22:00:37 +05:30
describe '#pipeline_status' do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project , :repository ) }
2017-08-17 22:00:37 +05:30
it 'builds a pipeline status' do
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.' \
2019-01-03 12:48:30 +05:30
' Validate fork Source project is not a fork of the target project'
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
expect { project . append_or_update_attribute ( :merge_requests , [ create ( :merge_request ) ] ) }
. to raise_error ( ActiveRecord :: RecordNotSaved , error_message )
2017-08-17 22:00:37 +05:30
end
2018-12-13 13:39:08 +05:30
it 'updates the project successfully' do
2017-08-17 22:00:37 +05:30
merge_request = create ( :merge_request , target_project : project , source_project : project )
2017-09-10 17:25:29 +05:30
expect { project . append_or_update_attribute ( :merge_requests , [ merge_request ] ) }
. not_to raise_error
2017-08-17 22:00:37 +05:30
end
end
2019-02-15 15:39:39 +05:30
describe '#update' do
let ( :project ) { create ( :project ) }
it 'validates the visibility' do
expect ( project ) . to receive ( :visibility_level_allowed_as_fork ) . and_call_original
expect ( project ) . to receive ( :visibility_level_allowed_by_group ) . and_call_original
project . update ( visibility_level : Gitlab :: VisibilityLevel :: INTERNAL )
end
it 'does not validate the visibility' do
expect ( project ) . not_to receive ( :visibility_level_allowed_as_fork ) . and_call_original
expect ( project ) . not_to receive ( :visibility_level_allowed_by_group ) . and_call_original
project . update ( updated_at : Time . now )
end
end
2017-08-17 22:00:37 +05:30
describe '#last_repository_updated_at' do
it 'sets to created_at upon creation' do
2017-09-10 17:25:29 +05:30
project = create ( :project , created_at : 2 . hours . ago )
2017-08-17 22:00:37 +05:30
expect ( project . last_repository_updated_at . to_i ) . to eq ( project . created_at . to_i )
end
end
2017-09-10 17:25:29 +05:30
describe '.public_or_visible_to_user' do
let! ( :user ) { create ( :user ) }
let! ( :private_project ) do
create ( :project , :private , creator : user , namespace : user . namespace )
end
let! ( :public_project ) { create ( :project , :public ) }
context 'with a user' do
let ( :projects ) do
described_class . 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 = described_class . all . public_or_visible_to_user
expect ( projects ) . to eq ( [ public_project ] )
end
end
end
2019-02-15 15:39:39 +05:30
describe '.with_feature_available_for_user' do
let! ( :user ) { create ( :user ) }
let! ( :feature ) { MergeRequest }
let! ( :project ) { create ( :project , :public , :merge_requests_enabled ) }
subject { described_class . with_feature_available_for_user ( feature , user ) }
context 'when user has access to project' do
subject { described_class . with_feature_available_for_user ( feature , user ) }
before do
project . add_guest ( user )
end
context 'when public project' do
context 'when feature is public' do
it 'returns project' do
is_expected . to include ( project )
end
end
context 'when feature is private' do
let! ( :project ) { create ( :project , :public , :merge_requests_private ) }
it 'returns project when user has access to the feature' do
project . add_maintainer ( user )
is_expected . to include ( project )
end
it 'does not return project when user does not have the minimum access level required' do
is_expected . not_to include ( project )
end
end
end
context 'when private project' do
let! ( :project ) { create ( :project ) }
it 'returns project when user has access to the feature' do
project . add_maintainer ( user )
is_expected . to include ( project )
end
it 'does not return project when user does not have the minimum access level required' do
is_expected . not_to include ( project )
end
end
end
context 'when user does not have access to project' do
let! ( :project ) { create ( :project ) }
it 'does not return project when user cant access project' do
is_expected . not_to include ( project )
end
end
end
2018-03-17 18:26:18 +05:30
describe '#pages_available?' do
let ( :project ) { create ( :project , group : group ) }
subject { project . pages_available? }
before do
allow ( Gitlab . config . pages ) . to receive ( :enabled ) . and_return ( true )
end
context 'when the project is in a top level namespace' do
let ( :group ) { create ( :group ) }
it { is_expected . to be ( true ) }
end
context 'when the project is in a subgroup' do
let ( :group ) { create ( :group , :nested ) }
2019-03-02 22:35:43 +05:30
it { is_expected . to be ( true ) }
2018-03-17 18:26:18 +05:30
end
end
2017-09-10 17:25:29 +05:30
describe '#remove_private_deploy_keys' do
let! ( :project ) { create ( :project ) }
context 'for a private deploy key' do
let! ( :key ) { create ( :deploy_key , public : false ) }
let! ( :deploy_keys_project ) { create ( :deploy_keys_project , deploy_key : key , project : project ) }
context 'when the key is not linked to another project' do
it 'removes the key' do
project . remove_private_deploy_keys
expect ( project . deploy_keys ) . not_to include ( key )
end
end
context 'when the key is linked to another project' do
before do
another_project = create ( :project )
create ( :deploy_keys_project , deploy_key : key , project : another_project )
end
it 'does not remove the key' do
project . remove_private_deploy_keys
expect ( project . deploy_keys ) . to include ( key )
end
end
end
context 'for a public deploy key' do
let! ( :key ) { create ( :deploy_key , public : true ) }
let! ( :deploy_keys_project ) { create ( :deploy_keys_project , deploy_key : key , project : project ) }
it 'does not remove the key' do
project . remove_private_deploy_keys
expect ( project . deploy_keys ) . to include ( key )
end
end
end
describe '#remove_pages' do
let ( :project ) { create ( :project ) }
let ( :namespace ) { project . namespace }
let ( :pages_path ) { project . pages_path }
around do | example |
FileUtils . mkdir_p ( pages_path )
begin
example . run
ensure
FileUtils . rm_rf ( pages_path )
end
end
it 'removes the pages directory' do
expect_any_instance_of ( Projects :: UpdatePagesConfigurationService ) . to receive ( :execute )
expect_any_instance_of ( Gitlab :: PagesTransfer ) . to receive ( :rename_project ) . and_return ( true )
expect ( PagesWorker ) . to receive ( :perform_in ) . with ( 5 . minutes , :remove , namespace . full_path , anything )
project . remove_pages
end
it 'is a no-op when there is no namespace' do
2018-03-27 19:54:05 +05:30
project . namespace . delete
project . reload
2017-09-10 17:25:29 +05:30
expect_any_instance_of ( Projects :: UpdatePagesConfigurationService ) . not_to receive ( :execute )
expect_any_instance_of ( Gitlab :: PagesTransfer ) . not_to receive ( :rename_project )
project . remove_pages
end
it 'is run when the project is destroyed' do
expect ( project ) . to receive ( :remove_pages ) . and_call_original
project . destroy
end
end
2018-05-09 12:01:36 +05:30
describe '#remove_export' do
2018-03-17 18:26:18 +05:30
let ( :project ) { create ( :project , :with_export ) }
2018-11-20 20:47:30 +05:30
it 'removes the export' do
2018-03-27 19:54:05 +05:30
project . remove_exports
2018-11-20 20:47:30 +05:30
expect ( project . export_file_exists? ) . to be_falsey
2018-05-09 12:01:36 +05:30
end
end
2017-09-10 17:25:29 +05:30
describe '#forks_count' do
it 'returns the number of forks' do
project = build ( :project )
2018-03-17 18:26:18 +05:30
expect_any_instance_of ( Projects :: ForksCountService ) . to receive ( :count ) . and_return ( 1 )
2017-09-10 17:25:29 +05:30
expect ( project . forks_count ) . to eq ( 1 )
end
end
2018-03-17 18:26:18 +05:30
2019-02-15 15:39:39 +05:30
describe '#git_transfer_in_progress?' do
let ( :project ) { build ( :project ) }
subject { project . git_transfer_in_progress? }
it 'returns false when repo_reference_count and wiki_reference_count are 0' do
allow ( project ) . to receive ( :repo_reference_count ) { 0 }
allow ( project ) . to receive ( :wiki_reference_count ) { 0 }
expect ( subject ) . to be_falsey
end
it 'returns true when repo_reference_count is > 0' do
allow ( project ) . to receive ( :repo_reference_count ) { 2 }
allow ( project ) . to receive ( :wiki_reference_count ) { 0 }
expect ( subject ) . to be_truthy
end
it 'returns true when wiki_reference_count is > 0' do
allow ( project ) . to receive ( :repo_reference_count ) { 0 }
allow ( project ) . to receive ( :wiki_reference_count ) { 2 }
expect ( subject ) . to be_truthy
end
end
2018-03-17 18:26:18 +05:30
context 'legacy storage' do
2019-03-02 22:35:43 +05:30
set ( :project ) { create ( :project , :repository , :legacy_storage ) }
2018-03-17 18:26:18 +05:30
let ( :gitlab_shell ) { Gitlab :: Shell . new }
let ( :project_storage ) { project . send ( :storage ) }
before do
allow ( project ) . to receive ( :gitlab_shell ) . and_return ( gitlab_shell )
end
describe '#base_dir' do
it 'returns base_dir based on namespace only' do
expect ( project . base_dir ) . to eq ( project . namespace . full_path )
end
end
describe '#disk_path' do
it 'returns disk_path based on namespace and project path' do
expect ( project . disk_path ) . to eq ( " #{ project . namespace . full_path } / #{ project . path } " )
end
end
describe '#ensure_storage_path_exists' do
it 'delegates to gitlab_shell to ensure namespace is created' do
2018-10-15 14:42:47 +05:30
expect ( gitlab_shell ) . to receive ( :add_namespace ) . with ( project . repository_storage , project . base_dir )
2018-03-17 18:26:18 +05:30
project . ensure_storage_path_exists
end
end
describe '#legacy_storage?' do
it 'returns true when storage_version is nil' do
project = build ( :project , storage_version : nil )
expect ( project . legacy_storage? ) . to be_truthy
end
it 'returns true when the storage_version is 0' do
project = build ( :project , storage_version : 0 )
expect ( project . legacy_storage? ) . to be_truthy
end
end
describe '#hashed_storage?' do
it 'returns false' do
expect ( project . hashed_storage? ( :repository ) ) . to be_falsey
end
end
describe '#pages_path' do
it 'returns a path where pages are stored' do
expect ( project . pages_path ) . to eq ( File . join ( Settings . pages . path , project . namespace . full_path , project . path ) )
end
end
describe '#migrate_to_hashed_storage!' do
2019-03-02 22:35:43 +05:30
let ( :project ) { create ( :project , :empty_repo , :legacy_storage ) }
2018-03-17 18:26:18 +05:30
it 'returns true' do
expect ( project . migrate_to_hashed_storage! ) . to be_truthy
end
2019-03-02 22:35:43 +05:30
it 'does not run validation' do
expect ( project ) . not_to receive ( :valid? )
2019-02-15 15:39:39 +05:30
project . migrate_to_hashed_storage!
2018-03-17 18:26:18 +05:30
end
it 'schedules ProjectMigrateHashedStorageWorker with delayed start when the project repo is in use' do
Gitlab :: ReferenceCounter . new ( project . gl_repository ( is_wiki : false ) ) . increase
expect ( ProjectMigrateHashedStorageWorker ) . to receive ( :perform_in )
project . migrate_to_hashed_storage!
end
it 'schedules ProjectMigrateHashedStorageWorker with delayed start when the wiki repo is in use' do
Gitlab :: ReferenceCounter . new ( project . gl_repository ( is_wiki : true ) ) . increase
expect ( ProjectMigrateHashedStorageWorker ) . to receive ( :perform_in )
project . migrate_to_hashed_storage!
end
it 'schedules ProjectMigrateHashedStorageWorker' do
expect ( ProjectMigrateHashedStorageWorker ) . to receive ( :perform_async ) . with ( project . id )
project . migrate_to_hashed_storage!
end
end
end
context 'hashed storage' do
2019-03-02 22:35:43 +05:30
set ( :project ) { create ( :project , :repository , skip_disk_validation : true ) }
2018-03-17 18:26:18 +05:30
let ( :gitlab_shell ) { Gitlab :: Shell . new }
let ( :hash ) { Digest :: SHA2 . hexdigest ( project . id . to_s ) }
2018-03-27 19:54:05 +05:30
let ( :hashed_prefix ) { File . join ( '@hashed' , hash [ 0 .. 1 ] , hash [ 2 .. 3 ] ) }
let ( :hashed_path ) { File . join ( hashed_prefix , hash ) }
2018-03-17 18:26:18 +05:30
before do
stub_application_setting ( hashed_storage_enabled : true )
end
describe '#legacy_storage?' do
it 'returns false' do
expect ( project . legacy_storage? ) . to be_falsey
end
end
describe '#hashed_storage?' do
it 'returns true if rolled out' do
expect ( project . hashed_storage? ( :attachments ) ) . to be_truthy
end
it 'returns false when not rolled out yet' do
project . storage_version = 1
expect ( project . hashed_storage? ( :attachments ) ) . to be_falsey
end
end
describe '#base_dir' do
it 'returns base_dir based on hash of project id' do
2018-03-27 19:54:05 +05:30
expect ( project . base_dir ) . to eq ( hashed_prefix )
2018-03-17 18:26:18 +05:30
end
end
describe '#disk_path' do
it 'returns disk_path based on hash of project id' do
expect ( project . disk_path ) . to eq ( hashed_path )
end
end
describe '#ensure_storage_path_exists' do
it 'delegates to gitlab_shell to ensure namespace is created' do
allow ( project ) . to receive ( :gitlab_shell ) . and_return ( gitlab_shell )
2018-10-15 14:42:47 +05:30
expect ( gitlab_shell ) . to receive ( :add_namespace ) . with ( project . repository_storage , hashed_prefix )
2018-03-17 18:26:18 +05:30
project . ensure_storage_path_exists
end
end
describe '#pages_path' do
it 'returns a path where pages are stored' do
expect ( project . pages_path ) . to eq ( File . join ( Settings . pages . path , project . namespace . full_path , project . path ) )
end
end
describe '#migrate_to_hashed_storage!' do
2019-03-02 22:35:43 +05:30
let ( :project ) { create ( :project , :repository , skip_disk_validation : true ) }
2018-03-17 18:26:18 +05:30
it 'returns nil' do
expect ( project . migrate_to_hashed_storage! ) . to be_nil
end
it 'does not flag as read-only' do
expect { project . migrate_to_hashed_storage! } . not_to change { project . repository_read_only }
end
2019-02-15 15:39:39 +05:30
context 'when partially migrated' do
2019-03-02 22:35:43 +05:30
it 'enqueues a job' do
2019-02-15 15:39:39 +05:30
project = create ( :project , storage_version : 1 , skip_disk_validation : true )
2019-03-02 22:35:43 +05:30
Sidekiq :: Testing . fake! do
expect { project . migrate_to_hashed_storage! } . to change ( ProjectMigrateHashedStorageWorker . jobs , :size ) . by ( 1 )
end
2019-02-15 15:39:39 +05:30
end
end
2018-03-17 18:26:18 +05:30
end
end
describe '#gl_repository' do
let ( :project ) { create ( :project ) }
it 'delegates to Gitlab::GlRepository.gl_repository' do
expect ( Gitlab :: GlRepository ) . to receive ( :gl_repository ) . with ( project , true )
project . gl_repository ( is_wiki : true )
end
end
describe '#has_ci?' do
set ( :project ) { create ( :project ) }
let ( :repository ) { double }
before do
expect ( project ) . to receive ( :repository ) { repository }
end
context 'when has .gitlab-ci.yml' do
before do
expect ( repository ) . to receive ( :gitlab_ci_yml ) { 'content' }
end
it " CI is available " do
expect ( project ) . to have_ci
end
end
context 'when there is no .gitlab-ci.yml' do
before do
expect ( repository ) . to receive ( :gitlab_ci_yml ) { nil }
end
2018-11-20 20:47:30 +05:30
it " CI is available " do
expect ( project ) . to have_ci
2018-03-17 18:26:18 +05:30
end
2018-11-20 20:47:30 +05:30
context 'when auto devops is disabled' do
2018-03-17 18:26:18 +05:30
before do
2018-11-20 20:47:30 +05:30
stub_application_setting ( auto_devops_enabled : false )
2018-03-17 18:26:18 +05:30
end
2018-11-20 20:47:30 +05:30
it " CI is not available " do
expect ( project ) . not_to have_ci
2018-03-17 18:26:18 +05:30
end
end
end
end
describe '#auto_devops_enabled?' do
2018-11-20 20:47:30 +05:30
before do
allow ( Feature ) . to receive ( :enabled? ) . and_call_original
Feature . get ( :force_autodevops_on_by_default ) . enable_percentage_of_actors ( 0 )
end
2018-03-17 18:26:18 +05:30
set ( :project ) { create ( :project ) }
subject { project . auto_devops_enabled? }
context 'when enabled in settings' do
before do
stub_application_setting ( auto_devops_enabled : true )
end
2018-11-20 20:47:30 +05:30
it { is_expected . to be_truthy }
2018-03-17 18:26:18 +05:30
context 'when explicitly enabled' do
before do
create ( :project_auto_devops , project : project )
end
2018-11-20 20:47:30 +05:30
it { is_expected . to be_truthy }
2018-03-17 18:26:18 +05:30
end
context 'when explicitly disabled' do
before do
create ( :project_auto_devops , project : project , enabled : false )
end
2018-11-20 20:47:30 +05:30
it { is_expected . to be_falsey }
2018-03-17 18:26:18 +05:30
end
end
context 'when disabled in settings' do
before do
stub_application_setting ( auto_devops_enabled : false )
end
2018-11-20 20:47:30 +05:30
it { is_expected . to be_falsey }
2018-03-17 18:26:18 +05:30
context 'when explicitly enabled' do
before do
create ( :project_auto_devops , project : project )
end
2018-11-20 20:47:30 +05:30
it { is_expected . to be_truthy }
end
context 'when force_autodevops_on_by_default is enabled for the project' do
before do
Feature . get ( :force_autodevops_on_by_default ) . enable_percentage_of_actors ( 100 )
2018-03-17 18:26:18 +05:30
end
2018-11-20 20:47:30 +05:30
it { is_expected . to be_truthy }
2018-03-17 18:26:18 +05:30
end
end
end
2018-11-18 11:00:15 +05:30
describe '#has_auto_devops_implicitly_enabled?' do
set ( :project ) { create ( :project ) }
context 'when disabled in settings' do
before do
stub_application_setting ( auto_devops_enabled : false )
end
it 'does not have auto devops implicitly disabled' do
expect ( project ) . not_to have_auto_devops_implicitly_enabled
end
end
context 'when enabled in settings' do
before do
stub_application_setting ( auto_devops_enabled : true )
end
it 'auto devops is implicitly disabled' do
expect ( project ) . to have_auto_devops_implicitly_enabled
end
context 'when explicitly disabled' do
before do
create ( :project_auto_devops , project : project , enabled : false )
end
it 'does not have auto devops implicitly disabled' do
expect ( project ) . not_to have_auto_devops_implicitly_enabled
end
end
context 'when explicitly enabled' do
before do
create ( :project_auto_devops , project : project , enabled : true )
end
it 'does not have auto devops implicitly disabled' do
expect ( project ) . not_to have_auto_devops_implicitly_enabled
end
end
end
end
2018-03-17 18:26:18 +05:30
describe '#has_auto_devops_implicitly_disabled?' do
2018-11-20 20:47:30 +05:30
before do
allow ( Feature ) . to receive ( :enabled? ) . and_call_original
Feature . get ( :force_autodevops_on_by_default ) . enable_percentage_of_actors ( 0 )
end
2018-03-17 18:26:18 +05:30
set ( :project ) { create ( :project ) }
context 'when enabled in settings' do
before do
stub_application_setting ( auto_devops_enabled : true )
end
it 'does not have auto devops implicitly disabled' do
expect ( project ) . not_to have_auto_devops_implicitly_disabled
end
end
context 'when disabled in settings' do
before do
stub_application_setting ( auto_devops_enabled : false )
end
it 'auto devops is implicitly disabled' do
expect ( project ) . to have_auto_devops_implicitly_disabled
end
2018-11-20 20:47:30 +05:30
context 'when force_autodevops_on_by_default is enabled for the project' do
before do
Feature . get ( :force_autodevops_on_by_default ) . enable_percentage_of_actors ( 100 )
end
it 'does not have auto devops implicitly disabled' do
expect ( project ) . not_to have_auto_devops_implicitly_disabled
end
end
2018-03-17 18:26:18 +05:30
context 'when explicitly disabled' do
before do
create ( :project_auto_devops , project : project , enabled : false )
end
it 'does not have auto devops implicitly disabled' do
expect ( project ) . not_to have_auto_devops_implicitly_disabled
end
end
context 'when explicitly enabled' do
before do
2018-11-18 11:00:15 +05:30
create ( :project_auto_devops , project : project , enabled : true )
2018-03-17 18:26:18 +05:30
end
it 'does not have auto devops implicitly disabled' do
expect ( project ) . not_to have_auto_devops_implicitly_disabled
end
end
end
end
2019-02-15 15:39:39 +05:30
describe '#api_variables' do
set ( :project ) { create ( :project ) }
it 'exposes API v4 URL' do
expect ( project . api_variables . first [ :key ] ) . to eq 'CI_API_V4_URL'
expect ( project . api_variables . first [ :value ] ) . to include '/api/v4'
end
it 'contains a URL variable for every supported API version' do
# Ensure future API versions have proper variables defined. We're not doing this for v3.
supported_versions = API :: API . versions - [ 'v3' ]
supported_versions = supported_versions . select do | version |
API :: API . routes . select { | route | route . version == version } . many?
end
required_variables = supported_versions . map do | version |
" CI_API_ #{ version . upcase } _URL "
end
expect ( project . api_variables . map { | variable | variable [ :key ] } )
. to contain_exactly ( * required_variables )
end
end
describe '#auto_devops_variables' do
2018-03-17 18:26:18 +05:30
set ( :project ) { create ( :project ) }
subject { project . auto_devops_variables }
context 'when enabled in instance settings' do
before do
stub_application_setting ( auto_devops_enabled : true )
end
context 'when domain is empty' do
before do
stub_application_setting ( auto_devops_domain : nil )
end
it 'variables does not include AUTO_DEVOPS_DOMAIN' do
is_expected . not_to include ( domain_variable )
end
end
context 'when domain is configured' do
before do
stub_application_setting ( auto_devops_domain : 'example.com' )
end
it 'variables includes AUTO_DEVOPS_DOMAIN' do
is_expected . to include ( domain_variable )
end
end
end
2018-12-13 13:39:08 +05:30
context 'when explicitly enabled' do
2018-03-17 18:26:18 +05:30
context 'when domain is empty' do
before do
create ( :project_auto_devops , project : project , domain : nil )
end
it 'variables does not include AUTO_DEVOPS_DOMAIN' do
is_expected . not_to include ( domain_variable )
end
end
context 'when domain is configured' do
before do
create ( :project_auto_devops , project : project , domain : 'example.com' )
end
it 'variables includes AUTO_DEVOPS_DOMAIN' do
is_expected . to include ( domain_variable )
end
end
end
def domain_variable
{ key : 'AUTO_DEVOPS_DOMAIN' , value : 'example.com' , public : true }
end
end
describe '#latest_successful_builds_for' do
let ( :project ) { build ( :project ) }
before do
allow ( project ) . to receive ( :default_branch ) . and_return ( 'master' )
end
context 'without a ref' do
it 'returns a pipeline for the default branch' do
expect ( project )
. to receive ( :latest_successful_pipeline_for_default_branch )
project . latest_successful_pipeline_for
end
end
context 'with the ref set to the default branch' do
it 'returns a pipeline for the default branch' do
expect ( project )
. to receive ( :latest_successful_pipeline_for_default_branch )
project . latest_successful_pipeline_for ( project . default_branch )
end
end
context 'with a ref that is not the default branch' do
it 'returns the latest successful pipeline for the given ref' do
2019-02-15 15:39:39 +05:30
expect ( project . ci_pipelines ) . to receive ( :latest_successful_for ) . with ( 'foo' )
2018-03-17 18:26:18 +05:30
project . latest_successful_pipeline_for ( 'foo' )
end
end
end
describe '#check_repository_path_availability' do
let ( :project ) { build ( :project ) }
it 'skips gitlab-shell exists?' do
project . skip_disk_validation = true
expect ( project . gitlab_shell ) . not_to receive ( :exists? )
expect ( project . check_repository_path_availability ) . to be_truthy
end
end
describe '#latest_successful_pipeline_for_default_branch' do
let ( :project ) { build ( :project ) }
before do
allow ( project ) . to receive ( :default_branch ) . and_return ( 'master' )
end
it 'memoizes and returns the latest successful pipeline for the default branch' do
pipeline = double ( :pipeline )
2019-02-15 15:39:39 +05:30
expect ( project . ci_pipelines ) . to receive ( :latest_successful_for )
2018-03-17 18:26:18 +05:30
. with ( project . default_branch )
. and_return ( pipeline )
. once
2 . times do
expect ( project . latest_successful_pipeline_for_default_branch )
. to eq ( pipeline )
end
end
end
describe '#after_import' do
2018-11-08 19:23:39 +05:30
let ( :project ) { create ( :project ) }
2019-02-15 15:39:39 +05:30
let ( :import_state ) { create ( :import_state , project : project ) }
2018-03-17 18:26:18 +05:30
it 'runs the correct hooks' do
expect ( project . repository ) . to receive ( :after_import )
2018-11-08 19:23:39 +05:30
expect ( project . wiki . repository ) . to receive ( :after_import )
2019-02-15 15:39:39 +05:30
expect ( import_state ) . to receive ( :finish )
2018-03-17 18:26:18 +05:30
expect ( project ) . to receive ( :update_project_counter_caches )
2019-02-15 15:39:39 +05:30
expect ( import_state ) . to receive ( :remove_jid )
2018-03-17 18:26:18 +05:30
expect ( project ) . to receive ( :after_create_default_branch )
2018-05-09 12:01:36 +05:30
expect ( project ) . to receive ( :refresh_markdown_cache! )
2019-03-02 22:35:43 +05:30
expect ( InternalId ) . to receive ( :flush_records! ) . with ( project : project )
2018-03-17 18:26:18 +05:30
project . after_import
end
context 'branch protection' do
let ( :project ) { create ( :project , :repository ) }
2019-02-15 15:39:39 +05:30
before do
create ( :import_state , :started , project : project )
end
2018-03-17 18:26:18 +05:30
it 'does not protect when branch protection is disabled' do
stub_application_setting ( default_branch_protection : Gitlab :: Access :: PROTECTION_NONE )
project . after_import
expect ( project . protected_branches ) . to be_empty
end
it " gives developer access to push when branch protection is set to 'developers can push' " do
stub_application_setting ( default_branch_protection : Gitlab :: Access :: PROTECTION_DEV_CAN_PUSH )
project . after_import
expect ( project . protected_branches ) . not_to be_empty
expect ( project . default_branch ) . to eq ( project . protected_branches . first . name )
expect ( project . protected_branches . first . push_access_levels . map ( & :access_level ) ) . to eq ( [ Gitlab :: Access :: DEVELOPER ] )
end
it " gives developer access to merge when branch protection is set to 'developers can merge' " do
stub_application_setting ( default_branch_protection : Gitlab :: Access :: PROTECTION_DEV_CAN_MERGE )
project . after_import
expect ( project . protected_branches ) . not_to be_empty
expect ( project . default_branch ) . to eq ( project . protected_branches . first . name )
expect ( project . protected_branches . first . merge_access_levels . map ( & :access_level ) ) . to eq ( [ Gitlab :: Access :: DEVELOPER ] )
end
it 'protects default branch' do
project . after_import
expect ( project . protected_branches ) . not_to be_empty
expect ( project . default_branch ) . to eq ( project . protected_branches . first . name )
2018-11-18 11:00:15 +05:30
expect ( project . protected_branches . first . push_access_levels . map ( & :access_level ) ) . to eq ( [ Gitlab :: Access :: MAINTAINER ] )
expect ( project . protected_branches . first . merge_access_levels . map ( & :access_level ) ) . to eq ( [ Gitlab :: Access :: MAINTAINER ] )
2018-03-17 18:26:18 +05:30
end
end
end
describe '#update_project_counter_caches' do
let ( :project ) { create ( :project ) }
it 'updates all project counter caches' do
expect_any_instance_of ( Projects :: OpenIssuesCountService )
. to receive ( :refresh_cache )
. and_call_original
expect_any_instance_of ( Projects :: OpenMergeRequestsCountService )
. to receive ( :refresh_cache )
. and_call_original
project . update_project_counter_caches
end
end
describe '#wiki_repository_exists?' do
it 'returns true when the wiki repository exists' do
project = create ( :project , :wiki_repo )
expect ( project . wiki_repository_exists? ) . to eq ( true )
end
it 'returns false when the wiki repository does not exist' do
project = create ( :project )
expect ( project . wiki_repository_exists? ) . to eq ( false )
end
end
describe '#write_repository_config' do
set ( :project ) { create ( :project , :repository ) }
it 'writes full path in .git/config when key is missing' do
project . write_repository_config
2018-11-08 19:23:39 +05:30
expect ( rugged_config [ 'gitlab.fullpath' ] ) . to eq project . full_path
2018-03-17 18:26:18 +05:30
end
it 'updates full path in .git/config when key is present' do
project . write_repository_config ( gl_full_path : 'old/path' )
2018-11-08 19:23:39 +05:30
expect { project . write_repository_config } . to change { rugged_config [ 'gitlab.fullpath' ] } . from ( 'old/path' ) . to ( project . full_path )
2018-03-17 18:26:18 +05:30
end
it 'does not raise an error with an empty repository' do
project = create ( :project_empty_repo )
expect { project . write_repository_config } . not_to raise_error
end
end
describe '#execute_hooks' do
2018-11-20 20:47:30 +05:30
let ( :data ) { { ref : 'refs/heads/master' , data : 'data' } }
it 'executes active projects hooks with the specified scope' do
hook = create ( :project_hook , merge_requests_events : false , push_events : true )
expect ( ProjectHook ) . to receive ( :select_active )
. with ( :push_hooks , data )
. and_return ( [ hook ] )
project = create ( :project , hooks : [ hook ] )
2018-03-17 18:26:18 +05:30
expect_any_instance_of ( ProjectHook ) . to receive ( :async_execute ) . once
2018-11-20 20:47:30 +05:30
project . execute_hooks ( data , :push_hooks )
end
it 'does not execute project hooks that dont match the specified scope' do
hook = create ( :project_hook , merge_requests_events : true , push_events : false )
project = create ( :project , hooks : [ hook ] )
expect_any_instance_of ( ProjectHook ) . not_to receive ( :async_execute ) . once
project . execute_hooks ( data , :push_hooks )
end
it 'does not execute project hooks which are not active' do
hook = create ( :project_hook , push_events : true )
expect ( ProjectHook ) . to receive ( :select_active )
. with ( :push_hooks , data )
. and_return ( [ ] )
project = create ( :project , hooks : [ hook ] )
expect_any_instance_of ( ProjectHook ) . not_to receive ( :async_execute ) . once
project . execute_hooks ( data , :push_hooks )
2018-03-17 18:26:18 +05:30
end
it 'executes the system hooks with the specified scope' do
2018-11-20 20:47:30 +05:30
expect_any_instance_of ( SystemHooksService ) . to receive ( :execute_hooks ) . with ( data , :merge_request_hooks )
2018-03-17 18:26:18 +05:30
project = build ( :project )
2018-11-20 20:47:30 +05:30
project . execute_hooks ( data , :merge_request_hooks )
2018-03-17 18:26:18 +05:30
end
it 'executes the system hooks when inside a transaction' do
allow_any_instance_of ( WebHookService ) . to receive ( :execute )
create ( :system_hook , merge_requests_events : true )
project = build ( :project )
# Ideally, we'd test that `WebHookWorker.jobs.size` increased by 1,
# but since the entire spec run takes place in a transaction, we never
# actually get to the `after_commit` hook that queues these jobs.
expect do
project . transaction do
2018-11-20 20:47:30 +05:30
project . execute_hooks ( data , :merge_request_hooks )
2018-03-17 18:26:18 +05:30
end
end . not_to raise_error # Sidekiq::Worker::EnqueueFromTransactionError
end
end
2018-03-27 19:54:05 +05:30
describe '#badges' do
let ( :project_group ) { create ( :group ) }
2019-03-02 22:35:43 +05:30
let ( :project ) { create ( :project , path : 'avatar' , namespace : project_group ) }
2018-03-27 19:54:05 +05:30
before do
create_list ( :project_badge , 2 , project : project )
create ( :group_badge , group : project_group )
end
it 'returns the project and the project group badges' do
create ( :group_badge , group : create ( :group ) )
expect ( Badge . count ) . to eq 4
expect ( project . badges . count ) . to eq 3
end
2019-02-15 15:39:39 +05:30
if Group . supports_nested_objects?
2018-03-27 19:54:05 +05:30
context 'with nested_groups' do
let ( :parent_group ) { create ( :group ) }
before do
create_list ( :group_badge , 2 , group : project_group )
project_group . update ( parent : parent_group )
end
it 'returns the project and the project nested groups badges' do
expect ( project . badges . count ) . to eq 5
end
end
end
end
context 'with cross project merge requests' do
let ( :user ) { create ( :user ) }
let ( :target_project ) { create ( :project , :repository ) }
let ( :project ) { fork_project ( target_project , nil , repository : true ) }
2019-02-15 15:39:39 +05:30
let! ( :local_merge_request ) do
create (
:merge_request ,
target_project : project ,
target_branch : 'target-branch' ,
source_project : project ,
source_branch : 'awesome-feature-1' ,
allow_collaboration : true
)
end
2018-03-27 19:54:05 +05:30
let! ( :merge_request ) do
create (
:merge_request ,
target_project : target_project ,
target_branch : 'target-branch' ,
source_project : project ,
source_branch : 'awesome-feature-1' ,
2018-11-08 19:23:39 +05:30
allow_collaboration : true
2018-03-27 19:54:05 +05:30
)
end
before do
target_project . add_developer ( user )
end
describe '#merge_requests_allowing_push_to_user' do
it 'returns open merge requests for which the user has developer access to the target project' do
expect ( project . merge_requests_allowing_push_to_user ( user ) ) . to include ( merge_request )
end
it 'does not include closed merge requests' do
merge_request . close
expect ( project . merge_requests_allowing_push_to_user ( user ) ) . to be_empty
end
it 'does not include merge requests for guest users' do
guest = create ( :user )
target_project . add_guest ( guest )
expect ( project . merge_requests_allowing_push_to_user ( guest ) ) . to be_empty
end
it 'does not include the merge request for other users' do
other_user = create ( :user )
expect ( project . merge_requests_allowing_push_to_user ( other_user ) ) . to be_empty
end
it 'is empty when no user is passed' do
expect ( project . merge_requests_allowing_push_to_user ( nil ) ) . to be_empty
end
end
2019-02-15 15:39:39 +05:30
describe '#any_branch_allows_collaboration?' do
it 'allows access when there are merge requests open allowing collaboration' do
expect ( project . any_branch_allows_collaboration? ( user ) )
2018-11-08 19:23:39 +05:30
. to be_truthy
end
2019-02-15 15:39:39 +05:30
it 'does not allow access when there are no merge requests open allowing collaboration' do
merge_request . close!
expect ( project . any_branch_allows_collaboration? ( user ) )
. to be_falsey
end
end
describe '#branch_allows_collaboration?' do
it 'allows access if the user can merge the merge request' do
expect ( project . branch_allows_collaboration? ( user , 'awesome-feature-1' ) )
2018-03-27 19:54:05 +05:30
. to be_truthy
end
it 'does not allow guest users access' do
guest = create ( :user )
target_project . add_guest ( guest )
2018-11-08 19:23:39 +05:30
expect ( project . branch_allows_collaboration? ( guest , 'awesome-feature-1' ) )
2018-03-27 19:54:05 +05:30
. to be_falsy
end
it 'does not allow access to branches for which the merge request was closed' do
create ( :merge_request , :closed ,
target_project : target_project ,
target_branch : 'target-branch' ,
source_project : project ,
source_branch : 'rejected-feature-1' ,
2018-11-08 19:23:39 +05:30
allow_collaboration : true )
2018-03-27 19:54:05 +05:30
2018-11-08 19:23:39 +05:30
expect ( project . branch_allows_collaboration? ( user , 'rejected-feature-1' ) )
2018-03-27 19:54:05 +05:30
. to be_falsy
end
it 'does not allow access if the user cannot merge the merge request' do
2018-11-18 11:00:15 +05:30
create ( :protected_branch , :maintainers_can_push , project : target_project , name : 'target-branch' )
2018-03-27 19:54:05 +05:30
2018-11-08 19:23:39 +05:30
expect ( project . branch_allows_collaboration? ( user , 'awesome-feature-1' ) )
2018-03-27 19:54:05 +05:30
. to be_falsy
end
context 'when the requeststore is active' , :request_store do
it 'only queries per project across instances' do
2018-11-08 19:23:39 +05:30
control = ActiveRecord :: QueryRecorder . new { project . branch_allows_collaboration? ( user , 'awesome-feature-1' ) }
2018-03-27 19:54:05 +05:30
2018-11-08 19:23:39 +05:30
expect { 2 . times { described_class . find ( project . id ) . branch_allows_collaboration? ( user , 'awesome-feature-1' ) } }
2018-03-27 19:54:05 +05:30
. not_to exceed_query_limit ( control ) . with_threshold ( 2 )
end
end
end
end
2018-05-09 12:01:36 +05:30
describe " # pages_https_only? " do
subject { build ( :project ) }
context " when HTTPS pages are disabled " do
it { is_expected . not_to be_pages_https_only }
end
context " when HTTPS pages are enabled " , :https_pages_enabled do
it { is_expected . to be_pages_https_only }
end
end
describe " # pages_https_only? validation " , :https_pages_enabled do
subject ( :project ) do
# set-up dirty object:
create ( :project , pages_https_only : false ) . tap do | p |
p . pages_https_only = true
end
end
context " when no domains are associated " do
it { is_expected . to be_valid }
end
context " when domains including keys and certificates are associated " do
before do
allow ( project )
. to receive ( :pages_domains )
. and_return ( [ instance_double ( PagesDomain , https? : true ) ] )
end
it { is_expected . to be_valid }
end
context " when domains including no keys or certificates are associated " do
before do
allow ( project )
. to receive ( :pages_domains )
. and_return ( [ instance_double ( PagesDomain , https? : false ) ] )
end
it { is_expected . not_to be_valid }
end
end
2018-10-15 14:42:47 +05:30
describe '#toggle_ci_cd_settings!' do
it 'toggles the value on #settings' do
project = create ( :project , group_runners_enabled : false )
expect ( project . group_runners_enabled ) . to be false
project . toggle_ci_cd_settings! ( :group_runners_enabled )
expect ( project . group_runners_enabled ) . to be true
end
end
describe '#gitlab_deploy_token' do
let ( :project ) { create ( :project ) }
subject { project . gitlab_deploy_token }
context 'when there is a gitlab deploy token associated' do
let! ( :deploy_token ) { create ( :deploy_token , :gitlab_deploy_token , projects : [ project ] ) }
it { is_expected . to eq ( deploy_token ) }
end
context 'when there is no a gitlab deploy token associated' do
it { is_expected . to be_nil }
end
context 'when there is a gitlab deploy token associated but is has been revoked' do
let! ( :deploy_token ) { create ( :deploy_token , :gitlab_deploy_token , :revoked , projects : [ project ] ) }
it { is_expected . to be_nil }
end
context 'when there is a gitlab deploy token associated but it is expired' do
let! ( :deploy_token ) { create ( :deploy_token , :gitlab_deploy_token , :expired , projects : [ project ] ) }
it { is_expected . to be_nil }
end
context 'when there is a deploy token associated with a different name' do
let! ( :deploy_token ) { create ( :deploy_token , projects : [ project ] ) }
it { is_expected . to be_nil }
end
context 'when there is a deploy token associated to a different project' do
let ( :project_2 ) { create ( :project ) }
let! ( :deploy_token ) { create ( :deploy_token , projects : [ project_2 ] ) }
it { is_expected . to be_nil }
end
end
2018-11-08 19:23:39 +05:30
context 'with uploads' do
2019-02-15 15:39:39 +05:30
it_behaves_like 'model with uploads' , true do
2018-11-08 19:23:39 +05:30
let ( :model_object ) { create ( :project , :with_avatar ) }
let ( :upload_attribute ) { :avatar }
let ( :uploader_class ) { AttachmentUploader }
end
end
2018-11-18 11:00:15 +05:30
context '#commits_by' do
let ( :project ) { create ( :project , :repository ) }
let ( :commits ) { project . repository . commits ( 'HEAD' , limit : 3 ) . commits }
let ( :commit_shas ) { commits . map ( & :id ) }
it 'retrieves several commits from the repository by oid' do
expect ( project . commits_by ( oids : commit_shas ) ) . to eq commits
end
end
2018-12-05 23:21:45 +05:30
context '#members_among' do
let ( :users ) { create_list ( :user , 3 ) }
set ( :group ) { create ( :group ) }
set ( :project ) { create ( :project , namespace : group ) }
before do
project . add_guest ( users . first )
project . group . add_maintainer ( users . last )
end
context 'when users is an Array' do
it 'returns project members among the users' do
expect ( project . members_among ( users ) ) . to eq ( [ users . first , users . last ] )
end
it 'maintains input order' do
expect ( project . members_among ( users . reverse ) ) . to eq ( [ users . last , users . first ] )
end
it 'returns empty array if users is empty' do
result = project . members_among ( [ ] )
expect ( result ) . to be_empty
end
end
context 'when users is a relation' do
it 'returns project members among the users' do
result = project . members_among ( User . where ( id : users . map ( & :id ) ) )
expect ( result ) . to be_a ( ActiveRecord :: Relation )
expect ( result ) . to eq ( [ users . first , users . last ] )
end
it 'returns empty relation if users is empty' do
result = project . members_among ( User . none )
expect ( result ) . to be_a ( ActiveRecord :: Relation )
expect ( result ) . to be_empty
end
end
end
describe " # find_or_initialize_services " do
subject { build ( :project ) }
it 'returns only enabled services' do
allow ( Service ) . to receive ( :available_services_names ) . and_return ( %w( prometheus pushover ) )
allow ( subject ) . to receive ( :disabled_services ) . and_return ( %w( prometheus ) )
services = subject . find_or_initialize_services
expect ( services . count ) . to eq 1
expect ( services ) . to include ( PushoverService )
end
end
describe " # find_or_initialize_service " do
subject { build ( :project ) }
it 'avoids N+1 database queries' do
allow ( Service ) . to receive ( :available_services_names ) . and_return ( %w( prometheus pushover ) )
control_count = ActiveRecord :: QueryRecorder . new { subject . find_or_initialize_service ( 'prometheus' ) } . count
allow ( Service ) . to receive ( :available_services_names ) . and_call_original
expect { subject . find_or_initialize_service ( 'prometheus' ) } . not_to exceed_query_limit ( control_count )
2018-11-08 19:23:39 +05:30
end
2018-12-05 23:21:45 +05:30
it 'returns nil if service is disabled' do
allow ( subject ) . to receive ( :disabled_services ) . and_return ( %w( prometheus ) )
expect ( subject . find_or_initialize_service ( 'prometheus' ) ) . to be_nil
end
end
2018-12-13 13:39:08 +05:30
describe '.find_without_deleted' do
it 'returns nil if the project is about to be removed' do
project = create ( :project , pending_delete : true )
expect ( described_class . find_without_deleted ( project . id ) ) . to be_nil
end
it 'returns a project when it is not about to be removed' do
project = create ( :project )
expect ( described_class . find_without_deleted ( project . id ) ) . to eq ( project )
end
end
describe '.for_group' do
it 'returns the projects for a given group' do
group = create ( :group )
project = create ( :project , namespace : group )
expect ( described_class . for_group ( group ) ) . to eq ( [ project ] )
end
end
describe '.deployments' do
subject { project . deployments }
let ( :project ) { create ( :project ) }
before do
allow_any_instance_of ( Deployment ) . to receive ( :create_ref )
end
context 'when there is a deployment record with created status' do
let ( :deployment ) { create ( :deployment , :created , project : project ) }
it 'does not return the record' do
is_expected . to be_empty
end
end
context 'when there is a deployment record with running status' do
let ( :deployment ) { create ( :deployment , :running , project : project ) }
it 'does not return the record' do
is_expected . to be_empty
end
end
context 'when there is a deployment record with success status' do
let ( :deployment ) { create ( :deployment , :success , project : project ) }
it 'returns the record' do
is_expected . to eq ( [ deployment ] )
end
end
end
describe '#snippets_visible?' do
it 'returns true when a logged in user can read snippets' do
project = create ( :project , :public )
user = create ( :user )
expect ( project . snippets_visible? ( user ) ) . to eq ( true )
end
it 'returns true when an anonymous user can read snippets' do
project = create ( :project , :public )
expect ( project . snippets_visible? ) . to eq ( true )
end
it 'returns false when a user can not read snippets' do
project = create ( :project , :private )
user = create ( :user )
expect ( project . snippets_visible? ( user ) ) . to eq ( false )
end
end
2019-02-15 15:39:39 +05:30
describe '#all_clusters' do
let ( :project ) { create ( :project ) }
let ( :cluster ) { create ( :cluster , cluster_type : :project_type , projects : [ project ] ) }
subject { project . all_clusters }
it 'returns project level cluster' do
expect ( subject ) . to eq ( [ cluster ] )
end
context 'project belongs to a group' do
let ( :group_cluster ) { create ( :cluster , :group ) }
let ( :group ) { group_cluster . group }
let ( :project ) { create ( :project , group : group ) }
it 'returns clusters for groups of this project' do
expect ( subject ) . to contain_exactly ( cluster , group_cluster )
end
end
end
describe '#object_pool_params' do
let ( :project ) { create ( :project , :repository , :public ) }
subject { project . object_pool_params }
before do
stub_application_setting ( hashed_storage_enabled : true )
end
context 'when the objects cannot be pooled' do
let ( :project ) { create ( :project , :repository , :private ) }
it { is_expected . to be_empty }
end
context 'when a pool is created' do
it 'returns that pool repository' do
expect ( subject ) . not_to be_empty
expect ( subject [ :pool_repository ] ) . to be_persisted
end
end
end
describe '#git_objects_poolable?' do
subject { project }
context 'when the feature flag is turned off' do
before do
stub_feature_flags ( object_pools : false )
end
let ( :project ) { create ( :project , :repository , :public ) }
it { is_expected . not_to be_git_objects_poolable }
end
context 'when the feature flag is enabled' do
context 'when not using hashed storage' do
let ( :project ) { create ( :project , :legacy_storage , :public , :repository ) }
it { is_expected . not_to be_git_objects_poolable }
end
context 'when the project is not public' do
let ( :project ) { create ( :project , :private ) }
it { is_expected . not_to be_git_objects_poolable }
end
context 'when objects are poolable' do
let ( :project ) { create ( :project , :repository , :public ) }
before do
stub_application_setting ( hashed_storage_enabled : true )
end
it { is_expected . to be_git_objects_poolable }
end
end
end
2019-03-02 22:35:43 +05:30
describe '#leave_pool_repository' do
let ( :pool ) { create ( :pool_repository ) }
let ( :project ) { create ( :project , :repository , pool_repository : pool ) }
it 'removes the membership' do
project . leave_pool_repository
expect ( pool . member_projects . reload ) . not_to include ( project )
end
end
describe '#check_personal_projects_limit' do
context 'when creating a project for a group' do
it 'does nothing' do
creator = build ( :user )
project = build ( :project , namespace : build ( :group ) , creator : creator )
allow ( creator )
. to receive ( :can_create_project? )
. and_return ( false )
project . check_personal_projects_limit
expect ( project . errors ) . to be_empty
end
end
context 'when the user is not allowed to create a personal project' do
let ( :user ) { build ( :user ) }
let ( :project ) { build ( :project , creator : user ) }
before do
allow ( user )
. to receive ( :can_create_project? )
. and_return ( false )
end
context 'when the project limit is zero' do
it 'adds a validation error' do
allow ( user )
. to receive ( :projects_limit )
. and_return ( 0 )
project . check_personal_projects_limit
expect ( project . errors [ :limit_reached ] . first )
. to match ( / Personal project creation is not allowed / )
end
end
context 'when the project limit is greater than zero' do
it 'adds a validation error' do
allow ( user )
. to receive ( :projects_limit )
. and_return ( 5 )
project . check_personal_projects_limit
expect ( project . errors [ :limit_reached ] . first )
. to match ( / Your project limit is 5 projects / )
end
end
end
context 'when the user is allowed to create personal projects' do
it 'does nothing' do
user = build ( :user )
project = build ( :project , creator : user )
allow ( user )
. to receive ( :can_create_project? )
. and_return ( true )
project . check_personal_projects_limit
expect ( project . errors ) . to be_empty
end
end
end
2018-12-05 23:21:45 +05:30
def rugged_config
rugged_repo ( project . repository ) . config
2018-11-08 19:23:39 +05:30
end
2019-03-02 22:35:43 +05:30
def create_pipeline ( project , status = 'success' )
create ( :ci_pipeline , project : project ,
sha : project . commit . sha ,
ref : project . default_branch ,
status : status )
end
def create_build ( new_pipeline = pipeline , name = 'test' )
create ( :ci_build , :success , :artifacts ,
pipeline : new_pipeline ,
status : new_pipeline . status ,
name : name )
end
2014-09-02 18:07:02 +05:30
end