From c6a401b6a9fa8d70411363c0891820f7211da596 Mon Sep 17 00:00:00 2001 From: anhefti Date: Thu, 7 Jul 2022 16:22:19 +0200 Subject: [PATCH] More integration tests --- .../servicelayer/dao/FilterMap.java | 2 +- .../impl/ConfigurationAttributeDAOImpl.java | 2 +- .../weblayer/api/EntityController.java | 44 ++-- .../integration/UseCasesIntegrationTest.java | 70 +++++++ .../admin/ConfigurationAttributeAPITest.java | 193 ++++++++++++++++++ 5 files changed, 278 insertions(+), 33 deletions(-) create mode 100644 src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/admin/ConfigurationAttributeAPITest.java diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/FilterMap.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/FilterMap.java index 85ce64fe..8000a979 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/FilterMap.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/FilterMap.java @@ -156,7 +156,7 @@ public class FilterMap extends POSTMapper { } public String getConfigAttributeType() { - return getSQLWildcard(ConfigurationAttribute.FILTER_ATTR_TYPE); + return getString(ConfigurationAttribute.FILTER_ATTR_TYPE); } public Long getConfigValueConfigId() { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationAttributeDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationAttributeDAOImpl.java index cc3b6697..a7a6964e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationAttributeDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ConfigurationAttributeDAOImpl.java @@ -177,7 +177,7 @@ public class ConfigurationAttributeDAOImpl implements ConfigurationAttributeDAO final ConfigurationAttributeRecord newRecord = new ConfigurationAttributeRecord( data.id, data.name, - data.type.name(), + data.type != null ? data.type.name() : null, data.parentId, data.resources, data.validator, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java index d06abd76..fbf9d380 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java @@ -206,19 +206,6 @@ public abstract class EntityController { return page; } - protected void populateFilterMap(final FilterMap filterMap, final Long institutionId, final String sort) { - // If current user has no read access for specified entity type within other institution - // then the current users institutionId is put as a SQL filter criteria attribute to extends query performance - if (!this.authorization.hasGrant(PrivilegeType.READ, getGrantEntityType())) { - filterMap.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId)); - } - - // If sorting is on institution name we need to join the institution table - if (sort != null && sort.contains(Entity.FILTER_ATTR_INSTITUTION)) { - filterMap.putIfAbsent(FilterMap.ATTR_ADD_INSITUTION_JOIN, Constants.TRUE_STRING); - } - } - // ****************** // * GET (names) // ****************** @@ -581,6 +568,19 @@ public abstract class EntityController { .getOrThrow(); } + protected void populateFilterMap(final FilterMap filterMap, final Long institutionId, final String sort) { + // If current user has no read access for specified entity type within other institution + // then the current users institutionId is put as a SQL filter criteria attribute to extends query performance + if (!this.authorization.hasGrant(PrivilegeType.READ, getGrantEntityType())) { + filterMap.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId)); + } + + // If sorting is on institution name we need to join the institution table + if (sort != null && sort.contains(Entity.FILTER_ATTR_INSTITUTION)) { + filterMap.putIfAbsent(FilterMap.ATTR_ADD_INSITUTION_JOIN, Constants.TRUE_STRING); + } + } + protected EnumSet convertToEntityType(final boolean addIncludes, final List includes) { final EnumSet includeDependencies = (includes != null) ? (includes.isEmpty()) @@ -783,24 +783,6 @@ public abstract class EntityController { return this.userActivityLogDAO.logModify(entity); } - /** Makes a DELETE user activity log for the specified entity. - * This may be overwritten if the create user activity log should be skipped. - * - * @param entity the Entity instance - * @return Result refer to the logged Entity instance or to an error if happened */ - protected String logDelete(final String modelId) { - try { - return this.entityDAO - .byModelId(modelId) - .flatMap(this::logDelete) - .map(Entity::getModelId) - .getOrThrow(); - } catch (final Exception e) { - log.warn("Failed to log delete for entity id: {}", modelId, e); - return modelId; - } - } - /** Makes a DELETE user activity log for the specified entity. * This may be overwritten if the create user activity log should be skipped. * diff --git a/src/test/java/ch/ethz/seb/sebserver/gui/integration/UseCasesIntegrationTest.java b/src/test/java/ch/ethz/seb/sebserver/gui/integration/UseCasesIntegrationTest.java index 944ab1e7..53a3ff1b 100644 --- a/src/test/java/ch/ethz/seb/sebserver/gui/integration/UseCasesIntegrationTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/gui/integration/UseCasesIntegrationTest.java @@ -126,6 +126,7 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.batch.DoBatchActi import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.batch.GetBatchAction; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.batch.GetBatchActionPage; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.ActivateSEBRestriction; +import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.ArchiveExam; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.CheckExamConsistency; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.CheckExamImported; import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.CheckSEBRestriction; @@ -3945,4 +3946,73 @@ public class UseCasesIntegrationTest extends GuiIntegrationTest { assertFalse(page.content.isEmpty()); } + @Test + @Order(30) + // ************************************* + // Use Case 30: Login as admin and archive finished exam + // - Get Exam (finished), archive and check + public void testUsecase30_TestArchiveExam() throws IOException { + final RestServiceImpl restService = createRestServiceForUser( + "admin", + "admin", + new GetExamPage(), + new GetExam(), + new ArchiveExam()); + + final Page finishedExams = restService + .getBuilder(GetExamPage.class) + .withQueryParam(Exam.FILTER_ATTR_STATUS, ExamStatus.FINISHED.name()) + .call() + .get(); + + assertNotNull(finishedExams); + assertFalse(finishedExams.content.isEmpty()); + final Exam exam = finishedExams.content.get(0); + assertEquals(ExamStatus.FINISHED, exam.status); + + final Result archiveCall = restService.getBuilder(ArchiveExam.class) + .withURIVariable(API.PARAM_MODEL_ID, exam.getModelId()) + .call(); + + assertNotNull(archiveCall); + assertFalse(archiveCall.hasError()); + final Exam exam2 = archiveCall.get(); + assertNotNull(exam2); + assertEquals(exam.id, exam2.id); + assertEquals(ExamStatus.ARCHIVED, exam2.status); + } + + @Test + @Order(31) + // ************************************* + // Use Case 31: Login as admin and archive finished exam + // - Get Exam (running), archive and check not possible + public void testUsecase31_TestArchiveRunningExam_NotPossible() throws IOException { + final RestServiceImpl restService = createRestServiceForUser( + "admin", + "admin", + new GetExamPage(), + new GetExam(), + new ArchiveExam()); + + final Page finishedExams = restService + .getBuilder(GetExamPage.class) + .withQueryParam(Exam.FILTER_ATTR_STATUS, ExamStatus.RUNNING.name()) + .call() + .get(); + + assertNotNull(finishedExams); + assertFalse(finishedExams.content.isEmpty()); + final Exam exam = finishedExams.content.get(0); + assertEquals(ExamStatus.RUNNING, exam.status); + + final Result archiveCall = restService.getBuilder(ArchiveExam.class) + .withURIVariable(API.PARAM_MODEL_ID, exam.getModelId()) + .call(); + + assertNotNull(archiveCall); + assertTrue(archiveCall.hasError()); + assertTrue(archiveCall.getError().getMessage().contains("Exam is in wrong status to archive")); + } + } diff --git a/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/admin/ConfigurationAttributeAPITest.java b/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/admin/ConfigurationAttributeAPITest.java new file mode 100644 index 00000000..af5c0ad4 --- /dev/null +++ b/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/admin/ConfigurationAttributeAPITest.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2022 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver.webservice.integration.api.admin; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumSet; +import java.util.List; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; + +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.Order; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +import ch.ethz.seb.sebserver.gbl.model.Domain; +import ch.ethz.seb.sebserver.gbl.model.EntityName; +import ch.ethz.seb.sebserver.gbl.model.Page; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType; +import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute; +import ch.ethz.seb.sebserver.gbl.model.user.UserInfo; +import ch.ethz.seb.sebserver.gbl.model.user.UserRole; +import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.SEBServerUser; +import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.UserServiceImpl; +import ch.ethz.seb.sebserver.webservice.weblayer.api.ConfigurationAttributeController; + +@Sql(scripts = { "classpath:schema-test.sql", "classpath:data-test.sql", "classpath:data-test-additional.sql" }) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class ConfigurationAttributeAPITest extends AdministrationAPIIntegrationTester { + + @Autowired + private ConfigurationAttributeController configurationAttributeController; + @Autowired + private UserServiceImpl userServiceImpl; + @Mock + private HttpServletRequest mockRequest; + + private final MultiValueMap params = new LinkedMultiValueMap<>(); + + @Before + public void init() { + this.userServiceImpl.setAuthenticationIfAbsent(new SEBServerUser( + -1L, + new UserInfo("user1", 1L, null, "admin", null, null, null, true, null, null, + EnumSet.allOf(UserRole.class).stream().map(r -> r.name()).collect(Collectors.toSet())), + null)); + Mockito.when(this.mockRequest.getQueryString()).thenReturn(""); + } + + @Test + @Order(1) + public void test1_GetPage() { + final Page page = this.configurationAttributeController.getPage( + 1L, 0, 100, null, + new LinkedMultiValueMap(), + this.mockRequest); + + assertNotNull(page); + assertFalse(page.content.isEmpty()); + assertEquals("100", String.valueOf(page.content.size())); + } + + @Test + @Order(2) + public void test2_GetNames() { + Collection names = this.configurationAttributeController.getNames( + 1L, + new LinkedMultiValueMap(), + this.mockRequest); + + assertNotNull(names); + assertFalse(names.isEmpty()); + assertEquals("241", String.valueOf(names.size())); + + this.params.clear(); + this.params.add(ConfigurationAttribute.FILTER_ATTR_TYPE, AttributeType.CHECKBOX.name()); + + names = this.configurationAttributeController.getNames( + 1L, + this.params, + this.mockRequest); + + assertNotNull(names); + assertFalse(names.isEmpty()); + assertEquals("139", String.valueOf(names.size())); + } + + @Test + @Order(3) + public void test3_GetSingle() { + final ConfigurationAttribute attr = this.configurationAttributeController.getBy("1"); + + assertNotNull(attr); + assertEquals("hashedAdminPassword", attr.name); + } + + @Test + @Order(4) + public void test4_GetList() { + List forIds = this.configurationAttributeController.getForIds("1,2"); + + assertNotNull(forIds); + assertEquals("2", String.valueOf(forIds.size())); + + forIds = this.configurationAttributeController.getForIds(null); + + assertNotNull(forIds); + assertEquals("241", String.valueOf(forIds.size())); + } + + @Test + @Order(5) + public void test5_CreateAndSaveAndDelete() { + this.params.clear(); + this.params.add(Domain.CONFIGURATION_ATTRIBUTE.ATTR_PARENT_ID, null); + this.params.add(Domain.CONFIGURATION_ATTRIBUTE.ATTR_NAME, "testAttribute"); + this.params.add(Domain.CONFIGURATION_ATTRIBUTE.ATTR_TYPE, AttributeType.CHECKBOX.name()); + this.params.add(Domain.CONFIGURATION_ATTRIBUTE.ATTR_RESOURCES, ""); + this.params.add(Domain.CONFIGURATION_ATTRIBUTE.ATTR_VALIDATOR, ""); + this.params.add(Domain.CONFIGURATION_ATTRIBUTE.ATTR_DEPENDENCIES, ""); + this.params.add(Domain.CONFIGURATION_ATTRIBUTE.ATTR_DEFAULT_VALUE, "true"); + + final ConfigurationAttribute create = this.configurationAttributeController.create( + this.params, + 1L, + this.mockRequest); + + assertNotNull(create); + assertNotNull(create.id); + assertEquals("testAttribute", create.name); + assertEquals("true", create.defaultValue); + + final ConfigurationAttribute savePut = this.configurationAttributeController.savePut(new ConfigurationAttribute( + create.id, + null, null, null, null, null, null, + "false")); + + assertNotNull(savePut); + assertNotNull(savePut.id); + assertEquals("testAttribute", savePut.name); + assertEquals("false", savePut.defaultValue); + + } + + @Test + @Order(6) + public void test6_NoDeletionSupport() { + + try { + this.configurationAttributeController.hardDeleteAll( + Arrays.asList("1,2,3"), + false, + null, + 1L); + fail("Error expected here"); + } catch (final Exception e) { + assertEquals( + "No bulk action support for: BulkAction [type=HARD_DELETE, sourceType=CONFIGURATION_ATTRIBUTE, sources=[]]", + e.getMessage()); + } + + try { + this.configurationAttributeController.hardDelete( + "1", + false, + null); + fail("Error expected here"); + } catch (final Exception e) { + assertEquals( + "No bulk action support for: BulkAction [type=HARD_DELETE, sourceType=CONFIGURATION_ATTRIBUTE, sources=[EntityName [entityType=CONFIGURATION_ATTRIBUTE, modelId=1, name=hashedAdminPassword]]]", + e.getMessage()); + } + + } + +}