kanbanworkflowstimelinescrumrubyroadmapproject-planningproject-managementopenprojectangularissue-trackerifcgantt-chartganttbug-trackerboardsbcf
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
646 lines
23 KiB
646 lines
23 KiB
#-- encoding: UTF-8
|
|
|
|
#-- copyright
|
|
# OpenProject is an open source project management software.
|
|
# Copyright (C) 2012-2021 the OpenProject GmbH
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License version 3.
|
|
#
|
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
|
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
|
# Copyright (C) 2010-2013 the ChiliProject Team
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License
|
|
# as published by the Free Software Foundation; either version 2
|
|
# of the License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
#
|
|
# See docs/COPYRIGHT.rdoc for more details.
|
|
#++
|
|
|
|
require 'spec_helper'
|
|
|
|
describe Projects::CopyService, 'integration', type: :model do
|
|
shared_let(:status_locked) { FactoryBot.create :status, is_readonly: true }
|
|
shared_let(:source) { FactoryBot.create :project, enabled_module_names: %w[wiki work_package_tracking] }
|
|
shared_let(:source_wp) { FactoryBot.create :work_package, project: source, subject: 'source wp' }
|
|
shared_let(:source_wp_locked) { FactoryBot.create :work_package, project: source, subject: 'source wp locked', status: status_locked }
|
|
shared_let(:source_query) { FactoryBot.create :query, project: source, name: 'My query' }
|
|
shared_let(:source_category) { FactoryBot.create :category, project: source, name: 'Stock management' }
|
|
shared_let(:source_version) { FactoryBot.create :version, project: source, name: 'Version A' }
|
|
shared_let(:source_wiki_page) { FactoryBot.create(:wiki_page_with_content, wiki: source.wiki) }
|
|
shared_let(:source_child_wiki_page) { FactoryBot.create(:wiki_page_with_content, wiki: source.wiki, parent: source_wiki_page) }
|
|
shared_let(:source_forum) { FactoryBot.create(:forum, project: source) }
|
|
shared_let(:source_topic) { FactoryBot.create(:message, forum: source_forum) }
|
|
|
|
let(:current_user) do
|
|
FactoryBot.create(:user,
|
|
member_in_project: source,
|
|
member_through_role: role)
|
|
end
|
|
let(:role) { FactoryBot.create :role, permissions: %i[copy_projects view_work_packages] }
|
|
shared_let(:new_project_role) { FactoryBot.create :role, permissions: %i[] }
|
|
let(:instance) do
|
|
described_class.new(source: source, user: current_user)
|
|
end
|
|
let(:only_args) { nil }
|
|
let(:target_project_params) do
|
|
{ name: 'Some name', identifier: 'some-identifier' }
|
|
end
|
|
let(:params) do
|
|
{ target_project_params: target_project_params, only: only_args }
|
|
end
|
|
|
|
before do
|
|
with_enterprise_token(:readonly_work_packages)
|
|
|
|
allow(Setting)
|
|
.to receive(:new_project_user_role_id)
|
|
.and_return(new_project_role.id.to_s)
|
|
end
|
|
|
|
describe 'call' do
|
|
subject { instance.call(params) }
|
|
let(:project_copy) { subject.result }
|
|
|
|
context 'restricting only to members and categories' do
|
|
let(:only_args) { %w[members categories] }
|
|
|
|
it 'should limit copying' do
|
|
expect(subject).to be_success
|
|
|
|
expect(project_copy.members.count).to eq 1
|
|
expect(project_copy.categories.count).to eq 1
|
|
expect(project_copy.work_packages.count).to eq 0
|
|
expect(project_copy.forums.count).to eq 0
|
|
expect(project_copy.wiki.pages.count).to eq 0
|
|
expect(project_copy.versions.count).to eq 0
|
|
expect(project_copy.queries.count).to eq 0
|
|
end
|
|
end
|
|
|
|
it 'will copy all dependencies and set attributes' do
|
|
expect(subject).to be_success
|
|
|
|
expect(project_copy.members.count).to eq 1
|
|
expect(project_copy.categories.count).to eq 1
|
|
# normal wp and locked wp
|
|
expect(project_copy.work_packages.count).to eq 2
|
|
expect(project_copy.forums.count).to eq 1
|
|
expect(project_copy.forums.first.messages.count).to eq 1
|
|
expect(project_copy.wiki).to be_present
|
|
expect(project_copy.wiki.pages.count).to eq 2
|
|
expect(project_copy.queries.count).to eq 1
|
|
expect(project_copy.versions.count).to eq 1
|
|
expect(project_copy.wiki.pages.root.content.text).to eq source_wiki_page.content.text
|
|
expect(project_copy.wiki.pages.leaves.first.content.text).to eq source_child_wiki_page.content.text
|
|
expect(project_copy.wiki.start_page).to eq 'Wiki'
|
|
|
|
# Cleared attributes
|
|
expect(project_copy).to be_persisted
|
|
expect(project_copy.name).to eq 'Some name'
|
|
expect(project_copy.name).to eq 'Some name'
|
|
expect(project_copy.identifier).to eq 'some-identifier'
|
|
|
|
# Duplicated attributes
|
|
expect(project_copy.description).to eq source.description
|
|
expect(source.enabled_module_names.sort - %w[repository]).to eq project_copy.enabled_module_names.sort
|
|
expect(project_copy.types).to eq source.types
|
|
|
|
# Default attributes
|
|
expect(project_copy).to be_active
|
|
|
|
# Default role being assigned according to setting
|
|
# merged with the role the user already had.
|
|
member = project_copy.members.first
|
|
expect(member.principal)
|
|
.to eql(current_user)
|
|
expect(member.roles)
|
|
.to match_array [role, new_project_role]
|
|
end
|
|
|
|
it 'will copy the work package with category' do
|
|
source_wp.update!(category: source_category)
|
|
|
|
expect(subject).to be_success
|
|
|
|
wp = project_copy.work_packages.find_by(subject: source_wp.subject)
|
|
expect(wp.category.name).to eq 'Stock management'
|
|
# Category got copied
|
|
expect(wp.category.id).not_to eq source_category.id
|
|
end
|
|
|
|
describe '#public' do
|
|
before do
|
|
source.update!(public: public)
|
|
end
|
|
|
|
context 'when not public' do
|
|
let(:public) { false }
|
|
|
|
it 'copies correctly' do
|
|
expect(subject).to be_success
|
|
expect(project_copy.public).to eq public
|
|
end
|
|
end
|
|
|
|
context 'when public' do
|
|
let(:public) { true }
|
|
|
|
it 'copies correctly' do
|
|
expect(subject).to be_success
|
|
expect(project_copy.public).to eq public
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'with an assigned version' do
|
|
let!(:assigned_version) { FactoryBot.create(:version, name: 'Assigned Issues', project: source, status: 'open') }
|
|
|
|
before do
|
|
source_wp.update!(version: assigned_version)
|
|
assigned_version.update!(status: 'closed')
|
|
end
|
|
|
|
it 'will update the version' do
|
|
expect(subject).to be_success
|
|
|
|
wp = project_copy.work_packages.find_by(subject: source_wp.subject)
|
|
expect(wp.version.name).to eq 'Assigned Issues'
|
|
expect(wp.version).to be_closed
|
|
expect(wp.version.id).not_to eq assigned_version.id
|
|
end
|
|
end
|
|
|
|
context 'with group memberships' do
|
|
let(:only_args) { %w[members] }
|
|
|
|
let!(:user) { FactoryBot.create :user }
|
|
let!(:another_role) { FactoryBot.create(:role) }
|
|
let!(:group) { FactoryBot.create :group, members: [user]
|
|
}
|
|
|
|
it 'will copy them as well' do
|
|
source.add_member! group, another_role
|
|
source.reload
|
|
expect(source.users).to include current_user
|
|
expect(source.users).to include user
|
|
expect(project_copy.groups).to include group
|
|
expect(source.member_principals.count).to eq 3
|
|
|
|
expect(subject).to be_success
|
|
|
|
expect(project_copy.member_principals.count).to eq 3
|
|
expect(project_copy.groups).to include group
|
|
expect(project_copy.users).to include current_user
|
|
expect(project_copy.users).to include user
|
|
|
|
group_member = Member.find_by(user_id: group.id, project_id: project_copy.id)
|
|
expect(group_member).to be_present
|
|
expect(group_member.roles.map(&:id)).to eq [another_role.id]
|
|
|
|
member = Member.find_by(user_id: user.id, project_id: project_copy.id)
|
|
expect(member).to be_present
|
|
expect(member.roles.map(&:id)).to eq [another_role.id]
|
|
expect(member.member_roles.first.inherited_from).to eq group_member.member_roles.first.id
|
|
end
|
|
end
|
|
|
|
context 'with work package relations', with_settings: { cross_project_work_package_relations: '1' } do
|
|
let!(:source_wp2) { FactoryBot.create(:work_package, project: source, subject: 'source wp2') }
|
|
let!(:source_relation) { FactoryBot.create(:relation, from: source_wp, to: source_wp2, relation_type: 'relates') }
|
|
|
|
let!(:other_project) { FactoryBot.create(:project) }
|
|
let!(:other_wp) { FactoryBot.create(:work_package, project: other_project, subject: 'other wp') }
|
|
let!(:cross_relation) { FactoryBot.create(:relation, from: source_wp, to: other_wp, relation_type: 'duplicates') }
|
|
|
|
let(:only_args) { %w[work_packages] }
|
|
|
|
it 'should the relations relations' do
|
|
expect(subject).to be_success
|
|
|
|
expect(source.work_packages.count).to eq(project_copy.work_packages.count)
|
|
copied_wp = project_copy.work_packages.find_by(subject: 'source wp')
|
|
copied_wp_2 = project_copy.work_packages.find_by(subject: 'source wp2')
|
|
|
|
# First issue with a relation on project
|
|
# copied relation + reflexive relation
|
|
expect(copied_wp.relations.direct.count).to eq 2
|
|
relates_relation = copied_wp.relations.direct.find { |r| r.relation_type == 'relates' }
|
|
expect(relates_relation.from_id).to eq copied_wp.id
|
|
expect(relates_relation.to_id).to eq copied_wp_2.id
|
|
|
|
# Second issue with a cross project relation
|
|
# copied relation + reflexive relation
|
|
duplicates_relation = copied_wp.relations.direct.find { |r| r.relation_type == 'duplicates' }
|
|
expect(duplicates_relation.from_id).to eq copied_wp.id
|
|
expect(duplicates_relation.to_id).to eq other_wp.id
|
|
end
|
|
end
|
|
|
|
describe '#copy_wiki' do
|
|
it 'will not copy wiki pages without content' do
|
|
source.wiki.pages << FactoryBot.create(:wiki_page)
|
|
expect(source.wiki.pages.count).to eq 3
|
|
|
|
expect(subject).to be_success
|
|
expect(subject.errors).to be_empty
|
|
expect(project_copy.wiki.pages.count).to eq 2
|
|
end
|
|
|
|
it 'will copy menu items' do
|
|
source.wiki.wiki_menu_items << FactoryBot.create(:wiki_menu_item_with_parent, wiki: source.wiki)
|
|
|
|
expect(subject).to be_success
|
|
expect(project_copy.wiki.wiki_menu_items.count).to eq 3
|
|
end
|
|
end
|
|
|
|
describe 'valid queries' do
|
|
context 'with a filter' do
|
|
let!(:query) do
|
|
query = FactoryBot.build(:query, project: source)
|
|
query.add_filter('subject', '~', ['bogus'])
|
|
query.save!
|
|
end
|
|
|
|
it 'produces a valid query in the new project' do
|
|
expect(subject).to be_success
|
|
expect(project_copy.queries.all?(&:valid?)).to eq(true)
|
|
expect(project_copy.queries.count).to eq 2
|
|
end
|
|
end
|
|
|
|
context 'with a filter to be mapped' do
|
|
let!(:query) do
|
|
query = FactoryBot.build(:query, project: source)
|
|
query.add_filter('parent', '=', [source_wp.id.to_s])
|
|
# Not valid due to wp not visible
|
|
query.save!(validate: false)
|
|
query
|
|
end
|
|
|
|
it 'produces a valid query that is mapped in the new project' do
|
|
expect(subject).to be_success
|
|
copied_wp = project_copy.work_packages.find_by(subject: 'source wp')
|
|
copied = project_copy.queries.find_by(name: query.name)
|
|
expect(copied.filters[1].values).to eq [copied_wp.id.to_s]
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'query menu items' do
|
|
let!(:query) do
|
|
query = FactoryBot.build(:query, project: source, name: 'Query with item')
|
|
query.add_filter('subject', '~', ['bogus'])
|
|
query.save!
|
|
|
|
MenuItems::QueryMenuItem.create(
|
|
navigatable_id: query.id,
|
|
name: 'some-uuid',
|
|
title: 'My query title'
|
|
)
|
|
|
|
query
|
|
end
|
|
|
|
it 'copies the menu item' do
|
|
expect(subject).to be_success
|
|
query = project_copy.queries.find_by(name: 'Query with item')
|
|
expect(query).to be_present
|
|
expect(query.query_menu_item.title).to eq('My query title')
|
|
end
|
|
end
|
|
|
|
describe 'work packages' do
|
|
let(:work_package) { FactoryBot.create(:work_package, project: source) }
|
|
let(:work_package2) { FactoryBot.create(:work_package, project: source) }
|
|
let(:work_package3) { FactoryBot.create(:work_package, project: source) }
|
|
|
|
let(:only_args) { %w[work_packages] }
|
|
|
|
describe '#attachments' do
|
|
let!(:attachment) { FactoryBot.create(:attachment, container: work_package) }
|
|
|
|
context 'when requested' do
|
|
let(:only_args) { %i[work_packages work_package_attachments] }
|
|
it 'copies them' do
|
|
expect(subject).to be_success
|
|
expect(project_copy.work_packages.count).to eq(3)
|
|
|
|
wp = project_copy.work_packages.find_by(subject: work_package.subject)
|
|
expect(wp.attachments.count).to eq(1)
|
|
expect(wp.attachments.first.author).to eql(current_user)
|
|
end
|
|
end
|
|
|
|
context 'when not requested' do
|
|
it 'ignores them' do
|
|
expect(subject).to be_success
|
|
expect(project_copy.work_packages.count).to eq(3)
|
|
|
|
wp = project_copy.work_packages.find_by(subject: work_package.subject)
|
|
expect(wp.attachments.count).to eq(0)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'in an ordered query (Feature #31317)' do
|
|
let!(:query) do
|
|
FactoryBot.create(:query, name: 'Manual query', user: current_user, project: source, show_hierarchies: false).tap do |q|
|
|
q.sort_criteria = [[:manual_sorting, 'asc']]
|
|
q.save!
|
|
end
|
|
end
|
|
|
|
before do
|
|
::OrderedWorkPackage.create(query: query, work_package: work_package, position: 100)
|
|
::OrderedWorkPackage.create(query: query, work_package: work_package2, position: 0)
|
|
::OrderedWorkPackage.create(query: query, work_package: work_package3, position: 50)
|
|
end
|
|
|
|
let(:only_args) { %w[work_packages queries] }
|
|
|
|
it 'copies the query and order' do
|
|
expect(subject).to be_success
|
|
expect(project_copy.work_packages.count).to eq(5)
|
|
expect(project_copy.queries.count).to eq(2)
|
|
|
|
manual_query = project_copy.queries.find_by name: 'Manual query'
|
|
expect(manual_query).to be_manually_sorted
|
|
|
|
expect(query.ordered_work_packages.count).to eq 3
|
|
original_order = query.ordered_work_packages.map { |ow| ow.work_package.subject }
|
|
copied_order = manual_query.ordered_work_packages.map { |ow| ow.work_package.subject }
|
|
|
|
expect(copied_order).to eq(original_order)
|
|
end
|
|
|
|
context 'if one work package is a cross project reference' do
|
|
let(:other_project) { FactoryBot.create :project }
|
|
before do
|
|
work_package2.update! project: other_project
|
|
end
|
|
|
|
let(:only_args) { %w[work_packages queries] }
|
|
|
|
it 'copies the query and order' do
|
|
expect(subject).to be_success
|
|
# Only 4 out of the 5 work packages got copied this time
|
|
expect(project_copy.work_packages.count).to eq(4)
|
|
expect(project_copy.queries.count).to eq(2)
|
|
|
|
manual_query = project_copy.queries.find_by name: 'Manual query'
|
|
expect(manual_query).to be_manually_sorted
|
|
|
|
expect(query.ordered_work_packages.count).to eq 3
|
|
original_order = query.ordered_work_packages.map { |ow| ow.work_package.subject }
|
|
copied_order = manual_query.ordered_work_packages.map { |ow| ow.work_package.subject }
|
|
|
|
expect(copied_order).to eq(original_order)
|
|
|
|
# Expect reference to the original work package
|
|
referenced = query.ordered_work_packages.detect { |ow| ow.work_package == work_package2 }
|
|
expect(referenced).to be_present
|
|
end
|
|
end
|
|
end
|
|
|
|
describe '#parent' do
|
|
before do
|
|
work_package.parent = work_package2
|
|
work_package.save!
|
|
work_package2.parent = work_package3
|
|
work_package2.save!
|
|
end
|
|
|
|
it do
|
|
expect(subject).to be_success
|
|
|
|
grandparent_wp_copy = project_copy.work_packages.find_by(subject: work_package3.subject)
|
|
parent_wp_copy = project_copy.work_packages.find_by(subject: work_package2.subject)
|
|
child_wp_copy = project_copy.work_packages.find_by(subject: work_package.subject)
|
|
|
|
[grandparent_wp_copy,
|
|
parent_wp_copy,
|
|
child_wp_copy].each do |wp|
|
|
expect(wp).to be_present
|
|
end
|
|
|
|
expect(child_wp_copy.parent).to eq(parent_wp_copy)
|
|
expect(parent_wp_copy.parent).to eq(grandparent_wp_copy)
|
|
end
|
|
end
|
|
|
|
describe '#category' do
|
|
let(:only_args) { %w[work_packages categories] }
|
|
|
|
before do
|
|
wp = work_package
|
|
wp.category = FactoryBot.create(:category, project: source)
|
|
wp.save
|
|
|
|
source.work_packages << wp.reload
|
|
end
|
|
|
|
it do
|
|
expect(subject).to be_success
|
|
wp = project_copy.work_packages.find_by(subject: work_package.subject)
|
|
expect(cat = wp.category).not_to eq(nil)
|
|
expect(cat.project).to eq(project_copy)
|
|
end
|
|
end
|
|
|
|
describe '#watchers' do
|
|
let(:watcher_role) { FactoryBot.create(:role, permissions: [:view_work_packages]) }
|
|
let(:watcher) { FactoryBot.create(:user, member_in_project: source, member_through_role: watcher_role) }
|
|
|
|
let(:only_args) { %w[work_packages members] }
|
|
|
|
describe '#active_watcher' do
|
|
before do
|
|
wp = work_package
|
|
wp.add_watcher watcher
|
|
wp.save
|
|
|
|
source.work_packages << wp
|
|
end
|
|
|
|
it 'does copy active watchers' do
|
|
expect(subject).to be_success
|
|
expect(project_copy.work_packages[0].watchers.first.user).to eq(watcher)
|
|
end
|
|
end
|
|
|
|
describe '#locked_watcher' do
|
|
before do
|
|
user = watcher
|
|
wp = work_package
|
|
wp.add_watcher user
|
|
wp.save
|
|
|
|
user.lock!
|
|
|
|
source.work_packages << wp
|
|
end
|
|
|
|
it 'does not copy locked watchers' do
|
|
expect(subject).to be_success
|
|
expect(project_copy.work_packages[0].watchers).to eq([])
|
|
end
|
|
end
|
|
|
|
describe 'versions' do
|
|
let(:version) { FactoryBot.create(:version, project: source) }
|
|
let(:version2) { FactoryBot.create(:version, project: source) }
|
|
|
|
let(:only_args) { %w[versions work_packages] }
|
|
|
|
before do
|
|
work_package.update_column(:version_id, version.id)
|
|
work_package2.update_column(:version_id, version2.id)
|
|
work_package3
|
|
end
|
|
|
|
it 'assigns the work packages to copies of the versions' do
|
|
expect(subject).to be_success
|
|
expect(project_copy.work_packages.detect { |wp| wp.subject == work_package.subject }.version.name)
|
|
.to eql version.name
|
|
expect(project_copy.work_packages.detect { |wp| wp.subject == work_package2.subject }.version.name)
|
|
.to eql version2.name
|
|
expect(project_copy.work_packages.detect { |wp| wp.subject == work_package3.subject }.version)
|
|
.to be_nil
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'assigned_to' do
|
|
before do
|
|
work_package.update_column(:assigned_to_id, current_user.id)
|
|
end
|
|
|
|
context 'with the members being copied' do
|
|
let(:only_args) { %w[members work_packages] }
|
|
|
|
it 'copies the assigned_to' do
|
|
expect(subject).to be_success
|
|
expect(project_copy.users).to include current_user
|
|
expect(project_copy.work_packages[0].assigned_to)
|
|
.to eql current_user
|
|
end
|
|
end
|
|
|
|
context 'with the assignee not being a member' do
|
|
let(:only_args) { %w[work_packages] }
|
|
|
|
it 'nils the assigned_to' do
|
|
expect(subject).to be_success
|
|
expect(project_copy.work_packages[0].assigned_to)
|
|
.to be_nil
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'responsible' do
|
|
before do
|
|
work_package.update_column(:responsible_id, current_user.id)
|
|
end
|
|
|
|
context 'with the members being copied' do
|
|
let(:only_args) { %w[members work_packages] }
|
|
|
|
it 'copies the responsible' do
|
|
expect(subject).to be_success
|
|
expect(project_copy.users).to include current_user
|
|
expect(project_copy.work_packages[0].responsible)
|
|
.to eql current_user
|
|
end
|
|
end
|
|
|
|
context 'with the responsible not being a member' do
|
|
let(:only_args) { %w[work_packages] }
|
|
|
|
it 'nils the assigned_to' do
|
|
expect(subject).to be_success
|
|
expect(project_copy.work_packages[0].responsible)
|
|
.to be_nil
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'work package user custom field' do
|
|
let(:custom_field) do
|
|
FactoryBot.create(:user_wp_custom_field).tap do |cf|
|
|
source.work_package_custom_fields << cf
|
|
work_package.type.custom_fields << cf
|
|
end
|
|
end
|
|
|
|
before do
|
|
custom_field
|
|
work_package.reload
|
|
work_package.send(:"custom_field_#{custom_field.id}=", current_user.id)
|
|
work_package.save!(validate: false)
|
|
end
|
|
|
|
context 'with the value being a member' do
|
|
let(:only_args) { %w[members work_packages] }
|
|
|
|
it 'copies the custom_field' do
|
|
expect(subject).to be_success
|
|
wp = project_copy.work_packages.find_by(subject: work_package.subject)
|
|
expect(wp.send(:"custom_field_#{custom_field.id}"))
|
|
.to eql current_user
|
|
end
|
|
end
|
|
|
|
context 'with the value not being a member' do
|
|
let(:only_args) { %w[work_packages] }
|
|
|
|
it 'nils the custom_field' do
|
|
expect(subject).to be_success
|
|
wp = project_copy.work_packages.find_by(subject: work_package.subject)
|
|
expect(wp.send(:"custom_field_#{custom_field.id}"))
|
|
.to be_nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'project custom fields' do
|
|
context 'with user project CF' do
|
|
let(:user_custom_field) { FactoryBot.create(:user_project_custom_field) }
|
|
let(:user_value) do
|
|
FactoryBot.create(:user,
|
|
member_in_project: source,
|
|
member_through_role: role)
|
|
end
|
|
|
|
before do
|
|
source.custom_values << CustomValue.new(custom_field: user_custom_field, value: user_value.id.to_s)
|
|
end
|
|
|
|
let(:only_args) { %w[wiki] }
|
|
|
|
it 'copies the custom_field' do
|
|
expect(subject).to be_success
|
|
|
|
cv = project_copy.custom_values.reload.find_by(custom_field: user_custom_field)
|
|
expect(cv).to be_present
|
|
expect(cv.value).to eq user_value.id.to_s
|
|
expect(cv.typed_value).to eq user_value
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|