Skip to content

Commit

Permalink
Added remaining tests + Rejigged some current version logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Ben-Edwards-cgi committed Feb 27, 2025
1 parent 6ec4c45 commit ea7d204
Show file tree
Hide file tree
Showing 8 changed files with 452 additions and 25 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
package uk.gov.hmcts.darts.audio.controller;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.skyscreamer.jsonassert.JSONAssert;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import uk.gov.hmcts.darts.common.entity.MediaEntity;
import uk.gov.hmcts.darts.common.enums.SecurityRoleEnum;
import uk.gov.hmcts.darts.testutils.GivenBuilder;
import uk.gov.hmcts.darts.testutils.IntegrationBase;
import uk.gov.hmcts.darts.testutils.stubs.DartsDatabaseStub;

import java.time.Duration;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

import static org.junit.jupiter.params.provider.EnumSource.Mode.EXCLUDE;
import static org.junit.jupiter.params.provider.EnumSource.Mode.INCLUDE;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static uk.gov.hmcts.darts.test.common.TestUtils.getContentsFromFile;

@AutoConfigureMockMvc
class AudioControllerGetAdminMediaVersionsByIdIntTest extends IntegrationBase {
@Autowired
private GivenBuilder given;

@Autowired
private MockMvc mockMvc;

@Autowired
private DartsDatabaseStub databaseStub;

private static final String ENDPOINT_URL = "/admin/medias/{id}/versions";
private static final String COURTHOUSE_NAME = "TESTCOURTHOUSE";
private static final String COURTROOM_NAME = "TESTCOURTROOM";
private static final OffsetDateTime HEARING_START_AT = OffsetDateTime.parse("2024-01-01T12:10:10Z");
private static final OffsetDateTime MEDIA_START_AT = HEARING_START_AT;
private static final OffsetDateTime MEDIA_END_AT = MEDIA_START_AT.plusHours(1);
private static final String RETAIN_UNTIL = "2200-02-01T00:00:00Z";


@ParameterizedTest
@EnumSource(value = SecurityRoleEnum.class, names = {"SUPER_USER", "SUPER_ADMIN"}, mode = INCLUDE)
void shouldReturn200_whenChronicleIdHasBothCurrentAndNonCurrentVersions(SecurityRoleEnum role) throws Exception {
final String chronicleId = "chronicleId";
MediaEntity currentMediaEntity = createAndSaveMediaEntity(true, chronicleId, Duration.ofDays(3));
MediaEntity versionedMediaEntity1 = createAndSaveMediaEntity(false, chronicleId, Duration.ofDays(2));
MediaEntity versionedMediaEntity2 = createAndSaveMediaEntity(false, chronicleId, Duration.ofDays(1));
//Craeted unrelated media to ensure not returned
createAndSaveMediaEntity(true, "unrealted");

given.anAuthenticatedUserWithGlobalAccessAndRole(role);

// When
MvcResult mvcResult = mockMvc.perform(get(ENDPOINT_URL, currentMediaEntity.getId()))
.andExpect(status().isOk())
.andReturn();

String expectedResponse = getContentsFromFile(
"tests/audio/AudioControllerGetAdminMediaVersionsByIdIntTest/expectedResponseTypical.json")
.replace("<created_at_current>", currentMediaEntity.getCreatedDateTime().format(DateTimeFormatter.ISO_DATE_TIME))
.replace("<versioned_at_current_1>", versionedMediaEntity2.getCreatedDateTime().format(DateTimeFormatter.ISO_DATE_TIME))
.replace("<versioned_at_current_2>", versionedMediaEntity1.getCreatedDateTime().format(DateTimeFormatter.ISO_DATE_TIME));
JSONAssert.assertEquals(expectedResponse, mvcResult.getResponse().getContentAsString(), JSONCompareMode.STRICT);
}

@Test
void shouldReturn200_whenMediaIdPassedIsNotCurrent_shouldReturnTheCorrectCorrentVersion() throws Exception {
final String chronicleId = "chronicleId";
MediaEntity currentMediaEntity = createAndSaveMediaEntity(true, chronicleId, Duration.ofDays(3));
MediaEntity versionedMediaEntity1 = createAndSaveMediaEntity(false, chronicleId, Duration.ofDays(2));
MediaEntity versionedMediaEntity2 = createAndSaveMediaEntity(false, chronicleId, Duration.ofDays(1));
//Craeted unrelated media to ensure not returned
createAndSaveMediaEntity(true, "unrealted");

given.anAuthenticatedUserWithGlobalAccessAndRole(SecurityRoleEnum.SUPER_ADMIN);

// When
MvcResult mvcResult = mockMvc.perform(get(ENDPOINT_URL, versionedMediaEntity1.getId()))
.andExpect(status().isOk())
.andReturn();

String expectedResponse = getContentsFromFile(
"tests/audio/AudioControllerGetAdminMediaVersionsByIdIntTest/expectedResponseTypical.json")
.replace("<created_at_current>", currentMediaEntity.getCreatedDateTime().format(DateTimeFormatter.ISO_DATE_TIME))
.replace("<versioned_at_current_1>", versionedMediaEntity2.getCreatedDateTime().format(DateTimeFormatter.ISO_DATE_TIME))
.replace("<versioned_at_current_2>", versionedMediaEntity1.getCreatedDateTime().format(DateTimeFormatter.ISO_DATE_TIME));
JSONAssert.assertEquals(expectedResponse, mvcResult.getResponse().getContentAsString(), JSONCompareMode.STRICT);
}

@Test
void shouldReturn200_whenChronicleIdHasOnlyCurrentAndNoVersions() throws Exception {
final String chronicleId = "chronicleId";
MediaEntity currentMediaEntity = createAndSaveMediaEntity(true, chronicleId, Duration.ofDays(3));
//Craeted unrelated media to ensure not returned
createAndSaveMediaEntity(true, "unrealted");

given.anAuthenticatedUserWithGlobalAccessAndRole(SecurityRoleEnum.SUPER_ADMIN);

// When
MvcResult mvcResult = mockMvc.perform(get(ENDPOINT_URL, currentMediaEntity.getId()))
.andExpect(status().isOk())
.andReturn();

String expectedResponse = getContentsFromFile(
"tests/audio/AudioControllerGetAdminMediaVersionsByIdIntTest/expectedResponseNoVersions.json")
.replace("<created_at_current>", currentMediaEntity.getCreatedDateTime().format(DateTimeFormatter.ISO_DATE_TIME));
JSONAssert.assertEquals(expectedResponse, mvcResult.getResponse().getContentAsString(), JSONCompareMode.STRICT);
}

@ParameterizedTest
@EnumSource(value = SecurityRoleEnum.class, names = {"SUPER_USER", "SUPER_ADMIN"}, mode = INCLUDE)
void shouldReturn404_WhenMediaRecordDoesNotExist(SecurityRoleEnum role) throws Exception {
// Given
given.anAuthenticatedUserWithGlobalAccessAndRole(role);

// When
MvcResult mvcResult = mockMvc.perform(get(ENDPOINT_URL, "123456789"))
.andExpect(status().isNotFound())
.andReturn();

// Then
var jsonString = mvcResult.getResponse().getContentAsString();
JSONAssert.assertEquals("""
{
"type": "AUDIO_102",
"title": "The requested media cannot be found",
"status": 404
}
""", jsonString, JSONCompareMode.STRICT);
}

@ParameterizedTest
@EnumSource(value = SecurityRoleEnum.class, names = {"SUPER_USER", "SUPER_ADMIN"}, mode = INCLUDE)
void shouldReturn404_WhenMediaRecordIsDeleted(SecurityRoleEnum role) throws Exception {
// Given
given.anAuthenticatedUserWithGlobalAccessAndRole(role);


var mediaEntity = createAndSaveMediaEntity(true, true, "chronicleId", Duration.ofMillis(0));
// When
MvcResult mvcResult = mockMvc.perform(get(ENDPOINT_URL, String.valueOf(mediaEntity.getId())))
.andExpect(status().isNotFound())
.andReturn();

// Then
var jsonString = mvcResult.getResponse().getContentAsString();
JSONAssert.assertEquals("""
{
"type": "AUDIO_102",
"title": "The requested media cannot be found",
"status": 404
}
""", jsonString, JSONCompareMode.STRICT);

}

@ParameterizedTest
@EnumSource(value = SecurityRoleEnum.class, names = {"SUPER_USER", "SUPER_ADMIN"}, mode = EXCLUDE)
void shouldDenyAccess_whenNotAuthorised(SecurityRoleEnum role) throws Exception {
// Given
given.anAuthenticatedUserWithGlobalAccessAndRole(role);

// When
MvcResult mvcResult = mockMvc.perform(get(ENDPOINT_URL, "123456789"))
.andExpect(status().isForbidden())
.andReturn();

// Then
var jsonString = mvcResult.getResponse().getContentAsString();
JSONAssert.assertEquals("""
{
"type": "AUTHORISATION_109",
"title": "User is not authorised for this endpoint",
"status": 403
}
""", jsonString, JSONCompareMode.STRICT);
}

private MediaEntity createAndSaveMediaEntity(boolean isCurrent, String chronicleId) {
return createAndSaveMediaEntity(false, isCurrent, chronicleId, Duration.ofMillis(0));
}

private MediaEntity createAndSaveMediaEntity(boolean isCurrent, String chronicleId, Duration timeOffset) {
return createAndSaveMediaEntity(false, isCurrent, chronicleId, timeOffset);
}

private MediaEntity createAndSaveMediaEntity(boolean isDeleted, boolean isCurrent, String chronicleId, Duration timeOffset) {
MediaEntity mediaEntity = databaseStub.createMediaEntity(COURTHOUSE_NAME,
COURTROOM_NAME,
MEDIA_START_AT.plus(timeOffset),
MEDIA_END_AT.plus(timeOffset),
2);
var userAccountEntity = databaseStub.getUserAccountRepository().findAll().stream()
.findFirst()
.orElseThrow();
mediaEntity.setLegacyObjectId("object-id-value");
mediaEntity.setContentObjectId("content-id-value");
mediaEntity.setClipId("clip-id-value");
mediaEntity.setMediaStatus("media-status-value");
mediaEntity.setHidden(true);
mediaEntity.setDeleted(isDeleted);
mediaEntity.setLegacyVersionLabel("version-label-value");
mediaEntity.setChronicleId(chronicleId);
mediaEntity.setAntecedentId("antecedent-value");
mediaEntity.setRetainUntilTs(OffsetDateTime.parse(RETAIN_UNTIL));
mediaEntity.setCreatedBy(userAccountEntity);
mediaEntity.setLastModifiedBy(userAccountEntity);
mediaEntity.setIsCurrent(isCurrent);

return databaseStub.getMediaRepository()
.saveAndFlush(mediaEntity);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"media_object_id": "object-id-value",
"current_version": {
"id": 1,
"courthouse": {
"id": 1,
"display_name": "TESTCOURTHOUSE"
},
"courtroom": {
"id": 1,
"name": "TESTCOURTROOM"
},
"start_at": "2024-01-04T12:10:10Z",
"end_at": "2024-01-04T13:10:10Z",
"channel": 2,
"chronicle_id": "chronicleId",
"antecedent_id": "antecedent-value",
"is_current": true,
"created_at": "<created_at_current>"
},
"previous_versions": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"media_object_id": "object-id-value",
"current_version": {
"id": 1,
"courthouse": {
"id": 1,
"display_name": "TESTCOURTHOUSE"
},
"courtroom": {
"id": 1,
"name": "TESTCOURTROOM"
},
"start_at": "2024-01-04T12:10:10Z",
"end_at": "2024-01-04T13:10:10Z",
"channel": 2,
"chronicle_id": "chronicleId",
"antecedent_id": "antecedent-value",
"is_current": true,
"created_at": "<created_at_current>"
},
"previous_versions": [
{
"id": 3,
"courthouse": {
"id": 1,
"display_name": "TESTCOURTHOUSE"
},
"courtroom": {
"id": 1,
"name": "TESTCOURTROOM"
},
"start_at": "2024-01-02T12:10:10Z",
"end_at": "2024-01-02T13:10:10Z",
"channel": 2,
"chronicle_id": "chronicleId",
"antecedent_id": "antecedent-value",
"is_current": false,
"created_at": "<versioned_at_current_1>"
},
{
"id": 2,
"courthouse": {
"id": 1,
"display_name": "TESTCOURTHOUSE"
},
"courtroom": {
"id": 1,
"name": "TESTCOURTROOM"
},
"start_at": "2024-01-03T12:10:10Z",
"end_at": "2024-01-03T13:10:10Z",
"channel": 2,
"chronicle_id": "chronicleId",
"antecedent_id": "antecedent-value",
"is_current": false,
"created_at": "<versioned_at_current_2>"
}
]
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package uk.gov.hmcts.darts.audio.mapper;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import uk.gov.hmcts.darts.audio.model.AdminActionResponse;
import uk.gov.hmcts.darts.audio.model.AdminMediaVersionResponse;
Expand All @@ -26,10 +28,11 @@

@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class GetAdminMediaResponseMapper {

private CourtroomMapper courtroomMapper;
private CourthouseMapper courthouseMapper;
private final CourtroomMapper courtroomMapper;
private final CourthouseMapper courthouseMapper;

public static List<GetAdminMediaResponseItem> createResponseItemList(List<MediaEntity> mediaEntities, HearingEntity hearing) {
List<GetAdminMediaResponseItem> responseList = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -63,6 +64,7 @@

@Service
@RequiredArgsConstructor
@Slf4j
public class AdminMediaServiceImpl implements AdminMediaService {

private final SearchMediaValidator searchMediaValidator;
Expand Down Expand Up @@ -273,13 +275,43 @@ public MediaApproveMarkedForDeletionResponse adminApproveMediaMarkedForDeletion(

@Override
public AdminVersionedMediaResponse getMediaVersionsById(Integer id) {
MediaEntity mediaEntity = getMediaEntityById(id);
List<MediaEntity> mediaVersions = new ArrayList<>();
//Only fetch versions if the media is part of a chronicle
if (mediaEntity.getChronicleId() != null) {
mediaVersions.addAll(mediaRepository.findAllByChronicleId(mediaEntity.getChronicleId()));
MediaEntity mediaEntityFromRequest = getMediaEntityById(id);

if (mediaEntityFromRequest.getChronicleId() == null) {
throw new DartsApiException(CommonApiError.INTERNAL_SERVER_ERROR,
"Media " + id + " has a Chronicle Id that is null. As such we can not ensure accurate results are returned");
}
List<MediaEntity> mediaVersions = mediaRepository.findAllByChronicleId(mediaEntityFromRequest.getChronicleId());


List<MediaEntity> currentMediaVersions = mediaVersions.stream()
.filter(mediaEntity -> mediaEntity.getIsCurrent() != null)
.filter(media -> media.getIsCurrent())
.sorted((o1, o2) -> o1.getCreatedDateTime().compareTo(o2.getCreatedDateTime()))
.collect(Collectors.toCollection(ArrayList::new));

List<MediaEntity> versionedMedia = mediaVersions.stream()
.filter(media -> media.getIsCurrent() == null || !media.getIsCurrent())
.sorted((o1, o2) -> o2.getCreatedDateTime().compareTo(o1.getCreatedDateTime()))
.collect(Collectors.toCollection(ArrayList::new));

MediaEntity currentVersion;
if (currentMediaVersions.size() == 1) {
currentVersion = currentMediaVersions.getLast();
} else if (currentMediaVersions.size() == 0) {
currentVersion = null;
log.info("Media with id {} has {} current versions", id, currentMediaVersions.size());
} else {
log.warn("Media with id {} has {} current versions we only expect one", id, currentMediaVersions.size());
currentVersion = currentMediaVersions.getLast();
//Add any extra current events to top of versionedMedia so they still get displayed
currentMediaVersions.removeLast();
currentMediaVersions
.forEach(mediaEntity -> {
versionedMedia.addFirst(mediaEntity);
});
}
return getAdminMediaResponseMapper.mapAdminVersionedMediaResponse(mediaEntity, mediaVersions);
return getAdminMediaResponseMapper.mapAdminVersionedMediaResponse(currentVersion, versionedMedia);
}

private ApplyAdminActionComponent.AdminActionProperties mapToAdminActionProperties(AdminActionRequest adminActionRequest) {
Expand Down
Loading

0 comments on commit ea7d204

Please sign in to comment.