From 5c52e9259cfceee2bd5c9541a275622590704354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9DAndrei=E2=80=9D?= <”andrei.chirila07121999@gmail.com”> Date: Sun, 1 Mar 2026 20:49:31 +0200 Subject: [PATCH 1/3] feat: add support for revalidate qa checks * Created additional files: QaCheckRevalidation.class represents the new resource, QaCheckRevalidationRequest.class represents the request body for the POST request, QaCheckRevalidationResponseObject.class to map as a ResponseObject, and QaCheckRevalidationResponseList.class to map as a ResponseList; * Implemented the required methods to support the new endpoints (GET, POST, and DELETE); * Added new JSON files: qaChecksRevalidation.json this mocks the response you would get from calling the GET or POST endpoint; qaChecksRevalidationRequest.json this mocks the payload for POST endpoint. --- .../TranslationStatusApi.java | 46 ++++++++++++++++++ .../model/QaCheckRevalidation.java | 25 ++++++++++ .../model/QaCheckRevalidationRequest.java | 13 +++++ .../QaCheckRevalidationResponseList.java | 26 ++++++++++ .../QaCheckRevalidationResponseObject.java | 9 ++++ .../TranslationStatusApiTest.java | 47 ++++++++++++++++++- .../qaChecksRevalidation.json | 21 +++++++++ .../qaChecksRevalidationRequest.json | 10 ++++ 8 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidation.java create mode 100644 src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidationRequest.java create mode 100644 src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidationResponseList.java create mode 100644 src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidationResponseObject.java create mode 100644 src/test/resources/api/translationstatus/qaChecksRevalidation.json create mode 100644 src/test/resources/api/translationstatus/qaChecksRevalidationRequest.json diff --git a/src/main/java/com/crowdin/client/translationstatus/TranslationStatusApi.java b/src/main/java/com/crowdin/client/translationstatus/TranslationStatusApi.java index 8fcd970fb..586493f60 100644 --- a/src/main/java/com/crowdin/client/translationstatus/TranslationStatusApi.java +++ b/src/main/java/com/crowdin/client/translationstatus/TranslationStatusApi.java @@ -7,6 +7,7 @@ import com.crowdin.client.core.model.ClientConfig; import com.crowdin.client.core.model.Credentials; import com.crowdin.client.core.model.ResponseList; +import com.crowdin.client.core.model.ResponseObject; import com.crowdin.client.translationstatus.model.Category; import com.crowdin.client.translationstatus.model.FileBranchProgress; import com.crowdin.client.translationstatus.model.FileProgressResponseList; @@ -14,6 +15,9 @@ import com.crowdin.client.translationstatus.model.LanguageProgressResponseList; import com.crowdin.client.translationstatus.model.QaCheck; import com.crowdin.client.translationstatus.model.QaCheckResponseList; +import com.crowdin.client.translationstatus.model.QaCheckRevalidation; +import com.crowdin.client.translationstatus.model.QaCheckRevalidationRequest; +import com.crowdin.client.translationstatus.model.QaCheckRevalidationResponseObject; import com.crowdin.client.translationstatus.model.Validation; import java.util.Map; @@ -152,4 +156,46 @@ public ResponseList listQaCheckIssues(Long projectId, Integer limit, In QaCheckResponseList qaCheckResponseList = this.httpClient.get(builtUrl, new HttpRequestConfig(queryParams), QaCheckResponseList.class); return QaCheckResponseList.to(qaCheckResponseList); } + + /** + * @param projectId project identifier + * @param revalidationId qa checks revalidation identifier + * @return status of qa checks revalidation job + * @see + */ + public ResponseObject getQaChecksRevalidationStatus(Long projectId, String revalidationId) throws HttpException, HttpBadRequestException { + QaCheckRevalidationResponseObject qaCheckRevalidationResponseObject = this.httpClient.get(this.url + "/projects/" + projectId + "/qa-checks/revalidate/" + revalidationId, new HttpRequestConfig(), QaCheckRevalidationResponseObject.class); + + return ResponseObject.of(qaCheckRevalidationResponseObject.getData()); + } + + /** + * @param projectId project identifier + * @param request QaCheckRevalidationRequest + * @return QaCheckRevalidation + * @see + */ + public ResponseObject revalidateQaChecks(Long projectId, QaCheckRevalidationRequest request) throws HttpException, HttpBadRequestException { + QaCheckRevalidationResponseObject qaCheckRevalidationResponseObject = this.httpClient.post(this.url + "/projects/" + projectId + "/qa-checks/revalidate", request, new HttpRequestConfig(), QaCheckRevalidationResponseObject.class); + + return ResponseObject.of(qaCheckRevalidationResponseObject.getData()); + } + + /** + * @param projectId project identifier + * @param revalidationId qa checks revalidation identifier + * @see + */ + public void cancelQaChecksRevalidation(Long projectId, String revalidationId) throws HttpException, HttpBadRequestException { + this.httpClient.delete(this.url + "/projects/" + projectId + "/qa-checks/revalidate/" + revalidationId, new HttpRequestConfig(), Void.class); + } } diff --git a/src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidation.java b/src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidation.java new file mode 100644 index 000000000..3bf4bebb0 --- /dev/null +++ b/src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidation.java @@ -0,0 +1,25 @@ +package com.crowdin.client.translationstatus.model; + +import lombok.Data; + +import java.util.Date; +import java.util.List; + +@Data +public class QaCheckRevalidation { + private String identifier; + private String status; + private Long progress; + private Attributes attributes; + private Date createdAt; + private Date updatedAt; + private Date startedAt; + private Date finishedAt; + + @Data + public static class Attributes { + private List languageIds; + private List qaCheckCategories; + private Boolean failedOnly; + } +} diff --git a/src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidationRequest.java b/src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidationRequest.java new file mode 100644 index 000000000..06d347098 --- /dev/null +++ b/src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidationRequest.java @@ -0,0 +1,13 @@ +package com.crowdin.client.translationstatus.model; + +import lombok.Data; + +import java.util.List; + +@Data +public class QaCheckRevalidationRequest { + + private List qaCheckCategories; + private List languageIds; + private Boolean failedOnly; +} diff --git a/src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidationResponseList.java b/src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidationResponseList.java new file mode 100644 index 000000000..a1af71356 --- /dev/null +++ b/src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidationResponseList.java @@ -0,0 +1,26 @@ +package com.crowdin.client.translationstatus.model; + +import com.crowdin.client.core.model.Pagination; +import com.crowdin.client.core.model.ResponseList; +import com.crowdin.client.core.model.ResponseObject; +import lombok.Data; + +import java.util.List; +import java.util.stream.Collectors; + +@Data +public class QaCheckRevalidationResponseList { + + private List data; + private Pagination pagination; + + public static ResponseList to(QaCheckRevalidationResponseList qaCheckRevalidationResponseList) { + return ResponseList.of( + qaCheckRevalidationResponseList.getData().stream() + .map(QaCheckRevalidationResponseObject::getData) + .map(ResponseObject::of) + .collect(Collectors.toList()), + qaCheckRevalidationResponseList.getPagination() + ); + } +} diff --git a/src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidationResponseObject.java b/src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidationResponseObject.java new file mode 100644 index 000000000..01f6bc0d7 --- /dev/null +++ b/src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidationResponseObject.java @@ -0,0 +1,9 @@ +package com.crowdin.client.translationstatus.model; + +import lombok.Data; + +@Data +public class QaCheckRevalidationResponseObject { + + private QaCheckRevalidation data; +} diff --git a/src/test/java/com/crowdin/client/translationstatus/TranslationStatusApiTest.java b/src/test/java/com/crowdin/client/translationstatus/TranslationStatusApiTest.java index d62e8813c..e71de5c3a 100644 --- a/src/test/java/com/crowdin/client/translationstatus/TranslationStatusApiTest.java +++ b/src/test/java/com/crowdin/client/translationstatus/TranslationStatusApiTest.java @@ -1,15 +1,23 @@ package com.crowdin.client.translationstatus; import com.crowdin.client.core.model.ResponseList; +import com.crowdin.client.core.model.ResponseObject; import com.crowdin.client.framework.RequestMock; import com.crowdin.client.framework.TestClient; import com.crowdin.client.translationstatus.model.FileBranchProgress; import com.crowdin.client.translationstatus.model.LanguageProgress; import com.crowdin.client.translationstatus.model.QaCheck; +import com.crowdin.client.translationstatus.model.QaCheckRevalidation; +import com.crowdin.client.translationstatus.model.QaCheckRevalidationRequest; +import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; import org.junit.jupiter.api.Test; import java.util.Arrays; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -17,6 +25,7 @@ public class TranslationStatusApiTest extends TestClient { private final Long projectId = 2L; + private final String revalidationId = "b5215a34-1305-4b21-8054-fc2eb252842f"; private final Long branchId = 3L; private final Long directoryId = 4L; private final Long fileId = 5L; @@ -30,7 +39,10 @@ public List getMocks() { RequestMock.build(this.url + "/projects/" + projectId + "/files/" + fileId + "/languages/progress", HttpGet.METHOD_NAME, "api/translationstatus/fileProgress.json"), RequestMock.build(this.url + "/projects/" + projectId + "/languages/" + languageId + "/progress", HttpGet.METHOD_NAME, "api/translationstatus/languageProgress.json"), RequestMock.build(this.url + "/projects/" + projectId + "/languages/progress", HttpGet.METHOD_NAME, "api/translationstatus/projectProgress.json"), - RequestMock.build(this.url + "/projects/" + projectId + "/qa-checks", HttpGet.METHOD_NAME, "api/translationstatus/listQaChecks.json") + RequestMock.build(this.url + "/projects/" + projectId + "/qa-checks", HttpGet.METHOD_NAME, "api/translationstatus/listQaChecks.json"), + RequestMock.build(this.url + "/projects/" + projectId + "/qa-checks/revalidate/" + revalidationId, HttpGet.METHOD_NAME, "api/translationstatus/qaChecksRevalidation.json"), + RequestMock.build(this.url + "/projects/" + projectId + "/qa-checks/revalidate", HttpPost.METHOD_NAME, "api/translationstatus/qaChecksRevalidationRequest.json","api/translationstatus/qaChecksRevalidation.json"), + RequestMock.build(this.url + "/projects/" + projectId + "/qa-checks/revalidate/" + revalidationId, HttpDelete.METHOD_NAME) ); } @@ -80,4 +92,37 @@ public void listQaCheckIssuesTest() { assertEquals(qaCheckResponseList.getData().size(), 1); assertEquals(qaCheckResponseList.getData().get(0).getData().getLanguageId(), languageId); } + + @Test + public void getQaChecksRevalidationStatusTest() { + ResponseObject qaCheckRevalidationResponseObject = this.getTranslationStatusApi().getQaChecksRevalidationStatus(projectId, revalidationId); + assertEquals(qaCheckRevalidationResponseObject.getData().getStatus(), "created"); + assertEquals(qaCheckRevalidationResponseObject.getData().getProgress(), 0L); + assertEquals(qaCheckRevalidationResponseObject.getData().getAttributes().getLanguageIds(), Arrays.asList("uk", "fr")); + assertEquals(qaCheckRevalidationResponseObject.getData().getAttributes().getFailedOnly(), false); + Date createdDate = new Date(2025 - 1900, Calendar.SEPTEMBER, 23, 11, 51, 8); + assertEquals(qaCheckRevalidationResponseObject.getData().getCreatedAt(), createdDate); + } + + @Test + public void revalidateQaChecksTest() { + QaCheckRevalidationRequest request = new QaCheckRevalidationRequest(); + request.setLanguageIds(Arrays.asList("uk", "fr")); + request.setQaCheckCategories(Collections.singletonList("ai")); + request.setFailedOnly(true); + ResponseObject qaCheckRevalidationResponseObject = this.getTranslationStatusApi().revalidateQaChecks(projectId, request); + assertEquals(qaCheckRevalidationResponseObject.getData().getIdentifier(), revalidationId); + assertEquals(qaCheckRevalidationResponseObject.getData().getStatus(), "created"); + assertEquals(qaCheckRevalidationResponseObject.getData().getProgress(), 0L); + assertEquals(qaCheckRevalidationResponseObject.getData().getAttributes().getLanguageIds(), Arrays.asList("uk", "fr")); + assertEquals(qaCheckRevalidationResponseObject.getData().getAttributes().getQaCheckCategories(), Collections.singletonList("ai")); + assertEquals(qaCheckRevalidationResponseObject.getData().getAttributes().getFailedOnly(), false); + Date createdDate = new Date(2025 - 1900, Calendar.SEPTEMBER, 23, 11, 51, 8); + assertEquals(qaCheckRevalidationResponseObject.getData().getCreatedAt(), createdDate); + } + + @Test + public void cancelQaChecksRevalidationTest() { + this.getTranslationStatusApi().cancelQaChecksRevalidation(projectId, revalidationId); + } } diff --git a/src/test/resources/api/translationstatus/qaChecksRevalidation.json b/src/test/resources/api/translationstatus/qaChecksRevalidation.json new file mode 100644 index 000000000..8bed17718 --- /dev/null +++ b/src/test/resources/api/translationstatus/qaChecksRevalidation.json @@ -0,0 +1,21 @@ +{ + "data": { + "identifier": "b5215a34-1305-4b21-8054-fc2eb252842f", + "status": "created", + "progress": 0, + "attributes": { + "languageIds": [ + "uk", + "fr" + ], + "qaCheckCategories": [ + "ai" + ], + "failedOnly": false + }, + "createdAt": "2025-09-23T11:51:08+00:00", + "updatedAt": "2025-09-23T11:51:08+00:00", + "startedAt": "2025-09-23T11:51:08+00:00", + "finishedAt": null + } +} \ No newline at end of file diff --git a/src/test/resources/api/translationstatus/qaChecksRevalidationRequest.json b/src/test/resources/api/translationstatus/qaChecksRevalidationRequest.json new file mode 100644 index 000000000..38c899739 --- /dev/null +++ b/src/test/resources/api/translationstatus/qaChecksRevalidationRequest.json @@ -0,0 +1,10 @@ +{ + "qaCheckCategories": [ + "ai" + ], + "languageIds": [ + "uk", + "fr" + ], + "failedOnly": true +} \ No newline at end of file From ec81233bf1aacba57bdb352c6612e54fdda9d644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9DAndrei=E2=80=9D?= <”andrei.chirila07121999@gmail.com”> Date: Sun, 1 Mar 2026 21:43:13 +0200 Subject: [PATCH 2/3] chore: remove unused QaCheckRevalidationResponseList class --- .../QaCheckRevalidationResponseList.java | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidationResponseList.java diff --git a/src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidationResponseList.java b/src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidationResponseList.java deleted file mode 100644 index a1af71356..000000000 --- a/src/main/java/com/crowdin/client/translationstatus/model/QaCheckRevalidationResponseList.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.crowdin.client.translationstatus.model; - -import com.crowdin.client.core.model.Pagination; -import com.crowdin.client.core.model.ResponseList; -import com.crowdin.client.core.model.ResponseObject; -import lombok.Data; - -import java.util.List; -import java.util.stream.Collectors; - -@Data -public class QaCheckRevalidationResponseList { - - private List data; - private Pagination pagination; - - public static ResponseList to(QaCheckRevalidationResponseList qaCheckRevalidationResponseList) { - return ResponseList.of( - qaCheckRevalidationResponseList.getData().stream() - .map(QaCheckRevalidationResponseObject::getData) - .map(ResponseObject::of) - .collect(Collectors.toList()), - qaCheckRevalidationResponseList.getPagination() - ); - } -} From 8b9b5d8ba75018dfa601cd0351a60ffa047bc567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9DAndrei=E2=80=9D?= <”andrei.chirila07121999@gmail.com”> Date: Mon, 2 Mar 2026 14:31:33 +0200 Subject: [PATCH 3/3] docs: fix typos in anchor tags --- .../translationstatus/TranslationStatusApi.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/crowdin/client/translationstatus/TranslationStatusApi.java b/src/main/java/com/crowdin/client/translationstatus/TranslationStatusApi.java index 586493f60..513ddce3e 100644 --- a/src/main/java/com/crowdin/client/translationstatus/TranslationStatusApi.java +++ b/src/main/java/com/crowdin/client/translationstatus/TranslationStatusApi.java @@ -162,8 +162,8 @@ public ResponseList listQaCheckIssues(Long projectId, Integer limit, In * @param revalidationId qa checks revalidation identifier * @return status of qa checks revalidation job * @see */ public ResponseObject getQaChecksRevalidationStatus(Long projectId, String revalidationId) throws HttpException, HttpBadRequestException { @@ -177,8 +177,8 @@ public ResponseObject getQaChecksRevalidationStatus(Long pr * @param request QaCheckRevalidationRequest * @return QaCheckRevalidation * @see */ public ResponseObject revalidateQaChecks(Long projectId, QaCheckRevalidationRequest request) throws HttpException, HttpBadRequestException { @@ -191,8 +191,8 @@ public ResponseObject revalidateQaChecks(Long projectId, Qa * @param projectId project identifier * @param revalidationId qa checks revalidation identifier * @see */ public void cancelQaChecksRevalidation(Long projectId, String revalidationId) throws HttpException, HttpBadRequestException {