-
Notifications
You must be signed in to change notification settings - Fork 105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
https://github.com/JetBrains/YouTrackSharp/issues/40 #69
Merged
maartenba
merged 1 commit into
JetBrains:develop
from
aschoelzhorn:feature/Issue#40_Custom_Fields
Nov 15, 2017
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
using Newtonsoft.Json; | ||
|
||
namespace YouTrackSharp.Projects | ||
{ | ||
/// <summary> | ||
/// Custom field for a project | ||
/// </summary> | ||
public class CustomField | ||
{ | ||
/// <summary> | ||
/// Creates an instance of the <see cref="CustomField" /> class. | ||
/// </summary> | ||
public CustomField() | ||
{ | ||
Name = string.Empty; | ||
Url = string.Empty; | ||
Type = string.Empty; | ||
CanBeEmpty = false; | ||
EmptyText = string.Empty; | ||
} | ||
|
||
/// <summary> | ||
/// Name of project custom field. | ||
/// </summary> | ||
[JsonProperty("name")] | ||
public string Name { get; set; } | ||
|
||
/// <summary> | ||
/// The Url of the custom field. | ||
/// </summary> | ||
[JsonProperty("url")] | ||
public string Url { get; set; } | ||
|
||
/// <summary> | ||
/// Type of this custom field. | ||
/// </summary> | ||
[JsonProperty("type")] | ||
public string Type { get; set; } | ||
|
||
/// <summary> | ||
/// Mandatory binary parameter defining if the field can have empty value or not. | ||
/// </summary> | ||
[JsonProperty("canBeEmpty")] | ||
public bool CanBeEmpty { get; set; } | ||
|
||
/// <summary> | ||
/// Text that is shown when the custom field has no value. | ||
/// </summary> | ||
[JsonProperty("emptyText")] | ||
public string EmptyText { get; set; } | ||
} | ||
} |
159 changes: 159 additions & 0 deletions
159
src/YouTrackSharp/Projects/ProjectCustomFieldsService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Net; | ||
using System.Net.Http; | ||
using System.Net.Http.Headers; | ||
using System.Threading.Tasks; | ||
using Newtonsoft.Json; | ||
using Newtonsoft.Json.Linq; | ||
using YouTrackSharp.Management; | ||
|
||
namespace YouTrackSharp.Projects | ||
{ | ||
/// <summary> | ||
/// A class that represents a REST API client for <a href="https://www.jetbrains.com/help/youtrack/standalone/Project-Custom-Fields.html"> methods related to operations with custom fields of a project</a>. | ||
/// It uses a <see cref="Connection" /> implementation to connect to the remote YouTrack server instance. | ||
/// </summary> | ||
public class ProjectCustomFieldsService | ||
{ | ||
private readonly Connection _connection; | ||
|
||
/// <summary> | ||
/// Creates an instance of the <see cref="ProjectCustomFieldsService" /> class. | ||
/// </summary> | ||
/// <param name="connection">A <see cref="Connection" /> instance that provides a connection to the remote YouTrack server instance.</param> | ||
public ProjectCustomFieldsService(Connection connection) | ||
{ | ||
_connection = connection ?? throw new ArgumentNullException(nameof(connection)); | ||
} | ||
|
||
/// <summary> | ||
/// Get custom fields used in a project. | ||
/// </summary> | ||
/// <remarks>Uses the REST API <a href="https://www.jetbrains.com/help/youtrack/standalone/GET-Project-Custom-Fields.html">Get Project Custom Fields</a>.</remarks> | ||
/// <param name="projectId">Id of the project to get the custom fields for.</param> | ||
/// <returns>A <see cref="T:System.Collections.Generic.ICollection`1" /> of <see cref="CustomField" /> that are accessible for currently logged in user.</returns> | ||
/// <exception cref="T:System.Net.HttpRequestException">When the call to the remote YouTrack server instance failed.</exception> | ||
public async Task<ICollection<CustomField>> GetProjectCustomFields(string projectId) | ||
{ | ||
var client = await _connection.GetAuthenticatedHttpClient(); | ||
var response = await client.GetAsync($"rest/admin/project/{projectId}/customfield"); | ||
|
||
response.EnsureSuccessStatusCode(); | ||
|
||
return JsonConvert.DeserializeObject<ICollection<CustomField>>(await response.Content.ReadAsStringAsync()); | ||
} | ||
|
||
/// <summary> | ||
/// Get a project's custom field by its name. | ||
/// </summary> | ||
/// <remarks>Uses the REST API <a href="https://www.jetbrains.com/help/youtrack/standalone/GET-Project-Custom-Field.html">Get Project Custom Field</a>.</remarks> | ||
/// <param name="projectId">Id of the project to get the custom field for.</param> | ||
/// <param name="customFieldName">Name of the custom field to get.</param> | ||
/// <returns><see cref="CustomField" />.</returns> | ||
/// <exception cref="T:System.Net.HttpRequestException">When the call to the remote YouTrack server instance failed.</exception> | ||
public async Task<CustomField> GetProjectCustomField(string projectId, string customFieldName) | ||
{ | ||
var client = await _connection.GetAuthenticatedHttpClient(); | ||
var response = await client.GetAsync($"rest/admin/project/{projectId}/customfield/{customFieldName}"); | ||
|
||
response.EnsureSuccessStatusCode(); | ||
|
||
return JsonConvert.DeserializeObject<CustomField>(await response.Content.ReadAsStringAsync()); | ||
} | ||
|
||
/// <summary> | ||
/// Remove specified custom field from a project. | ||
/// </summary> | ||
/// <remarks>Uses the REST API <a href="https://www.jetbrains.com/help/youtrack/standalone/DELETE-Project-Custom-Field.html">Delete a project custom field</a>.</remarks> | ||
/// <param name="projectId">Id of the project to delete the custom field for.</param> | ||
/// <param name="customFieldName">Name of the custom field to delete.</param> | ||
/// <exception cref="T:System.ArgumentNullException">When the <paramref name="projectId"/> is null or empty.</exception> | ||
/// <exception cref="T:System.ArgumentNullException">When the <paramref name="customFieldName"/> is null or empty.</exception> | ||
/// <exception cref="T:System.Net.HttpRequestException">When the call to the remote YouTrack server instance failed.</exception> | ||
public async Task DeleteProjectCustomField(string projectId, string customFieldName) | ||
{ | ||
if (string.IsNullOrEmpty(projectId)) | ||
{ | ||
throw new ArgumentNullException(nameof(projectId)); | ||
} | ||
if (string.IsNullOrEmpty(customFieldName)) | ||
{ | ||
throw new ArgumentNullException(nameof(customFieldName)); | ||
} | ||
|
||
var client = await _connection.GetAuthenticatedHttpClient(); | ||
var response = await client.DeleteAsync($"rest/admin/project/{projectId}/customfield/{customFieldName}"); | ||
|
||
if (response.StatusCode == HttpStatusCode.NotFound) | ||
{ | ||
return; | ||
} | ||
|
||
response.EnsureSuccessStatusCode(); | ||
} | ||
|
||
/// <summary> | ||
/// Adds an existing custom field to a specific project. | ||
/// </summary> | ||
/// <remarks>Uses the REST API <a href="https://www.jetbrains.com/help/youtrack/standalone/PUT-Project-Custom-Field.html">Create a project custom field</a>.</remarks> | ||
/// <param name="projectId">Id of the project to add a custom field.</param> | ||
/// <param name="customField"><see cref="CustomField" /> to add to the project.</param> | ||
/// <exception cref="T:System.ArgumentNullException">When the <paramref name="projectId"/> is null or empty.</exception> | ||
/// <exception cref="T:System.ArgumentNullException">When the <paramref name="customField"/> is null or empty.</exception> | ||
/// <exception cref="T:YouTrackErrorException">When the call to the remote YouTrack server instance failed and YouTrack reported an error message.</exception> | ||
/// <exception cref="T:System.Net.HttpRequestException">When the call to the remote YouTrack server instance failed.</exception> | ||
public async Task CreateProjectCustomField(string projectId, CustomField customField) | ||
{ | ||
if (string.IsNullOrEmpty(customField?.Name)) | ||
{ | ||
throw new ArgumentNullException(nameof(customField)); | ||
} | ||
|
||
string query = string.Empty; | ||
if (!string.IsNullOrEmpty(customField.EmptyText)) | ||
{ | ||
query = $"?emptyFieldText={WebUtility.UrlEncode(customField.EmptyText)}"; | ||
} | ||
|
||
var client = await _connection.GetAuthenticatedHttpClient(); | ||
var response = await client.PutAsync($"rest/admin/project/{projectId}/customfield/{customField.Name}{query}", new MultipartContent()); | ||
|
||
response.EnsureSuccessStatusCode(); | ||
} | ||
|
||
/// <summary> | ||
/// Updates a custom field to a specific project. | ||
/// </summary> | ||
/// <remarks>Uses the REST API <a href="https://www.jetbrains.com/help/youtrack/standalone/POST-Project-Custom-Field.html">Updates a project custom field</a>.</remarks> | ||
/// <param name="projectId">Id of the project.</param> | ||
/// <param name="customField"><see cref="CustomField" /> to update in project.</param> | ||
/// <exception cref="T:System.ArgumentNullException">When the <paramref name="projectId"/> is null or empty.</exception> | ||
/// <exception cref="T:System.ArgumentNullException">When the <paramref name="customField"/> is null or empty.</exception> | ||
/// <exception cref="T:YouTrackErrorException">When the call to the remote YouTrack server instance failed and YouTrack reported an error message.</exception> | ||
/// <exception cref="T:System.Net.HttpRequestException">When the call to the remote YouTrack server instance failed.</exception> | ||
public async Task UpdateProjectCustomField(string projectId, CustomField customField) | ||
{ | ||
if (string.IsNullOrEmpty(projectId)) | ||
{ | ||
throw new ArgumentNullException(nameof(projectId)); | ||
} | ||
|
||
if (string.IsNullOrEmpty(customField?.Name)) | ||
{ | ||
throw new ArgumentNullException(nameof(customField)); | ||
} | ||
|
||
string query = string.Empty; | ||
if (!string.IsNullOrEmpty(customField.EmptyText)) | ||
{ | ||
query = $"?emptyFieldText={WebUtility.UrlEncode(customField.EmptyText)}"; | ||
} | ||
|
||
var client = await _connection.GetAuthenticatedHttpClient(); | ||
var response = await client.PostAsync($"rest/admin/project/{projectId}/customfield/{customField.Name}{query}", new MultipartContent()); | ||
|
||
response.EnsureSuccessStatusCode(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 74 additions & 0 deletions
74
tests/YouTrackSharp.Tests/Integration/Projects/CreateProjectCustomField.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
using System; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Xunit; | ||
using YouTrackSharp.Projects; | ||
using YouTrackSharp.Tests.Infrastructure; | ||
|
||
namespace YouTrackSharp.Tests.Integration.Projects | ||
{ | ||
public partial class ProjectCustomFieldsServiceTests | ||
{ | ||
public class CreateProjectCustomField | ||
{ | ||
[Fact] | ||
public async Task Valid_Connection_Creates_CustomField_For_Project() | ||
{ | ||
// Arrange | ||
var connection = Connections.Demo1Password; | ||
var service = connection.ProjectCustomFieldsService(); | ||
var customField = new CustomField {Name = "TestField"}; | ||
var projectId = "DP1"; | ||
|
||
// Act | ||
await service.CreateProjectCustomField(projectId, customField); | ||
|
||
var created = await service.GetProjectCustomField(projectId, customField.Name); | ||
|
||
// Assert | ||
Assert.NotNull(created); | ||
|
||
Assert.Equal(customField.Name, created.Name); | ||
Assert.Equal(customField.EmptyText, string.Empty); | ||
|
||
// cleanup | ||
await service.DeleteProjectCustomField(projectId, customField.Name); | ||
} | ||
|
||
[Fact] | ||
public async Task Valid_Connection_Creates_CustomField_With_EmptyText_For_Project() | ||
{ | ||
// Arrange | ||
var connection = Connections.Demo1Password; | ||
var service = connection.ProjectCustomFieldsService(); | ||
var customField = new CustomField { Name = "TestField", EmptyText = "empty" }; | ||
var projectId = "DP1"; | ||
|
||
// Act | ||
await service.CreateProjectCustomField(projectId, customField); | ||
|
||
var created = await service.GetProjectCustomField(projectId, customField.Name); | ||
|
||
// Assert | ||
Assert.NotNull(created); | ||
|
||
Assert.Equal(customField.Name, created.Name); | ||
Assert.Equal(customField.EmptyText, created.EmptyText); | ||
|
||
// cleanup | ||
await service.DeleteProjectCustomField(projectId, customField.Name); | ||
} | ||
|
||
[Fact] | ||
public async Task Invalid_Connection_Throws_UnauthorizedConnectionException() | ||
{ | ||
// Arrange | ||
var service = Connections.UnauthorizedConnection.ProjectCustomFieldsService(); | ||
|
||
// Act & Assert | ||
await Assert.ThrowsAsync<UnauthorizedConnectionException>( | ||
async () => await service.GetProjectCustomField("DP1", "TestField")); | ||
} | ||
} | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
tests/YouTrackSharp.Tests/Integration/Projects/DeleteProjectCustomField.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
using System; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Xunit; | ||
using YouTrackSharp.Tests.Infrastructure; | ||
|
||
namespace YouTrackSharp.Tests.Integration.Projects | ||
{ | ||
public partial class ProjectCustomFieldsServiceTests | ||
{ | ||
public class DeleteProjectCustomField | ||
{ | ||
[Fact] | ||
public async Task Valid_Connection_Deletes_CustomField_For_Project() | ||
{ | ||
// Arrange | ||
var connection = Connections.Demo1Token; | ||
var service = connection.ProjectCustomFieldsService(); | ||
|
||
// Act & Assert | ||
var acted = false; | ||
await service.DeleteProjectCustomField("DP1", " TestField"); | ||
acted = true; | ||
|
||
Assert.True(acted); | ||
} | ||
|
||
[Fact] | ||
public async Task Invalid_Connection_Throws_UnauthorizedConnectionException() | ||
{ | ||
// Arrange | ||
var service = Connections.UnauthorizedConnection.ProjectCustomFieldsService(); | ||
|
||
// Act & Assert | ||
await Assert.ThrowsAsync<UnauthorizedConnectionException>( | ||
async () => await service.DeleteProjectCustomField("DP1", "TestField")); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, thanks!