|  | 
|  | 1 | +package uk.gov.hmcts.darts.transcriptions.controller; | 
|  | 2 | + | 
|  | 3 | +import com.jayway.jsonpath.JsonPath; | 
|  | 4 | +import org.junit.jupiter.api.BeforeEach; | 
|  | 5 | +import org.junit.jupiter.api.Test; | 
|  | 6 | +import org.junit.jupiter.params.ParameterizedTest; | 
|  | 7 | +import org.junit.jupiter.params.provider.CsvSource; | 
|  | 8 | +import org.skyscreamer.jsonassert.JSONAssert; | 
|  | 9 | +import org.skyscreamer.jsonassert.JSONCompareMode; | 
|  | 10 | +import org.springframework.beans.factory.annotation.Autowired; | 
|  | 11 | +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | 
|  | 12 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | 
|  | 13 | +import org.springframework.test.web.servlet.MockMvc; | 
|  | 14 | +import org.springframework.test.web.servlet.MvcResult; | 
|  | 15 | +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; | 
|  | 16 | +import org.springframework.transaction.annotation.Transactional; | 
|  | 17 | +import uk.gov.hmcts.darts.audit.api.AuditApi; | 
|  | 18 | +import uk.gov.hmcts.darts.authorisation.component.UserIdentity; | 
|  | 19 | +import uk.gov.hmcts.darts.common.entity.TranscriptionEntity; | 
|  | 20 | +import uk.gov.hmcts.darts.common.entity.TranscriptionStatusEntity; | 
|  | 21 | +import uk.gov.hmcts.darts.common.entity.TranscriptionWorkflowEntity; | 
|  | 22 | +import uk.gov.hmcts.darts.common.entity.UserAccountEntity; | 
|  | 23 | +import uk.gov.hmcts.darts.common.repository.UserAccountRepository; | 
|  | 24 | +import uk.gov.hmcts.darts.notification.api.NotificationApi; | 
|  | 25 | +import uk.gov.hmcts.darts.testutils.IntegrationBase; | 
|  | 26 | +import uk.gov.hmcts.darts.testutils.stubs.AuthorisationStub; | 
|  | 27 | +import uk.gov.hmcts.darts.testutils.stubs.TranscriptionStub; | 
|  | 28 | +import uk.gov.hmcts.darts.transcriptions.model.UpdateTranscriptionRequest; | 
|  | 29 | + | 
|  | 30 | +import java.net.URI; | 
|  | 31 | +import java.util.List; | 
|  | 32 | + | 
|  | 33 | +import static org.junit.jupiter.api.Assertions.assertEquals; | 
|  | 34 | +import static org.junit.jupiter.api.Assertions.assertNotNull; | 
|  | 35 | +import static org.mockito.ArgumentMatchers.any; | 
|  | 36 | +import static org.mockito.Mockito.doNothing; | 
|  | 37 | +import static org.mockito.Mockito.verify; | 
|  | 38 | +import static org.mockito.Mockito.verifyNoInteractions; | 
|  | 39 | +import static org.mockito.Mockito.when; | 
|  | 40 | +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; | 
|  | 41 | +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | 
|  | 42 | +import static uk.gov.hmcts.darts.audit.api.AuditActivity.UNFULFILLED_TRANSCRIPTION; | 
|  | 43 | +import static uk.gov.hmcts.darts.transcriptions.enums.TranscriptionStatusEnum.CLOSED; | 
|  | 44 | +import static uk.gov.hmcts.darts.transcriptions.enums.TranscriptionStatusEnum.UNFULFILLED; | 
|  | 45 | +import static uk.gov.hmcts.darts.transcriptions.enums.TranscriptionStatusEnum.WITH_TRANSCRIBER; | 
|  | 46 | + | 
|  | 47 | +@AutoConfigureMockMvc | 
|  | 48 | +@Transactional | 
|  | 49 | +class TranscriptionControllerUpdateTranscriptionUnfulfilledIntTest extends IntegrationBase { | 
|  | 50 | + | 
|  | 51 | +    @Autowired | 
|  | 52 | +    private AuthorisationStub authorisationStub; | 
|  | 53 | + | 
|  | 54 | +    @Autowired | 
|  | 55 | +    private MockMvc mockMvc; | 
|  | 56 | + | 
|  | 57 | +    @MockitoBean | 
|  | 58 | +    private UserIdentity mockUserIdentity; | 
|  | 59 | +    @MockitoBean | 
|  | 60 | +    private AuditApi mockAuditApi; | 
|  | 61 | +    @MockitoBean | 
|  | 62 | +    private NotificationApi notificationApi; | 
|  | 63 | + | 
|  | 64 | +    private Long transcriptionId; | 
|  | 65 | +    private Integer testUserId; | 
|  | 66 | +    private UserAccountEntity testUser; | 
|  | 67 | + | 
|  | 68 | +    @BeforeEach | 
|  | 69 | +    void beforeEach() { | 
|  | 70 | +        authorisationStub.givenTestSchema(); | 
|  | 71 | + | 
|  | 72 | +        TranscriptionEntity transcriptionEntity = authorisationStub.getTranscriptionEntity(); | 
|  | 73 | + | 
|  | 74 | +        TranscriptionStub transcriptionStub = dartsDatabase.getTranscriptionStub(); | 
|  | 75 | +        TranscriptionStatusEntity withTranscriberTranscriptionStatus = transcriptionStub.getTranscriptionStatusByEnum(WITH_TRANSCRIBER); | 
|  | 76 | + | 
|  | 77 | +        TranscriptionWorkflowEntity withTranscriberTranscriptionWorkflowEntity = transcriptionStub.createTranscriptionWorkflowEntity( | 
|  | 78 | +            transcriptionEntity, | 
|  | 79 | +            transcriptionEntity.getLastModifiedById(), | 
|  | 80 | +            transcriptionEntity.getCreatedDateTime().plusHours(1), | 
|  | 81 | +            withTranscriberTranscriptionStatus | 
|  | 82 | +        ); | 
|  | 83 | + | 
|  | 84 | +        assertEquals(0, dartsDatabase.getTranscriptionCommentRepository().findAll().size()); | 
|  | 85 | +        transcriptionEntity.getTranscriptionWorkflowEntities().add(withTranscriberTranscriptionWorkflowEntity); | 
|  | 86 | +        transcriptionEntity.setTranscriptionStatus(withTranscriberTranscriptionStatus); | 
|  | 87 | +        dartsDatabase.getTranscriptionRepository().save(transcriptionEntity); | 
|  | 88 | + | 
|  | 89 | +        assertEquals(WITH_TRANSCRIBER.getId(), transcriptionEntity.getTranscriptionStatus().getId()); | 
|  | 90 | +        assertEquals(3, transcriptionEntity.getTranscriptionWorkflowEntities().size()); | 
|  | 91 | + | 
|  | 92 | +        transcriptionId = transcriptionEntity.getId(); | 
|  | 93 | + | 
|  | 94 | +        testUser = authorisationStub.getTestUser(); | 
|  | 95 | +        when(mockUserIdentity.getUserAccount()).thenReturn(testUser); | 
|  | 96 | +        testUserId = testUser.getId(); | 
|  | 97 | + | 
|  | 98 | +        doNothing().when(mockAuditApi) | 
|  | 99 | +            .record(UNFULFILLED_TRANSCRIPTION, testUser, transcriptionEntity.getCourtCase()); | 
|  | 100 | +    } | 
|  | 101 | + | 
|  | 102 | +    @ParameterizedTest | 
|  | 103 | +    @CsvSource({ | 
|  | 104 | +        "UNFULFILLED REASON: INAUDIBLE", | 
|  | 105 | +        "UNFULFILLED REASON: NO AUDIO / WHITE NOISE", | 
|  | 106 | +        "UNFULFILLED REASON: 1 SECOND AUDIO", | 
|  | 107 | +        "UNFULFILLED REASON: OTHER - USER ENTERED COMMENTS" | 
|  | 108 | +    }) | 
|  | 109 | +    void updateTranscription_ShouldReturnOk_WithTranscriptionComment(String transcriptionComment) throws Exception { | 
|  | 110 | + | 
|  | 111 | +        UpdateTranscriptionRequest updateTranscription = new UpdateTranscriptionRequest(); | 
|  | 112 | +        updateTranscription.setTranscriptionStatusId(UNFULFILLED.getId()); | 
|  | 113 | +        updateTranscription.setWorkflowComment(transcriptionComment); | 
|  | 114 | + | 
|  | 115 | +        MockHttpServletRequestBuilder requestBuilder = patch(URI.create( | 
|  | 116 | +            String.format("/transcriptions/%d", transcriptionId))) | 
|  | 117 | +            .header("Content-Type", "application/json") | 
|  | 118 | +            .content(objectMapper.writeValueAsString(updateTranscription)); | 
|  | 119 | +        MvcResult mvcResult = mockMvc.perform(requestBuilder) | 
|  | 120 | +            .andExpect(status().isOk()) | 
|  | 121 | +            .andReturn(); | 
|  | 122 | + | 
|  | 123 | +        Integer transcriptionWorkflowId = JsonPath.parse(mvcResult.getResponse().getContentAsString()) | 
|  | 124 | +            .read("$.transcription_workflow_id"); | 
|  | 125 | +        assertNotNull(transcriptionWorkflowId); | 
|  | 126 | + | 
|  | 127 | +        final TranscriptionEntity unfulfilledTranscriptionEntity = dartsDatabase.getTranscriptionRepository() | 
|  | 128 | +            .findById(transcriptionId).orElseThrow(); | 
|  | 129 | +        assertEquals(UNFULFILLED.getId(), unfulfilledTranscriptionEntity.getTranscriptionStatus().getId()); | 
|  | 130 | +        assertEquals(testUserId, unfulfilledTranscriptionEntity.getCreatedById()); | 
|  | 131 | +        assertEquals(testUserId, unfulfilledTranscriptionEntity.getLastModifiedById()); | 
|  | 132 | +        final List<TranscriptionWorkflowEntity> transcriptionWorkflowEntities = unfulfilledTranscriptionEntity.getTranscriptionWorkflowEntities(); | 
|  | 133 | +        final TranscriptionWorkflowEntity transcriptionWorkflowEntity = transcriptionWorkflowEntities | 
|  | 134 | +            .get(transcriptionWorkflowEntities.size() - 1); | 
|  | 135 | +        assertEquals(transcriptionWorkflowId, transcriptionWorkflowEntity.getId()); | 
|  | 136 | +        assertEquals( | 
|  | 137 | +            updateTranscription.getTranscriptionStatusId(), | 
|  | 138 | +            transcriptionWorkflowEntity.getTranscriptionStatus().getId() | 
|  | 139 | +        ); | 
|  | 140 | +        assertEquals(1, dartsDatabase.getTranscriptionCommentRepository().findAll().size()); | 
|  | 141 | +        assertEquals(testUserId, transcriptionWorkflowEntity.getWorkflowActor().getId()); | 
|  | 142 | + | 
|  | 143 | +        verify(notificationApi).scheduleNotification(any()); | 
|  | 144 | +        verify(mockAuditApi).record(UNFULFILLED_TRANSCRIPTION, testUser, unfulfilledTranscriptionEntity.getCourtCase()); | 
|  | 145 | +    } | 
|  | 146 | + | 
|  | 147 | +    @Test | 
|  | 148 | +    void updateTranscription_ShouldReturnTranscriptionUnprocessableEntityError_WhereTranscriptionCommentIsNull() throws Exception { | 
|  | 149 | + | 
|  | 150 | +        UpdateTranscriptionRequest updateTranscription = new UpdateTranscriptionRequest(); | 
|  | 151 | +        updateTranscription.setTranscriptionStatusId(UNFULFILLED.getId()); | 
|  | 152 | + | 
|  | 153 | +        MockHttpServletRequestBuilder requestBuilder = patch(URI.create( | 
|  | 154 | +            String.format("/transcriptions/%d", transcriptionId))) | 
|  | 155 | +            .header("Content-Type", "application/json") | 
|  | 156 | +            .content(objectMapper.writeValueAsString(updateTranscription)); | 
|  | 157 | +        MvcResult mvcResult = mockMvc.perform(requestBuilder) | 
|  | 158 | +            .andExpect(status().isUnprocessableEntity()) | 
|  | 159 | +            .andReturn(); | 
|  | 160 | + | 
|  | 161 | +        String actualJson = mvcResult.getResponse().getContentAsString(); | 
|  | 162 | +        String expectedJson = """ | 
|  | 163 | +            {"type":"TRANSCRIPTION_103","title":"The workflow comment is required for this transcription update","status":422} | 
|  | 164 | +            """; | 
|  | 165 | +        JSONAssert.assertEquals(expectedJson, actualJson, JSONCompareMode.NON_EXTENSIBLE); | 
|  | 166 | +        verifyNoInteractions(notificationApi); | 
|  | 167 | +        verifyNoInteractions(mockAuditApi); | 
|  | 168 | +    } | 
|  | 169 | + | 
|  | 170 | +    @Test | 
|  | 171 | +    void updateTranscription_ShouldReturnTranscriptionNotFoundError() throws Exception { | 
|  | 172 | +        UpdateTranscriptionRequest updateTranscription = new UpdateTranscriptionRequest(); | 
|  | 173 | +        updateTranscription.setTranscriptionStatusId(UNFULFILLED.getId()); | 
|  | 174 | + | 
|  | 175 | +        MockHttpServletRequestBuilder requestBuilder = patch(URI.create( | 
|  | 176 | +            String.format("/transcriptions/%d", -1))) | 
|  | 177 | +            .header("Content-Type", "application/json") | 
|  | 178 | +            .content(objectMapper.writeValueAsString(updateTranscription)); | 
|  | 179 | +        MvcResult mvcResult = mockMvc.perform(requestBuilder) | 
|  | 180 | +            .andExpect(status().isNotFound()) | 
|  | 181 | +            .andReturn(); | 
|  | 182 | + | 
|  | 183 | +        String actualJson = mvcResult.getResponse().getContentAsString(); | 
|  | 184 | +        String expectedJson = """ | 
|  | 185 | +            {"type":"TRANSCRIPTION_101","title":"The requested transcription cannot be found","status":404} | 
|  | 186 | +            """; | 
|  | 187 | +        JSONAssert.assertEquals(expectedJson, actualJson, JSONCompareMode.NON_EXTENSIBLE); | 
|  | 188 | +        verifyNoInteractions(notificationApi); | 
|  | 189 | +        verifyNoInteractions(mockAuditApi); | 
|  | 190 | +    } | 
|  | 191 | + | 
|  | 192 | +    @Test | 
|  | 193 | +    void updateTranscription_ShouldReturnTranscriptionWorkflowActionInvalidError() throws Exception { | 
|  | 194 | +        UpdateTranscriptionRequest updateTranscription = new UpdateTranscriptionRequest(); | 
|  | 195 | +        updateTranscription.setTranscriptionStatusId(UNFULFILLED.getId()); | 
|  | 196 | +        updateTranscription.setWorkflowComment("test comment"); | 
|  | 197 | + | 
|  | 198 | +        MockHttpServletRequestBuilder requestBuilder = patch(URI.create( | 
|  | 199 | +            String.format("/transcriptions/%d", transcriptionId))) | 
|  | 200 | +            .header("Content-Type", "application/json") | 
|  | 201 | +            .content(objectMapper.writeValueAsString(updateTranscription)); | 
|  | 202 | +        mockMvc.perform(requestBuilder) | 
|  | 203 | +            .andExpect(status().isOk()) | 
|  | 204 | +            .andReturn(); | 
|  | 205 | + | 
|  | 206 | +        UpdateTranscriptionRequest updateTranscription2 = new UpdateTranscriptionRequest(); | 
|  | 207 | +        updateTranscription2.setTranscriptionStatusId(CLOSED.getId()); | 
|  | 208 | +        updateTranscription2.setWorkflowComment("test comment"); | 
|  | 209 | + | 
|  | 210 | +        MockHttpServletRequestBuilder requestBuilder2 = patch(URI.create( | 
|  | 211 | +            String.format("/transcriptions/%d", transcriptionId))) | 
|  | 212 | +            .header("Content-Type", "application/json") | 
|  | 213 | +            .content(objectMapper.writeValueAsString(updateTranscription)); | 
|  | 214 | +        MvcResult mvcResult = mockMvc.perform(requestBuilder2) | 
|  | 215 | +            .andExpect(status().isConflict()) | 
|  | 216 | +            .andReturn(); | 
|  | 217 | + | 
|  | 218 | +        String actualJson = mvcResult.getResponse().getContentAsString(); | 
|  | 219 | +        String expectedJson = """ | 
|  | 220 | +            {"type":"TRANSCRIPTION_105","title":"Transcription workflow action is not permitted","status":409} | 
|  | 221 | +            """; | 
|  | 222 | +        JSONAssert.assertEquals(expectedJson, actualJson, JSONCompareMode.NON_EXTENSIBLE); | 
|  | 223 | +    } | 
|  | 224 | + | 
|  | 225 | +    @Test | 
|  | 226 | +    void updateTranscription_ShouldReturnForbiddenError() throws Exception { | 
|  | 227 | + | 
|  | 228 | +        UserAccountRepository userAccountRepository = dartsDatabase.getUserAccountRepository(); | 
|  | 229 | +        UserAccountEntity testUser = dartsDatabase.getUserAccountRepository().findById(testUserId).orElseThrow(); | 
|  | 230 | +        testUser.getSecurityGroupEntities().clear(); | 
|  | 231 | +        userAccountRepository.save(testUser); | 
|  | 232 | + | 
|  | 233 | +        UpdateTranscriptionRequest updateTranscription = new UpdateTranscriptionRequest(); | 
|  | 234 | +        updateTranscription.setTranscriptionStatusId(UNFULFILLED.getId()); | 
|  | 235 | + | 
|  | 236 | +        MockHttpServletRequestBuilder requestBuilder = patch(URI.create( | 
|  | 237 | +            String.format("/transcriptions/%d", transcriptionId))) | 
|  | 238 | +            .header("Content-Type", "application/json") | 
|  | 239 | +            .content(objectMapper.writeValueAsString(updateTranscription)); | 
|  | 240 | +        MvcResult mvcResult = mockMvc.perform(requestBuilder) | 
|  | 241 | +            .andExpect(status().isForbidden()) | 
|  | 242 | +            .andReturn(); | 
|  | 243 | + | 
|  | 244 | +        String actualJson = mvcResult.getResponse().getContentAsString(); | 
|  | 245 | +        String expectedJson = """ | 
|  | 246 | +            {"type":"AUTHORISATION_100","title":"User is not authorised for the associated courthouse","status":403} | 
|  | 247 | +            """; | 
|  | 248 | +        JSONAssert.assertEquals(expectedJson, actualJson, JSONCompareMode.NON_EXTENSIBLE); | 
|  | 249 | + | 
|  | 250 | +        verifyNoInteractions(notificationApi); | 
|  | 251 | +        verifyNoInteractions(mockAuditApi); | 
|  | 252 | +    } | 
|  | 253 | + | 
|  | 254 | +    @Test | 
|  | 255 | +    void updateTranscription_ShouldReturnOk_WhenTranscriberOnlyUser() throws Exception { | 
|  | 256 | + | 
|  | 257 | +        UserAccountRepository userAccountRepository = dartsDatabase.getUserAccountRepository(); | 
|  | 258 | +        UserAccountEntity testUser = dartsDatabase.getUserAccountRepository().findById(testUserId).orElseThrow(); | 
|  | 259 | +        testUser.getSecurityGroupEntities().clear(); | 
|  | 260 | +        userAccountRepository.save(testUser); | 
|  | 261 | + | 
|  | 262 | +        testUser = dartsDatabase.getUserAccountStub() | 
|  | 263 | +            .createTranscriptionCompanyUser(authorisationStub.getCourthouseEntity()); | 
|  | 264 | +        assertEquals(1, testUser.getSecurityGroupEntities().size()); | 
|  | 265 | + | 
|  | 266 | +        UpdateTranscriptionRequest updateTranscription = new UpdateTranscriptionRequest(); | 
|  | 267 | +        updateTranscription.setTranscriptionStatusId(UNFULFILLED.getId()); | 
|  | 268 | +        updateTranscription.setWorkflowComment("test comment"); | 
|  | 269 | + | 
|  | 270 | +        MockHttpServletRequestBuilder requestBuilder = patch(URI.create( | 
|  | 271 | +            String.format("/transcriptions/%d", transcriptionId))) | 
|  | 272 | +            .header("Content-Type", "application/json") | 
|  | 273 | +            .content(objectMapper.writeValueAsString(updateTranscription)); | 
|  | 274 | +        MvcResult mvcResult = mockMvc.perform(requestBuilder) | 
|  | 275 | +            .andExpect(status().isOk()) | 
|  | 276 | +            .andReturn(); | 
|  | 277 | + | 
|  | 278 | +        Integer transcriptionWorkflowId = JsonPath.parse(mvcResult.getResponse().getContentAsString()) | 
|  | 279 | +            .read("$.transcription_workflow_id"); | 
|  | 280 | +        assertNotNull(transcriptionWorkflowId); | 
|  | 281 | + | 
|  | 282 | +        final TranscriptionEntity withTranscriberTranscriptionEntity = dartsDatabase.getTranscriptionRepository() | 
|  | 283 | +            .findById(transcriptionId).orElseThrow(); | 
|  | 284 | +        assertEquals(UNFULFILLED.getId(), withTranscriberTranscriptionEntity.getTranscriptionStatus().getId()); | 
|  | 285 | +        assertEquals(testUserId, withTranscriberTranscriptionEntity.getCreatedById()); | 
|  | 286 | +        assertEquals(testUserId, withTranscriberTranscriptionEntity.getLastModifiedById()); | 
|  | 287 | +        final List<TranscriptionWorkflowEntity> transcriptionWorkflowEntities = withTranscriberTranscriptionEntity.getTranscriptionWorkflowEntities(); | 
|  | 288 | +        final TranscriptionWorkflowEntity transcriptionWorkflowEntity = transcriptionWorkflowEntities | 
|  | 289 | +            .get(transcriptionWorkflowEntities.size() - 1); | 
|  | 290 | +        assertEquals(transcriptionWorkflowId, transcriptionWorkflowEntity.getId()); | 
|  | 291 | +        assertEquals( | 
|  | 292 | +            updateTranscription.getTranscriptionStatusId(), | 
|  | 293 | +            transcriptionWorkflowEntity.getTranscriptionStatus().getId() | 
|  | 294 | +        ); | 
|  | 295 | +        assertEquals(1, dartsDatabase.getTranscriptionCommentRepository().findAll().size()); | 
|  | 296 | +        assertEquals(testUserId, transcriptionWorkflowEntity.getWorkflowActor().getId()); | 
|  | 297 | + | 
|  | 298 | +        verify(notificationApi).scheduleNotification(any()); | 
|  | 299 | + | 
|  | 300 | +        verify(mockAuditApi).record(UNFULFILLED_TRANSCRIPTION, testUser, withTranscriberTranscriptionEntity.getCourtCase()); | 
|  | 301 | + | 
|  | 302 | +    } | 
|  | 303 | + | 
|  | 304 | +} | 
0 commit comments