Skip to content

Commit

Permalink
Improvements of custom field usage as suggested in #52 (also a docume…
Browse files Browse the repository at this point in the history
…ntation improvement)
  • Loading branch information
Lakritzator committed Jan 4, 2021
1 parent dc04096 commit 258ce65
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 34 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ A example to find issues which are assigned to someone who is currently (or lang
<!-- snippet: SearchExample -->
<a id='snippet-searchexample'></a>
```cs
var client = JiraClient.Create(TestJiraUri);
// Preferably use a "bot" user for maintenance
var username = Environment.GetEnvironmentVariable("jira_test_username");
var password = Environment.GetEnvironmentVariable("jira_test_password");
client.SetBasicAuthentication(username, password);
var client = JiraClient
.Create(TestJiraUri)
.SetBasicAuthentication(username, password);

const string unavailableUser = "Robin Krom";
// Find all issues in a certain state and assigned to a user who is not available
Expand All @@ -47,5 +48,5 @@ foreach (var issue in searchResult.Issues)
await issue.AddCommentAsync($"{unavailableUser} is currently not available.");
}
```
<sup><a href='/src/Dapplo.Jira.Tests/IssueTests.cs#L251-L270' title='Snippet source file'>snippet source</a> | <a href='#snippet-searchexample' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Dapplo.Jira.Tests/IssueTests.cs#L264-L284' title='Snippet source file'>snippet source</a> | <a href='#snippet-searchexample' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
7 changes: 4 additions & 3 deletions doc/articles/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ A example to find issues which are assigned to someone who is currently (or lang
<!-- snippet: SearchExample -->
<a id='snippet-searchexample'></a>
```cs
var client = JiraClient.Create(TestJiraUri);
// Preferably use a "bot" user for maintenance
var username = Environment.GetEnvironmentVariable("jira_test_username");
var password = Environment.GetEnvironmentVariable("jira_test_password");
client.SetBasicAuthentication(username, password);
var client = JiraClient
.Create(TestJiraUri)
.SetBasicAuthentication(username, password);

const string unavailableUser = "Robin Krom";
// Find all issues in a certain state and assigned to a user who is not available
Expand All @@ -47,6 +48,6 @@ foreach (var issue in searchResult.Issues)
await issue.AddCommentAsync($"{unavailableUser} is currently not available.");
}
```
<sup><a href='/src/Dapplo.Jira.Tests/IssueTests.cs#L251-L270' title='Snippet source file'>snippet source</a> | <a href='#snippet-searchexample' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Dapplo.Jira.Tests/IssueTests.cs#L264-L284' title='Snippet source file'>snippet source</a> | <a href='#snippet-searchexample' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
<!-- endInclude -->
7 changes: 4 additions & 3 deletions doc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ A example to find issues which are assigned to someone who is currently (or lang
<!-- snippet: SearchExample -->
<a id='snippet-searchexample'></a>
```cs
var client = JiraClient.Create(TestJiraUri);
// Preferably use a "bot" user for maintenance
var username = Environment.GetEnvironmentVariable("jira_test_username");
var password = Environment.GetEnvironmentVariable("jira_test_password");
client.SetBasicAuthentication(username, password);
var client = JiraClient
.Create(TestJiraUri)
.SetBasicAuthentication(username, password);

const string unavailableUser = "Robin Krom";
// Find all issues in a certain state and assigned to a user who is not available
Expand All @@ -47,6 +48,6 @@ foreach (var issue in searchResult.Issues)
await issue.AddCommentAsync($"{unavailableUser} is currently not available.");
}
```
<sup><a href='/src/Dapplo.Jira.Tests/IssueTests.cs#L251-L270' title='Snippet source file'>snippet source</a> | <a href='#snippet-searchexample' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Dapplo.Jira.Tests/IssueTests.cs#L264-L284' title='Snippet source file'>snippet source</a> | <a href='#snippet-searchexample' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
<!-- endInclude -->
60 changes: 37 additions & 23 deletions src/Dapplo.Jira.Tests/IssueTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Dapplo and contributors. All rights reserved.
// Copyright (c) Dapplo and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
Expand Down Expand Up @@ -136,8 +136,8 @@ public async Task Test_CreateIssue()
await Client.Issue.DeleteAsync(createdIssue.Key);
}

//[Fact]
public async Task Test_CreateIssueWithCustomFields()
[Fact]
public async Task Test_Create_and_Retrieve_IssueWithCustomFields()
{
var meMyselfAndI = await Client.User.GetMyselfAsync();
Assert.NotNull(meMyselfAndI);
Expand All @@ -148,8 +148,20 @@ public async Task Test_CreateIssueWithCustomFields()
var bugIssueType = issueTypes.First(type => type.Name == "Bug");
var projectForIssue = projects.First(digest => digest.Key == TestProjectKey);

var cfTextField = "customfield_10001";
var cfLabelField = "customfield_10002";
var cfTextField = "customfield_10001"; // Make sure this custom field is created with: Configure 'Text Field (single line)' Field
var cfTextFieldValue = "plain text";
var cfLabelField = "customfield_10002"; // Make sure this custom field is created with: Configure 'Labels' Field
var cfLabelFieldValue = new[]
{
"label1",
"label2"
};

// Translate custom field names to ids

var fields = await Client.Server.GetFieldsAsync();
var cfTextFieldId = fields.First(f => f.Name == cfTextField).Id;
var cfLabelFieldId = fields.First(f => f.Name == cfLabelField).Id;

var issueToCreate = new Issue
{
Expand All @@ -161,27 +173,28 @@ public async Task Test_CreateIssueWithCustomFields()
},
IssueType = bugIssueType,
Summary = "Some summary, this is a test",
Description = "Some description, this is a test",
CustomFields =
{
{
cfTextField, "plain text"
},
{
cfLabelField, new[]
{
"label1 label2"
}
},
}
Description = "Some description, this is a test"
}
};
}
.AddCustomField(cfTextFieldId, cfTextFieldValue)
.AddCustomField(cfLabelFieldId, cfLabelFieldValue);

var createdIssue = await Client.Issue.CreateAsync(issueToCreate);
Assert.NotNull(createdIssue);
Assert.NotNull(createdIssue.Key);
// Remove again
await Client.Issue.DeleteAsync(createdIssue.Key);

try
{
var testIssue = await Client.Issue.GetAsync(createdIssue.Key);
Assert.Equal(cfTextFieldValue, testIssue.GetCustomField(cfTextFieldId));
Assert.Equal(cfLabelFieldValue, testIssue.GetCustomField<string[]>(cfLabelFieldId));
}
finally
{
// Remove again
await Client.Issue.DeleteAsync(createdIssue.Key);
}

}

[Fact]
Expand Down Expand Up @@ -249,11 +262,12 @@ public async Task Test_GetPossibleTransitions()
public async Task Test_SearchSnippet()
{
// begin-snippet: SearchExample
var client = JiraClient.Create(TestJiraUri);
// Preferably use a "bot" user for maintenance
var username = Environment.GetEnvironmentVariable("jira_test_username");
var password = Environment.GetEnvironmentVariable("jira_test_password");
client.SetBasicAuthentication(username, password);
var client = JiraClient
.Create(TestJiraUri)
.SetBasicAuthentication(username, password);

const string unavailableUser = "Robin Krom";
// Find all issues in a certain state and assigned to a user who is not available
Expand Down
2 changes: 1 addition & 1 deletion src/Dapplo.Jira/Entities/Field.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace Dapplo.Jira.Entities
{
/// <summary>
/// Filter information
/// Field information
/// </summary>
[JsonObject]
public class Field : BaseProperties<string>
Expand Down
101 changes: 100 additions & 1 deletion src/Dapplo.Jira/IssueExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
// Copyright (c) Dapplo and contributors. All rights reserved.
// Copyright (c) Dapplo and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Dapplo.Jira.Entities;
using Newtonsoft.Json;

namespace Dapplo.Jira
{
Expand Down Expand Up @@ -66,5 +67,103 @@ public static Task AssignAsync(this IssueBase issue, User newUser, CancellationT
{
return issue.AssociatedJiraClient.Issue.AssignAsync(issue.Key, newUser, cancellationToken);
}

/// <summary>
/// Retrieve a custom field from an issue
/// </summary>
/// <typeparam name="TCustomField">type for the custom field</typeparam>
/// <param name="issue">Issue to retrieve custom field value from</param>
/// <param name="customFieldName">string with the name of the custom field</param>
/// <returns>TCustomField</returns>
public static TCustomField GetCustomField<TCustomField>(this Issue issue, string customFieldName)
{
var customFields = issue.Fields.CustomFields;
if (customFields == null || !customFields.ContainsKey(customFieldName))
{
return default;
}
return JsonConvert.DeserializeObject<TCustomField>(issue.Fields.CustomFields[customFieldName].ToString());
}

/// <summary>
/// Retrieve a custom field from an issue
/// </summary>
/// <param name="issue">Issue to retrieve custom field value from</param>
/// <param name="customFieldName">string with the name of the custom field</param>
/// <returns>string</returns>
public static string GetCustomField(this Issue issue, string customFieldName)
{
var customFields = issue.Fields.CustomFields;
if (customFields == null || !customFields.ContainsKey(customFieldName))
{
return default;
}
return issue.Fields.CustomFields[customFieldName].ToString();
}

/// <summary>
/// Retrieve a custom field from an agile issue
/// </summary>
/// <typeparam name="TCustomField">type for the custom field</typeparam>
/// <param name="issue">AgileIssue to retrieve custom field value from</param>
/// <param name="customFieldName">string with the name of the custom field</param>
/// <returns>TCustomField</returns>
public static TCustomField GetCustomField<TCustomField>(this AgileIssue issue, string customFieldName)
{
var customFields = issue.Fields.CustomFields;
if (customFields == null || !customFields.ContainsKey(customFieldName))
{
return default;
}
return JsonConvert.DeserializeObject<TCustomField>(issue.Fields.CustomFields[customFieldName].ToString());
}

/// <summary>
/// Retrieve a custom field from an agile issue
/// </summary>
/// <param name="issue">AgileIssue to retrieve custom field value from</param>
/// <param name="customFieldName">string with the name of the custom field</param>
/// <returns>string</returns>
public static string GetCustomField(this AgileIssue issue, string customFieldName)
{
var customFields = issue.Fields.CustomFields;
if (customFields == null || !customFields.ContainsKey(customFieldName))
{
return default;
}
return issue.Fields.CustomFields[customFieldName].ToString();
}

/// <summary>
/// Add a custom field to an IssueEdit
/// </summary>
/// <typeparam name="TCustomField">type for the custom field</typeparam>
/// <param name="issueToEdit">IssueEdit to add a custom field with value to</param>
/// <param name="customFieldName">string with the name of the custom field</param>
/// <param name="customFieldValue">TCustomField with the value</param>
/// <returns>IssueEdit for a fluent usage</returns>
public static IssueEdit AddCustomField<TCustomField>(this IssueEdit issueToEdit, string customFieldName, TCustomField customFieldValue)
{
// Make sure that IssueFields is available
issueToEdit.Fields ??= new IssueFields();
issueToEdit.Fields.CustomFields.Add(customFieldName, customFieldValue);
return issueToEdit;
}

/// <summary>
/// Add a custom field to an Issue
/// </summary>
/// <typeparam name="TCustomField">type for the custom field</typeparam>
/// <param name="issueToEdit">IssueEdit to add a custom field with value to</param>
/// <param name="customFieldName">string with the name of the custom field</param>
/// <param name="customFieldValue">TCustomField with the value</param>
/// <returns>Issue for a fluent usage</returns>
public static Issue AddCustomField<TCustomField>(this Issue issueToEdit, string customFieldName, TCustomField customFieldValue)
{
// Make sure that IssueFields is available
issueToEdit.Fields ??= new IssueFields();
issueToEdit.Fields.CustomFields.Add(customFieldName, customFieldValue);
return issueToEdit;
}
}
}

0 comments on commit 258ce65

Please sign in to comment.