summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-01-17 18:08:41 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-01-17 18:08:41 +0000
commit22a0d312ae82e7dda3073d5d1a5a766d7641738d (patch)
tree41a677a7212f24e2f29c2fbd5623430f92fb2b45 /spec
parent37eff29d5ce44899e34c7c2ac319b314f2f26d15 (diff)
downloadgitlab-ce-22a0d312ae82e7dda3073d5d1a5a766d7641738d.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects/forks_controller_spec.rb80
-rw-r--r--spec/factories/projects.rb5
-rw-r--r--spec/features/projects/features_visibility_spec.rb2
-rw-r--r--spec/features/projects/fork_spec.rb83
-rw-r--r--spec/features/projects/settings/project_settings_spec.rb20
-rw-r--r--spec/frontend/sidebar/assignees_spec.js1
-rw-r--r--spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js1
-rw-r--r--spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js1
-rw-r--r--spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js1
-rw-r--r--spec/graphql/types/group_type_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb6
-rw-r--r--spec/lib/gitlab/import_export/base_object_builder_spec.rb53
-rw-r--r--spec/lib/gitlab/import_export/base_relation_factory_spec.rb145
-rw-r--r--spec/lib/gitlab/import_export/project_relation_factory_spec.rb (renamed from spec/lib/gitlab/import_export/relation_factory_spec.rb)11
-rw-r--r--spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb4
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml1
-rw-r--r--spec/models/error_tracking/project_error_tracking_setting_spec.rb16
-rw-r--r--spec/requests/api/groups_spec.rb2
-rw-r--r--spec/requests/api/projects_spec.rb14
-rw-r--r--spec/services/projects/fork_service_spec.rb13
-rw-r--r--spec/services/system_note_service_spec.rb113
-rw-r--r--spec/services/system_notes/time_tracking_service_spec.rb129
-rw-r--r--spec/support/import_export/configuration_helper.rb4
23 files changed, 574 insertions, 137 deletions
diff --git a/spec/controllers/projects/forks_controller_spec.rb b/spec/controllers/projects/forks_controller_spec.rb
index 80b5eb9a7ee..e351fb2b1f6 100644
--- a/spec/controllers/projects/forks_controller_spec.rb
+++ b/spec/controllers/projects/forks_controller_spec.rb
@@ -12,6 +12,21 @@ describe Projects::ForksController do
group.add_owner(user)
end
+ shared_examples 'forking disabled' do
+ let(:project) { create(:project, :private, :repository, :forking_disabled) }
+
+ before do
+ project.add_developer(user)
+ sign_in(user)
+ end
+
+ it 'returns with 404' do
+ subject
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
describe 'GET index' do
def get_forks(search: nil)
get :index,
@@ -138,19 +153,19 @@ describe Projects::ForksController do
end
describe 'GET new' do
- def get_new
+ subject do
get :new,
- params: {
- namespace_id: project.namespace,
- project_id: project
- }
+ params: {
+ namespace_id: project.namespace,
+ project_id: project
+ }
end
context 'when user is signed in' do
it 'responds with status 200' do
sign_in(user)
- get_new
+ subject
expect(response).to have_gitlab_http_status(200)
end
@@ -160,21 +175,26 @@ describe Projects::ForksController do
it 'redirects to the sign-in page' do
sign_out(user)
- get_new
+ subject
expect(response).to redirect_to(new_user_session_path)
end
end
+
+ it_behaves_like 'forking disabled'
end
describe 'POST create' do
- def post_create(params = {})
- post :create,
- params: {
- namespace_id: project.namespace,
- project_id: project,
- namespace_key: user.namespace.id
- }.merge(params)
+ let(:params) do
+ {
+ namespace_id: project.namespace,
+ project_id: project,
+ namespace_key: user.namespace.id
+ }
+ end
+
+ subject do
+ post :create, params: params
end
context 'when user is signed in' do
@@ -183,18 +203,34 @@ describe Projects::ForksController do
end
it 'responds with status 302' do
- post_create
+ subject
expect(response).to have_gitlab_http_status(302)
expect(response).to redirect_to(namespace_project_import_path(user.namespace, project))
end
- it 'passes continue params to the redirect' do
- continue_params = { to: '/-/ide/project/path', notice: 'message' }
- post_create continue: continue_params
+ context 'continue params' do
+ let(:params) do
+ {
+ namespace_id: project.namespace,
+ project_id: project,
+ namespace_key: user.namespace.id,
+ continue: continue_params
+ }
+ end
+ let(:continue_params) do
+ {
+ to: '/-/ide/project/path',
+ notice: 'message'
+ }
+ end
- expect(response).to have_gitlab_http_status(302)
- expect(response).to redirect_to(namespace_project_import_path(user.namespace, project, continue: continue_params))
+ it 'passes continue params to the redirect' do
+ subject
+
+ expect(response).to have_gitlab_http_status(302)
+ expect(response).to redirect_to(namespace_project_import_path(user.namespace, project, continue: continue_params))
+ end
end
end
@@ -202,10 +238,12 @@ describe Projects::ForksController do
it 'redirects to the sign-in page' do
sign_out(user)
- post_create
+ subject
expect(response).to redirect_to(new_user_session_path)
end
end
+
+ it_behaves_like 'forking disabled'
end
end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 46efc0111c0..490ae9e84e7 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -25,6 +25,7 @@ FactoryBot.define do
builds_access_level { ProjectFeature::ENABLED }
snippets_access_level { ProjectFeature::ENABLED }
issues_access_level { ProjectFeature::ENABLED }
+ forking_access_level { ProjectFeature::ENABLED }
merge_requests_access_level { ProjectFeature::ENABLED }
repository_access_level { ProjectFeature::ENABLED }
pages_access_level do
@@ -48,6 +49,7 @@ FactoryBot.define do
builds_access_level: builds_access_level,
snippets_access_level: evaluator.snippets_access_level,
issues_access_level: evaluator.issues_access_level,
+ forking_access_level: evaluator.forking_access_level,
merge_requests_access_level: merge_requests_access_level,
repository_access_level: evaluator.repository_access_level
}
@@ -264,6 +266,9 @@ FactoryBot.define do
trait(:issues_disabled) { issues_access_level { ProjectFeature::DISABLED } }
trait(:issues_enabled) { issues_access_level { ProjectFeature::ENABLED } }
trait(:issues_private) { issues_access_level { ProjectFeature::PRIVATE } }
+ trait(:forking_disabled) { forking_access_level { ProjectFeature::DISABLED } }
+ trait(:forking_enabled) { forking_access_level { ProjectFeature::ENABLED } }
+ trait(:forking_private) { forking_access_level { ProjectFeature::PRIVATE } }
trait(:merge_requests_enabled) { merge_requests_access_level { ProjectFeature::ENABLED } }
trait(:merge_requests_disabled) { merge_requests_access_level { ProjectFeature::DISABLED } }
trait(:merge_requests_private) { merge_requests_access_level { ProjectFeature::PRIVATE } }
diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb
index a825911b01a..9854335a7ad 100644
--- a/spec/features/projects/features_visibility_spec.rb
+++ b/spec/features/projects/features_visibility_spec.rb
@@ -186,7 +186,7 @@ describe 'Edit Project Settings' do
click_button "Save changes"
end
- expect(find(".sharing-permissions")).to have_selector(".project-feature-toggle.is-disabled", count: 2)
+ expect(find(".sharing-permissions")).to have_selector(".project-feature-toggle.is-disabled", count: 3)
end
it "shows empty features project homepage" do
diff --git a/spec/features/projects/fork_spec.rb b/spec/features/projects/fork_spec.rb
index 0f97032eefa..bfab4387688 100644
--- a/spec/features/projects/fork_spec.rb
+++ b/spec/features/projects/fork_spec.rb
@@ -27,6 +27,89 @@ describe 'Project fork' do
expect(page).to have_css('a.disabled', text: 'Fork')
end
+ context 'forking enabled / disabled in project settings' do
+ before do
+ project.project_feature.update_attribute(
+ :forking_access_level, forking_access_level)
+ end
+
+ context 'forking is enabled' do
+ let(:forking_access_level) { ProjectFeature::ENABLED }
+
+ it 'enables fork button' do
+ visit project_path(project)
+
+ expect(page).to have_css('a', text: 'Fork')
+ expect(page).not_to have_css('a.disabled', text: 'Fork')
+ end
+
+ it 'renders new project fork page' do
+ visit new_project_fork_path(project)
+
+ expect(page.status_code).to eq(200)
+ expect(page).to have_text(' Select a namespace to fork the project ')
+ end
+ end
+
+ context 'forking is disabled' do
+ let(:forking_access_level) { ProjectFeature::DISABLED }
+
+ it 'does not render fork button' do
+ visit project_path(project)
+
+ expect(page).not_to have_css('a', text: 'Fork')
+ end
+
+ it 'does not render new project fork page' do
+ visit new_project_fork_path(project)
+
+ expect(page.status_code).to eq(404)
+ end
+ end
+
+ context 'forking is private' do
+ let(:forking_access_level) { ProjectFeature::PRIVATE }
+
+ before do
+ project.update(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+ end
+
+ context 'user is not a team member' do
+ it 'does not render fork button' do
+ visit project_path(project)
+
+ expect(page).not_to have_css('a', text: 'Fork')
+ end
+
+ it 'does not render new project fork page' do
+ visit new_project_fork_path(project)
+
+ expect(page.status_code).to eq(404)
+ end
+ end
+
+ context 'user is a team member' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'enables fork button' do
+ visit project_path(project)
+
+ expect(page).to have_css('a', text: 'Fork')
+ expect(page).not_to have_css('a.disabled', text: 'Fork')
+ end
+
+ it 'renders new project fork page' do
+ visit new_project_fork_path(project)
+
+ expect(page.status_code).to eq(200)
+ expect(page).to have_text(' Select a namespace to fork the project ')
+ end
+ end
+ end
+ end
+
it 'forks the project', :sidekiq_might_not_need_inline do
visit project_path(project)
diff --git a/spec/features/projects/settings/project_settings_spec.rb b/spec/features/projects/settings/project_settings_spec.rb
index 7afddc0e712..b601866c96b 100644
--- a/spec/features/projects/settings/project_settings_spec.rb
+++ b/spec/features/projects/settings/project_settings_spec.rb
@@ -34,6 +34,26 @@ describe 'Projects settings' do
expect_toggle_state(:expanded)
end
+ context 'forking enabled', :js do
+ it 'toggles forking enabled / disabled' do
+ visit edit_project_path(project)
+
+ forking_enabled_input = find('input[name="project[project_feature_attributes][forking_access_level]"]', visible: :hidden)
+ forking_enabled_button = find('input[name="project[project_feature_attributes][forking_access_level]"] + label > button')
+
+ expect(forking_enabled_input.value).to eq('20')
+
+ # disable by clicking toggle
+ forking_enabled_button.click
+ page.within('.sharing-permissions') do
+ find('input[value="Save changes"]').click
+ end
+ wait_for_requests
+
+ expect(forking_enabled_input.value).to eq('0')
+ end
+ end
+
def expect_toggle_state(state)
is_collapsed = state == :collapsed
diff --git a/spec/frontend/sidebar/assignees_spec.js b/spec/frontend/sidebar/assignees_spec.js
index fcd08dc2dc7..0cb182b2df4 100644
--- a/spec/frontend/sidebar/assignees_spec.js
+++ b/spec/frontend/sidebar/assignees_spec.js
@@ -15,7 +15,6 @@ describe('Assignee component', () => {
const createWrapper = (propsData = getDefaultProps()) => {
wrapper = mount(Assignee, {
propsData,
- attachToDocument: true,
});
};
diff --git a/spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js b/spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js
index 8d57fd94eb5..03d1ac3ab8d 100644
--- a/spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js
+++ b/spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js
@@ -23,7 +23,6 @@ describe('AssigneeAvatarLink component', () => {
};
wrapper = shallowMount(AssigneeAvatarLink, {
- attachToDocument: true,
propsData,
});
}
diff --git a/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js b/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js
index a303e5f493e..a1e19c1dd8e 100644
--- a/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js
+++ b/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js
@@ -16,7 +16,6 @@ describe('CollapsedAssigneeList component', () => {
};
wrapper = shallowMount(CollapsedAssigneeList, {
- attachToDocument: true,
propsData,
});
}
diff --git a/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js b/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js
index 6d8e62404e0..1cf0af48bef 100644
--- a/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js
+++ b/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js
@@ -18,7 +18,6 @@ describe('UncollapsedAssigneeList component', () => {
};
wrapper = mount(UncollapsedAssigneeList, {
- attachToDocument: true,
propsData,
});
}
diff --git a/spec/graphql/types/group_type_spec.rb b/spec/graphql/types/group_type_spec.rb
index 3dd5b602aa2..de11bad0723 100644
--- a/spec/graphql/types/group_type_spec.rb
+++ b/spec/graphql/types/group_type_spec.rb
@@ -8,4 +8,10 @@ describe GitlabSchema.types['Group'] do
it { expect(described_class.graphql_name).to eq('Group') }
it { expect(described_class).to require_graphql_authorizations(:read_group) }
+
+ it 'has the expected fields' do
+ expected_fields = %w[web_url avatar_url mentions_disabled parent]
+
+ is_expected.to include_graphql_fields(*expected_fields)
+ end
end
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index 058afddd73f..11168a969fc 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -1331,9 +1331,9 @@ module Gitlab
stub_feature_flags(ci_release_generation: false)
end
- it "returns release info" do
- expect(processor.stage_builds_attributes('release').first[:options].include?(config[:release]))
- .to be false
+ it 'raises error' do
+ expect { processor }.to raise_error(
+ 'jobs:release config release features are not enabled: release')
end
end
end
diff --git a/spec/lib/gitlab/import_export/base_object_builder_spec.rb b/spec/lib/gitlab/import_export/base_object_builder_spec.rb
new file mode 100644
index 00000000000..fbb3b08cf56
--- /dev/null
+++ b/spec/lib/gitlab/import_export/base_object_builder_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::ImportExport::BaseObjectBuilder do
+ let(:project) do
+ create(:project, :repository,
+ :builds_disabled,
+ :issues_disabled,
+ name: 'project',
+ path: 'project')
+ end
+ let(:klass) { Milestone }
+ let(:attributes) { { 'title' => 'Test BaseObjectBuilder Milestone', 'project' => project } }
+
+ subject { described_class.build(klass, attributes) }
+
+ describe '#build' do
+ context 'when object exists' do
+ context 'when where_clauses are implemented' do
+ before do
+ allow_next_instance_of(described_class) do |object_builder|
+ allow(object_builder).to receive(:where_clauses).and_return([klass.arel_table['title'].eq(attributes['title'])])
+ end
+ end
+
+ let!(:milestone) { create(:milestone, title: attributes['title'], project: project) }
+
+ it 'finds existing object instead of creating one' do
+ expect(subject).to eq(milestone)
+ end
+ end
+
+ context 'when where_clauses are not implemented' do
+ it 'raises NotImplementedError' do
+ expect { subject }.to raise_error(NotImplementedError)
+ end
+ end
+ end
+
+ context 'when object does not exist' do
+ before do
+ allow_next_instance_of(described_class) do |object_builder|
+ allow(object_builder).to receive(:find_object).and_return(nil)
+ end
+ end
+
+ it 'creates new object' do
+ expect { subject }.to change { Milestone.count }.from(0).to(1)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/base_relation_factory_spec.rb b/spec/lib/gitlab/import_export/base_relation_factory_spec.rb
new file mode 100644
index 00000000000..def3e43de9b
--- /dev/null
+++ b/spec/lib/gitlab/import_export/base_relation_factory_spec.rb
@@ -0,0 +1,145 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::ImportExport::BaseRelationFactory do
+ let(:user) { create(:admin) }
+ let(:project) { create(:project) }
+ let(:members_mapper) { double('members_mapper').as_null_object }
+ let(:relation_sym) { :project_snippets }
+ let(:merge_requests_mapping) { {} }
+ let(:relation_hash) { {} }
+ let(:excluded_keys) { [] }
+
+ subject do
+ described_class.create(relation_sym: relation_sym,
+ relation_hash: relation_hash,
+ object_builder: Gitlab::ImportExport::GroupProjectObjectBuilder,
+ members_mapper: members_mapper,
+ merge_requests_mapping: merge_requests_mapping,
+ user: user,
+ importable: project,
+ excluded_keys: excluded_keys)
+ end
+
+ describe '#create' do
+ context 'when relation is invalid' do
+ before do
+ expect_next_instance_of(described_class) do |relation_factory|
+ expect(relation_factory).to receive(:invalid_relation?).and_return(true)
+ end
+ end
+
+ it 'returns without creating new relations' do
+ expect(subject).to be_nil
+ end
+ end
+
+ context 'when #setup_models is not implemented' do
+ it 'raises NotImplementedError' do
+ expect { subject }.to raise_error(NotImplementedError)
+ end
+ end
+
+ context 'when #setup_models is implemented' do
+ let(:relation_sym) { :notes }
+ let(:relation_hash) do
+ {
+ "id" => 4947,
+ "note" => "merged",
+ "noteable_type" => "MergeRequest",
+ "author_id" => 999,
+ "created_at" => "2016-11-18T09:29:42.634Z",
+ "updated_at" => "2016-11-18T09:29:42.634Z",
+ "project_id" => 1,
+ "attachment" => {
+ "url" => nil
+ },
+ "noteable_id" => 377,
+ "system" => true,
+ "events" => []
+ }
+ end
+
+ before do
+ expect_next_instance_of(described_class) do |relation_factory|
+ expect(relation_factory).to receive(:setup_models).and_return(true)
+ end
+ end
+
+ it 'creates imported object' do
+ expect(subject).to be_instance_of(Note)
+ end
+
+ context 'when relation contains user references' do
+ let(:new_user) { create(:user) }
+ let(:exported_member) do
+ {
+ "id" => 111,
+ "access_level" => 30,
+ "source_id" => 1,
+ "source_type" => "Project",
+ "user_id" => 3,
+ "notification_level" => 3,
+ "created_at" => "2016-11-18T09:29:42.634Z",
+ "updated_at" => "2016-11-18T09:29:42.634Z",
+ "user" => {
+ "id" => 999,
+ "email" => new_user.email,
+ "username" => new_user.username
+ }
+ }
+ end
+
+ let(:members_mapper) do
+ Gitlab::ImportExport::MembersMapper.new(
+ exported_members: [exported_member],
+ user: user,
+ importable: project)
+ end
+
+ it 'maps the right author to the imported note' do
+ expect(subject.author).to eq(new_user)
+ end
+ end
+
+ context 'when relation contains token attributes' do
+ let(:relation_sym) { 'ProjectHook' }
+ let(:relation_hash) { { token: 'secret' } }
+
+ it 'removes token attributes' do
+ expect(subject.token).to be_nil
+ end
+ end
+
+ context 'when relation contains encrypted attributes' do
+ let(:relation_sym) { 'Ci::Variable' }
+ let(:relation_hash) do
+ create(:ci_variable).as_json
+ end
+
+ it 'removes encrypted attributes' do
+ expect(subject.value).to be_nil
+ end
+ end
+ end
+ end
+
+ describe '.relation_class' do
+ context 'when relation name is pluralized' do
+ let(:relation_name) { 'MergeRequest::Metrics' }
+
+ it 'returns constantized class' do
+ expect(described_class.relation_class(relation_name)).to eq(MergeRequest::Metrics)
+ end
+ end
+
+ context 'when relation name is singularized' do
+ let(:relation_name) { 'Badge' }
+
+ it 'returns constantized class' do
+ expect(described_class.relation_class(relation_name)).to eq(Badge)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/relation_factory_spec.rb b/spec/lib/gitlab/import_export/project_relation_factory_spec.rb
index 5704f823b93..0ade7ac4fc7 100644
--- a/spec/lib/gitlab/import_export/relation_factory_spec.rb
+++ b/spec/lib/gitlab/import_export/project_relation_factory_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-describe Gitlab::ImportExport::RelationFactory do
+describe Gitlab::ImportExport::ProjectRelationFactory do
let(:group) { create(:group) }
let(:project) { create(:project, :repository, group: group) }
let(:members_mapper) { double('members_mapper').as_null_object }
@@ -12,10 +12,11 @@ describe Gitlab::ImportExport::RelationFactory do
let(:created_object) do
described_class.create(relation_sym: relation_sym,
relation_hash: relation_hash,
+ object_builder: Gitlab::ImportExport::GroupProjectObjectBuilder,
members_mapper: members_mapper,
merge_requests_mapping: merge_requests_mapping,
user: user,
- project: project,
+ importable: project,
excluded_keys: excluded_keys)
end
@@ -97,7 +98,7 @@ describe Gitlab::ImportExport::RelationFactory do
end
end
- context 'merge_requset object' do
+ context 'merge_request object' do
let(:relation_sym) { :merge_requests }
let(:exported_member) do
@@ -244,11 +245,11 @@ describe Gitlab::ImportExport::RelationFactory do
context 'Project references' do
let(:relation_sym) { :project_foo_model }
let(:relation_hash) do
- Gitlab::ImportExport::RelationFactory::PROJECT_REFERENCES.map { |ref| { ref => 99 } }.inject(:merge)
+ Gitlab::ImportExport::ProjectRelationFactory::PROJECT_REFERENCES.map { |ref| { ref => 99 } }.inject(:merge)
end
class ProjectFooModel < FooModel
- attr_accessor(*Gitlab::ImportExport::RelationFactory::PROJECT_REFERENCES)
+ attr_accessor(*Gitlab::ImportExport::ProjectRelationFactory::PROJECT_REFERENCES)
end
before do
diff --git a/spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb
index c761f9652ab..edb2c0a131a 100644
--- a/spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb
@@ -27,6 +27,7 @@ describe Gitlab::ImportExport::RelationTreeRestorer do
shared: shared,
tree_hash: tree_hash,
importable: importable,
+ object_builder: object_builder,
members_mapper: members_mapper,
relation_factory: relation_factory,
reader: reader
@@ -38,7 +39,8 @@ describe Gitlab::ImportExport::RelationTreeRestorer do
context 'when restoring a project' do
let(:path) { 'spec/fixtures/lib/gitlab/import_export/complex/project.json' }
let(:importable) { create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project') }
- let(:relation_factory) { Gitlab::ImportExport::RelationFactory }
+ let(:object_builder) { Gitlab::ImportExport::GroupProjectObjectBuilder }
+ let(:relation_factory) { Gitlab::ImportExport::ProjectRelationFactory }
let(:reader) { Gitlab::ImportExport::Reader.new(shared: shared) }
let(:tree_hash) { importable_hash }
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index 01beb5ba33c..ad363233bfe 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -545,6 +545,7 @@ ProjectFeature:
- id
- project_id
- merge_requests_access_level
+- forking_access_level
- issues_access_level
- wiki_access_level
- snippets_access_level
diff --git a/spec/models/error_tracking/project_error_tracking_setting_spec.rb b/spec/models/error_tracking/project_error_tracking_setting_spec.rb
index 6babc39cdc3..5b402e572c3 100644
--- a/spec/models/error_tracking/project_error_tracking_setting_spec.rb
+++ b/spec/models/error_tracking/project_error_tracking_setting_spec.rb
@@ -64,6 +64,22 @@ describe ErrorTracking::ProjectErrorTrackingSetting do
end
end
+ describe '.extract_sentry_external_url' do
+ subject { described_class.extract_sentry_external_url(sentry_url) }
+
+ describe 'when passing a URL' do
+ let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' }
+
+ it { is_expected.to eq('https://sentrytest.gitlab.com/sentry-org/sentry-project') }
+ end
+
+ describe 'when passing nil' do
+ let(:sentry_url) { nil }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
describe '#sentry_external_url' do
let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' }
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index a4f68df928f..35b77832c73 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -358,6 +358,7 @@ describe API::Groups do
expect(json_response['two_factor_grace_period']).to eq(group1.two_factor_grace_period)
expect(json_response['auto_devops_enabled']).to eq(group1.auto_devops_enabled)
expect(json_response['emails_disabled']).to eq(group1.emails_disabled)
+ expect(json_response['mentions_disabled']).to eq(group1.mentions_disabled)
expect(json_response['project_creation_level']).to eq('maintainer')
expect(json_response['subgroup_creation_level']).to eq('maintainer')
expect(json_response['web_url']).to eq(group1.web_url)
@@ -556,6 +557,7 @@ describe API::Groups do
expect(json_response['two_factor_grace_period']).to eq(48)
expect(json_response['auto_devops_enabled']).to eq(nil)
expect(json_response['emails_disabled']).to eq(nil)
+ expect(json_response['mentions_disabled']).to eq(nil)
expect(json_response['project_creation_level']).to eq("noone")
expect(json_response['subgroup_creation_level']).to eq("maintainer")
expect(json_response['request_access_enabled']).to eq(true)
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index e1297c035b5..fce49d0248c 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -2858,6 +2858,20 @@ describe API::Projects do
expect(json_response['message']).to eq('401 Unauthorized')
end
end
+
+ context 'forking disabled' do
+ before do
+ project.project_feature.update_attribute(
+ :forking_access_level, ProjectFeature::DISABLED)
+ end
+
+ it 'denies project to be forked' do
+ post api("/projects/#{project.id}/fork", admin)
+
+ expect(response).to have_gitlab_http_status(409)
+ expect(json_response['message']['forked_from_project_id']).to eq(['is forbidden'])
+ end
+ end
end
describe 'POST /projects/:id/housekeeping' do
diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb
index fc01c93b5cf..e7b904fcd60 100644
--- a/spec/services/projects/fork_service_spec.rb
+++ b/spec/services/projects/fork_service_spec.rb
@@ -224,6 +224,19 @@ describe Projects::ForkService do
end
end
end
+
+ context 'when forking is disabled' do
+ before do
+ @from_project.project_feature.update_attribute(
+ :forking_access_level, ProjectFeature::DISABLED)
+ end
+
+ it 'fails' do
+ to_project = fork_project(@from_project, @to_user, namespace: @to_user.namespace)
+
+ expect(to_project.errors[:forked_from_project_id]).to eq(['is forbidden'])
+ end
+ end
end
describe 'fork to namespace' do
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index fa7b1003b8d..4ba22af85f0 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -76,28 +76,14 @@ describe SystemNoteService do
end
describe '.change_due_date' do
- subject { described_class.change_due_date(noteable, project, author, due_date) }
+ let(:due_date) { double }
- let(:due_date) { Date.today }
-
- it_behaves_like 'a note with overridable created_at'
-
- it_behaves_like 'a system note' do
- let(:action) { 'due_date' }
- end
-
- context 'when due date added' do
- it 'sets the note text' do
- expect(subject.note).to eq "changed due date to #{Date.today.to_s(:long)}"
+ it 'calls TimeTrackingService' do
+ expect_next_instance_of(::SystemNotes::TimeTrackingService) do |service|
+ expect(service).to receive(:change_due_date).with(due_date)
end
- end
- context 'when due date removed' do
- let(:due_date) { nil }
-
- it 'sets the note text' do
- expect(subject.note).to eq 'removed due date'
- end
+ described_class.change_due_date(noteable, project, author, due_date)
end
end
@@ -488,36 +474,12 @@ describe SystemNoteService do
end
describe '.change_time_estimate' do
- subject { described_class.change_time_estimate(noteable, project, author) }
-
- it_behaves_like 'a system note' do
- let(:action) { 'time_tracking' }
- end
-
- context 'with a time estimate' do
- it 'sets the note text' do
- noteable.update_attribute(:time_estimate, 277200)
-
- expect(subject.note).to eq "changed time estimate to 1w 4d 5h"
- end
-
- context 'when time_tracking_limit_to_hours setting is true' do
- before do
- stub_application_setting(time_tracking_limit_to_hours: true)
- end
-
- it 'sets the note text' do
- noteable.update_attribute(:time_estimate, 277200)
-
- expect(subject.note).to eq "changed time estimate to 77h"
- end
+ it 'calls TimeTrackingService' do
+ expect_next_instance_of(::SystemNotes::TimeTrackingService) do |service|
+ expect(service).to receive(:change_time_estimate)
end
- end
- context 'without a time estimate' do
- it 'sets the note text' do
- expect(subject.note).to eq "removed time estimate"
- end
+ described_class.change_time_estimate(noteable, project, author)
end
end
@@ -548,61 +510,12 @@ describe SystemNoteService do
end
describe '.change_time_spent' do
- # We need a custom noteable in order to the shared examples to be green.
- let(:noteable) do
- mr = create(:merge_request, source_project: project)
- mr.spend_time(duration: 360000, user_id: author.id)
- mr.save!
- mr
- end
-
- subject do
- described_class.change_time_spent(noteable, project, author)
- end
-
- it_behaves_like 'a system note' do
- let(:action) { 'time_tracking' }
- end
-
- context 'when time was added' do
- it 'sets the note text' do
- spend_time!(277200)
-
- expect(subject.note).to eq "added 1w 4d 5h of time spent"
+ it 'calls TimeTrackingService' do
+ expect_next_instance_of(::SystemNotes::TimeTrackingService) do |service|
+ expect(service).to receive(:change_time_spent)
end
- end
-
- context 'when time was subtracted' do
- it 'sets the note text' do
- spend_time!(-277200)
-
- expect(subject.note).to eq "subtracted 1w 4d 5h of time spent"
- end
- end
-
- context 'when time was removed' do
- it 'sets the note text' do
- spend_time!(:reset)
- expect(subject.note).to eq "removed time spent"
- end
- end
-
- context 'when time_tracking_limit_to_hours setting is true' do
- before do
- stub_application_setting(time_tracking_limit_to_hours: true)
- end
-
- it 'sets the note text' do
- spend_time!(277200)
-
- expect(subject.note).to eq "added 77h of time spent"
- end
- end
-
- def spend_time!(seconds)
- noteable.spend_time(duration: seconds, user_id: author.id)
- noteable.save!
+ described_class.change_time_spent(noteable, project, author)
end
end
diff --git a/spec/services/system_notes/time_tracking_service_spec.rb b/spec/services/system_notes/time_tracking_service_spec.rb
new file mode 100644
index 00000000000..7e3e6a75cdf
--- /dev/null
+++ b/spec/services/system_notes/time_tracking_service_spec.rb
@@ -0,0 +1,129 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ::SystemNotes::TimeTrackingService do
+ let_it_be(:author) { create(:user) }
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:noteable) { create(:issue, project: project) }
+
+ describe '#change_due_date' do
+ subject { described_class.new(noteable: noteable, project: project, author: author).change_due_date(due_date) }
+
+ let(:due_date) { Date.today }
+
+ it_behaves_like 'a note with overridable created_at'
+
+ it_behaves_like 'a system note' do
+ let(:action) { 'due_date' }
+ end
+
+ context 'when due date added' do
+ it 'sets the note text' do
+ expect(subject.note).to eq "changed due date to #{due_date.to_s(:long)}"
+ end
+ end
+
+ context 'when due date removed' do
+ let(:due_date) { nil }
+
+ it 'sets the note text' do
+ expect(subject.note).to eq 'removed due date'
+ end
+ end
+ end
+
+ describe '.change_time_estimate' do
+ subject { described_class.new(noteable: noteable, project: project, author: author).change_time_estimate }
+
+ it_behaves_like 'a system note' do
+ let(:action) { 'time_tracking' }
+ end
+
+ context 'with a time estimate' do
+ it 'sets the note text' do
+ noteable.update_attribute(:time_estimate, 277200)
+
+ expect(subject.note).to eq "changed time estimate to 1w 4d 5h"
+ end
+
+ context 'when time_tracking_limit_to_hours setting is true' do
+ before do
+ stub_application_setting(time_tracking_limit_to_hours: true)
+ end
+
+ it 'sets the note text' do
+ noteable.update_attribute(:time_estimate, 277200)
+
+ expect(subject.note).to eq "changed time estimate to 77h"
+ end
+ end
+ end
+
+ context 'without a time estimate' do
+ it 'sets the note text' do
+ expect(subject.note).to eq "removed time estimate"
+ end
+ end
+ end
+
+ describe '.change_time_spent' do
+ # We need a custom noteable in order to the shared examples to be green.
+ let(:noteable) do
+ mr = create(:merge_request, source_project: project)
+ mr.spend_time(duration: 360000, user_id: author.id)
+ mr.save!
+ mr
+ end
+
+ subject do
+ described_class.new(noteable: noteable, project: project, author: author).change_time_spent
+ end
+
+ it_behaves_like 'a system note' do
+ let(:action) { 'time_tracking' }
+ end
+
+ context 'when time was added' do
+ it 'sets the note text' do
+ spend_time!(277200)
+
+ expect(subject.note).to eq "added 1w 4d 5h of time spent"
+ end
+ end
+
+ context 'when time was subtracted' do
+ it 'sets the note text' do
+ spend_time!(-277200)
+
+ expect(subject.note).to eq "subtracted 1w 4d 5h of time spent"
+ end
+ end
+
+ context 'when time was removed' do
+ it 'sets the note text' do
+ spend_time!(:reset)
+
+ expect(subject.note).to eq "removed time spent"
+ end
+ end
+
+ context 'when time_tracking_limit_to_hours setting is true' do
+ before do
+ stub_application_setting(time_tracking_limit_to_hours: true)
+ end
+
+ it 'sets the note text' do
+ spend_time!(277200)
+
+ expect(subject.note).to eq "added 77h of time spent"
+ end
+ end
+
+ def spend_time!(seconds)
+ noteable.spend_time(duration: seconds, user_id: author.id)
+ noteable.save!
+ end
+ end
+end
diff --git a/spec/support/import_export/configuration_helper.rb b/spec/support/import_export/configuration_helper.rb
index 2e5a99bb8b2..27819b5201a 100644
--- a/spec/support/import_export/configuration_helper.rb
+++ b/spec/support/import_export/configuration_helper.rb
@@ -36,8 +36,8 @@ module ConfigurationHelper
end
def relation_class_for_name(relation_name)
- relation_name = Gitlab::ImportExport::RelationFactory.overrides[relation_name.to_sym] || relation_name
- Gitlab::ImportExport::RelationFactory.relation_class(relation_name)
+ relation_name = Gitlab::ImportExport::ProjectRelationFactory.overrides[relation_name.to_sym] || relation_name
+ Gitlab::ImportExport::ProjectRelationFactory.relation_class(relation_name)
end
def parsed_attributes(relation_name, attributes, config: Gitlab::ImportExport.config_file)