-
Notifications
You must be signed in to change notification settings - Fork 105
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
711e181
commit 6a7fc09
Showing
9 changed files
with
475 additions
and
1 deletion.
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.