diff --git a/server/services/src/main/java/org/zanata/rest/editor/dto/ReviewData.java b/server/services/src/main/java/org/zanata/rest/editor/dto/ReviewData.java index 272f5b8c074..6bc765a03dd 100644 --- a/server/services/src/main/java/org/zanata/rest/editor/dto/ReviewData.java +++ b/server/services/src/main/java/org/zanata/rest/editor/dto/ReviewData.java @@ -73,4 +73,34 @@ public void setStatus(ContentState status) { this.status = status; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ReviewData that = (ReviewData) o; + + if (transUnitId != null ? !transUnitId.equals(that.transUnitId) : + that.transUnitId != null) return false; + if (revision != null ? !revision.equals(that.revision) : + that.revision != null) return false; + if (comment != null ? !comment.equals(that.comment) : + that.comment != null) + return false; + if (reviewCriteriaId != null ? + !reviewCriteriaId.equals(that.reviewCriteriaId) : + that.reviewCriteriaId != null) return false; + return status == that.status; + } + + @Override + public int hashCode() { + int result = transUnitId != null ? transUnitId.hashCode() : 0; + result = 31 * result + (revision != null ? revision.hashCode() : 0); + result = 31 * result + (comment != null ? comment.hashCode() : 0); + result = 31 * result + + (reviewCriteriaId != null ? reviewCriteriaId.hashCode() : 0); + result = 31 * result + (status != null ? status.hashCode() : 0); + return result; + } } diff --git a/server/services/src/main/java/org/zanata/rest/editor/service/TranslationReviewService.java b/server/services/src/main/java/org/zanata/rest/editor/service/TranslationReviewService.java index cd03907115c..1875c54752b 100644 --- a/server/services/src/main/java/org/zanata/rest/editor/service/TranslationReviewService.java +++ b/server/services/src/main/java/org/zanata/rest/editor/service/TranslationReviewService.java @@ -1,8 +1,6 @@ package org.zanata.rest.editor.service; import com.google.common.collect.Lists; -import net.customware.gwt.dispatch.shared.ActionException; -import org.omg.PortableInterceptor.ACTIVE; import org.zanata.common.EntityStatus; import org.zanata.common.LocaleId; import org.zanata.dao.ReviewCriteriaDAO; @@ -24,10 +22,9 @@ import javax.enterprise.context.RequestScoped; import javax.inject.Inject; +import javax.validation.constraints.NotNull; import javax.ws.rs.Path; import javax.ws.rs.core.Response; -import java.util.List; - @Path(TranslationReviewResource.SERVICE_PATH) @RequestScoped @@ -35,22 +32,38 @@ public class TranslationReviewService implements TranslationReviewResource { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TranslationReviewService.class); - @Inject private TextFlowTargetDAO textFlowTargetDAO; - @Inject private LocaleService localeServiceImpl; - @Inject private ZanataIdentity identity; - @Inject private ReviewCriteriaDAO reviewCriteriaDAO; - @Inject - @Authenticated private HAccount authenticatedAccount; - @Inject private TextFlowTargetReviewCommentsDAO textFlowTargetReviewCommentsDAO; + @Inject + public TranslationReviewService( + TextFlowTargetDAO textFlowTargetDAO, + LocaleService localeServiceImpl, + ZanataIdentity identity, + ReviewCriteriaDAO reviewCriteriaDAO, + TextFlowTargetReviewCommentsDAO textFlowTargetReviewCommentsDAO, + @Authenticated HAccount authenticatedAccount) { + + this.textFlowTargetDAO = textFlowTargetDAO; + this.localeServiceImpl = localeServiceImpl; + this.identity =identity; + this.reviewCriteriaDAO = reviewCriteriaDAO; + this.textFlowTargetReviewCommentsDAO = textFlowTargetReviewCommentsDAO; + this.authenticatedAccount = authenticatedAccount; + } + @Override - public Response put(String localeId, ReviewData data) { + public Response put(String localeId, @NotNull ReviewData data) { + if (data == null) { + return Response.status( + Response.Status.BAD_REQUEST) + .entity(Lists.newArrayList("data is invalid")) + .build(); + } HLocale locale = localeServiceImpl.getByLocaleId(localeId); if (locale == null) { diff --git a/server/services/src/main/java/org/zanata/rest/editor/service/resource/TranslationReviewResource.java b/server/services/src/main/java/org/zanata/rest/editor/service/resource/TranslationReviewResource.java index db003dd2113..f19aeba6db3 100644 --- a/server/services/src/main/java/org/zanata/rest/editor/service/resource/TranslationReviewResource.java +++ b/server/services/src/main/java/org/zanata/rest/editor/service/resource/TranslationReviewResource.java @@ -2,6 +2,7 @@ import org.zanata.rest.editor.dto.ReviewData; +import javax.validation.constraints.NotNull; import javax.ws.rs.Consumes; import javax.ws.rs.PUT; import javax.ws.rs.PathParam; @@ -39,5 +40,5 @@ public interface TranslationReviewResource { @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON }) Response put(@PathParam("localeId") String localeId, - ReviewData data); + @NotNull ReviewData data); } diff --git a/server/services/src/test/java/org/zanata/rest/editor/dto/ReviewDataTest.java b/server/services/src/test/java/org/zanata/rest/editor/dto/ReviewDataTest.java new file mode 100644 index 00000000000..7a0d6e349b8 --- /dev/null +++ b/server/services/src/test/java/org/zanata/rest/editor/dto/ReviewDataTest.java @@ -0,0 +1,67 @@ +package org.zanata.rest.editor.dto; + +import org.junit.Test; +import org.zanata.common.ContentState; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; + +/** + * @author Alex Eng aeng@redhat.com + **/ +public class ReviewDataTest { + + @Test + public void transUnitIdTest() { + Long id = 10L; + ReviewData data = new ReviewData(); + data.setTransUnitId(id); + assertThat(data.getTransUnitId()).isEqualTo(id); + } + + @Test + public void revisionTest() { + int revision = 10; + ReviewData data = new ReviewData(); + data.setRevision(revision); + assertThat(data.getRevision()).isEqualTo(revision); + } + + @Test + public void commentTest() { + String comment = "comment"; + ReviewData data = new ReviewData(); + data.setComment(comment); + assertThat(data.getComment()).isEqualTo(comment); + } + + @Test + public void criteriaIdTest() { + Long id = 10L; + ReviewData data = new ReviewData(); + data.setReviewCriteriaId(id); + assertThat(data.getReviewCriteriaId()).isEqualTo(id); + } + + @Test + public void statusTest() { + ContentState status = ContentState.Approved; + ReviewData data = new ReviewData(); + data.setStatus(status); + assertThat(data.getStatus()).isEqualTo(status); + } + + @Test + public void equalTest() { + ContentState status = ContentState.Approved; + ReviewData data = new ReviewData(); + data.setStatus(status); + data.setReviewCriteriaId(1L); + + ReviewData data2 = new ReviewData(); + data2.setStatus(status); + data2.setReviewCriteriaId(1L); + + assertThat(data).isEqualTo(data2); + assertThat(data.hashCode()).isEqualTo(data2.hashCode()); + } +} diff --git a/server/services/src/test/java/org/zanata/rest/editor/service/TranslationReviewServiceTest.java b/server/services/src/test/java/org/zanata/rest/editor/service/TranslationReviewServiceTest.java new file mode 100644 index 00000000000..df1c403871a --- /dev/null +++ b/server/services/src/test/java/org/zanata/rest/editor/service/TranslationReviewServiceTest.java @@ -0,0 +1,241 @@ +/* + * Copyright 2018, Red Hat, Inc. and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ + +package org.zanata.rest.editor.service; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.zanata.common.ContentState; +import org.zanata.common.ContentType; +import org.zanata.common.EntityStatus; +import org.zanata.common.IssuePriority; +import org.zanata.common.LocaleId; +import org.zanata.dao.ReviewCriteriaDAO; +import org.zanata.dao.TextFlowTargetDAO; +import org.zanata.dao.TextFlowTargetReviewCommentsDAO; +import org.zanata.model.HAccount; +import org.zanata.model.HDocument; +import org.zanata.model.HLocale; +import org.zanata.model.HPerson; +import org.zanata.model.HProject; +import org.zanata.model.HProjectIteration; +import org.zanata.model.HTextFlow; +import org.zanata.model.HTextFlowTarget; +import org.zanata.model.ReviewCriteria; +import org.zanata.rest.editor.dto.ReviewData; +import org.zanata.security.ZanataIdentity; +import org.zanata.service.LocaleService; + +import javax.ws.rs.core.Response; + +import static org.assertj.core.api.Java6Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * @author Alex Eng aeng@redhat.com + **/ +public class TranslationReviewServiceTest { + private TranslationReviewService service; + + @Mock + private TextFlowTargetDAO textFlowTargetDAO; + + @Mock + private LocaleService localeServiceImpl; + + @Mock + private ZanataIdentity identity; + + @Mock + private ReviewCriteriaDAO reviewCriteriaDAO; + + @Mock + private TextFlowTargetReviewCommentsDAO textFlowTargetReviewCommentsDAO; + + @Mock + private HAccount authenticatedAccount; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + service = new TranslationReviewService( + textFlowTargetDAO, + localeServiceImpl, + identity, + reviewCriteriaDAO, + textFlowTargetReviewCommentsDAO, + authenticatedAccount); + } + + @Test + public void testNullData() { + Response response = service.put(null, null); + assertThat(response.getStatus()) + .isEqualTo(Response.Status.BAD_REQUEST.getStatusCode()); + } + + @Test + public void testNullLocale() { + String locale = "de"; + ReviewData data = new ReviewData(); + when(localeServiceImpl.getByLocaleId(locale)).thenReturn(null); + + Response response = service.put(locale, data); + assertThat(response.getStatus()) + .isEqualTo(Response.Status.BAD_REQUEST.getStatusCode()); + } + + @Test + public void testNullTft() { + String locale = "de"; + LocaleId localeId = new LocaleId(locale); + HLocale hLocale = new HLocale(localeId); + ReviewData data = new ReviewData(); + data.setTransUnitId(1L); + + when(localeServiceImpl.getByLocaleId(locale)).thenReturn(hLocale); + when(textFlowTargetDAO + .getTextFlowTarget(data.getTransUnitId(), localeId)) + .thenReturn(null); + + Response response = service.put(locale, data); + assertThat(response.getStatus()) + .isEqualTo(Response.Status.BAD_REQUEST.getStatusCode()); + } + + @Test + public void testNullTftUntranslated() { + String locale = "de"; + ReviewData data = new ReviewData(); + data.setTransUnitId(1L); + + HTextFlowTarget tft = + buildTft(locale, EntityStatus.ACTIVE, ContentState.New); + HLocale hLocale = tft.getLocale(); + + when(localeServiceImpl.getByLocaleId(locale)).thenReturn(hLocale); + when(textFlowTargetDAO.getTextFlowTarget(data.getTransUnitId(), + hLocale.getLocaleId())).thenReturn(tft); + + Response response = service.put(locale, data); + assertThat(response.getStatus()) + .isEqualTo(Response.Status.BAD_REQUEST.getStatusCode()); + } + + @Test + public void testNonActiveProjectVersion() { + String locale = "de"; + ReviewData data = new ReviewData(); + data.setTransUnitId(1L); + + HTextFlowTarget tft = buildTft(locale, EntityStatus.READONLY, + ContentState.Translated); + HLocale hLocale = tft.getLocale(); + + when(localeServiceImpl.getByLocaleId(locale)).thenReturn(hLocale); + when(textFlowTargetDAO.getTextFlowTarget(data.getTransUnitId(), + hLocale.getLocaleId())).thenReturn(tft); + + Response response = service.put(locale, data); + assertThat(response.getStatus()) + .isEqualTo(Response.Status.FORBIDDEN.getStatusCode()); + } + + @Test + public void testReviewCriteriaNull() { + String locale = "de"; + ReviewData data = new ReviewData(); + data.setTransUnitId(1L); + data.setReviewCriteriaId(1L); + + HTextFlowTarget tft = buildTft(locale, EntityStatus.ACTIVE, + ContentState.Translated); + HLocale hLocale = tft.getLocale(); + + when(localeServiceImpl.getByLocaleId(locale)).thenReturn(hLocale); + when(textFlowTargetDAO.getTextFlowTarget(data.getTransUnitId(), + hLocale.getLocaleId())).thenReturn(tft); + when(reviewCriteriaDAO.findById(data.getReviewCriteriaId())).thenReturn(null); + + Response response = service.put(locale, data); + assertThat(response.getStatus()) + .isEqualTo(Response.Status.BAD_REQUEST.getStatusCode()); + } + + @Test + public void testPut() { + String locale = "de"; + ReviewData data = new ReviewData(); + data.setTransUnitId(1L); + data.setReviewCriteriaId(1L); + + HTextFlowTarget tft = buildTft(locale, EntityStatus.ACTIVE, + ContentState.Translated); + HLocale hLocale = tft.getLocale(); + + ReviewCriteria reviewCriteria = new ReviewCriteria(IssuePriority.Major, + true, "description"); + + HPerson person = new HPerson(); + person.setName("name"); + + when(authenticatedAccount.getPerson()).thenReturn(person); + when(localeServiceImpl.getByLocaleId(locale)).thenReturn(hLocale); + when(textFlowTargetDAO.getTextFlowTarget(data.getTransUnitId(), + hLocale.getLocaleId())).thenReturn(tft); + when(reviewCriteriaDAO.findById(data.getReviewCriteriaId())) + .thenReturn(reviewCriteria); + + Response response = service.put(locale, data); + + verify(textFlowTargetReviewCommentsDAO).makePersistent(any()); + verify(textFlowTargetReviewCommentsDAO).flush(); + + assertThat(response.getStatus()) + .isEqualTo(Response.Status.OK.getStatusCode()); + assertThat(response.getEntity()).isNotNull(); + assertThat((ReviewData)response.getEntity()).isEqualTo(data); + } + + private HTextFlowTarget buildTft(String localeId, EntityStatus status, + ContentState contentState) { + HProject project = new HProject(); + project.setStatus(status); + + HProjectIteration version = new HProjectIteration(); + version.setStatus(status); + version.setProject(project); + + HDocument doc = + new HDocument("", ContentType.PO, new HLocale(LocaleId.EN_US)); + doc.setProjectIteration(version); + HLocale hLocale = new HLocale(new LocaleId(localeId)); + HTextFlow tf = new HTextFlow(doc, "resId", "content"); + + HTextFlowTarget tft = new HTextFlowTarget(tf, hLocale); + tft.setState(contentState); + return tft; + } +}