Skip to content

Commit

Permalink
Merge pull request #947 from solidify/bugfix/changelog-mapping-for-cu…
Browse files Browse the repository at this point in the history
…stom-fields

Bugfix/changelog mapping for custom fields
  • Loading branch information
Alexander-Hjelm authored Dec 28, 2023
2 parents 108677d + 93753e7 commit 4ec0daf
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 59 deletions.
24 changes: 2 additions & 22 deletions src/WorkItemMigrator/JiraExport/JiraItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,7 @@ private static List<JiraRevision> BuildRevisions(JiraItem jiraItem, IJiraProvide
{
string issueKey = jiraItem.Key;
var remoteIssue = jiraItem.RemoteIssue;
Dictionary<string, object> fieldsTemp = ExtractFields(issueKey, remoteIssue, jiraProvider);

// Add CustomFieldName fields, copy over all non-custom fields.
// These get removed as we loop over the changeLog, so we're left with the original Jira values by the time we reach firstRevision.
Dictionary<string, object> fields = new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase);
foreach (var field in fieldsTemp)
{
var key = GetCustomFieldName(field.Key, jiraProvider);
if (!String.IsNullOrEmpty(key))
{
fields[key] = field.Value;
}
else
{
fields[field.Key] = field.Value;
}
}
Dictionary<string, object> fields = ExtractFields(issueKey, remoteIssue, jiraProvider);

List<JiraAttachment> attachments = ExtractAttachments(remoteIssue.SelectTokens("$.fields.attachment[*]").Cast<JObject>()) ?? new List<JiraAttachment>();
List<JiraLink> links = ExtractLinks(issueKey, remoteIssue.SelectTokens("$.fields.issuelinks[*]").Cast<JObject>()) ?? new List<JiraLink>();
Expand Down Expand Up @@ -332,11 +316,7 @@ private static (string, string, string) TransformFieldChange(JiraChangeItem item

private static string GetCustomFieldId(string fieldName, IJiraProvider jira)
{
var customField = jira.GetCustomField(fieldName);
if (customField != null)
return customField.Id;
else return null;

return jira.GetCustomId(fieldName);
}

protected static string GetCustomFieldName(string fieldId, IJiraProvider jira)
Expand Down
24 changes: 6 additions & 18 deletions src/WorkItemMigrator/JiraExport/JiraMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ internal Dictionary<string, FieldMapping<JiraRevision>> InitializeFieldMappings(
if (item.Source != null)
{
var isCustomField = item.SourceType == "name";
if (isCustomField && _jiraProvider.GetCustomId(item.Source) == null)
Logger.Log(LogLevel.Warning, $"Could not find the field id for '{item.Source}', please check the field mapping!");

Func<JiraRevision, (bool, object)> value;

if (item.Mapping?.Values != null)
Expand Down Expand Up @@ -248,7 +251,7 @@ internal List<WiLink> MapLinks(JiraRevision r)
}

// map epic link
LinkMapperUtils.AddRemoveSingleLink(r, links, _config.EpicLinkField, "Epic", _config);
LinkMapperUtils.AddRemoveSingleLink(r, links, _jiraProvider.GetSettings().EpicLinkField, "Epic", _config);

// map parent
LinkMapperUtils.AddRemoveSingleLink(r, links, "parent", "Parent", _config);
Expand Down Expand Up @@ -375,29 +378,14 @@ private HashSet<string> InitializeTypeMappings()

private Func<JiraRevision, (bool, object)> IfChanged<T>(string sourceField, bool isCustomField, Func<T, object> mapperFunc = null)
{
// Store both the customFieldName and the sourceField as the changelog seems to only use the customFieldName, which is then passed into this function as the sourceField.
string customFieldName = "";
if (isCustomField)
{
customFieldName = _jiraProvider.GetCustomId(sourceField);
sourceField = _jiraProvider.GetCustomId(sourceField) ?? sourceField;
}

return (r) =>
{
object value;
// This sourceField is often actually the customFieldName.
if (r.Fields.TryGetValue(sourceField.ToLower(), out value))
{
if (mapperFunc != null)
{
return (true, mapperFunc((T)value));
}
else
{
return (true, (T)value);
}
}
else if (r.Fields.TryGetValue(customFieldName.ToLower(), out value))
if (r.Fields.TryGetValue(sourceField.ToLower(), out object value))
{
if (mapperFunc != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ public void When_an_epic_link_was_removed_Then_the_result_should_be_successful()
}

[Test]
public void When_a_custom_field_is_added_Then_a_customfield_is_added_to_the_revision_with_name_as_key()
public void When_a_custom_field_is_added_Then_no_customfield_is_added_to_the_revision_with_name_as_key()
{
//Arrange
var provider = _fixture.Freeze<IJiraProvider>();
Expand All @@ -586,7 +586,7 @@ public void When_a_custom_field_is_added_Then_a_customfield_is_added_to_the_revi
string customFieldId = _fixture.Create<string>();
string customFieldName = _fixture.Create<string>();

var fields = JObject.Parse(@"{'issuetype': {'name': 'Story'},'" + customFieldId + @"': {'name':'SomeValue'}}");
var fields = JObject.Parse(@"{'issuetype': {'name': 'Story'},'" + customFieldId + @"': {'name':'SomeValue', 'key':'" + customFieldId + "'}}");
var renderedFields = new JObject();

var changelog = new List<JObject>();
Expand All @@ -604,10 +604,7 @@ public void When_a_custom_field_is_added_Then_a_customfield_is_added_to_the_revi
var jiraSettings = createJiraSettings();
provider.GetSettings().ReturnsForAnyArgs(jiraSettings);

RemoteField remoteField = new RemoteField();
remoteField.id = customFieldId;
remoteField.name = customFieldName;
CustomField customField = new CustomField(remoteField);
CustomField customField = null;

provider.GetCustomField(default).ReturnsForAnyArgs(customField);

Expand All @@ -618,25 +615,37 @@ public void When_a_custom_field_is_added_Then_a_customfield_is_added_to_the_revi
Assert.Multiple(() =>
{
Assert.AreEqual(1, jiraItem.Revisions.Count);
Assert.IsFalse(jiraItem.Revisions[0].Fields.Any(f => f.Key == customFieldId));
Assert.IsTrue(jiraItem.Revisions[0].Fields.Any(f => f.Key == customFieldName));
Assert.IsFalse(jiraItem.Revisions[0].Fields.Any(f => f.Key == customFieldName));
});
}

[Test]
public void When_a_custom_field_is_added_Then_no_customfield_is_added_to_the_revision_with_name_as_key()
public void When_an_custom_field_is_changed_Then_it_should_have_the_previous_value_in_the_initial_revision()
{
//Arrange
var provider = _fixture.Freeze<IJiraProvider>();
long issueId = _fixture.Create<long>();
string issueKey = _fixture.Create<string>();
string customFieldId = _fixture.Create<string>();
string customFieldName = _fixture.Create<string>();
string customFieldPreviousValue = _fixture.Create<string>();
string customFieldNewValue = _fixture.Create<string>();

var fields = JObject.Parse(@"{'issuetype': {'name': 'Story'},'" + customFieldId + @"': {'name':'SomeValue', 'key':'" + customFieldId + "'}}");
var fields = JObject.Parse(@"{'issuetype': {'name': 'Story'},'" + customFieldId + @"': '" + customFieldNewValue + @"', 'key':'" + issueKey + "'}");
var renderedFields = new JObject();

var changelog = new List<JObject>();
var changelog = new List<JObject>()
{
new HistoryItem()
{
Field = customFieldName,
FieldType = "custom",
From = customFieldPreviousValue,
FromString = customFieldPreviousValue,
To = customFieldNewValue,
ToString = customFieldNewValue
}.ToJObject()
};

JObject remoteIssue = new JObject
{
Expand All @@ -651,18 +660,74 @@ public void When_a_custom_field_is_added_Then_no_customfield_is_added_to_the_rev
var jiraSettings = createJiraSettings();
provider.GetSettings().ReturnsForAnyArgs(jiraSettings);

CustomField customField = null;
provider.GetCustomId(customFieldName).Returns(customFieldId);

provider.GetCustomField(default).ReturnsForAnyArgs(customField);
//Act
var jiraItem = JiraItem.CreateFromRest(issueKey, provider);

//Assert
Assert.Multiple(() =>
{
Assert.AreEqual(2, jiraItem.Revisions.Count);
Assert.IsTrue(jiraItem.Revisions[0].Fields.ContainsKey(customFieldId));
Assert.AreEqual(customFieldPreviousValue, jiraItem.Revisions[0].Fields[customFieldId]);
Assert.IsTrue(jiraItem.Revisions[1].Fields.ContainsKey(customFieldId));
Assert.AreEqual(customFieldNewValue, jiraItem.Revisions[1].Fields[customFieldId]);
});
}

[Test]
public void When_an_custom_field_is_added_and_changed_later_Then_it_should_not_be_in_the_initial_revision()
{
//Arrange
var provider = _fixture.Freeze<IJiraProvider>();
long issueId = _fixture.Create<long>();
string issueKey = _fixture.Create<string>();
string customFieldId = _fixture.Create<string>();
string customFieldName = _fixture.Create<string>();
string customFieldNewValue = _fixture.Create<string>();

var fields = JObject.Parse(@"{'issuetype': {'name': 'Story'},'" + customFieldId + @"': '" + customFieldNewValue + @"', 'key':'" + issueKey + "'}");
var renderedFields = new JObject();

var changelog = new List<JObject>()
{
new HistoryItem()
{
Field = customFieldName,
FieldType = "custom",
To = customFieldNewValue,
ToString = customFieldNewValue
}.ToJObject()
};

JObject remoteIssue = new JObject
{
{ "id", issueId },
{ "key", issueKey },
{ "fields", fields },
{ "renderedFields", renderedFields }
};

provider.DownloadIssue(default).ReturnsForAnyArgs(remoteIssue);
provider.DownloadChangelog(default).ReturnsForAnyArgs(changelog);
var jiraSettings = createJiraSettings();
provider.GetSettings().ReturnsForAnyArgs(jiraSettings);

provider.GetCustomId(customFieldName).Returns(customFieldId);

//Act
var jiraItem = JiraItem.CreateFromRest(issueKey, provider);

//Assert
Assert.Multiple(() =>
{
Assert.AreEqual(1, jiraItem.Revisions.Count);
Assert.IsFalse(jiraItem.Revisions[0].Fields.Any(f => f.Key == customFieldName));
Assert.AreEqual(2, jiraItem.Revisions.Count);
Assert.IsFalse(jiraItem.Revisions[0].Fields.ContainsKey(customFieldId));
Assert.IsFalse(jiraItem.Revisions[0].Fields.ContainsKey(customFieldName));
Assert.IsTrue(jiraItem.Revisions[1].Fields.ContainsKey(customFieldId));
Assert.IsFalse(jiraItem.Revisions[1].Fields.ContainsKey(customFieldName));
Assert.AreEqual(customFieldNewValue, jiraItem.Revisions[1].Fields[customFieldId]);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public void When_calling_map_on_an_issue_with_an_epic_link_and_a_parent_Then_two

var fields = JObject.Parse(@"{
'issuetype': {'name': 'Story'},
'Epic Link': 'EpicKey'
'EpicLinkField': 'EpicKey'
}");
var renderedFields = JObject.Parse("{ 'custom_field_name': 'SomeValue', 'description': 'RenderedDescription' }");

Expand All @@ -88,7 +88,7 @@ public void When_calling_map_on_an_issue_with_an_epic_link_and_a_parent_Then_two
new HistoryItem()
{
Id = 1,
Field = "parent",
Field = "Parent",
FieldType = "jira",
To = parentId,
ToString = parentKey
Expand Down Expand Up @@ -273,8 +273,6 @@ private JiraMapper createJiraMapper()
repositoryMap.Repositories.Add(repository);
cjson.RepositoryMap = repositoryMap;

cjson.EpicLinkField = "Epic Link";

JiraMapper sut = new JiraMapper(provider, cjson);

return sut;
Expand Down

0 comments on commit 4ec0daf

Please sign in to comment.