diff --git a/.travis.yml b/.travis.yml
index ea3e425194..9ff5c02260 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -93,7 +93,7 @@ jobs:
name: 'spec_legacy (1/1) - bim'
script:
- bash script/ci/setup.sh spec_legacy bim
- - bash script/ci/runner.sh spec_legacy 1 1
+ - bash script/ci/runner.sh spec_legacy 1 1 bim
if: head_branch =~ /^(bim\/|dev|release\/)/
- stage: test
name: 'units (1/4) - standard'
@@ -104,7 +104,7 @@ jobs:
name: 'units (1/4) - bim'
script:
- bash script/ci/setup.sh units bim
- - bash script/ci/runner.sh units 4 1
+ - bash script/ci/runner.sh units 4 1 bim
if: head_branch =~ /^(bim\/|dev|release\/)/
- stage: test
name: 'units (2/4) - standard'
@@ -115,7 +115,7 @@ jobs:
name: 'units (2/4) - bim'
script:
- bash script/ci/setup.sh units bim
- - bash script/ci/runner.sh units 4 2
+ - bash script/ci/runner.sh units 4 2 bim
if: head_branch =~ /^(bim\/|dev|release\/)/
- stage: test
name: 'units (3/4) - standard'
@@ -126,7 +126,7 @@ jobs:
name: 'units (3/4) - bim'
script:
- bash script/ci/setup.sh units bim
- - bash script/ci/runner.sh units 4 3
+ - bash script/ci/runner.sh units 4 3 bim
if: head_branch =~ /^(bim\/|dev|release\/)/
- stage: test
name: 'units (4/4) - standard'
@@ -137,7 +137,7 @@ jobs:
name: 'units (4/4) - bim'
script:
- bash script/ci/setup.sh units bim
- - bash script/ci/runner.sh units 4 4
+ - bash script/ci/runner.sh units 4 4 bim
if: head_branch =~ /^(bim\/|dev|release\/)/
- stage: test
name: 'features (1/4) - standard'
@@ -148,7 +148,7 @@ jobs:
name: 'features (1/4) - bim'
script:
- bash script/ci/setup.sh features bim
- - bash script/ci/runner.sh features 4 1
+ - bash script/ci/runner.sh features 4 1 bim
if: head_branch =~ /^(bim\/|dev|release\/)/
- stage: test
name: 'features (2/4) - standard'
@@ -159,7 +159,7 @@ jobs:
name: 'features (2/4) - bim'
script:
- bash script/ci/setup.sh features bim
- - bash script/ci/runner.sh features 4 2
+ - bash script/ci/runner.sh features 4 2 bim
if: head_branch =~ /^(bim\/|dev|release\/)/
- stage: test
name: 'features (3/4) - standard'
@@ -170,7 +170,7 @@ jobs:
name: 'features (3/4) - bim'
script:
- bash script/ci/setup.sh features bim
- - bash script/ci/runner.sh features 4 3
+ - bash script/ci/runner.sh features 4 3 bim
if: head_branch =~ /^(bim\/|dev|release\/)/
- stage: test
name: 'features (4/4) - standard'
@@ -181,7 +181,7 @@ jobs:
name: 'features (4/4) - bim'
script:
- bash script/ci/setup.sh features bim
- - bash script/ci/runner.sh features 4 4
+ - bash script/ci/runner.sh features 4 4 bim
if: head_branch =~ /^(bim\/|dev|release\/)/
- stage: test
name: 'plugins:units (1/1) - standard'
@@ -193,7 +193,7 @@ jobs:
name: 'plugins:units (1/1) - bim'
script:
- bash script/ci/setup.sh plugins:units bim
- - bash script/ci/runner.sh plugins:units 1 1
+ - bash script/ci/runner.sh plugins:units 1 1 bim
if: head_branch =~ /^(bim\/|dev|release\/)/
- stage: test
name: 'plugins:features (1/1) - standard'
@@ -205,7 +205,7 @@ jobs:
name: 'plugins:features (1/1) - bim'
script:
- bash script/ci/setup.sh plugins:features bim
- - bash script/ci/runner.sh plugins:features 1 1
+ - bash script/ci/runner.sh plugins:features 1 1 bim
if: head_branch =~ /^(bim\/|dev|release\/)/
- stage: test
name: 'plugins:cucumber (1/1) - standard'
@@ -217,7 +217,7 @@ jobs:
name: 'plugins:cucumber (1/1) - bim'
script:
- bash script/ci/setup.sh plugins:cucumber bim
- - bash script/ci/runner.sh plugins:cucumber 1 1
+ - bash script/ci/runner.sh plugins:cucumber 1 1 bim
if: head_branch =~ /^(bim\/|dev|release\/)/
addons:
diff --git a/modules/bcf/lib/open_project/bcf/bcf_xml/importer.rb b/modules/bcf/lib/open_project/bcf/bcf_xml/importer.rb
index 5c2a93f2c0..c0c383973b 100644
--- a/modules/bcf/lib/open_project/bcf/bcf_xml/importer.rb
+++ b/modules/bcf/lib/open_project/bcf/bcf_xml/importer.rb
@@ -6,6 +6,18 @@ module OpenProject::Bcf::BcfXml
class Importer
attr_reader :file, :project, :current_user
+ DEFAULT_IMPORT_OPTIONS = {
+ unknown_types_action: "use_default",
+ unknown_statuses_action: "use_default",
+ invalid_people_action: "anonymize",
+ unknown_mails_action: 'invite',
+ non_members_action: 'add',
+ unknown_types_chose_ids: [],
+ unknown_statuses_chose_ids: [],
+ unknown_mails_invite_role_ids: [],
+ non_members_add_role_ids: []
+ }.freeze
+
def initialize(file, project, current_user:)
@file = file
@project = project
@@ -29,10 +41,9 @@ module OpenProject::Bcf::BcfXml
end
def import!(options = {})
+ options = options.merge(DEFAULT_IMPORT_OPTIONS)
Zip::File.open(@file) do |zip|
- treat_invalid_people(options)
- treat_unknown_mails(options)
- treat_non_members(options)
+ apply_import_replacements(options)
# Extract all topics of the zip and save them
synchronize_topics(zip, options)
@@ -49,6 +60,12 @@ module OpenProject::Bcf::BcfXml
private
+ def apply_import_replacements(options)
+ treat_invalid_people(options)
+ treat_unknown_mails(options)
+ treat_non_members(options)
+ end
+
def treat_invalid_people(options)
if aggregations.invalid_people.any?
unless options[:invalid_people_action] == 'anonymize'
diff --git a/modules/bcf/lib/open_project/bcf/bcf_xml/issue_reader.rb b/modules/bcf/lib/open_project/bcf/bcf_xml/issue_reader.rb
index 83ee2dcf11..7ef0e67d42 100644
--- a/modules/bcf/lib/open_project/bcf/bcf_xml/issue_reader.rb
+++ b/modules/bcf/lib/open_project/bcf/bcf_xml/issue_reader.rb
@@ -151,7 +151,7 @@ module OpenProject::Bcf::BcfXml
end
def start_date
- extractor.creation_date unless is_update
+ extractor.creation_date.to_date unless is_update
end
def update_work_package
@@ -331,8 +331,17 @@ module OpenProject::Bcf::BcfXml
end
def update_comment(comment_data)
- bcf_comment = issue.comments.find_by(comment_data.slice(:uuid))
- bcf_comment.journal.update_attribute(:notes, comment_data[:comment])
+ if comment_data[:modified_date]
+ bcf_comment = issue.comments.find_by(comment_data.slice(:uuid))
+ if bcf_comment.journal.created_at < comment_data[:modified_date]
+ update_journal_attributes(bcf_comment, comment_data)
+ end
+ end
+ end
+
+ def update_journal_attributes(bcf_comment, comment_data)
+ bcf_comment.journal.update_attributes(notes: comment_data[:comment],
+ created_at: comment_data[:modified_date])
bcf_comment.journal.save
end
diff --git a/modules/bcf/lib/open_project/bcf/bcf_xml/markup_extractor.rb b/modules/bcf/lib/open_project/bcf/bcf_xml/markup_extractor.rb
index f411929250..2f83076743 100644
--- a/modules/bcf/lib/open_project/bcf/bcf_xml/markup_extractor.rb
+++ b/modules/bcf/lib/open_project/bcf/bcf_xml/markup_extractor.rb
@@ -14,54 +14,51 @@ module OpenProject::Bcf::BcfXml
end
def uuid
- extract_non_empty :@Guid, attribute: true
+ extract :@Guid, attribute: true
end
def title
- extract_non_empty :Title
+ extract :Title
end
def priority
- extract_non_empty :Priority
+ extract :Priority
end
def status
- extract_non_empty :@TopicStatus, attribute: true
+ extract :@TopicStatus, attribute: true
end
def type
- extract_non_empty :@TopicType, attribute: true
+ extract :@TopicType, attribute: true
end
def description
- extract_non_empty :Description
+ extract :Description
end
def author
- extract_non_empty :CreationAuthor
+ extract :CreationAuthor
end
def assignee
- extract_non_empty :AssignedTo
+ extract :AssignedTo
end
def modified_author
- extract_non_empty :ModifiedAuthor
+ extract :ModifiedAuthor
end
def creation_date
- date = extract_non_empty :CreationDate
- Date.iso8601(date) unless date.nil?
+ extract_date_time '/Markup/Topic/CreationDate'
end
def modified_date
- date = extract_non_empty :ModifiedDate
- Date.iso8601(date) unless date.nil?
+ extract_date_time '/Markup/Topic/ModifiedDate'
end
def due_date
- date = extract_non_empty :DueDate
- Date.iso8601(date) unless date.nil?
+ extract_date_time '/Markup/Topic/DueDate'
rescue ArgumentError
nil
end
@@ -70,8 +67,8 @@ module OpenProject::Bcf::BcfXml
doc.xpath('/Markup/Viewpoints').map do |node|
{
uuid: node['Guid'],
- viewpoint: node.xpath('Viewpoint/text()').to_s,
- snapshot: node.xpath('Snapshot/text()').to_s
+ viewpoint: extract_from_node('Viewpoint', node),
+ snapshot: extract_from_node('Snapshot', node)
}.with_indifferent_access
end
end
@@ -80,9 +77,11 @@ module OpenProject::Bcf::BcfXml
doc.xpath('/Markup/Comment').map do |node|
{
uuid: node['Guid'],
- date: node.xpath('Date/text()').to_s,
- author: node.xpath('Author/text()').to_s,
- comment: node.xpath('Comment/text()').to_s
+ date: extract_date_time("Date", node),
+ author: extract_from_node('Author', node),
+ comment: extract_from_node('Comment', node),
+ modified_date: extract_date_time("ModifiedDate", node),
+ modified_author: extract_from_node("ModifiedAuthor", node)
}.with_indifferent_access
end
end
@@ -102,10 +101,21 @@ module OpenProject::Bcf::BcfXml
private
- def extract_non_empty(path, prefix: '/Markup/Topic/'.freeze, attribute: false)
+ def extract_date_time(path, node = nil)
+ node ||= doc
+ date_time = extract_from_node(path, node)
+ Time.iso8601(date_time) unless date_time.nil?
+ end
+
+ def extract(path, prefix: '/Markup/Topic/'.freeze, attribute: false)
+ path = [prefix, path.to_s].join('')
+ extract_from_node(path, doc, attribute: attribute)
+ end
+
+ def extract_from_node(path, node, attribute: false)
suffix = attribute ? '' : '/text()'.freeze
- path = [prefix, path.to_s, suffix].join('')
- doc.xpath(path).to_s.presence
+ path = [path.to_s, suffix].join('')
+ node.xpath(path).to_s.presence
end
end
end
diff --git a/modules/bcf/spec/api/v3/work_packages/work_package_representer_spec.rb b/modules/bcf/spec/api/v3/work_packages/work_package_representer_spec.rb
index 74bf981622..c3f0a528a7 100644
--- a/modules/bcf/spec/api/v3/work_packages/work_package_representer_spec.rb
+++ b/modules/bcf/spec/api/v3/work_packages/work_package_representer_spec.rb
@@ -53,7 +53,7 @@ describe ::API::V3::WorkPackages::WorkPackageRepresenter do
2015-06-21T14:22:47Z
mike@example.com
andy@example.com
- This is a topic with all informations present.
+ This is a topic with all information present.
JsonElement.json
http://json-schema.org
@@ -110,7 +110,7 @@ describe ::API::V3::WorkPackages::WorkPackageRepresenter do
MARKUP
end
let(:bcf_issue) do
- FactoryBot.create(:bcf_issue, markup: markup)
+ FactoryBot.create(:bcf_issue_with_comment, markup: markup)
end
let(:work_package) do
FactoryBot.create(:work_package,
diff --git a/modules/bcf/spec/bcf/bcf_xml/importer_spec.rb b/modules/bcf/spec/bcf/bcf_xml/importer_spec.rb
index 49b0253ec1..4fe0b4eb3b 100644
--- a/modules/bcf/spec/bcf/bcf_xml/importer_spec.rb
+++ b/modules/bcf/spec/bcf/bcf_xml/importer_spec.rb
@@ -27,7 +27,7 @@ describe ::OpenProject::Bcf::BcfXml::Importer do
'application/octet-stream'
)
end
- let(:type) { FactoryBot.create :type, name: 'Issue [BCF]' }
+ let(:type) { FactoryBot.create :type, name: 'Issue' }
let(:project) do
FactoryBot.create(:project,
identifier: 'bim_project',
diff --git a/modules/bcf/spec/bcf/bcf_xml/issue_reader_spec.rb b/modules/bcf/spec/bcf/bcf_xml/issue_reader_spec.rb
index e979b2709d..027e1158cd 100644
--- a/modules/bcf/spec/bcf/bcf_xml/issue_reader_spec.rb
+++ b/modules/bcf/spec/bcf/bcf_xml/issue_reader_spec.rb
@@ -69,7 +69,7 @@ describe ::OpenProject::Bcf::BcfXml::IssueReader do
2015-06-21T14:22:47Z
mike@example.com
andy@example.com
- This is a topic with all informations present.
+ This is a topic with all information present.
@@ -108,7 +108,24 @@ describe ::OpenProject::Bcf::BcfXml::IssueReader do
let(:bcf_issue) { subject.extract! }
it 'WP start date gets initialized with BCF CreationDate' do
- expect(bcf_issue.work_package.start_date).to eql(subject.extractor.creation_date)
+ expect(bcf_issue.work_package.start_date).to eql(subject.extractor.creation_date.to_date)
+ end
+ end
+
+ context 'on updating import' do
+ context '#update_comment' do
+ let!(:bcf_issue) { FactoryBot.create :bcf_issue_with_comment }
+
+ it '#update_comment' do
+ allow(subject).to receive(:issue).and_return(bcf_issue)
+
+ modified_time = Time.now + 1.minute
+ comment_data = { uuid: bcf_issue.comments.first.uuid, comment: 'Updated comment', modified_date: modified_time }
+ subject.send(:update_comment, comment_data)
+
+ expect(bcf_issue.comments.first.journal.notes).to eql('Updated comment')
+ expect(bcf_issue.comments.first.journal.created_at.utc.to_s).to eql(modified_time.utc.to_s)
+ end
end
end
end
diff --git a/modules/bcf/spec/bcf/bcf_xml/issue_writer_spec.rb b/modules/bcf/spec/bcf/bcf_xml/issue_writer_spec.rb
index 441387f66b..68bed6ff4e 100644
--- a/modules/bcf/spec/bcf/bcf_xml/issue_writer_spec.rb
+++ b/modules/bcf/spec/bcf/bcf_xml/issue_writer_spec.rb
@@ -52,7 +52,7 @@ describe ::OpenProject::Bcf::BcfXml::IssueWriter do
2015-06-21T14:22:47Z
mike@example.com
andy@example.com
- This is a topic with all informations present.
+ This is a topic with all information present.
JsonElement.json
http://json-schema.org
diff --git a/modules/bcf/spec/bcf/bcf_xml/markup_extractor_spec.rb b/modules/bcf/spec/bcf/bcf_xml/markup_extractor_spec.rb
index 91e9c18fd9..6b193c4acc 100644
--- a/modules/bcf/spec/bcf/bcf_xml/markup_extractor_spec.rb
+++ b/modules/bcf/spec/bcf/bcf_xml/markup_extractor_spec.rb
@@ -67,7 +67,7 @@ describe ::OpenProject::Bcf::BcfXml::MarkupExtractor do
end
it '#description' do
- expect(subject.description).to be_eql 'This is a topic with all informations present.'
+ expect(subject.description).to be_eql 'This is a topic with all information present.'
end
it '#author' do
@@ -87,11 +87,11 @@ describe ::OpenProject::Bcf::BcfXml::MarkupExtractor do
end
it '#creation_date' do
- expect(subject.creation_date).to eql Date.iso8601('2015-06-21T12:00:00Z')
+ expect(subject.creation_date).to eql(Time.iso8601('2015-06-21T12:00:00Z'))
end
it '#modified_date' do
- expect(subject.modified_date).to eql Date.iso8601('2015-06-21T14:22:47Z')
+ expect(subject.modified_date).to eql(Time.iso8601('2015-06-21T14:22:47Z'))
end
it '#viewpoints' do
@@ -103,11 +103,14 @@ describe ::OpenProject::Bcf::BcfXml::MarkupExtractor do
it '#comments' do
expect(subject.comments.size).to eql 4
- expect(subject.comments.first[:uuid]).to eql '780FAE52-C432-42BE-ADEA-FF3E7A8CD8E1'
- expect(subject.comments.first[:date]).to eql '2015-08-31T12:40:17Z'
- expect(subject.comments.first[:author]).to eql 'mike@example.com'
- expect(subject.comments.first[:comment]).to eql 'This is an unmodified topic at the uppermost hierarchical level.
-All times in the XML are marked as UTC times.'
+ expect(subject.comments.first[:uuid]).to eql('780FAE52-C432-42BE-ADEA-FF3E7A8CD8E1')
+ expect(subject.comments.first[:date]).to eql(Time.iso8601('2015-08-31T12:40:17Z'))
+ expect(subject.comments.first[:modified_date]).to eql(Time.iso8601('2015-08-31T16:07:11Z'))
+ expect(subject.comments.first[:author]).to eql('mike@example.com')
+ expect(subject.comments.first[:modified_author]).to eql('mike@example.com')
+ expect(subject.comments.first[:comment]).to(
+ eql("This comment contained some spllng errs.\nHopefully, the modifier did catch them all.")
+ )
end
it '#people' do
diff --git a/modules/bcf/spec/factories/bcf_comment_factory.rb b/modules/bcf/spec/factories/bcf_comment_factory.rb
new file mode 100644
index 0000000000..a2a61a3912
--- /dev/null
+++ b/modules/bcf/spec/factories/bcf_comment_factory.rb
@@ -0,0 +1,45 @@
+#-- copyright
+# OpenProject Backlogs Plugin
+#
+# Copyright (C)2013-2014 the OpenProject Foundation (OPF)
+# Copyright (C)2011 Stephan Eckardt, Tim Felgentreff, Marnen Laibow-Koser, Sandro Munda
+# Copyright (C)2010-2011 friflaj
+# Copyright (C)2010 Maxime Guilbot, Andrew Vit, Joakim Kolsjö, ibussieres, Daniel Passos, Jason Vasquez, jpic, Emiliano Heyns
+# Copyright (C)2009-2010 Mark Maglana
+# Copyright (C)2009 Joe Heck, Nate Lowrie
+#
+# 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 Backlogs is a derivative work based on ChiliProject Backlogs.
+# The copyright follows:
+# Copyright (C) 2010-2011 - Emiliano Heyns, Mark Maglana, friflaj
+# Copyright (C) 2011 - Jens Ulferts, Gregor Schmidt - Finn GmbH - Berlin, Germany
+#
+# 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 doc/COPYRIGHT.rdoc for more details.
+#++
+
+FactoryBot.define do
+ factory :bcf_comment, class: ::Bcf::Comment do
+ after(:create) do |bcf_comment|
+ bcf_comment.journal = create(:work_package_journal)
+ bcf_comment.journal.update_attribute(:notes, 'Some BCF comment.')
+ bcf_comment.journal.save
+ bcf_comment.save
+ end
+ end
+end
diff --git a/modules/bcf/spec/factories/bcf_issue_factory.rb b/modules/bcf/spec/factories/bcf_issue_factory.rb
index e9b20a91a7..566a2319ff 100644
--- a/modules/bcf/spec/factories/bcf_issue_factory.rb
+++ b/modules/bcf/spec/factories/bcf_issue_factory.rb
@@ -35,8 +35,11 @@
FactoryBot.define do
factory :bcf_issue, class: ::Bcf::Issue do
- after(:create) do |issue|
- create(:bcf_viewpoint, issue: issue)
+ factory :bcf_issue_with_comment do
+ after(:create) do |issue|
+ create(:bcf_viewpoint, issue: issue)
+ create(:bcf_comment, issue: issue)
+ end
end
end
end
diff --git a/modules/bcf/spec/fixtures/files/MaximumInformation.bcf b/modules/bcf/spec/fixtures/files/MaximumInformation.bcf
index b18ffadd07..6cd3017eb2 100644
Binary files a/modules/bcf/spec/fixtures/files/MaximumInformation.bcf and b/modules/bcf/spec/fixtures/files/MaximumInformation.bcf differ
diff --git a/modules/bcf/spec/models/bcf/issue_spec.rb b/modules/bcf/spec/models/bcf/issue_spec.rb
index d7bdf2860f..f661d89258 100644
--- a/modules/bcf/spec/models/bcf/issue_spec.rb
+++ b/modules/bcf/spec/models/bcf/issue_spec.rb
@@ -53,7 +53,7 @@ describe ::Bcf::Issue, type: :model do
2015-06-21T14:22:47Z
mike@example.com
andy@example.com
- This is a topic with all informations present.
+ This is a topic with all information present.
JsonElement.json
http://json-schema.org
@@ -115,7 +115,7 @@ describe ::Bcf::Issue, type: :model do
shared_examples_for 'provides attributes' do
it "provides attributes" do
expect(subject.title).to be_eql 'Maximum Content'
- expect(subject.description).to be_eql 'This is a topic with all informations present.'
+ expect(subject.description).to be_eql 'This is a topic with all information present.'
expect(subject.priority_text).to be_eql 'High'
expect(subject.status_text).to be_eql 'Open'
expect(subject.type_text).to be_eql 'Structural'
diff --git a/script/ci/runner.sh b/script/ci/runner.sh
index adf3b3e854..c2af1bd3de 100644
--- a/script/ci/runner.sh
+++ b/script/ci/runner.sh
@@ -32,11 +32,18 @@
# $1 = TEST_SUITE
# $2 = GROUP_SIZE
# $3 = GROUP
+# $4 = OPENPROJECT_EDITION
#!/bin/sh
set -e
+if [ "$4" = "bim" ]; then
+ export OPENPROJECT_EDITION="$4";
+else
+ unset OPENPROJECT_EDITION
+fi
+
# Use the current HEAD as input to the seed
export CI_SEED=$(git rev-parse HEAD | tr -d 'a-z' | cut -b 1-5 | tr -d '0')
# Do not assume to have the angular cli running to serve assets. They are provided