From dab66ef85a3fa96163f67896bc3c9e4dcf586fa9 Mon Sep 17 00:00:00 2001 From: alexeiak Date: Tue, 16 Aug 2022 13:34:20 +0300 Subject: [PATCH 1/9] test: [#100] add tests for all TODO in web/TypoController --- .../typoreporter/web/TypoControllerIT.java | 144 ++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 src/test/java/io/hexlet/typoreporter/web/TypoControllerIT.java diff --git a/src/test/java/io/hexlet/typoreporter/web/TypoControllerIT.java b/src/test/java/io/hexlet/typoreporter/web/TypoControllerIT.java new file mode 100644 index 00000000..afe9c0dc --- /dev/null +++ b/src/test/java/io/hexlet/typoreporter/web/TypoControllerIT.java @@ -0,0 +1,144 @@ +package io.hexlet.typoreporter.web; + +import com.github.database.rider.core.api.configuration.DBUnit; +import com.github.database.rider.core.api.dataset.DataSet; +import com.github.database.rider.spring.api.DBRider; +import io.hexlet.typoreporter.domain.typo.Typo; +import io.hexlet.typoreporter.domain.typo.TypoStatus; +import io.hexlet.typoreporter.repository.TypoRepository; +import io.hexlet.typoreporter.test.DBUnitEnumPostgres; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import static com.github.database.rider.core.api.configuration.Orthography.LOWERCASE; +import static io.hexlet.typoreporter.domain.typo.TypoEvent.CANCEL; +import static io.hexlet.typoreporter.test.Constraints.POSTGRES_IMAGE; + +import static io.hexlet.typoreporter.web.Routers.ID_PATH; +import static io.hexlet.typoreporter.web.Routers.Typo.TYPOS; +import static io.hexlet.typoreporter.web.Routers.Typo.TYPO_STATUS; +import static io.hexlet.typoreporter.web.Routers.Workspace.WORKSPACE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; + +@Testcontainers +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +@DBRider +@DBUnit(caseInsensitiveStrategy = LOWERCASE, dataTypeFactoryClass = DBUnitEnumPostgres.class, cacheConnection = false) +@DataSet(value = {"workspaces.yml", "typos.yml"}) +public class TypoControllerIT { + + @Container + static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer<>(POSTGRES_IMAGE) + .withPassword("inmemory") + .withUsername("inmemory"); + + @Autowired + private TypoRepository typoRepository; + + @Autowired + private MockMvc mockMvc; + + @DynamicPropertySource + static void datasourceProperties(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl); + registry.add("spring.datasource.password", postgreSQLContainer::getPassword); + registry.add("spring.datasource.username", postgreSQLContainer::getUsername); + } + + @ParameterizedTest + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypoIdsExist") + void updateTypoStatusIsSuccessful(final Long typoId) throws Exception { + Typo typo = typoRepository.findById(typoId).orElse(null); + String wksName = typo.getWorkspace().getName(); + + typo.setTypoStatus(TypoStatus.IN_PROGRESS); + TypoStatus previousStatus = typo.getTypoStatus(); // IN_PROGRESS + + mockMvc.perform(patch(TYPOS + ID_PATH + TYPO_STATUS, typoId) + .param("wksName", wksName) + .param("event", CANCEL.name()) + .with(csrf())) + .andExpect(redirectedUrl(WORKSPACE + "/" + wksName + TYPOS)); + assertThat(previousStatus).isNotEqualTo(typo.getTypoStatus()); + } + + @ParameterizedTest + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypoIdsExist") + void updateTypoStatusWithEventIsEmpty(final Long typoId) throws Exception { + Typo typo = typoRepository.findById(typoId).orElse(null); + String wksName = typo.getWorkspace().getName(); + + typo.setTypoStatus(TypoStatus.IN_PROGRESS); + TypoStatus previousStatus = typo.getTypoStatus(); // IN_PROGRESS + + mockMvc.perform(patch(TYPOS + ID_PATH + TYPO_STATUS, typoId) + .param("wksName", wksName) + .param("event", "") + .with(csrf())) + .andExpect(redirectedUrl(WORKSPACE + "/" + wksName + TYPOS)); + assertThat(previousStatus).isEqualTo(typo.getTypoStatus()); + } + + @ParameterizedTest + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") + void updateTypoStatusWithUpdatedTypoIsEmpty(final String wksName) throws Exception { + Long NOT_EXIST_TYPO_ID = 11L; + mockMvc.perform(patch(TYPOS + ID_PATH + TYPO_STATUS, NOT_EXIST_TYPO_ID) + .param("wksName", wksName) + .param("event", CANCEL.name()) + .with(csrf())) + .andExpect(redirectedUrl(WORKSPACE + "/" + wksName + TYPOS)); + } + + + @ParameterizedTest + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypoIdsExist") + void deleteTypoByIdIsSuccessful(final Long typoId) throws Exception { + Typo typo = typoRepository.findById(typoId).orElse(null); + String wksName = typo.getWorkspace().getName(); + + assertThat(typoRepository.existsById(typoId)).isTrue(); + + mockMvc.perform(delete(TYPOS + ID_PATH, typoId) + .param("wksName", wksName) + .with(csrf())) + .andExpect(redirectedUrl(WORKSPACE + "/" + wksName + TYPOS)); + + assertThat(typoRepository.existsById(typoId)).isFalse(); + } + + @ParameterizedTest + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypoIdsExist") + void deleteTypoByIdWithEmptyAndNotExistWksName(final Long typoId) throws Exception { + assertThat(typoRepository.existsById(typoId)).isTrue(); + + String emptyWksName = ""; + mockMvc.perform(delete(TYPOS + ID_PATH, typoId) + .param("wksName", emptyWksName) + .with(csrf())) + .andExpect(redirectedUrl("/")); + + String notExistsWksName = "noExistsWks"; + mockMvc.perform(delete(TYPOS + ID_PATH, typoId) + .param("wksName", notExistsWksName) + .with(csrf())) + .andExpect(redirectedUrl("/")); + + assertThat(typoRepository.existsById(typoId)).isTrue(); + } +} From 8058d38ce3e318e775bedbec3ab47c209279d610 Mon Sep 17 00:00:00 2001 From: alexeiak Date: Tue, 9 Aug 2022 13:56:04 +0300 Subject: [PATCH 2/9] test: [#100] add tests for all TODO in repository/WorkspaceRepository --- .../repository/WorkspaceRepository.java | 3 -- .../repository/WorkspaceRepositoryIT.java | 34 +++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/hexlet/typoreporter/repository/WorkspaceRepository.java b/src/main/java/io/hexlet/typoreporter/repository/WorkspaceRepository.java index 7ca6f654..757a60ba 100644 --- a/src/main/java/io/hexlet/typoreporter/repository/WorkspaceRepository.java +++ b/src/main/java/io/hexlet/typoreporter/repository/WorkspaceRepository.java @@ -12,15 +12,12 @@ public interface WorkspaceRepository extends JpaRepository { Optional getWorkspaceByName(String name); - //TODO add tests Optional getSecuredWorkspaceByName(String name); boolean existsWorkspaceByName(String name); - //TODO add tests Integer deleteWorkspaceByName(String name); - //TODO add tests @Modifying @Query("update Workspace set apiAccessToken = :token where name = :wksName") Integer updateApiAccessTokenByWorkspaceName(String wksName, UUID token); diff --git a/src/test/java/io/hexlet/typoreporter/repository/WorkspaceRepositoryIT.java b/src/test/java/io/hexlet/typoreporter/repository/WorkspaceRepositoryIT.java index bd76b32d..465fdf16 100644 --- a/src/test/java/io/hexlet/typoreporter/repository/WorkspaceRepositoryIT.java +++ b/src/test/java/io/hexlet/typoreporter/repository/WorkspaceRepositoryIT.java @@ -5,6 +5,7 @@ import com.github.database.rider.spring.api.DBRider; import io.hexlet.typoreporter.config.audit.AuditConfiguration; import io.hexlet.typoreporter.domain.workspace.Workspace; +import io.hexlet.typoreporter.security.model.SecuredWorkspace; import io.hexlet.typoreporter.test.DBUnitEnumPostgres; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.*; @@ -17,6 +18,9 @@ import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.junit.jupiter.*; +import java.util.Optional; +import java.util.UUID; + import static com.github.database.rider.core.api.configuration.Orthography.LOWERCASE; import static io.hexlet.typoreporter.test.Constraints.POSTGRES_IMAGE; import static org.assertj.core.api.Assertions.assertThat; @@ -30,6 +34,7 @@ @DataSet(value = {"workspaces.yml", "typos.yml"}) @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) class WorkspaceRepositoryIT { + final Integer SUCCESSFUL_CODE = 1; @Container public static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer<>(POSTGRES_IMAGE) @@ -73,4 +78,33 @@ void existsWorkspaceByName(final String wksName) { void existsWorkspaceByNameNotExist(final String wksName) { assertThat(workspaceRepository.existsWorkspaceByName(wksName)).isFalse(); } + + @ParameterizedTest + @ValueSource(strings = "wks-test") + void deleteWorkspaceByNameIsSuccessful(final String wksName) { + assertThat(workspaceRepository.deleteWorkspaceByName(wksName)).isEqualTo(SUCCESSFUL_CODE); + assertThat(workspaceRepository.existsWorkspaceByName(wksName)).isFalse(); + } + + @ParameterizedTest + @ValueSource(strings = "wks-test") + void getSecuredWorkspaceByNameIsSuccessful(final String wksName) { + Optional securedWorkspace = workspaceRepository.getSecuredWorkspaceByName(wksName); + String name = securedWorkspace.map(SecuredWorkspace::getUsername).orElse(null); + + assertThat(name).isEqualTo("wks-test"); + assertThat(workspaceRepository.existsWorkspaceByName(wksName)).isTrue(); + } + + @ParameterizedTest + @ValueSource(strings = "wks-test") + void updateApiAccessTokenByWorkspaceNameIsSuccessful(final String wksName) { + final UUID newToken = UUID.randomUUID(); + assertThat(workspaceRepository.updateApiAccessTokenByWorkspaceName(wksName, newToken)).isEqualTo(SUCCESSFUL_CODE); + + String newUuid = workspaceRepository.getWorkspaceByName(wksName) + .map(Workspace::getApiAccessToken) + .map(Object::toString).orElse(null); + assertThat(newUuid).isEqualTo(newToken.toString()); + } } From a4cccaf029e0471db8c7fe99a22f952322adc1b7 Mon Sep 17 00:00:00 2001 From: alexeiak Date: Tue, 9 Aug 2022 21:44:54 +0300 Subject: [PATCH 3/9] test: [#100] add tests for all TODO in service/converter --- .../converter/TypoToTypoInfoConverter.java | 1 - .../converter/WorkspaceToWorkspaceInfo.java | 1 - .../TypoToTypoInfoConverterTest.java | 20 +++++++++++++++ .../WorkspaceToWorkspaceInfoTest.java | 22 ++++++++++++++++ .../test/asserts/TypoInfoAssert.java | 25 +++++++++++++++++++ 5 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 src/test/java/io/hexlet/typoreporter/service/converter/TypoToTypoInfoConverterTest.java create mode 100644 src/test/java/io/hexlet/typoreporter/service/converter/WorkspaceToWorkspaceInfoTest.java create mode 100644 src/test/java/io/hexlet/typoreporter/test/asserts/TypoInfoAssert.java diff --git a/src/main/java/io/hexlet/typoreporter/service/converter/TypoToTypoInfoConverter.java b/src/main/java/io/hexlet/typoreporter/service/converter/TypoToTypoInfoConverter.java index ea2fe1bf..13d90374 100644 --- a/src/main/java/io/hexlet/typoreporter/service/converter/TypoToTypoInfoConverter.java +++ b/src/main/java/io/hexlet/typoreporter/service/converter/TypoToTypoInfoConverter.java @@ -6,7 +6,6 @@ import org.springframework.core.convert.converter.Converter; import org.springframework.stereotype.Component; -//TODO add tests @Component public class TypoToTypoInfoConverter implements Converter { diff --git a/src/main/java/io/hexlet/typoreporter/service/converter/WorkspaceToWorkspaceInfo.java b/src/main/java/io/hexlet/typoreporter/service/converter/WorkspaceToWorkspaceInfo.java index aae28af5..6717ad77 100644 --- a/src/main/java/io/hexlet/typoreporter/service/converter/WorkspaceToWorkspaceInfo.java +++ b/src/main/java/io/hexlet/typoreporter/service/converter/WorkspaceToWorkspaceInfo.java @@ -6,7 +6,6 @@ import org.springframework.core.convert.converter.Converter; import org.springframework.stereotype.Component; -//TODO add tests @Component public class WorkspaceToWorkspaceInfo implements Converter { diff --git a/src/test/java/io/hexlet/typoreporter/service/converter/TypoToTypoInfoConverterTest.java b/src/test/java/io/hexlet/typoreporter/service/converter/TypoToTypoInfoConverterTest.java new file mode 100644 index 00000000..57c058b7 --- /dev/null +++ b/src/test/java/io/hexlet/typoreporter/service/converter/TypoToTypoInfoConverterTest.java @@ -0,0 +1,20 @@ +package io.hexlet.typoreporter.service.converter; + +import io.hexlet.typoreporter.domain.typo.Typo; +import io.hexlet.typoreporter.service.dto.typo.TypoInfo; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.core.convert.converter.Converter; + +import static io.hexlet.typoreporter.test.asserts.TypoInfoAssert.assertThat; + +public class TypoToTypoInfoConverterTest { + private final Converter converter = new TypoToTypoInfoConverter(); + + @ParameterizedTest + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypos") + void requestToTypoInfo(final Typo typo) { + final var typoInfo = converter.convert(typo); + assertThat(typoInfo).isEqualsToTypoInfo(typo); + } +} diff --git a/src/test/java/io/hexlet/typoreporter/service/converter/WorkspaceToWorkspaceInfoTest.java b/src/test/java/io/hexlet/typoreporter/service/converter/WorkspaceToWorkspaceInfoTest.java new file mode 100644 index 00000000..f227f5ee --- /dev/null +++ b/src/test/java/io/hexlet/typoreporter/service/converter/WorkspaceToWorkspaceInfoTest.java @@ -0,0 +1,22 @@ +package io.hexlet.typoreporter.service.converter; + +import io.hexlet.typoreporter.domain.workspace.Workspace; +import io.hexlet.typoreporter.service.dto.workspace.WorkspaceInfo; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.core.convert.converter.Converter; + +import static org.assertj.core.api.Assertions.assertThat; + +public class WorkspaceToWorkspaceInfoTest { + private final Converter converter = new WorkspaceToWorkspaceInfo(); + + @ParameterizedTest + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaces") + void requestWorkspaceToInfo(final Workspace workspace) { + final var workspaceInfo = converter.convert(workspace); + assertThat(workspaceInfo).usingRecursiveComparison() + .ignoringFields("createdBy", "createdDate", "createdDateAgo", "modifiedBy", "modifiedDate", "modifiedDateAgo") + .isEqualTo(workspace); + } +} diff --git a/src/test/java/io/hexlet/typoreporter/test/asserts/TypoInfoAssert.java b/src/test/java/io/hexlet/typoreporter/test/asserts/TypoInfoAssert.java new file mode 100644 index 00000000..f378afff --- /dev/null +++ b/src/test/java/io/hexlet/typoreporter/test/asserts/TypoInfoAssert.java @@ -0,0 +1,25 @@ +package io.hexlet.typoreporter.test.asserts; + +import io.hexlet.typoreporter.domain.typo.Typo; +import io.hexlet.typoreporter.service.dto.typo.TypoInfo; +import org.assertj.core.api.ObjectAssert; + +public class TypoInfoAssert extends ObjectAssert { + + public TypoInfoAssert(TypoInfo typoInfo) { + super(typoInfo); + } + + public static TypoInfoAssert assertThat(TypoInfo actual) { + return new TypoInfoAssert(actual); + } + + public TypoInfoAssert isEqualsToTypoInfo(Typo expected) { + isNotNull(); + assertThat(actual) + .usingRecursiveComparison() + .ignoringFields("typoStatusStr", "createdBy", "createdDateAgo", "createdDate", "modifiedBy", "modifiedDateAgo", "modifiedDate", "account") + .isEqualTo(expected); + return this; + } +} From 9736259cc59e562d225e34bb574703ae1bb56bb4 Mon Sep 17 00:00:00 2001 From: alexeiak Date: Wed, 10 Aug 2022 18:44:04 +0300 Subject: [PATCH 4/9] test: [#100] add tests for WorkspaceService. All TODOs in package /service have done. --- .../service/WorkspaceService.java | 1 - .../service/WorkspaceServiceIT.java | 84 ++++++++++++++++++- 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/hexlet/typoreporter/service/WorkspaceService.java b/src/main/java/io/hexlet/typoreporter/service/WorkspaceService.java index cf4dc0b4..10d0d0eb 100644 --- a/src/main/java/io/hexlet/typoreporter/service/WorkspaceService.java +++ b/src/main/java/io/hexlet/typoreporter/service/WorkspaceService.java @@ -13,7 +13,6 @@ import static java.util.Objects.requireNonNull; -//TODO add tests @Service @RequiredArgsConstructor public class WorkspaceService { diff --git a/src/test/java/io/hexlet/typoreporter/service/WorkspaceServiceIT.java b/src/test/java/io/hexlet/typoreporter/service/WorkspaceServiceIT.java index b1dd214d..6dd14869 100644 --- a/src/test/java/io/hexlet/typoreporter/service/WorkspaceServiceIT.java +++ b/src/test/java/io/hexlet/typoreporter/service/WorkspaceServiceIT.java @@ -3,8 +3,16 @@ import com.github.database.rider.core.api.configuration.DBUnit; import com.github.database.rider.core.api.dataset.DataSet; import com.github.database.rider.spring.api.DBRider; +import io.hexlet.typoreporter.domain.workspace.Workspace; import io.hexlet.typoreporter.repository.WorkspaceRepository; +import io.hexlet.typoreporter.service.dto.workspace.CreateWorkspace; +import io.hexlet.typoreporter.service.dto.workspace.WorkspaceInfo; import io.hexlet.typoreporter.test.DBUnitEnumPostgres; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.NullAndEmptySource; +import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.*; @@ -12,8 +20,15 @@ import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.junit.jupiter.*; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; + import static com.github.database.rider.core.api.configuration.Orthography.LOWERCASE; import static io.hexlet.typoreporter.test.Constraints.POSTGRES_IMAGE; +import static io.hexlet.typoreporter.test.factory.EntitiesFactory.WORKSPACE_101_NAME; +import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest @Testcontainers @@ -40,5 +55,72 @@ static void datasourceProperties(DynamicPropertyRegistry registry) { registry.add("spring.datasource.password", postgreSQLContainer::getPassword); registry.add("spring.datasource.username", postgreSQLContainer::getUsername); } - //TODO add tests + + @ParameterizedTest + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaces") + void getAllWorkspacesInfoIsSuccessful() { + WorkspaceInfo workspaceInfo = service.getAllWorkspacesInfo().stream() + .filter(wksInfo -> wksInfo.name().equals(WORKSPACE_101_NAME)) + .findFirst().orElse(null); + + assertThat(Objects.requireNonNull(workspaceInfo).createdDateAgo()).isNotEmpty(); + } + + @ParameterizedTest + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaces") + void getWorkspaceInfoByNameIsSuccessful() { + WorkspaceInfo workspaceInfo = service.getWorkspaceInfoByName(WORKSPACE_101_NAME).orElse(null); + assertThat(workspaceInfo != null).isTrue(); + } + + @ParameterizedTest + @ValueSource(strings = "wks-test") + void existsWorkspaceByNameIsSuccessful(final String wksName) { + assertThat(service.existsWorkspaceByName(wksName)).isTrue(); + } + + @Test + void createWorkspaceIsSuccessful() { + final var newWks = new CreateWorkspace("wks-name-1", "wks desc"); + WorkspaceInfo workspaceInfo = service.createWorkspace(newWks); + assertThat(workspaceInfo.name()).isNotEmpty(); + } + + @ParameterizedTest + @ValueSource(strings = "wks-test") + void updateWorkspaceIsSuccessful() { + final var newWks = new CreateWorkspace("wks-name-1", "wks desc"); + WorkspaceInfo workspaceInfo = service.updateWorkspace(newWks, "wks-test").orElse(null); + assertThat(Objects.requireNonNull(workspaceInfo).name()).isEqualTo(newWks.name()); + } + + @ParameterizedTest + @ValueSource(strings = "wks-test") + void deleteWorkspaceByNameIsSuccessful(final String wksName) { + final Integer successfulCode = 1; + assertThat(service.deleteWorkspaceByName(wksName)).isEqualTo(successfulCode); + assertThat(service.existsWorkspaceByName(wksName)).isFalse(); + } + + @ParameterizedTest + @ValueSource(strings = "wks-test") + void getWorkspaceApiAccessTokenByNameIsSuccessful(final String wksName) { + UUID uuid = service.getWorkspaceApiAccessTokenByName(wksName).orElse(null); + assertThat(uuid != null).isTrue(); + } + + @ParameterizedTest + @ValueSource(strings = "wks-test") + void regenerateWorkspaceApiAccessTokenByNameIsSuccessful(final String wksName) { + UUID previousUuid = service.getWorkspaceApiAccessTokenByName(wksName).orElse(null); + UUID newUuid = service.regenerateWorkspaceApiAccessTokenByName(wksName).orElse(null); + assertThat(previousUuid).isNotEqualTo(newUuid); + } + + @ParameterizedTest + @ValueSource(strings = "wks-test") + void getWorkspaceByNameIsSuccessful(final String wksName) { + Workspace workspace = service.getWorkspaceByName(wksName).orElse(null); + assertThat(workspace != null).isTrue(); + } } From 38892df1aa613880aeab2df8a3187d9ed4b03f88 Mon Sep 17 00:00:00 2001 From: alexeiak Date: Wed, 10 Aug 2022 19:23:30 +0300 Subject: [PATCH 5/9] test: [#100] update previous commit: add additional test Add test for createWorkspace() on exception situation --- .../typoreporter/service/WorkspaceServiceIT.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/test/java/io/hexlet/typoreporter/service/WorkspaceServiceIT.java b/src/test/java/io/hexlet/typoreporter/service/WorkspaceServiceIT.java index 6dd14869..0b46cc57 100644 --- a/src/test/java/io/hexlet/typoreporter/service/WorkspaceServiceIT.java +++ b/src/test/java/io/hexlet/typoreporter/service/WorkspaceServiceIT.java @@ -8,10 +8,10 @@ import io.hexlet.typoreporter.service.dto.workspace.CreateWorkspace; import io.hexlet.typoreporter.service.dto.workspace.WorkspaceInfo; import io.hexlet.typoreporter.test.DBUnitEnumPostgres; +import io.hexlet.typoreporter.web.exception.WorkspaceAlreadyExistException; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.params.provider.NullAndEmptySource; import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -20,15 +20,15 @@ import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.junit.jupiter.*; -import java.util.List; import java.util.Objects; -import java.util.Optional; import java.util.UUID; import static com.github.database.rider.core.api.configuration.Orthography.LOWERCASE; import static io.hexlet.typoreporter.test.Constraints.POSTGRES_IMAGE; import static io.hexlet.typoreporter.test.factory.EntitiesFactory.WORKSPACE_101_NAME; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; @SpringBootTest @Testcontainers @@ -86,6 +86,15 @@ void createWorkspaceIsSuccessful() { assertThat(workspaceInfo.name()).isNotEmpty(); } + @ParameterizedTest + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getCreateWorkspaces") + void createWorkspaceWithWorkspaceAlreadyExistException(CreateWorkspace createWks) { + Throwable thrown = assertThrows(WorkspaceAlreadyExistException.class, () -> { + service.createWorkspace(createWks); + }); + assertNotNull(thrown.getMessage()); + } + @ParameterizedTest @ValueSource(strings = "wks-test") void updateWorkspaceIsSuccessful() { From a8e0864367c3a78b98b5fdb43ef73e6dd9a25012 Mon Sep 17 00:00:00 2001 From: Maxim Skriov <77053797+acidmaksim@users.noreply.github.com> Date: Mon, 15 Aug 2022 19:36:11 +0300 Subject: [PATCH 6/9] Update README.md Add text about project --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b8671344..76d7ea18 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Hexlet Typo Reporter -This application created for receive the typo errors from a site. +A service to notify site owners of errors and typos. After integrating with the site, visitors are able to highlight an error or typo and report it to the administrator. The project works in Java. + +Tasks can be discussed in the #hexlet-volunteers channel in the [Slack community](https://slack-ru.hexlet.io/). ## Development From b4887aa2b88d85cbb607dd1dd03601fd7ac9efa2 Mon Sep 17 00:00:00 2001 From: alexeiak Date: Tue, 16 Aug 2022 22:00:19 +0300 Subject: [PATCH 7/9] test: [#100] add tests for all TODO in web/TypoController --- src/test/java/io/hexlet/typoreporter/web/TypoControllerIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/io/hexlet/typoreporter/web/TypoControllerIT.java b/src/test/java/io/hexlet/typoreporter/web/TypoControllerIT.java index afe9c0dc..4dbe453d 100644 --- a/src/test/java/io/hexlet/typoreporter/web/TypoControllerIT.java +++ b/src/test/java/io/hexlet/typoreporter/web/TypoControllerIT.java @@ -97,7 +97,7 @@ void updateTypoStatusWithEventIsEmpty(final Long typoId) throws Exception { @ParameterizedTest @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") void updateTypoStatusWithUpdatedTypoIsEmpty(final String wksName) throws Exception { - Long NOT_EXIST_TYPO_ID = 11L; + final Long NOT_EXIST_TYPO_ID = 11L; mockMvc.perform(patch(TYPOS + ID_PATH + TYPO_STATUS, NOT_EXIST_TYPO_ID) .param("wksName", wksName) .param("event", CANCEL.name()) From 9aa73a1547b8d9338c58ae9eb6c030aee292c855 Mon Sep 17 00:00:00 2001 From: alexeiak Date: Wed, 17 Aug 2022 00:37:48 +0300 Subject: [PATCH 8/9] test: [#100] add tests for all TODO in web/WorkspaceController, excluding conurency test for putWorkspaceUpdate() --- .../typoreporter/web/WorkspaceController.java | 2 +- .../web/WorkspaceControllerIT.java | 582 +++++++----------- 2 files changed, 233 insertions(+), 351 deletions(-) diff --git a/src/main/java/io/hexlet/typoreporter/web/WorkspaceController.java b/src/main/java/io/hexlet/typoreporter/web/WorkspaceController.java index b373d781..d1e8d6f1 100644 --- a/src/main/java/io/hexlet/typoreporter/web/WorkspaceController.java +++ b/src/main/java/io/hexlet/typoreporter/web/WorkspaceController.java @@ -28,7 +28,6 @@ import static org.springframework.data.domain.Sort.Direction.*; import static org.springframework.data.domain.Sort.Order.asc; -//TODO add tests @Slf4j @Controller @RequestMapping(WORKSPACE + WKS_NAME_PATH) @@ -129,6 +128,7 @@ public String getWorkspaceUpdatePage(Model model, @PathVariable String wksName) return WKS_UPDATE_TEMPLATE; } + //TODO add tests @PutMapping(UPDATE) public String putWorkspaceUpdate(Model model, @PathVariable String wksName, diff --git a/src/test/java/io/hexlet/typoreporter/web/WorkspaceControllerIT.java b/src/test/java/io/hexlet/typoreporter/web/WorkspaceControllerIT.java index 7215ba91..dfd96b65 100644 --- a/src/test/java/io/hexlet/typoreporter/web/WorkspaceControllerIT.java +++ b/src/test/java/io/hexlet/typoreporter/web/WorkspaceControllerIT.java @@ -1,355 +1,237 @@ package io.hexlet.typoreporter.web; -//@Testcontainers -//@SpringBootTest -//@AutoConfigureMockMvc -//@Transactional -//@DBRider -//@DBUnit(caseInsensitiveStrategy = LOWERCASE, dataTypeFactoryClass = DBUnitEnumPostgres.class, cacheConnection = false) -//@DataSet(value = {"workspaces.yml", "typos.yml"}) +import com.github.database.rider.core.api.configuration.DBUnit; +import com.github.database.rider.core.api.dataset.DataSet; +import com.github.database.rider.spring.api.DBRider; +import io.hexlet.typoreporter.domain.AbstractAuditingEntity; +import io.hexlet.typoreporter.domain.typo.Typo; +import io.hexlet.typoreporter.domain.workspace.Workspace; +import io.hexlet.typoreporter.repository.WorkspaceRepository; +import io.hexlet.typoreporter.service.WorkspaceService; +import io.hexlet.typoreporter.service.dto.workspace.CreateWorkspace; +import io.hexlet.typoreporter.test.DBUnitEnumPostgres; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.context.*; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.*; + +import java.time.LocalDateTime; +import java.util.Comparator; + +import static com.github.database.rider.core.api.configuration.Orthography.LOWERCASE; +import static io.hexlet.typoreporter.test.Constraints.POSTGRES_IMAGE; +import static io.hexlet.typoreporter.web.Routers.SETTINGS; +import static io.hexlet.typoreporter.web.Routers.UPDATE; +import static io.hexlet.typoreporter.web.Routers.Typo.TYPOS; +import static io.hexlet.typoreporter.web.Routers.Workspace.WKS_NAME_PATH; +import static io.hexlet.typoreporter.web.Routers.Workspace.WORKSPACE; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; +import static org.assertj.core.api.Assertions.assertThat; + +@Testcontainers +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +@DBRider +@DBUnit(caseInsensitiveStrategy = LOWERCASE, dataTypeFactoryClass = DBUnitEnumPostgres.class, cacheConnection = false) +@DataSet(value = {"workspaces.yml"}) class WorkspaceControllerIT { -// -// @Container -// static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer<>(POSTGRES_IMAGE) -// .withPassword("inmemory") -// .withUsername("inmemory"); -// -// @Autowired -// private SpringDataWebProperties dataWebProperties; -// -// private String pageParameter; -// -// private String sizeParameter; -// -// private int defaultPageSize; -// -// private int firstPageNumber; -// -// @Autowired -// private TypoRepository repository; -// -// @Autowired -// private ObjectMapper objectMapper; -// -// @Autowired -// private MockMvc mockMvc; -// -// @DynamicPropertySource -// static void datasourceProperties(DynamicPropertyRegistry registry) { -// registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl); -// registry.add("spring.datasource.password", postgreSQLContainer::getPassword); -// registry.add("spring.datasource.username", postgreSQLContainer::getUsername); -// } -// -// @BeforeEach -// void setUp() { -// pageParameter = dataWebProperties.getPageable().getPageParameter(); -// sizeParameter = dataWebProperties.getPageable().getSizeParameter(); -// defaultPageSize = dataWebProperties.getPageable().getDefaultPageSize(); -// firstPageNumber = dataWebProperties.getPageable().isOneIndexedParameters() ? 1 : 0; -// } -// -// @ParameterizedTest -// @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypoReport") -// void addTypoReport(final TypoReport typoReport) throws Exception { -// final var content = mockMvc -// .perform(post(API_TYPOS) -// .content(objectMapper.writeValueAsString(typoReport)) -// .contentType(APPLICATION_JSON) -// ) -// .andDo(print()) -// .andExpect(status().isCreated()) -// .andExpect(content().contentType(APPLICATION_JSON)) -// .andExpect(header().exists("Location")) -// .andReturn().getResponse().getContentAsString(); -// final var reportedTypo = objectMapper.readValue(content, ReportedTypo.class); -// -// ReportedTypoAssert.assertThat(reportedTypo).isEqualsToTypoReport(typoReport); -// Assertions.assertThat(reportedTypo.createdDate()).isBeforeOrEqualTo(now()); -// Assertions.assertThat(repository.existsById(reportedTypo.id())).isTrue(); -// } -// -// @Test -// void addTypoReportWithPageUrlBlank() throws Exception { -// final var typoJson = """ -// { -// "pageUrl": "", -// "reporterName": "reporterName", -// "textTypo": "textTypo" -// } -// """; -// -// mockMvc.perform(post(API_TYPOS) -// .content(typoJson) -// .contentType(APPLICATION_JSON)) -// .andExpect(status().isBadRequest()) -// .andExpect(content().contentType(APPLICATION_PROBLEM_JSON)) -// .andExpect(jsonPath("$.title").value("Constraint Violation")) -// .andExpect(jsonPath("$.violations").isArray()) -// .andExpect(jsonPath("$.violations", hasSize(1))) -// .andExpect(jsonPath("$.violations[*].field", hasItem("pageUrl"))) -// .andExpect(jsonPath("$.violations[*].message", hasItem("must not be blank"))); -// } -// -// @Test -// void addTypoReportWithPageUrlNull() throws Exception { -// final var typoJson = """ -// { -// "reporterName": "reporterName", -// "textTypo": "textTypo" -// } -// """; -// -// mockMvc.perform(post(API_TYPOS) -// .content(typoJson) -// .contentType(APPLICATION_JSON)) -// .andExpect(status().isBadRequest()) -// .andExpect(content().contentType(APPLICATION_PROBLEM_JSON)) -// .andExpect(jsonPath("$.title").value("Constraint Violation")) -// .andExpect(jsonPath("$.violations").isArray()) -// .andExpect(jsonPath("$.violations", hasSize(2))) -// .andExpect(jsonPath("$.violations[*].field", hasItem("pageUrl"))) -// .andExpect(jsonPath("$.violations[*].message", hasItem("must not be null"))) -// .andExpect(jsonPath("$.violations[*].message", hasItem("must not be blank"))); -// } -// -// @Test -// void addTypoReportWithPageUrlNotValid() throws Exception { -// final var typoJson = """ -// { -// "pageUrl": "not valid", -// "reporterName": "reporterName", -// "textTypo": "textTypo" -// } -// """; -// -// mockMvc.perform(post(API_TYPOS) -// .content(typoJson) -// .contentType(APPLICATION_JSON)) -// .andExpect(status().isBadRequest()) -// .andExpect(content().contentType(APPLICATION_PROBLEM_JSON)) -// .andExpect(jsonPath("$.title").value("Constraint Violation")) -// .andExpect(jsonPath("$.violations").isArray()) -// .andExpect(jsonPath("$.violations", hasSize(1))) -// .andExpect(jsonPath("$.violations[*].field", hasItem("pageUrl"))) -// .andExpect(jsonPath("$.violations[*].message", hasItem("must be a valid URL"))); -// } -// -// @Test -// void getPageTypoDefault() throws Exception { -// final var totalSize = repository.count(); -// mockMvc.perform(get(API_TYPOS)) -// .andDo(print()) -// .andExpect(status().isOk()) -// .andExpect(content().contentType(APPLICATION_JSON)) -// .andExpect(jsonPath("$.totalPages").value(totalSize / defaultPageSize + 1)) -// .andExpect(jsonPath("$.totalElements").value(totalSize)) -// .andExpect(jsonPath("$.size").value(defaultPageSize)) -// .andExpect(jsonPath("$.number").value(firstPageNumber)) -// .andExpect(jsonPath("$.numberOfElements").value(totalSize % defaultPageSize)); -// } -// -// @Test -// void getPageTypo() throws Exception { -// final var totalSize = repository.count(); -// final var pageSize = 3; -// final var page = 1; -// mockMvc.perform(get(API_TYPOS).param(sizeParameter, pageSize + "").param(pageParameter, page + "")) -// .andDo(print()) -// .andExpect(status().isOk()) -// .andExpect(content().contentType(APPLICATION_JSON)) -// .andExpect(jsonPath("$.totalPages").value(totalSize / pageSize + 1)) -// .andExpect(jsonPath("$.totalElements").value(totalSize)) -// .andExpect(jsonPath("$.size").value(pageSize)) -// .andExpect(jsonPath("$.number").value(page)) -// .andExpect(jsonPath("$.numberOfElements").value(pageSize)); -// } -// -// @ParameterizedTest -// @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypoIdsExist") -// void getTypoById(final Long id) throws Exception { -// mockMvc.perform(get(API_TYPOS + ID_PATH, id)) -// .andDo(print()) -// .andExpect(status().isOk()) -// .andExpect(content().contentType(APPLICATION_JSON)) -// .andExpect(jsonPath("$.id").value(id)); -// } -// -// @ParameterizedTest -// @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypoIdsNotExist") -// void getTypoByIdNoFound(final Long id) throws Exception { -// Assertions.assertThat(repository.existsById(id)).isFalse(); -// mockMvc.perform(get(API_TYPOS + ID_PATH, id)) -// .andDo(print()) -// .andExpect(status().isNotFound()) -// .andExpect(content().contentType(APPLICATION_PROBLEM_JSON)); -// } -// -// @ParameterizedTest -// @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypoIdsExist") -// void patchTypoReporterComment(final Long id) throws Exception { -// final var typo = repository.findById(id).orElseThrow(); -// final var newComment = typo.getReporterComment() + " <- new comment"; -// final var body = format("'{' \"reporterComment\" : \"{0}\" '}'", newComment); -// mockMvc.perform(patch(API_TYPOS + ID_PATH, id) -// .content(body) -// .contentType(APPLICATION_JSON)) -// .andDo(print()) -// .andExpect(status().isOk()) -// .andExpect(content().contentType(APPLICATION_JSON)) -// .andExpect(jsonPath("$.id").value(id)) -// .andExpect(jsonPath("$.reporterComment").value(newComment)); -// } -// -// @ParameterizedTest -// @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypoIdsExist") -// void patchTypoWithEmptyBody(final Long id) throws Exception { -// final var typo = repository.findById(id).orElseThrow(); -// final var body = "{}"; -// mockMvc.perform(patch(API_TYPOS + ID_PATH, typo.getId()) -// .content(body) -// .contentType(APPLICATION_JSON)) -// .andDo(print()) -// .andExpect(status().isOk()) -// .andExpect(content().contentType(APPLICATION_JSON)) -// .andExpect(jsonPath("$.id").value(id)) -// .andExpect(jsonPath("$.reporterComment").value(nullValue())); -// } -// -// @ParameterizedTest -// @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypoIdsExist") -// void patchTypoReporterCommentNull(final Long id) throws Exception { -// final var typo = repository.findById(id).orElseThrow(); -// final var body = "{ \"reporterComment\" : null }"; -// mockMvc.perform(patch(API_TYPOS + ID_PATH, id) -// .content(body) -// .contentType(APPLICATION_JSON)) -// .andDo(print()) -// .andExpect(status().isOk()) -// .andExpect(content().contentType(APPLICATION_JSON)) -// .andExpect(jsonPath("$.id").value(id)) -// .andExpect(jsonPath("$.reporterComment").value(nullValue())); -// } -// -// -// @ParameterizedTest -// @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypoIdsExist") -// void patchTypoReporterCommentEmptyNotValid(final Long id) throws Exception { -// final var body = "{ \"reporterComment\" : \"\" }"; -// mockMvc.perform(patch(API_TYPOS + ID_PATH, id) -// .content(body) -// .contentType(APPLICATION_JSON)) -// .andDo(print()) -// .andExpect(status().isBadRequest()) -// .andExpect(content().contentType(APPLICATION_PROBLEM_JSON)) -// .andExpect(jsonPath("$.title").value("Constraint Violation")) -// .andExpect(jsonPath("$.violations").isArray()) -// .andExpect(jsonPath("$.violations", hasSize(2))) -// .andExpect(jsonPath("$.violations[*].field", hasItem("reporterComment"))) -// .andExpect(jsonPath("$.violations[*].message", hasItem("Reporter comment must be null"))) -// .andExpect(jsonPath("$.violations[*].message", hasItem("Reporter comment must not be blank"))); -// } -// -// @ParameterizedTest -// @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypoIdsExist") -// void patchTypoReporterCommentBlankNotValid(final Long id) throws Exception { -// final var body = "{ \"reporterComment\" : \" \" }"; -// mockMvc.perform(patch(API_TYPOS + ID_PATH, id) -// .content(body) -// .contentType(APPLICATION_JSON)) -// .andDo(print()) -// .andExpect(status().isBadRequest()) -// .andExpect(content().contentType(APPLICATION_PROBLEM_JSON)) -// .andExpect(jsonPath("$.title").value("Constraint Violation")) -// .andExpect(jsonPath("$.violations").isArray()) -// .andExpect(jsonPath("$.violations", hasSize(2))) -// .andExpect(jsonPath("$.violations[*].field", hasItem("reporterComment"))) -// .andExpect(jsonPath("$.violations[*].message", hasItem("Reporter comment must be null"))) -// .andExpect(jsonPath("$.violations[*].message", hasItem("Reporter comment must not be blank"))); -// } -// -// -// @ParameterizedTest -// @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypoIdsExist") -// void patchTypoEventResolveToResolved(final Long id) throws Exception { -// repository.findById(id) -// .map(t -> t.setTypoStatus(t.getTypoStatus().next(OPEN))) -// .map(repository::save) -// .orElseThrow(); -// final var updateTypo = new UpdateTypoEvent(id, RESOLVE); -// mockMvc.perform(patch(API_TYPOS + Typo.ID_PATH_TYPO_STATUS, id) -// .content(objectMapper.writeValueAsString(updateTypo)) -// .contentType(APPLICATION_JSON)) -// .andDo(print()) -// .andExpect(status().isOk()) -// .andExpect(content().contentType(APPLICATION_JSON)) -// .andExpect(jsonPath("$.id").value(id)) -// .andExpect(jsonPath("$.typoStatus", is(RESOLVED + ""))); -// } -// -// -// @ParameterizedTest -// @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypoIdsExist") -// void patchTypoEventOpenToInProgress(final Long id) throws Exception { -// final var patchTypo = new UpdateTypoEvent(id, OPEN); -// mockMvc.perform(patch(API_TYPOS + Typo.ID_PATH_TYPO_STATUS, id) -// .content(objectMapper.writeValueAsString(patchTypo)) -// .contentType(APPLICATION_JSON)) -// .andDo(print()) -// .andExpect(status().isOk()) -// .andExpect(content().contentType(APPLICATION_JSON)) -// .andExpect(jsonPath("$.id").value(id)) -// .andExpect(jsonPath("$.typoStatus", is(IN_PROGRESS + ""))); -// } -// -// -// @ParameterizedTest -// @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypoIdsExist") -// void patchTypoEventCancelToCanceled(final Long id) throws Exception { -// final var patchTypo = new UpdateTypoEvent(id, CANCEL); -// mockMvc.perform(patch(API_TYPOS + Typo.ID_PATH_TYPO_STATUS, id) -// .content(objectMapper.writeValueAsString(patchTypo)) -// .contentType(APPLICATION_JSON)) -// .andDo(print()) -// .andExpect(status().isOk()) -// .andExpect(content().contentType(APPLICATION_JSON)) -// .andExpect(jsonPath("$.id").value(id)) -// .andExpect(jsonPath("$.typoStatus", is(CANCELED + ""))); -// } -// -// -// @ParameterizedTest -// @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypoIdsExist") -// void patchTypoEventResolveNotValid(final Long id) throws Exception { -// final var patchTypo = new UpdateTypoEvent(id, RESOLVE); -// mockMvc.perform(patch(API_TYPOS + Typo.ID_PATH_TYPO_STATUS, id) -// .content(objectMapper.writeValueAsString(patchTypo)) -// .contentType(APPLICATION_JSON)) -// .andDo(print()) -// .andExpect(status().isBadRequest()) -// .andExpect(content().contentType(APPLICATION_PROBLEM_JSON)); -// } -// -// @ParameterizedTest -// @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypoIdsExist") -// void deleteTypoById(final Long id) throws Exception { -// Assertions.assertThat(repository.existsById(id)).isTrue(); -// mockMvc.perform(delete(API_TYPOS + ID_PATH, id)) -// .andDo(print()) -// .andExpect(status().isOk()); -// Assertions.assertThat(repository.existsById(id)).isFalse(); -// } -// -// @ParameterizedTest -// @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getTypoIdsNotExist") -// void deleteTypoByIdNotFound(final Long id) throws Exception { -// Assertions.assertThat(repository.existsById(id)).isFalse(); -// mockMvc.perform(delete(API_TYPOS + ID_PATH, id)) -// .andDo(print()) -// .andExpect(status().isNotFound()) -// .andExpect(content().contentType(APPLICATION_PROBLEM_JSON)); -// Assertions.assertThat(repository.existsById(id)).isFalse(); -// } -} + @Container + static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer<>(POSTGRES_IMAGE) + .withPassword("inmemory") + .withUsername("inmemory"); + + @DynamicPropertySource + static void datasourceProperties(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl); + registry.add("spring.datasource.password", postgreSQLContainer::getPassword); + registry.add("spring.datasource.username", postgreSQLContainer::getUsername); + } + + @Autowired + private WorkspaceRepository repository; + + @Autowired + private WorkspaceService service; + + @Autowired + private MockMvc mockMvc; + + @ParameterizedTest + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") + void getWorkspaceInfoPageIsSuccessful(final String wksName) throws Exception { + Workspace workspace = repository.getWorkspaceByName(wksName).orElse(null); + + MockHttpServletResponse response = mockMvc.perform(get(WORKSPACE + WKS_NAME_PATH, wksName)) + .andExpect(model().attributeExists("wksInfo", "wksName")) + .andReturn().getResponse(); + assertThat(response.getContentAsString()).contains(wksName, workspace.getCreatedBy()); + } + + @Test + void getWorkspaceInfoPageWithoutWks() throws Exception { + mockMvc.perform(get(WORKSPACE + WKS_NAME_PATH, "notExistsWksName")) + .andExpect(redirectedUrl("/")); + } + + + @ParameterizedTest + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") + void getWorkspaceSettingsPageIsSuccessful(final String wksName) throws Exception { + Workspace workspace = repository.getWorkspaceByName(wksName).orElse(null); + + MockHttpServletResponse response = mockMvc.perform(get(WORKSPACE + WKS_NAME_PATH + SETTINGS, wksName)) + .andExpect(model().attributeExists("wksToken")) + .andReturn().getResponse(); + assertThat(response.getContentAsString()).contains(workspace.getApiAccessToken().toString()); + } + + @Test + void getWorkspaceSettingsPageWithoutWks() throws Exception { + mockMvc.perform(get(WORKSPACE + WKS_NAME_PATH + SETTINGS, "notExistsWksName")) + .andExpect(redirectedUrl("/")); + } + + + @ParameterizedTest + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") + void getWorkspaceTyposPageIsSuccessful(final String wksName) throws Exception { + Workspace workspace = repository.getWorkspaceByName(wksName).orElse(null); + + MockHttpServletResponse response = mockMvc.perform(get(WORKSPACE + WKS_NAME_PATH + TYPOS, wksName)) + .andExpect(model().attributeExists("wksInfo", "wksName", "typoPage", "availableSizes", "sortProp", "sortDir", "DESC", "ASC")) + .andReturn().getResponse(); + + Typo typo = workspace.getTypos().stream() + .sorted(Comparator.comparing(AbstractAuditingEntity::getCreatedDate)) + .findFirst().orElse(null); + + if (typo != null) { + assertThat(response.getContentAsString()).contains( + typo.getPageUrl(), typo.getReporterName(), typo.getModifiedBy() + ); + } + } + + @Test + void getWorkspaceSettingsPageWithoutWksInfo() throws Exception { + mockMvc.perform(get(WORKSPACE + WKS_NAME_PATH + TYPOS, "notExistsWksName")) + .andExpect(redirectedUrl("/")); + } + + + @ParameterizedTest + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") + void getWorkspaceUpdatePageIsSuccessful(final String wksName) throws Exception { + Workspace workspace = repository.getWorkspaceByName(wksName).orElse(null); + MockHttpServletResponse response = mockMvc.perform(get(WORKSPACE + WKS_NAME_PATH + UPDATE, wksName)) + .andExpect(model().attributeExists("wksName", "formModified", "formModified")) + .andReturn().getResponse(); + assertThat(response.getContentAsString()).contains(workspace.getDescription()); + } + + @Test + void getWorkspaceUpdatePageWithoutWks() throws Exception { + mockMvc.perform(get(WORKSPACE + WKS_NAME_PATH + UPDATE, "notExistsWksName")) + .andExpect(redirectedUrl("/")); + } + + + @ParameterizedTest + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") + void putWorkspaceUpdateIsSuccessful(final String wksName) throws Exception { + Workspace workspace = repository.getWorkspaceByName(wksName).orElse(null); + String newWksName = "createWksName01"; + LocalDateTime previosModifiedDate = workspace.getModifiedDate(); + + mockMvc.perform(put(WORKSPACE + WKS_NAME_PATH + UPDATE, wksName) + .param("name", newWksName) + .param("description", "Wks description 01") + .with(csrf())) + .andExpect(redirectedUrl(WORKSPACE + "/" + newWksName)); + + LocalDateTime newModifiedDate = repository.getWorkspaceByName(newWksName).orElse(null).getModifiedDate(); + assertThat(previosModifiedDate).isNotEqualTo(newModifiedDate); + } + + @ParameterizedTest + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") + void putWorkspaceUpdateWithExistingWksUpdateName(final String wksName) throws Exception { + String newWksName = "createWksName01"; + String wksDescription = "Wks description"; + + LocalDateTime previosModifiedDate = repository.getWorkspaceByName(wksName).orElse(null).getModifiedDate(); + + service.createWorkspace(new CreateWorkspace(newWksName, wksDescription)); + assertThat(repository.existsWorkspaceByName(newWksName)).isTrue(); + + mockMvc.perform(put(WORKSPACE + WKS_NAME_PATH + UPDATE, wksName) + .param("name", newWksName) + .param("description", wksDescription) + .with(csrf())) + .andExpect(model().attributeExists("createWorkspace")); + + LocalDateTime newModifiedDate = repository.getWorkspaceByName(wksName).orElse(null).getModifiedDate(); + assertThat(previosModifiedDate).isEqualTo(newModifiedDate); + } + + //TODO tests for concurrency transactions in putWorkspaceUpdate() try-catch block + + + @ParameterizedTest + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") + void patchWorkspaceTokenIsSuccessful(final String wksName) throws Exception { + Workspace workspace = repository.getWorkspaceByName(wksName).orElse(null); + String previousWksToken = workspace.getApiAccessToken().toString(); + + MockHttpServletResponse response = mockMvc.perform(patch(WORKSPACE + WKS_NAME_PATH + "/token/regenerate", wksName) + .with(csrf())) + .andReturn().getResponse(); + + assertThat(previousWksToken).isEqualTo(String.valueOf(workspace.getApiAccessToken())); + assertThat(response.getRedirectedUrl()).isEqualTo(WORKSPACE + "/" + wksName + SETTINGS); + } + + @Test + void patchWorkspaceTokenWithoutWks() throws Exception { + mockMvc.perform(patch(WORKSPACE + WKS_NAME_PATH + "/token/regenerate", "notExistsWksName") + .with(csrf())) + .andExpect(redirectedUrl("/")); + } + + + @ParameterizedTest + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") + void deleteWorkspaceByNameIsSuccessful(final String wksName) throws Exception { + assertThat(repository.existsWorkspaceByName(wksName)).isTrue(); + + MockHttpServletResponse response = mockMvc.perform(delete(WORKSPACE + WKS_NAME_PATH, wksName) + .with(csrf())) + .andReturn().getResponse(); + + assertThat(response.getRedirectedUrl()).isEqualTo("/"); + assertThat(repository.existsWorkspaceByName(wksName)).isFalse(); + } + + @Test + void deleteWorkspaceByNameIsNotSuccessful() throws Exception { + mockMvc.perform(delete(WORKSPACE + WKS_NAME_PATH, "notExistsWksName").with(csrf())) + .andExpect(redirectedUrl("/")); + } +} From 5db60a50764b462ae0ffd2fafcecc827fdc6fc11 Mon Sep 17 00:00:00 2001 From: alexeiak Date: Thu, 18 Aug 2022 15:33:47 +0300 Subject: [PATCH 9/9] test: [#100] refactor some test classes: service/WorkspaceServiceIT, repository/WorkspaceRepositoryIT --- .../repository/WorkspaceRepositoryIT.java | 8 ++++---- .../service/WorkspaceServiceIT.java | 20 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/test/java/io/hexlet/typoreporter/repository/WorkspaceRepositoryIT.java b/src/test/java/io/hexlet/typoreporter/repository/WorkspaceRepositoryIT.java index 465fdf16..c63bd404 100644 --- a/src/test/java/io/hexlet/typoreporter/repository/WorkspaceRepositoryIT.java +++ b/src/test/java/io/hexlet/typoreporter/repository/WorkspaceRepositoryIT.java @@ -80,24 +80,24 @@ void existsWorkspaceByNameNotExist(final String wksName) { } @ParameterizedTest - @ValueSource(strings = "wks-test") + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") void deleteWorkspaceByNameIsSuccessful(final String wksName) { assertThat(workspaceRepository.deleteWorkspaceByName(wksName)).isEqualTo(SUCCESSFUL_CODE); assertThat(workspaceRepository.existsWorkspaceByName(wksName)).isFalse(); } @ParameterizedTest - @ValueSource(strings = "wks-test") + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") void getSecuredWorkspaceByNameIsSuccessful(final String wksName) { Optional securedWorkspace = workspaceRepository.getSecuredWorkspaceByName(wksName); String name = securedWorkspace.map(SecuredWorkspace::getUsername).orElse(null); - assertThat(name).isEqualTo("wks-test"); + assertThat(name).isEqualTo(wksName); assertThat(workspaceRepository.existsWorkspaceByName(wksName)).isTrue(); } @ParameterizedTest - @ValueSource(strings = "wks-test") + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") void updateApiAccessTokenByWorkspaceNameIsSuccessful(final String wksName) { final UUID newToken = UUID.randomUUID(); assertThat(workspaceRepository.updateApiAccessTokenByWorkspaceName(wksName, newToken)).isEqualTo(SUCCESSFUL_CODE); diff --git a/src/test/java/io/hexlet/typoreporter/service/WorkspaceServiceIT.java b/src/test/java/io/hexlet/typoreporter/service/WorkspaceServiceIT.java index 0b46cc57..f2402e90 100644 --- a/src/test/java/io/hexlet/typoreporter/service/WorkspaceServiceIT.java +++ b/src/test/java/io/hexlet/typoreporter/service/WorkspaceServiceIT.java @@ -67,14 +67,14 @@ void getAllWorkspacesInfoIsSuccessful() { } @ParameterizedTest - @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaces") - void getWorkspaceInfoByNameIsSuccessful() { - WorkspaceInfo workspaceInfo = service.getWorkspaceInfoByName(WORKSPACE_101_NAME).orElse(null); + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") + void getWorkspaceInfoByNameIsSuccessful(final String wksName) { + WorkspaceInfo workspaceInfo = service.getWorkspaceInfoByName(wksName).orElse(null); assertThat(workspaceInfo != null).isTrue(); } @ParameterizedTest - @ValueSource(strings = "wks-test") + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") void existsWorkspaceByNameIsSuccessful(final String wksName) { assertThat(service.existsWorkspaceByName(wksName)).isTrue(); } @@ -96,15 +96,15 @@ void createWorkspaceWithWorkspaceAlreadyExistException(CreateWorkspace createWks } @ParameterizedTest - @ValueSource(strings = "wks-test") - void updateWorkspaceIsSuccessful() { + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") + void updateWorkspaceIsSuccessful(final String wksName) { final var newWks = new CreateWorkspace("wks-name-1", "wks desc"); WorkspaceInfo workspaceInfo = service.updateWorkspace(newWks, "wks-test").orElse(null); assertThat(Objects.requireNonNull(workspaceInfo).name()).isEqualTo(newWks.name()); } @ParameterizedTest - @ValueSource(strings = "wks-test") + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") void deleteWorkspaceByNameIsSuccessful(final String wksName) { final Integer successfulCode = 1; assertThat(service.deleteWorkspaceByName(wksName)).isEqualTo(successfulCode); @@ -112,14 +112,14 @@ void deleteWorkspaceByNameIsSuccessful(final String wksName) { } @ParameterizedTest - @ValueSource(strings = "wks-test") + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") void getWorkspaceApiAccessTokenByNameIsSuccessful(final String wksName) { UUID uuid = service.getWorkspaceApiAccessTokenByName(wksName).orElse(null); assertThat(uuid != null).isTrue(); } @ParameterizedTest - @ValueSource(strings = "wks-test") + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") void regenerateWorkspaceApiAccessTokenByNameIsSuccessful(final String wksName) { UUID previousUuid = service.getWorkspaceApiAccessTokenByName(wksName).orElse(null); UUID newUuid = service.regenerateWorkspaceApiAccessTokenByName(wksName).orElse(null); @@ -127,7 +127,7 @@ void regenerateWorkspaceApiAccessTokenByNameIsSuccessful(final String wksName) { } @ParameterizedTest - @ValueSource(strings = "wks-test") + @MethodSource("io.hexlet.typoreporter.test.factory.EntitiesFactory#getWorkspaceNamesExist") void getWorkspaceByNameIsSuccessful(final String wksName) { Workspace workspace = service.getWorkspaceByName(wksName).orElse(null); assertThat(workspace != null).isTrue();