Skip to content

Commit

Permalink
feat(string-translations): add endpoint "Remove String Approvals" (#291)
Browse files Browse the repository at this point in the history
  • Loading branch information
innomaxx authored Jan 17, 2025
1 parent 850315f commit 9fbea65
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ Task<ResponseList<TranslationApproval>> ListTranslationApprovals(

Task RemoveApproval(int projectId, int approvalId);

Task RemoveStringApprovals(int projectId, int stringId);

#endregion

#region Translations
Expand All @@ -75,7 +77,7 @@ Task<ResponseList<StringTranslation>> ListStringTranslations(

Task<StringTranslation> AddTranslation(int projectId, AddTranslationRequest request);

Task DeleteStringTranslations(int projectId, int stringId, string languageId);
Task DeleteStringTranslations(int projectId, int stringId, string? languageId = null);

Task<StringTranslation> GetTranslation(int projectId, int translationId, bool? denormalizePlaceholders = null);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,25 @@ public async Task RemoveApproval(int projectId, int approvalId)
Utils.ThrowIfStatusNot204(statusCode, $"Approval {approvalId} removal failed");
}

/// <summary>
/// Remove string approvals. Documentation:
/// <a href="https://support.crowdin.com/developer/api/v2/#tag/String-Translations/operation/api.projects.approvals.deleteMany">Crowdin API</a>
/// <a href="https://support.crowdin.com/developer/enterprise/api/v2/#tag/String-Translations/operation/api.projects.approvals.deleteMany">Crowdin Enterprise API</a>
/// </summary>
[PublicAPI]
public async Task RemoveStringApprovals(int projectId, int stringId)
{
string url = FormUrl_Approvals(projectId);

var queryParams = new Dictionary<string, string>(1)
{
["stringId"] = stringId.ToString()
};

HttpStatusCode statusCode = await _apiClient.SendDeleteRequest(url, queryParams);
Utils.ThrowIfStatusNot204(statusCode, $"Approvals for string {stringId} removal failed");
}

#region Helper methods

private static string FormUrl_Approvals(int projectId)
Expand Down Expand Up @@ -231,16 +250,20 @@ public async Task<StringTranslation> AddTranslation(int projectId, AddTranslatio
/// <a href="https://support.crowdin.com/enterprise/api/#operation/api.projects.translations.deleteMany">Crowdin Enterprise API</a>
/// </summary>
[PublicAPI]
public async Task DeleteStringTranslations(int projectId, int stringId, string languageId)
public async Task DeleteStringTranslations(int projectId, int stringId, string? languageId = null)
{
string url = FormUrl_Translations(projectId);

var queryParams = new Dictionary<string, string>
{
{ "stringId", stringId.ToString() },
{ "languageId", languageId }
["stringId"] = stringId.ToString(),
};

if (!string.IsNullOrWhiteSpace(languageId))
{
queryParams.Add("languageId", languageId!);
}

HttpStatusCode statusCode = await _apiClient.SendDeleteRequest(url, queryParams);
Utils.ThrowIfStatusNot204(statusCode, "String translation removal failed");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@

using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;

using Moq;
using Newtonsoft.Json.Linq;
using Xunit;

using Crowdin.Api.Core;
using Crowdin.Api.StringTranslations;

namespace Crowdin.Api.UnitTesting.Tests.StringTranslations
{
public class ApprovalsApiTests
{
[Fact]
public async Task ListTranslationApprovals()
{
const int ProjectId = 1;
var url = $"/projects/{ProjectId}/approvals";

Mock<ICrowdinApiClient> mockClient = TestUtils.CreateMockClientWithDefaultParser();

IDictionary<string, string> queryParams = TestUtils.CreateQueryParamsFromPaging();

mockClient
.Setup(client => client.SendGetRequest(url, queryParams))
.ReturnsAsync(new CrowdinApiResult
{
StatusCode = HttpStatusCode.OK,
JsonObject = JObject.Parse(Resources.StringTranslations.ListTranslationsApproval_Response)
});

var executor = new StringTranslationsApiExecutor(mockClient.Object);
ResponseList<TranslationApproval> response = await executor.ListTranslationApprovals(ProjectId);

Assert.NotNull(response);

TranslationApproval data = response.Data[1];
Assert.Equal(200695, data.TranslationId);
Assert.Equal(1234, data.StringId);
Assert.IsType<User>(data.User);
}

[Fact]
public async Task RemoveStringApprovals()
{
const int ProjectId = 1;
const int StringId = 2;

Mock<ICrowdinApiClient> mockClient = TestUtils.CreateMockClientWithDefaultParser();

var url = $"/projects/{ProjectId}/approvals";

var queryParams = new Dictionary<string, string>
{
["stringId"] = StringId.ToString()
};

mockClient
.Setup(client => client.SendDeleteRequest(url, queryParams))
.ReturnsAsync(HttpStatusCode.NoContent);

var executor = new StringTranslationsApiExecutor(mockClient.Object);
await executor.RemoveStringApprovals(ProjectId, StringId);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Crowdin.Api.Core;
using Crowdin.Api.StringTranslations;

using Moq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Xunit;

using Crowdin.Api.Core;
using Crowdin.Api.StringTranslations;

namespace Crowdin.Api.UnitTesting.Tests.StringTranslations
{
public class StringTranslationsApiTests
Expand Down Expand Up @@ -108,6 +110,54 @@ public async Task RestoreTranslation()
Assert.Equal(PluralCategoryName.Few, response.PluralCategoryName);
}

[Fact]
public async Task DeleteStringTranslations()
{
const int ProjectId = 1;
const int StringId = 2;

Mock<ICrowdinApiClient> mockClient = TestUtils.CreateMockClientWithDefaultParser();

var url = $"/projects/{ProjectId}/translations";

var queryParams = new Dictionary<string, string>
{
["stringId"] = StringId.ToString()
};

mockClient
.Setup(client => client.SendDeleteRequest(url, queryParams))
.ReturnsAsync(HttpStatusCode.NoContent);

var executor = new StringTranslationsApiExecutor(mockClient.Object);
await executor.DeleteStringTranslations(ProjectId, StringId);
}

[Fact]
public async Task DeleteStringTranslations_WithLanguageId()
{
const int ProjectId = 1;
const int StringId = 2;
const string LanguageId = "uk";

Mock<ICrowdinApiClient> mockClient = TestUtils.CreateMockClientWithDefaultParser();

var url = $"/projects/{ProjectId}/translations";

var queryParams = new Dictionary<string, string>
{
["stringId"] = StringId.ToString(),
["languageId"] = LanguageId
};

mockClient
.Setup(client => client.SendDeleteRequest(url, queryParams))
.ReturnsAsync(HttpStatusCode.NoContent);

var executor = new StringTranslationsApiExecutor(mockClient.Object);
await executor.DeleteStringTranslations(ProjectId, StringId, LanguageId);
}

[Fact]
public async Task TranslationAlignment()
{
Expand Down Expand Up @@ -155,33 +205,6 @@ public async Task TranslationAlignment()
Assert.Equal(2, alignment.Probability);
}

[Fact]
public async Task ListTranslationApprovals()
{
const int projectId = 1;
var url = $"/projects/{projectId}/approvals";

Mock<ICrowdinApiClient> mockClient = TestUtils.CreateMockClientWithDefaultParser();

var queryParams = TestUtils.CreateQueryParamsFromPaging();

mockClient
.Setup(client => client.SendGetRequest(url, queryParams))
.ReturnsAsync(new CrowdinApiResult
{
StatusCode = HttpStatusCode.OK,
JsonObject = JObject.Parse(Resources.StringTranslations.ListTranslationsApproval_Response)
});

var executor = new StringTranslationsApiExecutor(mockClient.Object);
ResponseList<TranslationApproval> response = await executor.ListTranslationApprovals(projectId);
Assert.NotNull(response);
var data = response.Data[1];
Assert.Equal(200695, data.TranslationId);
Assert.Equal(1234, data.StringId);
Assert.IsType<User>(data.User);
}

[Fact]
public async Task ListTranslationVotes()
{
Expand Down

0 comments on commit 9fbea65

Please sign in to comment.