diff --git a/src/main/java/org/folio/fqm/repository/EntityTypeRepository.java b/src/main/java/org/folio/fqm/repository/EntityTypeRepository.java index 3d37082d..9da67305 100644 --- a/src/main/java/org/folio/fqm/repository/EntityTypeRepository.java +++ b/src/main/java/org/folio/fqm/repository/EntityTypeRepository.java @@ -69,7 +69,7 @@ public Optional getEntityTypeDefinition(UUID entityTypeId) { }); } - public List getEntityTypeSummary(Set entityTypeIds) { + public List getEntityTypeSummaries(Set entityTypeIds) { log.info("Fetching entityTypeSummary for ids: {}", entityTypeIds); Field definitionField = field(DEFINITION_FIELD_NAME, String.class); diff --git a/src/main/java/org/folio/fqm/resource/EntityTypeController.java b/src/main/java/org/folio/fqm/resource/EntityTypeController.java index 1240b3a4..9ffc8662 100644 --- a/src/main/java/org/folio/fqm/resource/EntityTypeController.java +++ b/src/main/java/org/folio/fqm/resource/EntityTypeController.java @@ -30,10 +30,10 @@ public ResponseEntity getEntityType(UUID entityTypeId) { } @Override - public ResponseEntity> getEntityTypeSummary(List entityTypeIds) { + public ResponseEntity> getEntityTypeSummary(List entityTypeIds, Boolean includeInaccessible) { Set idsSet = entityTypeIds == null ? Set.of() : Set.copyOf(entityTypeIds); // Permissions are handled in the service layer - return ResponseEntity.ok(entityTypeService.getEntityTypeSummary(idsSet)); + return ResponseEntity.ok(entityTypeService.getEntityTypeSummary(idsSet, Boolean.TRUE.equals(includeInaccessible))); } @EntityTypePermissionsRequired diff --git a/src/main/java/org/folio/fqm/service/EntityTypeService.java b/src/main/java/org/folio/fqm/service/EntityTypeService.java index a1ee6633..415dbf52 100644 --- a/src/main/java/org/folio/fqm/service/EntityTypeService.java +++ b/src/main/java/org/folio/fqm/service/EntityTypeService.java @@ -56,17 +56,29 @@ public class EntityTypeService { * @param entityTypeIds If provided, only the entity types having the provided Ids will be included in the results */ @Transactional(readOnly = true) - public List getEntityTypeSummary(Set entityTypeIds) { + public List getEntityTypeSummary(Set entityTypeIds, boolean includeInaccessible) { Set userPermissions = permissionsService.getUserPermissions(); return entityTypeRepository - .getEntityTypeSummary(entityTypeIds) + .getEntityTypeSummaries(entityTypeIds) .stream() - .filter(entityTypeSummary -> userPermissions.containsAll(entityTypeSummary.requiredPermissions())) - .map(rawEntityTypeSummary -> - new EntityTypeSummary() + .filter(entityTypeSummary -> includeInaccessible || userPermissions.containsAll(entityTypeSummary.requiredPermissions())) + .map(rawEntityTypeSummary -> { + EntityTypeSummary result = new EntityTypeSummary() .id(rawEntityTypeSummary.id()) - .label(localizationService.getEntityTypeLabel(rawEntityTypeSummary.name())) - ) + .label(localizationService.getEntityTypeLabel(rawEntityTypeSummary.name())); + + if (includeInaccessible) { + return result.missingPermissions( + rawEntityTypeSummary + .requiredPermissions() + .stream() + .filter(permission -> !userPermissions.contains(permission)) + .toList() + ); + } + + return result; + }) .sorted(Comparator.comparing(EntityTypeSummary::getLabel, String.CASE_INSENSITIVE_ORDER)) .toList(); } diff --git a/src/main/resources/swagger.api/mod-fqm-manager.yaml b/src/main/resources/swagger.api/mod-fqm-manager.yaml index fb6c23a1..945fca04 100644 --- a/src/main/resources/swagger.api/mod-fqm-manager.yaml +++ b/src/main/resources/swagger.api/mod-fqm-manager.yaml @@ -16,6 +16,7 @@ paths: description: Get names for a list of entity type ids. parameters: - $ref: '#/components/parameters/entity-type-ids' + - $ref: '#/components/parameters/include-inaccessible' responses: '200': description: 'Entity type summaries' @@ -79,6 +80,13 @@ components: items: type: string format: UUID + include-inaccessible: + name: includeInaccessible + in: query + required: false + description: Include inaccessible entity types in the result + schema: + type: boolean schemas: errorResponse: $ref: schemas/errors.json diff --git a/src/main/resources/swagger.api/schemas/EntityTypeSummaryDTO.json b/src/main/resources/swagger.api/schemas/EntityTypeSummaryDTO.json index ad918cf3..4dd53a34 100644 --- a/src/main/resources/swagger.api/schemas/EntityTypeSummaryDTO.json +++ b/src/main/resources/swagger.api/schemas/EntityTypeSummaryDTO.json @@ -11,6 +11,13 @@ "label" : { "description": "Entity type label", "type": "string" + }, + "missingPermissions": { + "description": "List of missing permissions", + "type": "array", + "items": { + "type": "string" + } } }, "additionalProperties": false, diff --git a/src/test/java/org/folio/fqm/controller/EntityTypeControllerTest.java b/src/test/java/org/folio/fqm/controller/EntityTypeControllerTest.java index 83c9c0d3..5d77183e 100644 --- a/src/test/java/org/folio/fqm/controller/EntityTypeControllerTest.java +++ b/src/test/java/org/folio/fqm/controller/EntityTypeControllerTest.java @@ -1,11 +1,19 @@ package org.folio.fqm.controller; +import static org.hamcrest.Matchers.is; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.util.*; +import org.folio.fqm.domain.dto.EntityTypeSummary; import org.folio.fqm.exception.EntityTypeNotFoundException; import org.folio.fqm.exception.FieldNotFoundException; import org.folio.fqm.resource.EntityTypeController; import org.folio.fqm.service.EntityTypeService; -import org.folio.fqm.domain.dto.EntityTypeSummary; import org.folio.querytool.domain.dto.ColumnValues; import org.folio.querytool.domain.dto.EntityType; import org.folio.querytool.domain.dto.EntityTypeColumn; @@ -14,31 +22,25 @@ import org.folio.spring.FolioExecutionContext; import org.folio.spring.integration.XOkapiHeaders; import org.junit.jupiter.api.Test; - -import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.RequestBuilder; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import java.util.*; - -import static org.mockito.Mockito.when; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.hamcrest.Matchers.is; - @WebMvcTest(EntityTypeController.class) class EntityTypeControllerTest { - private final static String GET_DEFINITION_URL = "/entity-types/{entity-type-id}"; + + private static final String GET_DEFINITION_URL = "/entity-types/{entity-type-id}"; + @Autowired private MockMvc mockMvc; + @MockBean private EntityTypeService entityTypeService; + @MockBean private FolioExecutionContext folioExecutionContext; @@ -50,9 +52,12 @@ void shouldReturnEntityTypeDefinition() throws Exception { EntityType mockDefinition = getEntityType(col); when(folioExecutionContext.getTenantId()).thenReturn("tenant_01"); when(entityTypeService.getEntityTypeDefinition(id)).thenReturn(Optional.of(mockDefinition)); - RequestBuilder builder = MockMvcRequestBuilders.get(GET_DEFINITION_URL, id).accept(MediaType.APPLICATION_JSON). - header(XOkapiHeaders.TENANT, "tenant_01"); - mockMvc.perform(builder) + RequestBuilder builder = MockMvcRequestBuilders + .get(GET_DEFINITION_URL, id) + .accept(MediaType.APPLICATION_JSON) + .header(XOkapiHeaders.TENANT, "tenant_01"); + mockMvc + .perform(builder) .andExpect(status().isOk()) .andExpect(jsonPath("$.name", is(derivedTableName))) .andExpect(jsonPath("$.labelAlias", is(mockDefinition.getLabelAlias()))) @@ -67,7 +72,10 @@ void shouldReturnNotFoundErrorWhenEntityNotFound() throws Exception { UUID id = UUID.randomUUID(); when(folioExecutionContext.getTenantId()).thenReturn("tenant_01"); when(entityTypeService.getEntityTypeDefinition(UUID.randomUUID())).thenReturn(Optional.empty()); - RequestBuilder builder = MockMvcRequestBuilders.get(GET_DEFINITION_URL, id).accept(MediaType.APPLICATION_JSON).header(XOkapiHeaders.TENANT, "tenant_01"); + RequestBuilder builder = MockMvcRequestBuilders + .get(GET_DEFINITION_URL, id) + .accept(MediaType.APPLICATION_JSON) + .header(XOkapiHeaders.TENANT, "tenant_01"); mockMvc.perform(builder).andExpect(status().isNotFound()); } @@ -78,17 +86,42 @@ void shouldGetEntityTypeSummaryForValidIds() throws Exception { Set ids = Set.of(id1, id2); List expectedSummary = List.of( new EntityTypeSummary().id(id1).label("label_01"), - new EntityTypeSummary().id(id2).label("label_02")); - RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/entity-types") + new EntityTypeSummary().id(id2).label("label_02") + ); + RequestBuilder requestBuilder = MockMvcRequestBuilders + .get("/entity-types") .header(XOkapiHeaders.TENANT, "tenant_01") .queryParam("ids", id1.toString(), id2.toString()); - when(entityTypeService.getEntityTypeSummary(ids)).thenReturn(expectedSummary); - mockMvc.perform(requestBuilder) + when(entityTypeService.getEntityTypeSummary(ids, false)).thenReturn(expectedSummary); + mockMvc + .perform(requestBuilder) .andExpect(status().isOk()) .andExpect(jsonPath("$.[0].id", is(expectedSummary.get(0).getId().toString()))) .andExpect(jsonPath("$.[0].label", is(expectedSummary.get(0).getLabel()))) + .andExpect(jsonPath("$.[0].missingPermissions").doesNotExist()) .andExpect(jsonPath("$.[1].id", is(expectedSummary.get(1).getId().toString()))) - .andExpect(jsonPath("$.[1].label", is(expectedSummary.get(1).getLabel()))); + .andExpect(jsonPath("$.[1].label", is(expectedSummary.get(1).getLabel()))) + .andExpect(jsonPath("$.[1].missingPermissions").doesNotExist()); + + verify(entityTypeService, times(1)).getEntityTypeSummary(ids, false); + verifyNoMoreInteractions(entityTypeService); + } + + @Test + void testSummaryIncludesMissingPermissionsIfRequested() throws Exception { + RequestBuilder requestBuilder = MockMvcRequestBuilders + .get("/entity-types") + .header(XOkapiHeaders.TENANT, "tenant_01") + .queryParam("includeInaccessible", "true"); + + when(entityTypeService.getEntityTypeSummary(Set.of(), true)).thenReturn(List.of()); + + // all we really want to check here is that the includeInaccessible parameter is correctly unboxed + // no sense making fake data to pass through to ourself; that's redundant with shouldGetEntityTypeSummaryForValidIds + mockMvc.perform(requestBuilder).andExpect(status().isOk()); + + verify(entityTypeService, times(1)).getEntityTypeSummary(Set.of(), true); + verifyNoMoreInteractions(entityTypeService); } @Test @@ -97,13 +130,12 @@ void shouldReturnEmptyListWhenEntityTypeSummaryNotFound() throws Exception { UUID id2 = UUID.randomUUID(); Set ids = Set.of(id1, id2); List expectedSummary = List.of(); - RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/entity-types") + RequestBuilder requestBuilder = MockMvcRequestBuilders + .get("/entity-types") .header(XOkapiHeaders.TENANT, "tenant_01") .queryParam("ids", id1.toString(), id2.toString()); - when(entityTypeService.getEntityTypeSummary(ids)).thenReturn(expectedSummary); - mockMvc.perform(requestBuilder) - .andExpect(status().isOk()) - .andExpect(jsonPath("$", is(expectedSummary))); + when(entityTypeService.getEntityTypeSummary(ids, false)).thenReturn(expectedSummary); + mockMvc.perform(requestBuilder).andExpect(status().isOk()).andExpect(jsonPath("$", is(expectedSummary))); } @Test @@ -115,11 +147,14 @@ void shouldReturnColumnValuesWithLabel() throws Exception { new ValueWithLabel().value("value_01").label("label_01"), new ValueWithLabel().value("value_02").label("label_02") ); - RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/entity-types/{id}/columns/{columnName}/values", entityTypeId, columnName) + RequestBuilder requestBuilder = MockMvcRequestBuilders + .get("/entity-types/{id}/columns/{columnName}/values", entityTypeId, columnName) .accept(MediaType.APPLICATION_JSON) .header(XOkapiHeaders.TENANT, "tenant_01"); - when(entityTypeService.getFieldValues(entityTypeId, columnName, null)).thenReturn(columnValues.content(expectedColumnValueLabel)); - mockMvc.perform(requestBuilder) + when(entityTypeService.getFieldValues(entityTypeId, columnName, null)) + .thenReturn(columnValues.content(expectedColumnValueLabel)); + mockMvc + .perform(requestBuilder) .andExpect(status().isOk()) .andExpect(jsonPath("$.content[0].value", is(expectedColumnValueLabel.get(0).getValue()))) .andExpect(jsonPath("$.content[0].label", is(expectedColumnValueLabel.get(0).getLabel()))) @@ -136,12 +171,15 @@ void shouldReturnColumnValuesWithLabelWithSearch() throws Exception { new ValueWithLabel().value("value_01").label("label_01"), new ValueWithLabel().value("value_02").label("label_02") ); - RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/entity-types/{id}/columns/{columnName}/values", entityTypeId, columnName) + RequestBuilder requestBuilder = MockMvcRequestBuilders + .get("/entity-types/{id}/columns/{columnName}/values", entityTypeId, columnName) .accept(MediaType.APPLICATION_JSON) .header(XOkapiHeaders.TENANT, "tenant_01") .queryParam("search", "label_01"); - when(entityTypeService.getFieldValues(entityTypeId, columnName, "label_01")).thenReturn(columnValues.content(expectedColumnValueLabel)); - mockMvc.perform(requestBuilder) + when(entityTypeService.getFieldValues(entityTypeId, columnName, "label_01")) + .thenReturn(columnValues.content(expectedColumnValueLabel)); + mockMvc + .perform(requestBuilder) .andExpect(status().isOk()) .andExpect(jsonPath("$.content[0].value", is(expectedColumnValueLabel.get(0).getValue()))) .andExpect(jsonPath("$.content[0].label", is(expectedColumnValueLabel.get(0).getLabel()))); @@ -156,11 +194,14 @@ void shouldReturnColumnValues() throws Exception { new ValueWithLabel().value("value_01"), new ValueWithLabel().value("value_02") ); - RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/entity-types/{id}/columns/{columnName}/values", entityTypeId, columnName) + RequestBuilder requestBuilder = MockMvcRequestBuilders + .get("/entity-types/{id}/columns/{columnName}/values", entityTypeId, columnName) .accept(MediaType.APPLICATION_JSON) .header(XOkapiHeaders.TENANT, "tenant_01"); - when(entityTypeService.getFieldValues(entityTypeId, columnName, null)).thenReturn(columnValues.content(expectedColumnValueLabel)); - mockMvc.perform(requestBuilder) + when(entityTypeService.getFieldValues(entityTypeId, columnName, null)) + .thenReturn(columnValues.content(expectedColumnValueLabel)); + mockMvc + .perform(requestBuilder) .andExpect(status().isOk()) .andExpect(jsonPath("$.content[0].value", is(expectedColumnValueLabel.get(0).getValue()))) .andExpect(jsonPath("$.content[1].value", is(expectedColumnValueLabel.get(1).getValue()))); @@ -175,12 +216,15 @@ void shouldReturnColumnValuesWithSearch() throws Exception { new ValueWithLabel().value("value_01"), new ValueWithLabel().value("value_02") ); - RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/entity-types/{id}/columns/{columnName}/values", entityTypeId, columnName) + RequestBuilder requestBuilder = MockMvcRequestBuilders + .get("/entity-types/{id}/columns/{columnName}/values", entityTypeId, columnName) .accept(MediaType.APPLICATION_JSON) .header(XOkapiHeaders.TENANT, "tenant_01") .queryParam("search", "value_01"); - when(entityTypeService.getFieldValues(entityTypeId, columnName, "value_01")).thenReturn(columnValues.content(expectedColumnValueLabel)); - mockMvc.perform(requestBuilder) + when(entityTypeService.getFieldValues(entityTypeId, columnName, "value_01")) + .thenReturn(columnValues.content(expectedColumnValueLabel)); + mockMvc + .perform(requestBuilder) .andExpect(status().isOk()) .andExpect(jsonPath("$.content[0].value", is(expectedColumnValueLabel.get(0).getValue()))); } @@ -189,26 +233,26 @@ void shouldReturnColumnValuesWithSearch() throws Exception { void shouldReturnErrorWhenColumnNameNotFound() throws Exception { UUID entityTypeId = UUID.randomUUID(); String columnName = "column_name"; - RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/entity-types/{id}/columns/{columnName}/values", entityTypeId, columnName) + RequestBuilder requestBuilder = MockMvcRequestBuilders + .get("/entity-types/{id}/columns/{columnName}/values", entityTypeId, columnName) .accept(MediaType.APPLICATION_JSON) .header(XOkapiHeaders.TENANT, "tenant_01"); when(entityTypeService.getFieldValues(entityTypeId, columnName, null)) .thenThrow(new FieldNotFoundException("entity_type", columnName)); - mockMvc.perform(requestBuilder) - .andExpect(status().isNotFound()); + mockMvc.perform(requestBuilder).andExpect(status().isNotFound()); } @Test void shouldReturnErrorWhenEntityTypeIdNotFound() throws Exception { UUID entityTypeId = UUID.randomUUID(); String columnName = "column_name"; - RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/entity-types/{id}/columns/{columnName}/values", entityTypeId, columnName) + RequestBuilder requestBuilder = MockMvcRequestBuilders + .get("/entity-types/{id}/columns/{columnName}/values", entityTypeId, columnName) .accept(MediaType.APPLICATION_JSON) .header(XOkapiHeaders.TENANT, "tenant_01"); when(entityTypeService.getFieldValues(entityTypeId, columnName, null)) .thenThrow(new EntityTypeNotFoundException(entityTypeId)); - mockMvc.perform(requestBuilder) - .andExpect(status().isNotFound()); + mockMvc.perform(requestBuilder).andExpect(status().isNotFound()); } private static EntityType getEntityType(EntityTypeColumn col) { diff --git a/src/test/java/org/folio/fqm/repository/EntityTypeRepositoryTest.java b/src/test/java/org/folio/fqm/repository/EntityTypeRepositoryTest.java index dc552fdb..939fcd81 100644 --- a/src/test/java/org/folio/fqm/repository/EntityTypeRepositoryTest.java +++ b/src/test/java/org/folio/fqm/repository/EntityTypeRepositoryTest.java @@ -49,7 +49,7 @@ void shouldFetchAllPublicEntityTypes() { new RawEntityTypeSummary(ENTITY_TYPE_02_ID, ENTITY_TYPE_02_LABEL, List.of()) ); - List actualSummary = repo.getEntityTypeSummary(Set.of()); + List actualSummary = repo.getEntityTypeSummaries(Set.of()); assertEquals(expectedSummary, actualSummary, "Expected Summary should equal Actual Summary"); } @@ -59,7 +59,7 @@ void shouldFetchEntityTypesOfGivenIds() { List expectedSummary = List.of( new RawEntityTypeSummary(ENTITY_TYPE_01_ID, ENTITY_TYPE_01_LABEL, List.of())); - List actualSummary = repo.getEntityTypeSummary(ids); + List actualSummary = repo.getEntityTypeSummaries(ids); assertEquals(expectedSummary, actualSummary, "Expected Summary should equal Actual Summary"); } diff --git a/src/test/java/org/folio/fqm/service/EntityTypeServiceTest.java b/src/test/java/org/folio/fqm/service/EntityTypeServiceTest.java index 9844a0ce..ed673623 100644 --- a/src/test/java/org/folio/fqm/service/EntityTypeServiceTest.java +++ b/src/test/java/org/folio/fqm/service/EntityTypeServiceTest.java @@ -61,17 +61,69 @@ void shouldGetEntityTypeSummaryForValidIds() { new EntityTypeSummary().id(id1).label("label_01"), new EntityTypeSummary().id(id2).label("label_02")); - when(repo.getEntityTypeSummary(ids)).thenReturn(List.of( + when(repo.getEntityTypeSummaries(ids)).thenReturn(List.of( new RawEntityTypeSummary(id1, "translation_label_01", List.of()), new RawEntityTypeSummary(id2, "translation_label_02", List.of()))); when(localizationService.getEntityTypeLabel("translation_label_01")).thenReturn("label_01"); when(localizationService.getEntityTypeLabel("translation_label_02")).thenReturn("label_02"); - List actualSummary = entityTypeService.getEntityTypeSummary(ids); + List actualSummary = entityTypeService.getEntityTypeSummary(ids, false); assertEquals(expectedSummary, actualSummary, "Expected Summary should equal Actual Summary"); - verify(repo, times(1)).getEntityTypeSummary(ids); + verify(repo, times(1)).getEntityTypeSummaries(ids); + + verify(localizationService, times(1)).getEntityTypeLabel("translation_label_01"); + verify(localizationService, times(1)).getEntityTypeLabel("translation_label_02"); + + verifyNoMoreInteractions(repo, localizationService); + } + + @Test + void testEntityTypeSummaryDoesNotIncludeInaccessibleWhenNotRequested() { + UUID id1 = UUID.randomUUID(); + UUID id2 = UUID.randomUUID(); + Set ids = Set.of(id1, id2); + List expectedSummary = List.of(new EntityTypeSummary().id(id2).label("label_02")); + + when(repo.getEntityTypeSummaries(ids)).thenReturn(List.of( + new RawEntityTypeSummary(id1, "translation_label_01", List.of("perm1")), + new RawEntityTypeSummary(id2, "translation_label_02", List.of("perm2")))); + when(permissionsService.getUserPermissions()).thenReturn(Set.of("perm2")); + when(localizationService.getEntityTypeLabel("translation_label_02")).thenReturn("label_02"); + + List actualSummary = entityTypeService.getEntityTypeSummary(ids, false); + + assertEquals(expectedSummary, actualSummary, "Expected Summary should equal Actual Summary"); + + verify(repo, times(1)).getEntityTypeSummaries(ids); + + verify(localizationService, times(1)).getEntityTypeLabel("translation_label_02"); + + verifyNoMoreInteractions(repo, localizationService); + } + + @Test + void testEntityTypeSummaryIncludesInaccessible() { + UUID id1 = UUID.randomUUID(); + UUID id2 = UUID.randomUUID(); + Set ids = Set.of(id1, id2); + List expectedSummary = List.of( + new EntityTypeSummary().id(id1).label("label_01").missingPermissions(List.of("perm1")), + new EntityTypeSummary().id(id2).label("label_02").missingPermissions(List.of())); + + when(repo.getEntityTypeSummaries(ids)).thenReturn(List.of( + new RawEntityTypeSummary(id1, "translation_label_01", List.of("perm1")), + new RawEntityTypeSummary(id2, "translation_label_02", List.of("perm2")))); + when(permissionsService.getUserPermissions()).thenReturn(Set.of("perm2")); + when(localizationService.getEntityTypeLabel("translation_label_01")).thenReturn("label_01"); + when(localizationService.getEntityTypeLabel("translation_label_02")).thenReturn("label_02"); + + List actualSummary = entityTypeService.getEntityTypeSummary(ids, true); + + assertEquals(expectedSummary, actualSummary, "Expected Summary should equal Actual Summary"); + + verify(repo, times(1)).getEntityTypeSummaries(ids); verify(localizationService, times(1)).getEntityTypeLabel("translation_label_01"); verify(localizationService, times(1)).getEntityTypeLabel("translation_label_02");