From 6661544dfbf28a6ead65b000f2e3e04f88888840 Mon Sep 17 00:00:00 2001 From: invictuzzzzz Date: Thu, 27 Jun 2024 12:00:38 +0200 Subject: [PATCH 01/21] fix bug, count always shows 0 --- .../user/service/UserSolutionServiceImp.java | 3 ++- .../user/controller/UserControllerTest.java | 23 +++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/itachallenge-user/src/main/java/com/itachallenge/user/service/UserSolutionServiceImp.java b/itachallenge-user/src/main/java/com/itachallenge/user/service/UserSolutionServiceImp.java index 09bd693e8..bc1b03608 100755 --- a/itachallenge-user/src/main/java/com/itachallenge/user/service/UserSolutionServiceImp.java +++ b/itachallenge-user/src/main/java/com/itachallenge/user/service/UserSolutionServiceImp.java @@ -41,7 +41,8 @@ public Mono> getChallengeById(String idUser, Strin .collectList() .map(userScoreDtos -> { SolutionUserDto solutionUserDto = new SolutionUserDto<>(); - solutionUserDto.setInfo(0, 1, 0, userScoreDtos.toArray(new UserScoreDto[0])); + int count = userScoreDtos.size(); + solutionUserDto.setInfo(0, 1, count, userScoreDtos.toArray(new UserScoreDto[0])); return solutionUserDto; }); } diff --git a/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java b/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java index 372c4da49..d765972f2 100755 --- a/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java +++ b/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java @@ -110,7 +110,7 @@ void getChallengeStatistics_URLToLong() { } @Test - void getSolutionsByUserIdChallengeIdLanguageId (){ + void getSolutionsByUserIdChallengeIdLanguageId() { String URI_TEST = "/solution/user/{idUser}/challenge/{idChallenge}/language/{idLanguage}"; @@ -121,12 +121,12 @@ void getSolutionsByUserIdChallengeIdLanguageId (){ UserScoreDto userScoreDto = new UserScoreDto(); SolutionUserDto expectedSolutionUserDto = new SolutionUserDto<>(); - expectedSolutionUserDto.setInfo(0,1,1, new UserScoreDto[]{userScoreDto}); + expectedSolutionUserDto.setInfo(0, 1, 1, new UserScoreDto[]{userScoreDto}); - when(userSolutionService.getChallengeById(any(),any(),any())).thenReturn(Mono.just(expectedSolutionUserDto)); + when(userSolutionService.getChallengeById(any(), any(), any())).thenReturn(Mono.just(expectedSolutionUserDto)); webTestClient.get() - .uri(CONTROLLER_URL + URI_TEST, userId,idLanguage,idChallenge) + .uri(CONTROLLER_URL + URI_TEST, userId, idLanguage, idChallenge) .exchange() .expectStatus().isOk() .expectBody(SolutionUserDto.class) @@ -253,6 +253,7 @@ void addSolutionIfValidSolutionThenSolutionAdded_test() { verify(userSolutionService).addSolution(userSolutionDto); }); } + @DisplayName("UserDocumentControllerTest - addSolution - return 400 BAD REQUEST and don't save if dto is invalid") @Test void addSolutionIfInvalidValuesThenBadRequest_test() { @@ -277,6 +278,7 @@ void addSolutionIfInvalidValuesThenBadRequest_test() { verifyNoInteractions(userSolutionService); } } + @DisplayName("UserDocumentControllerTest - addSolution - return 409 CONFLICT if Service returns UnmodifiableSolutionException") @Test void addSolutionServiceThrowsExceptionInternalServerError_test() { @@ -312,7 +314,20 @@ void getVersionTest() { .jsonPath("$.version").isEqualTo("1.0-SNAPSHOT"); } + @Test + public void testGetSolutionsByUserIdChallengeIdLanguageId() { + String userId = UUID.randomUUID().toString(); // Genera un UUID válido para userId + String challengeId = UUID.randomUUID().toString(); // Genera un UUID válido para challengeId + String languageId = UUID.randomUUID().toString(); // Genera un UUID válido para languageId + + webTestClient.get() + .uri("/itachallenge/api/v1/user/solution/user/{userId}/challenge/{challengeId}/language/{languageId}", userId, challengeId, languageId) + .exchange() + .expectStatus().isOk(); + } + } + From d4941bf18320315210ed155be8d8a925d390365b Mon Sep 17 00:00:00 2001 From: Dani Diaz Date: Thu, 27 Jun 2024 15:14:36 +0200 Subject: [PATCH 02/21] Delete itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java --- .../user/controller/UserControllerTest.java | 333 ------------------ 1 file changed, 333 deletions(-) delete mode 100755 itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java diff --git a/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java b/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java deleted file mode 100755 index d765972f2..000000000 --- a/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java +++ /dev/null @@ -1,333 +0,0 @@ -package com.itachallenge.user.controller; - -import com.itachallenge.user.document.UserSolutionDocument; -import com.itachallenge.user.dtos.*; -import com.itachallenge.user.exception.UnmodifiableSolutionException; -import com.itachallenge.user.dtos.*; -import com.itachallenge.user.service.IServiceChallengeStatistics; -import com.itachallenge.user.service.IUserSolutionService; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.core.env.Environment; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.test.web.reactive.server.WebTestClient; -import reactor.core.publisher.Mono; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.UUID; - -import static org.hamcrest.Matchers.equalTo; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; - - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@AutoConfigureWebTestClient -@ExtendWith(SpringExtension.class) -@ActiveProfiles("test") -class UserControllerTest { - @Autowired - private WebTestClient webTestClient; - - @Autowired - UserController userController; - - @Autowired - Environment env; - - private static final String CONTROLLER_URL = "/itachallenge/api/v1/user"; - - @MockBean - IUserSolutionService userSolutionService; - @MockBean - IServiceChallengeStatistics statisticsService; - - @BeforeEach - public void setUp() { - } - - @Test - void testHello() { - String URI_TEST = "/test"; - - webTestClient.get() - .uri(CONTROLLER_URL + URI_TEST) - .accept(MediaType.APPLICATION_JSON) - .exchange() - .expectStatus().isEqualTo(HttpStatus.OK) - .expectBody(String.class) - .value(String::toString, equalTo("Hello from ITA User!!!")); - } - - //TODO: This test needs mocking. Is calling actual service - /* @Test - void getChallengeStatistics() { - String URI_TEST = "/statistics?"; - - URI_TEST += queryCreation(10); - - List response = webTestClient.get() - .uri(CONTROLLER_URL + URI_TEST) - .accept(MediaType.APPLICATION_JSON) - .exchange() - .expectStatus().isEqualTo(HttpStatus.OK) - .expectHeader().contentType(MediaType.APPLICATION_JSON) - .expectBodyList(ChallengeStatisticsDto.class) - .returnResult().getResponseBody(); - - assertEquals(10, response.size()); - assertNotEquals(0, response.get(0).getPopularity()); - assertNotEquals(0, response.get(9).getPercentage()); - }*/ - - //TODO: This test needs mocking. Is calling actual service - @Test - void getChallengeStatistics_URLToLong() { - String URI_TEST = "/statistics?"; - - URI_TEST += queryCreation(100); - - webTestClient.get() - .uri(CONTROLLER_URL + URI_TEST) - .accept(MediaType.APPLICATION_JSON) - .exchange() - .expectStatus().isEqualTo(HttpStatus.URI_TOO_LONG); - } - - @Test - void getSolutionsByUserIdChallengeIdLanguageId() { - - String URI_TEST = "/solution/user/{idUser}/challenge/{idChallenge}/language/{idLanguage}"; - - final String VALID_MONGO_UUID = "c3a92f9d-5d10-4f76-8c0b-6d884c549b1c"; - String userId = VALID_MONGO_UUID; - String idLanguage = VALID_MONGO_UUID; - String idChallenge = VALID_MONGO_UUID; - - UserScoreDto userScoreDto = new UserScoreDto(); - SolutionUserDto expectedSolutionUserDto = new SolutionUserDto<>(); - expectedSolutionUserDto.setInfo(0, 1, 1, new UserScoreDto[]{userScoreDto}); - - when(userSolutionService.getChallengeById(any(), any(), any())).thenReturn(Mono.just(expectedSolutionUserDto)); - - webTestClient.get() - .uri(CONTROLLER_URL + URI_TEST, userId, idLanguage, idChallenge) - .exchange() - .expectStatus().isOk() - .expectBody(SolutionUserDto.class) - .value(dto -> { - assert dto != null; - assert dto.getCount() == 1; - assert dto.getResults() != null; - assert dto.getResults().length == 1; - }); - } - - - //TODO: This test needs mocking. Is calling actual service - @Test - void getChallengeStatistics_EmptyUUIDList() { - String URI_TEST = "/statistics"; - - webTestClient.get() - .uri(uriBuilder -> uriBuilder - .path(CONTROLLER_URL + URI_TEST) - .queryParam("", Collections.EMPTY_LIST) - .build()) - .accept(MediaType.APPLICATION_JSON) - .exchange() - .expectStatus().isEqualTo(HttpStatus.BAD_REQUEST) - .expectBody(ChallengeStatisticsDto.class); - } - - @Test - void testGetBookmarkCountByIdChallenge() { - final UUID VALID_MONGO_UUID = UUID.fromString("5c1a97e5-1cca-4144-9981-2de1fb73b178"); - String URI_TEST = "/bookmarks/{idChallenge}"; - Long testCount = 1L; - - when(statisticsService.getBookmarkCountByIdChallenge(VALID_MONGO_UUID)) - .thenReturn(Mono.just(testCount)); - - webTestClient.get() - .uri(CONTROLLER_URL + URI_TEST, VALID_MONGO_UUID) - .exchange() - .expectStatus().isOk() - .expectBody() - .jsonPath("$.bookmarked").isEqualTo(testCount.intValue()); - } - - /** - * Method to create a query string link "challenge=UUID&", repeat 'numberUUID' times. - * - * @param numberUUID Number of tiems that repeat. - * @return String with query - */ - private String queryCreation(int numberUUID) { - String URI_TEST = String.format("challenge=%s", UUID.randomUUID()); - - for (int i = 1; i < numberUUID; i++) URI_TEST += String.format("&challenge=%s", UUID.randomUUID()); - - return URI_TEST; - } - - @Test - void markOrAddBookmark() { - - BookmarkRequestDto bookmarkRequestDto = new BookmarkRequestDto(); - bookmarkRequestDto.setUuid_challenge("b860f3eb-ef9f-43bf-8c3c-9a5318d26a90"); - bookmarkRequestDto.setUuid_user("26cbe8eb-be68-4eb4-96a6-796168e80ec9"); - bookmarkRequestDto.setUuid_language("df99bae8-4f7f-4054-a957-37a12aa16364"); - bookmarkRequestDto.setBookmarked(true); - when(userSolutionService.markAsBookmarked( - bookmarkRequestDto.getUuid_challenge(), - bookmarkRequestDto.getUuid_language(), - bookmarkRequestDto.getUuid_user(), - bookmarkRequestDto.isBookmarked())) - .thenAnswer(invocation -> { - - UserSolutionDocument userSolutionDocument = new UserSolutionDocument(); - - return Mono.just(userSolutionDocument); - } - - ); - - Mono> responseMono = userController.markOrAddBookmark(bookmarkRequestDto); - - ResponseEntity responseEntity = responseMono.block(); - - assertNotNull(responseEntity); - - assertEquals(HttpStatus.OK, responseEntity.getStatusCode()); - - assertEquals(bookmarkRequestDto, responseEntity.getBody()); - } - - @DisplayName("UserDocumentControllerTest - addSolution - create and return a new document with status 200 OK") - @Test - void addSolutionIfValidSolutionThenSolutionAdded_test() { - String URI_TEST = "/solution"; - UserSolutionDto userSolutionDto = new UserSolutionDto(); - userSolutionDto.setUserId("550e8400-e29b-41d4-a716-446655440001"); - userSolutionDto.setChallengeId("550e8400-e29b-41d4-a716-446655440002"); - userSolutionDto.setLanguageId("550e8400-e29b-41d4-a716-446655440003"); - userSolutionDto.setSolutionText("This is a test solution"); - - UserSolutionScoreDto expectedResponse = new UserSolutionScoreDto(userSolutionDto.getUserId(), - userSolutionDto.getChallengeId(), userSolutionDto.getLanguageId(), - userSolutionDto.getSolutionText(), 13); - - when(userSolutionService.addSolution(userSolutionDto)) - .thenReturn(Mono.just(expectedResponse)); - - webTestClient.put() - .uri(CONTROLLER_URL + URI_TEST) - .contentType(MediaType.APPLICATION_JSON) - .bodyValue(userSolutionDto) - .exchange() - .expectStatus().isEqualTo(HttpStatus.OK) - .expectBody(UserSolutionScoreDto.class) - .value(dto -> { - assert dto != null; - assert dto.getUserId() != null; - assert dto.getChallengeId() != null; - assert dto.getLanguageId() != null; - assert dto.getScore() >= 0; - - verify(userSolutionService).addSolution(userSolutionDto); - }); - } - - @DisplayName("UserDocumentControllerTest - addSolution - return 400 BAD REQUEST and don't save if dto is invalid") - @Test - void addSolutionIfInvalidValuesThenBadRequest_test() { - String URI_TEST = "/solution"; - - List testCases = Arrays.asList( - new UserSolutionDto("invalid_uuid", "550e8400-e29b-41d4-a716-446655440002", "550e8400-e29b-41d4-a716-446655440003", null, "This is a test solution"), - new UserSolutionDto("550e8400-e29b-41d4-a716-446655440001", "invalid_uuid", "550e8400-e29b-41d4-a716-446655440003", null, "This is a test solution"), - new UserSolutionDto("550e8400-e29b-41d4-a716-446655440001", "550e8400-e29b-41d4-a716-446655440002", "invalid_uuid", null, "This is a test solution"), - new UserSolutionDto("550e8400-e29b-41d4-a716-446655440001", "550e8400-e29b-41d4-a716-446655440002", "550e8400-e29b-41d4-a716-446655440003", null, ""), - new UserSolutionDto() - ); - - for (UserSolutionDto testCase : testCases) { - webTestClient.put() - .uri(CONTROLLER_URL + URI_TEST) - .contentType(MediaType.APPLICATION_JSON) - .bodyValue(testCase) - .exchange() - .expectStatus().isBadRequest(); - - verifyNoInteractions(userSolutionService); - } - } - - @DisplayName("UserDocumentControllerTest - addSolution - return 409 CONFLICT if Service returns UnmodifiableSolutionException") - @Test - void addSolutionServiceThrowsExceptionInternalServerError_test() { - String URI_TEST = "/solution"; - UserSolutionDto userSolutionDto = new UserSolutionDto(); - userSolutionDto.setUserId("550e8400-e29b-41d4-a716-446655440001"); - userSolutionDto.setChallengeId("550e8400-e29b-41d4-a716-446655440002"); - userSolutionDto.setLanguageId("550e8400-e29b-41d4-a716-446655440003"); - userSolutionDto.setStatus("ENDED"); - userSolutionDto.setSolutionText("This is a test solution"); - - when(userSolutionService.addSolution(userSolutionDto)) - .thenReturn(Mono.error(new UnmodifiableSolutionException("Invalid challenge status: status was already ENDED"))); - - webTestClient.put() - .uri(CONTROLLER_URL + URI_TEST) - .contentType(MediaType.APPLICATION_JSON) - .bodyValue(userSolutionDto) - .exchange() - .expectStatus().isEqualTo(HttpStatus.CONFLICT); - } - - @Test - void getVersionTest() { - String expectedVersion = env.getProperty("spring.application.version"); // Obtiene la versión desde el archivo application-test.yml - - webTestClient.get() - .uri("/itachallenge/api/v1/user/version") - .exchange() - .expectStatus().isOk() - .expectBody() - .jsonPath("$.application_name").isEqualTo("itachallenge-user") - .jsonPath("$.version").isEqualTo("1.0-SNAPSHOT"); - } - - @Test - public void testGetSolutionsByUserIdChallengeIdLanguageId() { - String userId = UUID.randomUUID().toString(); // Genera un UUID válido para userId - String challengeId = UUID.randomUUID().toString(); // Genera un UUID válido para challengeId - String languageId = UUID.randomUUID().toString(); // Genera un UUID válido para languageId - - webTestClient.get() - .uri("/itachallenge/api/v1/user/solution/user/{userId}/challenge/{challengeId}/language/{languageId}", userId, challengeId, languageId) - .exchange() - .expectStatus().isOk(); - } - -} - - - - From e5fa2fd1812815962fc2f5b94cb92c9e144dcb9b Mon Sep 17 00:00:00 2001 From: invictuzzzzz Date: Sun, 30 Jun 2024 20:29:27 +0200 Subject: [PATCH 03/21] FEATURE#552 --- itachallenge-score/build.gradle | 6 ++ .../score/helper/CodeValidator.java | 33 +++++++ .../score/helper/DockerContainerHelper.java | 31 ++++++ .../score/docker/DockerIntegrationTest.java | 96 +++++++++++++++++++ 4 files changed, 166 insertions(+) create mode 100644 itachallenge-score/src/main/java/com/itachallenge/score/helper/CodeValidator.java create mode 100644 itachallenge-score/src/main/java/com/itachallenge/score/helper/DockerContainerHelper.java create mode 100644 itachallenge-score/src/test/java/com/itachallenge/score/docker/DockerIntegrationTest.java diff --git a/itachallenge-score/build.gradle b/itachallenge-score/build.gradle index f1398c318..6af107441 100755 --- a/itachallenge-score/build.gradle +++ b/itachallenge-score/build.gradle @@ -39,6 +39,11 @@ dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-consul-discovery:4.0.2' implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-bootstrap', version: '4.0.2' implementation 'org.springframework.boot:spring-boot-starter-actuator:3.0.6' + implementation 'org.testcontainers:testcontainers:1.17.6' + implementation 'org.apache.httpcomponents:httpclient:4.5.13' + implementation 'org.testcontainers:junit-jupiter:1.16.3' + implementation 'org.testcontainers:testcontainers:1.16.3' + // Borrado docker-java ya que no es necesario con la versión actual de testcontainers //testing testImplementation platform('org.junit:junit-bom:5.9.1') @@ -52,6 +57,7 @@ dependencies { testImplementation group: 'io.projectreactor', name: 'reactor-test', version: '3.1.0.RELEASE' testImplementation group: 'org.testcontainers', name: 'mongodb', version: '1.17.6' testImplementation group: 'org.testcontainers', name: 'junit-jupiter', version: '1.17.6' + } diff --git a/itachallenge-score/src/main/java/com/itachallenge/score/helper/CodeValidator.java b/itachallenge-score/src/main/java/com/itachallenge/score/helper/CodeValidator.java new file mode 100644 index 000000000..bdafb6cd1 --- /dev/null +++ b/itachallenge-score/src/main/java/com/itachallenge/score/helper/CodeValidator.java @@ -0,0 +1,33 @@ +package com.itachallenge.score.helper; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class CodeValidator { + + private static final String[] forbiddenLibraries = { + "java\\.lang\\.System", + "java\\.io\\.PrintStream", + "java\\.io\\.File", + "java\\.io\\.FileReader", + "java\\.io\\.FileWriter", + "java\\.io\\.BufferedReader", + "java\\.io\\.BufferedWriter", + "java\\.util\\.Scanner", + // se puede agregar más librerías aquí + }; + + public static boolean isLibraryImportAllowed(String code) { + for (String lib : forbiddenLibraries) { + String importPattern = "import\\s+" + lib + ";"; + Pattern pattern = Pattern.compile(importPattern); + Matcher matcher = pattern.matcher(code); + if (matcher.find()) { + return false; // Importación prohibida encontrada + } + } + return true; + } +} + + diff --git a/itachallenge-score/src/main/java/com/itachallenge/score/helper/DockerContainerHelper.java b/itachallenge-score/src/main/java/com/itachallenge/score/helper/DockerContainerHelper.java new file mode 100644 index 000000000..1a3e8ba24 --- /dev/null +++ b/itachallenge-score/src/main/java/com/itachallenge/score/helper/DockerContainerHelper.java @@ -0,0 +1,31 @@ +package com.itachallenge.score.helper; + +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.images.builder.Transferable; +import org.testcontainers.utility.DockerImageName; + +import java.io.IOException; + +public class DockerContainerHelper { + + public static GenericContainer createContainer(String image) { + GenericContainer container = new GenericContainer<>(DockerImageName.parse(image)); + container.start(); + return container; + } + + public static void stopContainer(GenericContainer container) { + if (container != null) { + container.stop(); + } + } + + public static void executeCommand(GenericContainer container, String... command) throws IOException, InterruptedException { + container.execInContainer(command); + } + + public static void copyFileToContainer(GenericContainer container, String content, String containerPath) { + container.copyFileToContainer(Transferable.of(content.getBytes()), containerPath); + } +} + diff --git a/itachallenge-score/src/test/java/com/itachallenge/score/docker/DockerIntegrationTest.java b/itachallenge-score/src/test/java/com/itachallenge/score/docker/DockerIntegrationTest.java new file mode 100644 index 000000000..68c6b123c --- /dev/null +++ b/itachallenge-score/src/test/java/com/itachallenge/score/docker/DockerIntegrationTest.java @@ -0,0 +1,96 @@ +package com.itachallenge.score.docker; + +import com.itachallenge.score.helper.CodeValidator; +import com.itachallenge.score.helper.DockerContainerHelper; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.images.builder.Transferable; + +import java.io.IOException; + +import static org.junit.Assert.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +public class DockerIntegrationTest { + + @Test + public void testJavaContainerSortNumbers() { + + String codeSort = "import java.util.Arrays;\n" + + "public class Main {\n" + + " public static void main(String[] args) {\n" + + " String numbers = \"3,1,4,1,5,9\";\n" + + " int[] numArray = Arrays.stream(numbers.split(\",\")).mapToInt(Integer::parseInt).toArray();\n" + + " Arrays.sort(numArray);\n" + + " System.out.println(Arrays.toString(numArray));\n" + + " }\n" + + "}"; + + GenericContainer containerJavaSort = DockerContainerHelper.createContainer("openjdk:11"); + + try { + DockerContainerHelper.copyFileToContainer(containerJavaSort, codeSort, "/app/Main.java"); + DockerContainerHelper.executeCommand(containerJavaSort, "javac", "/app/Main.java"); + String output = containerJavaSort.execInContainer("java", "-cp", "/app", "Main").getStdout().trim(); + + + assertTrue(output.contains("[1, 1, 3, 4, 5, 9]")); + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } finally { + DockerContainerHelper.stopContainer(containerJavaSort); + } + } + + @Test + public void testJavaContainerCompileError() { + + String codeError = "public class Main {\n" + + " public static void main(String[] args) {\n" + + " System.out.println(\"Esto no compila porque falta un paréntesis\";\n" + + " }\n" + + "}"; + + GenericContainer containerJavaError = DockerContainerHelper.createContainer("openjdk:11"); + + try { + DockerContainerHelper.copyFileToContainer(containerJavaError, codeError, "/app/Main.java"); + DockerContainerHelper.executeCommand(containerJavaError, "javac", "/app/Main.java"); + } catch (IOException | InterruptedException e) { + String errorMessage = e.getMessage(); + assertTrue(errorMessage.contains("error: ';' expected")); + } finally { + DockerContainerHelper.stopContainer(containerJavaError); + } + } + + @Test + public void testRestrictedLibraryImport() { + String code = "import java.lang.System;\n" + + "public class Main {\n" + + " public static void main(String[] args) {\n" + + " System.out.println(\"Hola! Estoy intentado importar System\");\n" + + " }\n" + + "}"; + + assertFalse(CodeValidator.isLibraryImportAllowed(code)); // Debería devolver false al intentar importar java.lang.System + + // Si el código no importa java.lang.System, entonces se intenta compilar + if (CodeValidator.isLibraryImportAllowed(code)) { + GenericContainer container = DockerContainerHelper.createContainer("openjdk:11"); + + try { + DockerContainerHelper.copyFileToContainer(container, code, "/app/Main.java"); + DockerContainerHelper.executeCommand(container, "javac", "/app/Main.java"); + + fail("Expected a compilation error, but the code compiled successfully"); + } catch (IOException | InterruptedException e) { + String errorMessage = e.getMessage(); + assertTrue(errorMessage.contains("error: package java.lang.System does not exist")); + } finally { + DockerContainerHelper.stopContainer(container); + } + } + } +} From ae7963faf4e70a27f0d8aa7eb91c8cacd0f21502 Mon Sep 17 00:00:00 2001 From: invictuzzzzz Date: Sun, 30 Jun 2024 20:54:26 +0200 Subject: [PATCH 04/21] FEATURE#552 --- .../score/docker/DockerIntegrationTest.java | 59 ++++++++++--------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/itachallenge-score/src/test/java/com/itachallenge/score/docker/DockerIntegrationTest.java b/itachallenge-score/src/test/java/com/itachallenge/score/docker/DockerIntegrationTest.java index 68c6b123c..ef03b7889 100644 --- a/itachallenge-score/src/test/java/com/itachallenge/score/docker/DockerIntegrationTest.java +++ b/itachallenge-score/src/test/java/com/itachallenge/score/docker/DockerIntegrationTest.java @@ -4,8 +4,6 @@ import com.itachallenge.score.helper.DockerContainerHelper; import org.junit.jupiter.api.Test; import org.testcontainers.containers.GenericContainer; -import org.testcontainers.images.builder.Transferable; - import java.io.IOException; import static org.junit.Assert.assertFalse; @@ -15,17 +13,21 @@ public class DockerIntegrationTest { @Test - public void testJavaContainerSortNumbers() { - - String codeSort = "import java.util.Arrays;\n" + - "public class Main {\n" + - " public static void main(String[] args) {\n" + - " String numbers = \"3,1,4,1,5,9\";\n" + - " int[] numArray = Arrays.stream(numbers.split(\",\")).mapToInt(Integer::parseInt).toArray();\n" + - " Arrays.sort(numArray);\n" + - " System.out.println(Arrays.toString(numArray));\n" + - " }\n" + - "}"; + void testJavaContainerSortNumbers() { + + String codeSort = """ + import java.util.Arrays; + + public class Main { + public static void main(String[] args) { + String numbers = "3,1,4,1,5,9"; + int[] numArray = Arrays.stream(numbers.split(",")).mapToInt(Integer::parseInt).toArray(); + Arrays.sort(numArray); + System.out.println(Arrays.toString(numArray)); + } + } + """; + GenericContainer containerJavaSort = DockerContainerHelper.createContainer("openjdk:11"); @@ -44,13 +46,15 @@ public void testJavaContainerSortNumbers() { } @Test - public void testJavaContainerCompileError() { + void testJavaContainerCompileError() { - String codeError = "public class Main {\n" + - " public static void main(String[] args) {\n" + - " System.out.println(\"Esto no compila porque falta un paréntesis\";\n" + - " }\n" + - "}"; + String codeError = """ + public class Main { + public static void main(String[] args) { + System.out.println("Esto no compila porque falta un paréntesis"; + } + } + """; GenericContainer containerJavaError = DockerContainerHelper.createContainer("openjdk:11"); @@ -66,14 +70,15 @@ public void testJavaContainerCompileError() { } @Test - public void testRestrictedLibraryImport() { - String code = "import java.lang.System;\n" + - "public class Main {\n" + - " public static void main(String[] args) {\n" + - " System.out.println(\"Hola! Estoy intentado importar System\");\n" + - " }\n" + - "}"; - + void testRestrictedLibraryImport() { + String code = """ + import java.lang.System; + public class Main { + public static void main(String[] args) { + System.out.println("Hola! Estoy intentado importar System"); + } + }" + """; assertFalse(CodeValidator.isLibraryImportAllowed(code)); // Debería devolver false al intentar importar java.lang.System // Si el código no importa java.lang.System, entonces se intenta compilar From 20433a05485c70d11b9164b6d250f9598446c663 Mon Sep 17 00:00:00 2001 From: invictuzzzzz Date: Sun, 30 Jun 2024 21:09:45 +0200 Subject: [PATCH 05/21] FEATURE#552 --- .../itachallenge/score/helper/CodeValidator.java | 4 +++- .../score/docker/DockerIntegrationTest.java | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/itachallenge-score/src/main/java/com/itachallenge/score/helper/CodeValidator.java b/itachallenge-score/src/main/java/com/itachallenge/score/helper/CodeValidator.java index bdafb6cd1..5290f602e 100644 --- a/itachallenge-score/src/main/java/com/itachallenge/score/helper/CodeValidator.java +++ b/itachallenge-score/src/main/java/com/itachallenge/score/helper/CodeValidator.java @@ -5,6 +5,9 @@ public class CodeValidator { + private CodeValidator() { + } + private static final String[] forbiddenLibraries = { "java\\.lang\\.System", "java\\.io\\.PrintStream", @@ -13,7 +16,6 @@ public class CodeValidator { "java\\.io\\.FileWriter", "java\\.io\\.BufferedReader", "java\\.io\\.BufferedWriter", - "java\\.util\\.Scanner", // se puede agregar más librerías aquí }; diff --git a/itachallenge-score/src/test/java/com/itachallenge/score/docker/DockerIntegrationTest.java b/itachallenge-score/src/test/java/com/itachallenge/score/docker/DockerIntegrationTest.java index ef03b7889..c18b0e77f 100644 --- a/itachallenge-score/src/test/java/com/itachallenge/score/docker/DockerIntegrationTest.java +++ b/itachallenge-score/src/test/java/com/itachallenge/score/docker/DockerIntegrationTest.java @@ -10,7 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; -public class DockerIntegrationTest { +class DockerIntegrationTest { @Test void testJavaContainerSortNumbers() { @@ -28,7 +28,6 @@ public static void main(String[] args) { } """; - GenericContainer containerJavaSort = DockerContainerHelper.createContainer("openjdk:11"); try { @@ -79,7 +78,18 @@ public static void main(String[] args) { } }" """; + + String code2 = """ + import java.util.Scanner; + public class Main { + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + System.out.println("Hola! Estoy intentado importar Scanner"); + } + }" + """; assertFalse(CodeValidator.isLibraryImportAllowed(code)); // Debería devolver false al intentar importar java.lang.System + assertTrue(CodeValidator.isLibraryImportAllowed(code2)); // Debería devolver true al intentar importar java.util.Scanner // Si el código no importa java.lang.System, entonces se intenta compilar if (CodeValidator.isLibraryImportAllowed(code)) { From ef089b4e527d81dcfc7ceb126d3f44cd85ce6b8c Mon Sep 17 00:00:00 2001 From: invictuzzzzz Date: Sun, 30 Jun 2024 21:20:29 +0200 Subject: [PATCH 06/21] FEATURE#552 --- itachallenge-score/build.gradle | 1 - .../java/com/itachallenge/score/helper/CodeValidator.java | 6 +++--- .../itachallenge/score/helper/DockerContainerHelper.java | 2 ++ .../itachallenge/score/docker/DockerIntegrationTest.java | 3 +++ 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/itachallenge-score/build.gradle b/itachallenge-score/build.gradle index 6af107441..5c181d81f 100755 --- a/itachallenge-score/build.gradle +++ b/itachallenge-score/build.gradle @@ -42,7 +42,6 @@ dependencies { implementation 'org.testcontainers:testcontainers:1.17.6' implementation 'org.apache.httpcomponents:httpclient:4.5.13' implementation 'org.testcontainers:junit-jupiter:1.16.3' - implementation 'org.testcontainers:testcontainers:1.16.3' // Borrado docker-java ya que no es necesario con la versión actual de testcontainers //testing diff --git a/itachallenge-score/src/main/java/com/itachallenge/score/helper/CodeValidator.java b/itachallenge-score/src/main/java/com/itachallenge/score/helper/CodeValidator.java index 5290f602e..fce548e3a 100644 --- a/itachallenge-score/src/main/java/com/itachallenge/score/helper/CodeValidator.java +++ b/itachallenge-score/src/main/java/com/itachallenge/score/helper/CodeValidator.java @@ -1,13 +1,13 @@ package com.itachallenge.score.helper; +import lombok.NoArgsConstructor; + import java.util.regex.Matcher; import java.util.regex.Pattern; +@NoArgsConstructor public class CodeValidator { - private CodeValidator() { - } - private static final String[] forbiddenLibraries = { "java\\.lang\\.System", "java\\.io\\.PrintStream", diff --git a/itachallenge-score/src/main/java/com/itachallenge/score/helper/DockerContainerHelper.java b/itachallenge-score/src/main/java/com/itachallenge/score/helper/DockerContainerHelper.java index 1a3e8ba24..89e6e3da1 100644 --- a/itachallenge-score/src/main/java/com/itachallenge/score/helper/DockerContainerHelper.java +++ b/itachallenge-score/src/main/java/com/itachallenge/score/helper/DockerContainerHelper.java @@ -1,11 +1,13 @@ package com.itachallenge.score.helper; +import lombok.NoArgsConstructor; import org.testcontainers.containers.GenericContainer; import org.testcontainers.images.builder.Transferable; import org.testcontainers.utility.DockerImageName; import java.io.IOException; +@NoArgsConstructor public class DockerContainerHelper { public static GenericContainer createContainer(String image) { diff --git a/itachallenge-score/src/test/java/com/itachallenge/score/docker/DockerIntegrationTest.java b/itachallenge-score/src/test/java/com/itachallenge/score/docker/DockerIntegrationTest.java index c18b0e77f..0f79a6da5 100644 --- a/itachallenge-score/src/test/java/com/itachallenge/score/docker/DockerIntegrationTest.java +++ b/itachallenge-score/src/test/java/com/itachallenge/score/docker/DockerIntegrationTest.java @@ -4,12 +4,15 @@ import com.itachallenge.score.helper.DockerContainerHelper; import org.junit.jupiter.api.Test; import org.testcontainers.containers.GenericContainer; +import org.testcontainers.junit.jupiter.Testcontainers; + import java.io.IOException; import static org.junit.Assert.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +@Testcontainers class DockerIntegrationTest { @Test From fbef7b2f4a29932f635d913c92654ae04eb61485 Mon Sep 17 00:00:00 2001 From: Marcos Pagliaruzza Date: Fri, 5 Jul 2024 15:16:29 +0200 Subject: [PATCH 07/21] Added getAllSolutionsByIdUser endpoint --- .../user/controller/UserController.java | 22 ++++++++++++++ .../user/helper/ConverterDocumentToDto.java | 12 ++++++++ .../user/service/IUserSolutionService.java | 5 ++++ .../user/service/UserSolutionServiceImp.java | 5 ++++ .../user/controller/UserControllerTest.java | 30 +++++++++++++++++++ .../helper/ConverterDocumentToDtoTest.java | 17 +++++++++++ .../service/UserSolutionServiceImpTest.java | 27 +++++++++++++++++ 7 files changed, 118 insertions(+) diff --git a/itachallenge-user/src/main/java/com/itachallenge/user/controller/UserController.java b/itachallenge-user/src/main/java/com/itachallenge/user/controller/UserController.java index 64c05a9d9..169088926 100755 --- a/itachallenge-user/src/main/java/com/itachallenge/user/controller/UserController.java +++ b/itachallenge-user/src/main/java/com/itachallenge/user/controller/UserController.java @@ -5,6 +5,7 @@ import com.itachallenge.user.service.IServiceChallengeStatistics; import com.itachallenge.user.service.IUserSolutionService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -150,4 +151,25 @@ public Mono>> getVersion() { response.put("version", version); return Mono.just(ResponseEntity.ok(response)); } + + @GetMapping(path = "/{idUser}/challenges") + @Operation( + summary = "Retrieves all user challenges solutions and their status.", + description = "Retrieves all user-contributed solutions for all challenges and their status (whether they've finished completing them or not).", + responses = { + @ApiResponse(responseCode = "200", description = "Challenges retrieved successfully", content = {@Content(array = @ArraySchema(schema = @Schema(implementation = UserSolutionDto.class)), mediaType = "application/json")}), + @ApiResponse(responseCode = "400", description = "Invalid UUID for user"), + @ApiResponse(responseCode = "404", description = "User not found") + } + ) + public Mono>> getAllSolutionsByIdUser( + @PathVariable("idUser") @GenericUUIDValid(message = "Invalid UUID for user") String idUser) { + UUID userUuid = UUID.fromString(idUser); + + return userScoreService.showAllUserSolutions(userUuid) + .collectList() + .map(ResponseEntity::ok) + .defaultIfEmpty(ResponseEntity.notFound().build()); + } + } \ No newline at end of file diff --git a/itachallenge-user/src/main/java/com/itachallenge/user/helper/ConverterDocumentToDto.java b/itachallenge-user/src/main/java/com/itachallenge/user/helper/ConverterDocumentToDto.java index 03974673c..3378fb7f2 100755 --- a/itachallenge-user/src/main/java/com/itachallenge/user/helper/ConverterDocumentToDto.java +++ b/itachallenge-user/src/main/java/com/itachallenge/user/helper/ConverterDocumentToDto.java @@ -2,6 +2,7 @@ import com.itachallenge.user.document.UserSolutionDocument; import com.itachallenge.user.dtos.UserScoreDto; +import com.itachallenge.user.dtos.UserSolutionDto; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; @@ -22,4 +23,15 @@ private UserScoreDto toUserScoreDto(UserSolutionDocument userScoreDocument) { .solutions(userScoreDocument.getSolutionDocument()) .build(); } + + public Flux fromUserSolutionDocumentToUserSolutionDto(UserSolutionDocument document) { + return Flux.just(UserSolutionDto.builder() + .userId(document.getUserId().toString()) + .challengeId(document.getChallengeId().toString()) + .languageId(document.getLanguageId().toString()) + .status(document.getStatus().toString()) + .solutionText(document.getSolutionDocument().get(0).getSolutionText()) + .build()); + } + } diff --git a/itachallenge-user/src/main/java/com/itachallenge/user/service/IUserSolutionService.java b/itachallenge-user/src/main/java/com/itachallenge/user/service/IUserSolutionService.java index 467ed83c9..6affd9781 100755 --- a/itachallenge-user/src/main/java/com/itachallenge/user/service/IUserSolutionService.java +++ b/itachallenge-user/src/main/java/com/itachallenge/user/service/IUserSolutionService.java @@ -5,12 +5,17 @@ import com.itachallenge.user.dtos.UserScoreDto; import com.itachallenge.user.dtos.UserSolutionDto; import com.itachallenge.user.dtos.UserSolutionScoreDto; +import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.util.List; +import java.util.UUID; + public interface IUserSolutionService { Mono> getChallengeById(String id, String idChallenge, String idLanguage); Mono addSolution(UserSolutionDto userSolutionDto); Mono markAsBookmarked(String uuidChallenge, String uuidLanguage, String uuidUser, boolean bookmarked); + Flux showAllUserSolutions(UUID userUuid); } diff --git a/itachallenge-user/src/main/java/com/itachallenge/user/service/UserSolutionServiceImp.java b/itachallenge-user/src/main/java/com/itachallenge/user/service/UserSolutionServiceImp.java index facf1ed93..82c3e8380 100755 --- a/itachallenge-user/src/main/java/com/itachallenge/user/service/UserSolutionServiceImp.java +++ b/itachallenge-user/src/main/java/com/itachallenge/user/service/UserSolutionServiceImp.java @@ -143,5 +143,10 @@ private ChallengeStatus determineChallengeStatus(String status) { return challengeStatus; } + public Flux showAllUserSolutions(UUID userUuid) { + return userSolutionRepository.findByUserId(userUuid) + .flatMap(converter::fromUserSolutionDocumentToUserSolutionDto); + } + } diff --git a/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java b/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java index 372c4da49..01f7ce55f 100755 --- a/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java +++ b/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java @@ -23,6 +23,7 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; +import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.util.Arrays; @@ -312,6 +313,35 @@ void getVersionTest() { .jsonPath("$.version").isEqualTo("1.0-SNAPSHOT"); } + @Test + void getAllSolutionsByIdUser() { + String URI_TEST = "/{idUser}/challenges"; + UUID userId = UUID.randomUUID(); + + UserSolutionDto userSolutionDto = UserSolutionDto.builder() + .userId(userId.toString()) + .challengeId(UUID.randomUUID().toString()) + .languageId(UUID.randomUUID().toString()) + .status("STARTED") + .solutionText("Sample Solution") + .build(); + + when(userSolutionService.showAllUserSolutions(userId)).thenReturn(Flux.just(userSolutionDto)); + + webTestClient.get() + .uri(CONTROLLER_URL + URI_TEST, userId.toString()) + .exchange() + .expectStatus().isOk() + .expectBodyList(UserSolutionDto.class) + .value(solutions -> { + assertNotNull(solutions); + assertEquals(1, solutions.size()); + UserSolutionDto solution = solutions.get(0); + assertEquals(userId.toString(), solution.getUserId()); + assertEquals("Sample Solution", solution.getSolutionText()); + }); + } + } diff --git a/itachallenge-user/src/test/java/com/itachallenge/user/helper/ConverterDocumentToDtoTest.java b/itachallenge-user/src/test/java/com/itachallenge/user/helper/ConverterDocumentToDtoTest.java index a181510c9..c508f18bb 100755 --- a/itachallenge-user/src/test/java/com/itachallenge/user/helper/ConverterDocumentToDtoTest.java +++ b/itachallenge-user/src/test/java/com/itachallenge/user/helper/ConverterDocumentToDtoTest.java @@ -3,6 +3,7 @@ import com.itachallenge.user.document.SolutionDocument; import com.itachallenge.user.document.UserSolutionDocument; import com.itachallenge.user.dtos.UserScoreDto; +import com.itachallenge.user.dtos.UserSolutionDto; import com.itachallenge.user.enums.ChallengeStatus; import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.DisplayName; @@ -17,6 +18,7 @@ import java.util.List; import java.util.UUID; +import java.util.stream.Collectors; @ExtendWith(SpringExtension.class) @SpringBootTest @@ -59,4 +61,19 @@ private boolean ValidateUserScoreDto(@NotNull UserScoreDto userScoreDto, @NotNul userScoreDto.getSolutions().equals(userScoreDocument.getSolutionDocument()) && userScoreDto.getLanguageID().equals(userScoreDocument.getLanguageId()); } + + public Flux fromUserSolutionDocumentToUserSolutionDto(UserSolutionDocument userSolutionDocument) { + return Flux.fromIterable( + userSolutionDocument.getSolutionDocument().stream() + .map(solution -> UserSolutionDto.builder() + .userId(userSolutionDocument.getUserId().toString()) + .challengeId(userSolutionDocument.getChallengeId().toString()) + .languageId(userSolutionDocument.getLanguageId().toString()) + .status(userSolutionDocument.getStatus().toString()) + .solutionText(solution.getSolutionText()) + .build()) + .collect(Collectors.toList()) + ); + } + } diff --git a/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java b/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java index 5b735b690..242de9a3f 100644 --- a/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java +++ b/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java @@ -19,6 +19,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.mockito.InjectMocks; +import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -202,4 +203,30 @@ void addSolutionWithInvalidStatus_test(String status) { } + @DisplayName("UserSolutionServiceImpTest - showAllUserSolutions returns all solutions for the user") + @Test + void showAllUserSolutions() { + when(userSolutionRepository.findByUserId(userUuid)).thenReturn(Flux.just(userSolutionDocument)); + + Flux resultFlux = userSolutionService.showAllUserSolutions(userUuid); + + StepVerifier.create(resultFlux) + .expectNextMatches(userSolutionDto -> + userSolutionDto.getUserId().equals(userUuid.toString()) + && userSolutionDto.getSolutionText().equals("Sample Solution")) + .verifyComplete(); + } + + @DisplayName("UserSolutionServiceImpTest - showAllUserSolutions returns empty flux when no solutions are found") + @Test + void showAllUserSolutions_NoSolutions() { + when(userSolutionRepository.findByUserId(userUuid)).thenReturn(Flux.empty()); + + Flux resultFlux = userSolutionService.showAllUserSolutions(userUuid); + + StepVerifier.create(resultFlux) + .expectNextCount(0) + .verifyComplete(); + } + } \ No newline at end of file From 3f91da9ce20a8455fdc644f00db9c12f8552e05b Mon Sep 17 00:00:00 2001 From: Marcos Pagliaruzza Date: Fri, 5 Jul 2024 15:54:16 +0200 Subject: [PATCH 08/21] Added getAllSolutionsByIdUser endpoint FIX Test --- .../service/UserSolutionServiceImpTest.java | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java b/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java index 242de9a3f..510b1e010 100644 --- a/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java +++ b/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java @@ -6,6 +6,7 @@ import com.itachallenge.user.dtos.UserSolutionScoreDto; import com.itachallenge.user.enums.ChallengeStatus; import com.itachallenge.user.exception.UnmodifiableSolutionException; +import com.itachallenge.user.helper.ConverterDocumentToDto; import com.itachallenge.user.repository.IUserSolutionRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -37,6 +38,9 @@ class UserSolutionServiceImpTest { @Mock IUserSolutionRepository userSolutionRepository; + @Mock + private ConverterDocumentToDto converter; + @InjectMocks UserSolutionServiceImp userSolutionService; @@ -206,17 +210,27 @@ void addSolutionWithInvalidStatus_test(String status) { @DisplayName("UserSolutionServiceImpTest - showAllUserSolutions returns all solutions for the user") @Test void showAllUserSolutions() { + UserSolutionDto userSolutionDto = UserSolutionDto.builder() + .userId(userUuid.toString()) + .challengeId(userSolutionDocument.getChallengeId().toString()) + .languageId(userSolutionDocument.getLanguageId().toString()) + .status(userSolutionDocument.getStatus().toString()) + .solutionText("Sample Solution") + .build(); + when(userSolutionRepository.findByUserId(userUuid)).thenReturn(Flux.just(userSolutionDocument)); + when(converter.fromUserSolutionDocumentToUserSolutionDto(userSolutionDocument)).thenReturn(Flux.just(userSolutionDto)); Flux resultFlux = userSolutionService.showAllUserSolutions(userUuid); StepVerifier.create(resultFlux) - .expectNextMatches(userSolutionDto -> - userSolutionDto.getUserId().equals(userUuid.toString()) - && userSolutionDto.getSolutionText().equals("Sample Solution")) + .expectNextMatches(dto -> + dto.getUserId().equals(userUuid.toString()) && + dto.getSolutionText().equals("Sample Solution")) .verifyComplete(); } + @DisplayName("UserSolutionServiceImpTest - showAllUserSolutions returns empty flux when no solutions are found") @Test void showAllUserSolutions_NoSolutions() { From 50041f48da81ad769765af7513361a206be62ea0 Mon Sep 17 00:00:00 2001 From: ecs90 Date: Tue, 2 Jul 2024 10:47:26 +0200 Subject: [PATCH 09/21] Feature #550 finished MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit id 0864463e-eb7c-4bb3-b8bc-766d71ab38b5 edited id find in right solution, deleted from other challenges id 75a74089-99bb-468d-ae71-b8c0b97ce6b3 deleted from all challenges challenges description diffrent from this id code solution ID unico para solutions javascript PHP and python unique ID in challenge and added 2 more unique solutions in solutions to python Añadida solucion cf6f54cf-6950-4d24-8bf9-7108e80dffbc Añadida solucion cf6f54cf-6950-4d24-8bf9-7108e80dffbc Añadida solucion 5508909d-b215-4ed7-9911-7dedcbb27153 Añadida solucion 5508909d-b215-4ed7-9911-7dedcbb27153 Añadida solucion 5508909d-b215-4ed7-9911-7dedcbb27153 added solution 9151e4cf-8195-4ad5-9363-b378aa322d31 small changes Añadida solucion 36ffd264-9eca-48c1-8cdd-09f190d7adca Modified solution 0864463e-eb7c-4bb3-b8bc-766d71ab38b5 add 2 solutions añadida solution 9ea9cec5-a442-4a6a-96cd-daa846d4bbe9 solution ce76eeb5-1a1f-4aa5-908a-dcf229c1f48f added solution d0f57f27-a5e0-49f6-8a72-24ad9a497b8d added añadida solution d624bae4-9a43-4515-8979-801c0d6fd88c añadida solution ea837e7d-3d39-42f1-a795-bfc1e928567b solution 429866e1-c489-4500-a458-d46ed62b26be added Added solutions - All challenges are for java language and point at a java solution - Added more than one solution for each challenge (if they're available for more than 1 language) - Fixed dcacb291-b4aa-4029-8e9b-284c8ca80296 9d2c4e2b-02af-4327-81b2-7dbf5c3f5a7d 6099f6e8-39b2-4c72-9ae1-21fdd3c9010a 7d8c6a2a-58a7-4c72-b4cf-8c63a9c18121 ec52b7f1-2f78-4a83-aef0-3b9b6f34a763 añadida solution a challenge 9d248e74-731f-4782-af2c-7ae9b53c9d5c, 5a72d6cb-3217-4d75-9368-689ed48cb9ec, c3946e8d-e7b4-4e3c-aacf-e8d6c5e9d0b6 añadida solution 6b1df7af-f32f-4f2b-8f97-7d7430874d34 Added java solution 4f8a6c91-8a9d-49b0-9f2c-3e67d2b18b8d añadida solution 6b1df7af-f32f-4f2b-8f97-7d7430874d34 borrado challenge 7c8f6d12-8c2f-4b7f-9e94-6d5f5c3e02e3 Added java solution for 6d3b9a2c-8e1d-45b4-98ac-e8f9c7d3a9a7 solution 2d423ff6-93fe-483d-bc86-9d8c58552942 created Remove redundant info --- .../mongodb-test-data/challenges.json | 281 ++++++++---------- .../mongodb-test-data/solutions.json | 202 ++++++++++++- 2 files changed, 318 insertions(+), 165 deletions(-) diff --git a/itachallenge-challenge/src/main/resources/mongodb-test-data/challenges.json b/itachallenge-challenge/src/main/resources/mongodb-test-data/challenges.json index 5c5bd8185..fe1e9506a 100755 --- a/itachallenge-challenge/src/main/resources/mongodb-test-data/challenges.json +++ b/itachallenge-challenge/src/main/resources/mongodb-test-data/challenges.json @@ -72,11 +72,17 @@ "$uuid": "409c9fe8-74de-4db3-81a1-a55280cf92ef" }, "language_name": "Python" + }, + { + "_id": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + }, + "language_name": "Java" } ], "solutions": [ - {"$uuid" : "1682b3e9-056a-45b7-a0e9-eaf1e11775ad"}, - {"$uuid" : "a7a789a9-2006-4b59-94bb-3afe0d1c161d"} + {"$uuid": "1682b3e9-056a-45b7-a0e9-eaf1e11775ad"}, + {"$uuid": "75a74089-99bb-468d-ae71-b8c0b97ce6b3"} ], "resources": [ { @@ -195,8 +201,7 @@ } ], "solutions": [ - {"$uuid": "0864463e-eb7c-4bb3-b8bc-766d71ab38b5"}, - {"$uuid": "75a74089-99bb-468d-ae71-b8c0b97ce6b3"} + {"$uuid": "0864463e-eb7c-4bb3-b8bc-766d71ab38b5"} ], "resources": [ {"$uuid": "6e0784c9-5951-4981-9f7c-30419dae6149"}, @@ -328,11 +333,17 @@ "$uuid": "409c9fe8-74de-4db3-81a1-a55280cf92ef" }, "language_name": "Python" + }, + { + "_id": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + }, + "language_name": "Java" } ], "solutions": [ - {"$uuid" : "1682b3e9-056a-45b7-a0e9-eaf1e11775ad"}, - {"$uuid" : "a7a789a9-2006-4b59-94bb-3afe0d1c161d"} + {"$uuid" : "a7a789a9-2006-4b59-94bb-3afe0d1c161d"}, + {"$uuid": "f7c9e2a1-8b6d-4c3f-a9e0-2d5f8c7b1e4a"} ], "resources": [ {"$uuid": "24fcf839-63c2-4ccf-b549-5bc2027798d5"}, @@ -439,8 +450,7 @@ } ], "solutions": [ - {"$uuid": "0864463e-eb7c-4bb3-b8bc-766d71ab38b5"}, - {"$uuid": "75a74089-99bb-468d-ae71-b8c0b97ce6b3"} + {"$uuid": "9151e4cf-8195-4ad5-9363-b378aa322d31"} ], "resources": [ {"$uuid": "0d1dcee8-6ee8-402f-815a-7d717be06aed"}, @@ -574,109 +584,7 @@ "$uuid": "09fabe32-7362-4bfb-ac05-b7bf854c6e0f" }, "language_name": "Javascript" - } - ], - "solutions": [ - {"$uuid" : "b3b2c8d7-4d0e-4f4d-b240-55d6a038d52e"}, - {"$uuid" : "c418ba4e-d69a-4fb4-a24c-2ee489a0c749"} - ], - "resources": [ - {"$uuid": "dec03f23-b034-4b2d-80e9-e504767f0519"}, - {"$uuid": "301c74dd-27b6-4be4-9a38-0c7ada2969cf"}, - {"$uuid": "527bad10-d689-4a10-a787-72507fafe415"} - ], - "related": [ - {"$uuid": "f6e0f877-9560-4e68-bab6-7dd5f16b46a5"}, - {"$uuid": "9d2c4e2b-02af-4327-81b2-7dbf5c3f5a7d"}, - {"$uuid": "2f948de0-6f0c-4089-90b9-7f70a0812319"} - ], - "testing_values": [ - { - "in_param": "Dermatoglyphics", - "out_param": true - }, - { - "in_param": "moose", - "out_param": false }, - { - "in_param": "aba", - "out_param": false - } - ] - }, - { - "_id": { - "$uuid": "7c8f6d12-8c2f-4b7f-9e94-6d5f5c3e02e3" - }, - "challenge_title": { - "ES": "Xs y Os", - "CA": "Xs i Os", - "EN": "Exes and Ohs" - }, - "level": "EASY", - "creation_date": { - "$date": "2011-11-09T11:43:54+0200" - }, - "detail": { - "description": { - "ES": "Verifica si una cadena tiene la misma cantidad de 'x' y 'o'. El método debe devolver un booleano y ser insensible a mayúsculas y minúsculas. La cadena puede contener cualquier carácter.", - "CA": "Comprova si una string the el mateix nombre de 'x' i de 'o'. El metode ha de retornar un boleà i ignorar la capitalització. la string pot contenir qualsevol char.", - "EN": "Check to see if a string has the same amount of 'x's and 'o's. The method must return a boolean and be case insensitive. The string can contain any char." - }, - "examples": [ - { - "_id": { - "$uuid": "2dab6eaa-fdf4-4a93-8088-810a956e2bf8" - }, - "example_text": - { - "ES": "xxoo, para esta cadena el resultado es true", - "CA": "xxoo, per aquesta string el resultat es true", - "EN": "xxoo, for this string the result is true" - } - }, - { - "_id": { - "$uuid": "6c02025e-b06f-420a-bafb-28c737b18473" - }, - "example_text": - { - "ES": "xXoo, para esta cadena el resultado es true", - "CA": "xXoo, per aquesta cadena el resultat es true", - "EN": "xXoo, for this string the result is true" - } - }, - { - "_id": { - "$uuid": "70e9755e-9e83-41d3-853a-665f1f2a2f5c" - }, - "example_text": - { - "ES": "OxoO, para esta cadena el resultado es false", - "CA": "OxoO, per aquesta cadena el resultat es fals", - "EN": "OxoO, for this string the result is false" - } - }, - { - "_id": { - "$uuid": "bb7897b8-517d-4843-8c17-e347aba086ca" - }, - "example_text": - { - "ES": "oxxxoox, para esta cadena el resultado es false", - "CA": "oxxxoox, per aquesta cadensa el resultat es fals", - "EN": "oxxxoox, for this string the result is false" - } - } - ], - "notes": { - "ES": "Revisa las arrays y los bucles para contar el número de 'x' y 'o' en una cadena", - "CA": "Revisa les arrays i els bucles per contar el nombre de 'x' i 'o' en una string", - "EN": "Look into arrays and loops to count the number of 'x's and 'o's in a string" - } - }, - "languages": [ { "_id": { "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" @@ -685,8 +593,8 @@ } ], "solutions": [ - {"$uuid": "0864463e-eb7c-4bb3-b8bc-766d71ab38b5"}, - {"$uuid": "75a74089-99bb-468d-ae71-b8c0b97ce6b3"} + {"$uuid" : "b3b2c8d7-4d0e-4f4d-b240-55d6a038d52e"}, + {"$uuid": "e1a9f2b8-7c3d-4e9b-8a1f-99c6d5f17a83"} ], "resources": [ {"$uuid": "dec03f23-b034-4b2d-80e9-e504767f0519"}, @@ -700,16 +608,16 @@ ], "testing_values": [ { - "in_param": "ooxx", + "in_param": "Dermatoglyphics", "out_param": true }, { - "in_param": "xooxx", + "in_param": "moose", "out_param": false }, { - "in_param": "ooxXm", - "out_param": true + "in_param": "aba", + "out_param": false } ] }, @@ -732,7 +640,7 @@ "CA": "Set donarà una paraula. La teva feina i retorna la lletra que es troba al mig. Si la llargada de la paraula es una nombre senar, retorna el caracter del mig. si la llargada es un nombre parell, retorna els dos caracters del mig.", "EN": "You are going to be given a word. Your job is to return the middle character of the word. If the word's length is odd, return the middle character. If the word's length is even, return the middle 2 characters." }, - "examples": [ + "examples": [ { "_id": { "$uuid": "2dab6eaa-fdf4-4a93-8088-810a956e2bf8" @@ -793,8 +701,7 @@ } ], "solutions": [ - {"$uuid": "75a74089-99bb-468d-ae71-b8c0b97ce6b3"}, - {"$uuid": "0864463e-eb7c-4bb3-b8bc-766d71ab38b5"} + {"$uuid": "6ab78fab-642a-4e25-baf0-4890794dd8e2"} ], "resources": [ {"$uuid": "dec03f23-b034-4b2d-80e9-e504767f0519"}, @@ -898,12 +805,17 @@ "$uuid": "09fabe32-7362-4bfb-ac05-b7bf854c6e0f" }, "language_name": "Javascript" + }, + { + "_id": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + }, + "language_name": "Java" } ], "solutions": [ - {"$uuid" : "b3b2c8d7-4d0e-4f4d-b240-55d6a038d52e"}, - {"$uuid" : "c418ba4e-d69a-4fb4-a24c-2ee489a0c749"} - + {"$uuid" : "c418ba4e-d69a-4fb4-a24c-2ee489a0c749"}, + {"$uuid": "d6a5b2c1-9e8d-4f7c-a3b0-1e9f8c2d5a4b"} ], "resources": [ {"$uuid": "dec03f23-b034-4b2d-80e9-e504767f0519"}, @@ -1007,8 +919,7 @@ } ], "solutions": [ - {"$uuid": "0864463e-eb7c-4bb3-b8bc-766d71ab38b5"}, - {"$uuid": "75a74089-99bb-468d-ae71-b8c0b97ce6b3"} + {"$uuid": "36ffd264-9eca-48c1-8cdd-09f190d7adca"} ], "resources": [ {"$uuid": "dec03f23-b034-4b2d-80e9-e504767f0519"}, @@ -1127,11 +1038,17 @@ "$uuid": "409c9fe8-74de-4db3-81a1-a55280cf92ef" }, "language_name": "Python" + }, + { + "_id": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + }, + "language_name": "Java" } ], "solutions": [ - {"$uuid" : "1682b3e9-056a-45b7-a0e9-eaf1e11775ad"}, - {"$uuid" : "a7a789a9-2006-4b59-94bb-3afe0d1c161d"} + {"$uuid": "9f5d7339-f87b-4d7e-b8e8-c6e850ff7a50"}, + {"$uuid": "edd8283a-3978-4657-b776-ff75536e231d"} ], "resources": [ {"$uuid": "dec03f23-b034-4b2d-80e9-e504767f0519"}, @@ -1246,11 +1163,17 @@ "$uuid": "409c9fe8-74de-4db3-81a1-a55280cf92ef" }, "language_name": "Python" + }, + { + "_id": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + }, + "language_name": "Java" } ], "solutions": [ - {"$uuid" : "1682b3e9-056a-45b7-a0e9-eaf1e11775ad"}, - {"$uuid" : "a7a789a9-2006-4b59-94bb-3afe0d1c161d"} + {"$uuid": "c2c2a6c4-83b1-4a8a-82e3-f5cfb64fcfb4"}, + {"$uuid": "046791ae-7355-4fc8-a696-4f9665eac927"} ], "resources": [ {"$uuid": "dec03f23-b034-4b2d-80e9-e504767f0519"}, @@ -1352,11 +1275,17 @@ "$uuid": "1e047ea2-b787-49e7-acea-d79e92be3909" }, "language_name": "PHP" + }, + { + "_id": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + }, + "language_name": "Java" } ], "solutions": [ - {"$uuid" : "9afabfaa-071c-4b29-94f1-4a536e2c4dd5"}, - {"$uuid" : "d0e7d7dd-8269-41b6-8e97-b66a952dd1e5"} + {"$uuid": "d0e7d7dd-8269-41b6-8e97-b66a952dd1e5"}, + {"$uuid": "396d1164-85c5-470a-8977-fc68b9b26fb1"} ], "resources": [ {"$uuid": "dec03f23-b034-4b2d-80e9-e504767f0519"}, @@ -1465,8 +1394,7 @@ } ], "solutions": [ - {"$uuid": "75a74089-99bb-468d-ae71-b8c0b97ce6b3"}, - {"$uuid": "0864463e-eb7c-4bb3-b8bc-766d71ab38b5"} + {"$uuid": "ce76eeb5-1a1f-4aa5-908a-dcf229c1f48f"} ], "resources": [ {"$uuid": "dec03f23-b034-4b2d-80e9-e504767f0519"}, @@ -1527,9 +1455,9 @@ }, "example_text": { - "ES": "Dado n = 35141, el dígito d = 1 con índice i = 2 debe moverse a la posición j = 0, para un resultado mínimo de m = 13541", - "CA": "Donat n = 35141, el dígit d = 1 amb índex i = 2 s'ha de moure a la posició j = 0, per un resultat mínim de m = 13541", - "EN": "Given n = 35141, digit d = 1 with index i = 2 must be moved to position j = 0, for a minimum result of m = 13541" + "ES": "Dado n = 35141, el dígito d = 1 con índice i = 2 puede moverse a la posición j = 0 para un resultado mínimo de m = 13541, pero si se mueve el digito d = 1 con indice i = 4 a la posicion j = 0, da un resultado aun menor m = 13514", + "CA": "Donat n = 35141, el dígit d = 1 amb índex i = 2 es pot moure a la posició j = 0 per a un resultat mínim de m = 13541, però si el dígit d = 1 amb índex i = 4 es mou a la posició j = 0, dóna un resultat encara més petit m = 13514", + "EN": "Given n = 35141, digit d = 1 with index i = 2 can be moved to position j = 0 for a minimum result of m = 13541, but if the digit d = 1 with index i = 4 is moved to position j = 0, it results in an even smaller number m = 13514." } }, { @@ -1549,9 +1477,9 @@ }, "example_text": { - "ES": "Dado n = 03540, el dígito d = 0 con índice i = 0 debe quedarse en la posición j = 0, para un resultado mínimo de m = 035440", - "CA": "Donat n = 035440, el dígit d = 0 amb índex i = 0 s'ha de quedar a la posició j = 0, per un resultat mínim de m = 035440", - "EN": "Given n = 035440, digit d = 0 with index i = 0 must stay in position j = 0, for a minimum result of m = 035440" + "ES": "Dado n = 03540, el dígito d = 0 con índice i = 4 debe moverse a la posición j = 0, para un resultado mínimo de m = 003544", + "CA": "Donat n = 03540, el dígit d = 0 amb índex i = 4 s'ha de mover a la posició j = 0, per un resultat mínim de m = 003544", + "EN": "Given n = 03540, digit d = 0 with index i = 4 must move to position j = 0, for a minimum result of m = 003544" } } ], @@ -1568,11 +1496,27 @@ "$uuid": "09fabe32-7362-4bfb-ac05-b7bf854c6e0f" }, "language_name": "Javascript" + }, + { + "_id": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + }, + "language_name": "Java" } ], "solutions": [ - {"$uuid" : "b3b2c8d7-4d0e-4f4d-b240-55d6a038d52e"}, - {"$uuid" : "c418ba4e-d69a-4fb4-a24c-2ee489a0c749"} + { + "$uuid" : "c8a5440d-6466-463a-bccc-7fefbe9396e4", + "language_id": { + "$uuid": "09fabe32-7362-4bfb-ac05-b7bf854c6e0f" + } + }, + { + "$uuid": "2d423ff6-93fe-483d-bc86-9d8c58552942", + "language_id": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + } ], "resources": [ {"$uuid": "dec03f23-b034-4b2d-80e9-e504767f0519"}, @@ -1693,8 +1637,7 @@ } ], "solutions": [ - {"$uuid": "75a74089-99bb-468d-ae71-b8c0b97ce6b3"}, - {"$uuid": "0864463e-eb7c-4bb3-b8bc-766d71ab38b5"} + {"$uuid": "d0f57f27-a5e0-49f6-8a72-24ad9a497b8d"} ], "resources": [ {"$uuid": "dec03f23-b034-4b2d-80e9-e504767f0519"}, @@ -1767,8 +1710,8 @@ }, "example_text": { - "ES": "Si la string de entrada es '10-6', la salida esperada sería 4.", - "CA": "Si la string d'entrada és '10-6', la sortida esperada seria 4.", + "ES": "Si el string de entrada es '10-6', la salida esperada sería 4.", + "CA": "Si el string d'entrada és '10-6', la sortida esperada seria 4.", "EN": "If the input string is '10-6', the expected output would be 4." } }, @@ -1778,8 +1721,8 @@ }, "example_text": { - "ES": "Si la string de entrada es '2*2', la salida esperada sería 4.", - "CA": "Si la string d'entrada és '2*2', la sortida esperada seria 4.", + "ES": "Si el string de entrada es '2*2', la salida esperada sería 4.", + "CA": "Si el string d'entrada és '2*2', la sortida esperada seria 4.", "EN": "If the input string is '2*2', the expected output would be 4." } }, @@ -1789,8 +1732,8 @@ }, "example_text": { - "ES": "Si la string de entrada es '8/2', la salida esperada sería 4.", - "CA": "Si la string d'entrada és '8/2', la sortida esperada seria 4.", + "ES": "Si el string de entrada es '8/2', la salida esperada sería 4.", + "CA": "Si el string d'entrada és '8/2', la sortida esperada seria 4.", "EN": "If the input string is '8/2', the expected output would be 4." } } @@ -1808,11 +1751,17 @@ "$uuid": "1e047ea2-b787-49e7-acea-d79e92be3909" }, "language_name": "PHP" + }, + { + "_id": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + }, + "language_name": "Java" } ], "solutions": [ {"$uuid" : "9afabfaa-071c-4b29-94f1-4a536e2c4dd5"}, - {"$uuid" : "d0e7d7dd-8269-41b6-8e97-b66a952dd1e5"} + {"$uuid": "f3b6c7d8-2e9a-4b1d-8c7e-4f5a9d0c3b2e"} ], "resources": [ {"$uuid": "dec03f23-b034-4b2d-80e9-e504767f0519"}, @@ -1917,8 +1866,7 @@ } ], "solutions": [ - {"$uuid": "75a74089-99bb-468d-ae71-b8c0b97ce6b3"}, - {"$uuid": "0864463e-eb7c-4bb3-b8bc-766d71ab38b5"} + {"$uuid": "d624bae4-9a43-4515-8979-801c0d6fd88c"} ], "resources": [ {"$uuid": "dec03f23-b034-4b2d-80e9-e504767f0519"}, @@ -2016,11 +1964,17 @@ "$uuid": "09fabe32-7362-4bfb-ac05-b7bf854c6e0f" }, "language_name": "Javascript" + }, + { + "_id": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + }, + "language_name": "Java" } ], "solutions": [ - {"$uuid" : "b3b2c8d7-4d0e-4f4d-b240-55d6a038d52e"}, - {"$uuid" : "c418ba4e-d69a-4fb4-a24c-2ee489a0c749"} + {"$uuid" : "998bc504-265d-40a4-b579-62feacc3c8cd"}, + {"$uuid": "9f1d2a4b-3c6e-4d7b-8a9c-5e0f7b3c2a1d"} ], "resources": [ {"$uuid": "dec03f23-b034-4b2d-80e9-e504767f0519"}, @@ -2054,7 +2008,7 @@ "$uuid": "8c7e3a9d-6b2d-43e4-9d1f-4e7a8c9d3e1b" }, "challenge_title": { - "ES": "Encuentra el Punto de Equilibri de un Array", + "ES": "Encuentra el Punto de Equilibrio de un Array", "CA": "Troba el Punt d'Equilibri d'un Array", "EN": "Find the Equilibrium Point in an Array" }, @@ -2131,8 +2085,7 @@ } ], "solutions": [ - {"$uuid": "75a74089-99bb-468d-ae71-b8c0b97ce6b3"}, - {"$uuid": "0864463e-eb7c-4bb3-b8bc-766d71ab38b5"} + {"$uuid": "429866e1-c489-4500-a458-d46ed62b26be"} ], "resources": [ {"$uuid": "dec03f23-b034-4b2d-80e9-e504767f0519"}, @@ -2240,8 +2193,7 @@ } ], "solutions": [ - {"$uuid": "75a74089-99bb-468d-ae71-b8c0b97ce6b3"}, - {"$uuid": "0864463e-eb7c-4bb3-b8bc-766d71ab38b5"} + {"$uuid": "ea837e7d-3d39-42f1-a795-bfc1e928567b"} ], "resources": [ {"$uuid": "dec03f23-b034-4b2d-80e9-e504767f0519"}, @@ -2340,11 +2292,17 @@ "$uuid": "09fabe32-7362-4bfb-ac05-b7bf854c6e0f" }, "language_name": "Javascript" + }, + { + "_id": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + }, + "language_name": "Java" } ], "solutions": [ - {"$uuid" : "b3b2c8d7-4d0e-4f4d-b240-55d6a038d52e"}, - {"$uuid" : "c418ba4e-d69a-4fb4-a24c-2ee489a0c749"} + {"$uuid": "4dc78169-d4c9-413f-a032-c9cd8e7ca50f"}, + {"$uuid": "6b1df7af-f32f-4f2b-8f97-7d7430874d34"} ], "resources": [ {"$uuid": "dec03f23-b034-4b2d-80e9-e504767f0519"}, @@ -2461,8 +2419,7 @@ } ], "solutions": [ - {"$uuid": "75a74089-99bb-468d-ae71-b8c0b97ce6b3"}, - {"$uuid": "0864463e-eb7c-4bb3-b8bc-766d71ab38b5"} + {"$uuid": "a8e7d3f9-2b5c-4a6e-9d8f-6c1b0a4e3f8d"} ], "resources": [ {"$uuid": "dec03f23-b034-4b2d-80e9-e504767f0519"}, diff --git a/itachallenge-challenge/src/main/resources/mongodb-test-data/solutions.json b/itachallenge-challenge/src/main/resources/mongodb-test-data/solutions.json index d54708e70..8f689d61e 100755 --- a/itachallenge-challenge/src/main/resources/mongodb-test-data/solutions.json +++ b/itachallenge-challenge/src/main/resources/mongodb-test-data/solutions.json @@ -29,6 +29,16 @@ "$uuid": "09fabe32-7362-4bfb-ac05-b7bf854c6e0f" } }, + { + "_id": { + "$uuid" : "9f1d2a4b-3c6e-4d7b-8a9c-5e0f7b3c2a1d" + }, + "solution_text": "String s1 = \"ABCBDAB\";\n String s2 = \"BDCAB\";\n int[][] dp = new int[s1.length() + 1][s2.length() + 1];\n\n for (int i = 1; i <= s1.length(); i++) {\n for (int j = 1; j <= s2.length(); j++) {\n if (s1.charAt(i - 1) == s2.charAt(j - 1)) {\n dp[i][j] = dp[i - 1][j - 1] + 1;\n } else {\n dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);\n }\n }\n }\n\n int index = dp[s1.length()][s2.length()];\n char[] lcs = new char[index];\n int i = s1.length(), j = s2.length();\n while (i > 0 && j > 0) {\n if (s1.charAt(i - 1) == s2.charAt(j - 1)) {\n lcs[index - 1] = s1.charAt(i - 1);\n i--;\n j--;\n index--;\n } else if (dp[i - 1][j] > dp[i][j - 1]) {\n i--;\n } else {\n j--;\n }\n }\n\n System.out.println(new String(lcs));", + "language": + { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + }, { "_id": { "$uuid" : "1682b3e9-056a-45b7-a0e9-eaf1e11775ad" @@ -59,6 +69,36 @@ "$uuid": "409c9fe8-74de-4db3-81a1-a55280cf92ef" } }, + { + "_id": { + "$uuid" : "f7c9e2a1-8b6d-4c3f-a9e0-2d5f8c7b1e4a" + }, + "solution_text": "int number = 16;\n double squareRoot = Math.sqrt(number);\n boolean isSquareNumber = squareRoot == Math.floor(squareRoot);\n System.out.println(isSquareNumber);", + "language": + { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + }, + { + "_id": { + "$uuid" : "9f5d7339-f87b-4d7e-b8e8-c6e850ff7a50" + }, + "solution_text": "Sed dictum. Proin eget odio. Aliquam vulputate ullamcorper magna. Sed eu eros. Nam consequat dolor vitae dolor. Donec fringilla. Donec", + "language": + { + "$uuid": "409c9fe8-74de-4db3-81a1-a55280cf92ef" + } + }, + { + "_id": { + "$uuid" : "c2c2a6c4-83b1-4a8a-82e3-f5cfb64fcfb4" + }, + "solution_text": "Sed dictum. Proin eget odio. Aliquam vulputate ullamcorper magna. Sed eu eros. Nam consequat dolor vitae dolor. Donec fringilla. Donec", + "language": + { + "$uuid": "409c9fe8-74de-4db3-81a1-a55280cf92ef" + } + }, { "_id": { "$uuid" : "d0e7d7dd-8269-41b6-8e97-b66a952dd1e5" @@ -79,11 +119,21 @@ "$uuid": "1e047ea2-b787-49e7-acea-d79e92be3909" } }, + { + "_id": { + "$uuid" : "f3b6c7d8-2e9a-4b1d-8c7e-4f5a9d0c3b2e" + }, + "solution_text": "String expression = \"6 + -(4)\";\n System.out.println(evaluate(expression));\n public static double evaluate(String expression) {\n return parseExpression(tokenize(expression));\n }\n\n private static String[] tokenize(String expression) {\n return expression.replaceAll(\"\\\\s+\", \"\")\n .replaceAll(\"([-+*/()])\", \" $1 \")\n .trim()\n .split(\"\\\\s+\");\n }\n\n private static double parseExpression(String[] tokens) {\n Stack numbers = new Stack<>();\n Stack operations = new Stack<>();\n\n for (String token : tokens) {\n if (token.matches(\"-?\\\\d+(\\\\.\\\\d+)?\")) {\n numbers.push(Double.parseDouble(token));\n } else if (token.equals(\"(\")) {\n operations.push('(');\n } else if (token.equals(\")\")) {\n while (operations.peek() != '(') {\n numbers.push(applyOp(operations.pop(), numbers.pop(), numbers.pop()));\n }\n operations.pop();\n } else if (\"+-*/\".contains(token)) {\n while (!operations.isEmpty() && hasPrecedence(token.charAt(0), operations.peek())) {\n numbers.push(applyOp(operations.pop(), numbers.pop(), numbers.pop()));\n }\n operations.push(token.charAt(0));\n }\n }\n\n while (!operations.isEmpty()) {\n numbers.push(applyOp(operations.pop(), numbers.pop(), numbers.pop()));\n }\n\n return numbers.pop();\n }\n\n private static boolean hasPrecedence(char op1, char op2) {\n if (op2 == '(' || op2 == ')') return false;\n if ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-')) return false;\n return true;\n }\n\n private static double applyOp(char op, double b, double a) {\n switch (op) {\n case '+':\n return a + b;\n case '-':\n return a - b;\n case '*':\n return a * b;\n case '/':\n if (b == 0) throw new UnsupportedOperationException(\"Cannot divide by zero\");\n return a / b;\n }\n return 0;\n }", + "language": + { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + }, { "_id": { "$uuid" : "75a74089-99bb-468d-ae71-b8c0b97ce6b3" }, - "solution_text": "import java.util.Arrays;\n\npublic class DescendingOrder {\n public static void main(String[] args) {\n int number = 583209;\n int result = descendingOrder(number);\n System.out.println(result);\n }\n\n public static int descendingOrder(int num) {\n // Convert the number to a char array\n char[] digits = String.valueOf(num).toCharArray();\n\n // Sort the array in descending order\n Arrays.sort(digits);\n StringBuilder result = new StringBuilder(new String(digits));\n result.reverse();\n\n // Convert the result back to an integer\n return Integer.parseInt(result.toString());\n }\n}\n", + "solution_text": "int numero = 2345;\n int[] conteoDigitos = new int[10];\n while (numero > 0) {\n int digito = numero % 10;\n conteoDigitos[digito]++;\n numero /= 10;\n }\n\n int resultado = 0;\n for (int i = 9; i >= 0; i--) {\n while (conteoDigitos[i] > 0) {\n resultado = resultado * 10 + i;\n conteoDigitos[i]--;\n }\n }\n\n System.out.println(resultado);", "language": { "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" @@ -93,7 +143,7 @@ "_id": { "$uuid" : "0864463e-eb7c-4bb3-b8bc-766d71ab38b5" }, - "solution_text": "public class HighLowNumbers {\n public static void main(String[] args) {\n String numbersString = \"4 5 29 54 4 0 -214 542 -64 1 -3 6 -6\";\n String result = findHighAndLow(numbersString);\n System.out.println(result);\n }\n\n public static String findHighAndLow(String numbersString) {\n String[] numbersArray = numbersString.split(\" \");\n\n int[] numbers = new int[numbersArray.length];\n for (int i = 0; i < numbersArray.length; i++) {\n numbers[i] = Integer.parseInt(numbersArray[i]);\n }\n\n int max = Arrays.stream(numbers).max().getAsInt();\n int min = Arrays.stream(numbers).min().getAsInt();\n\n return \"Max: \" + max + \", Min: \" + min;\n }\n}\n", + "solution_text": "public static String findHighAndLow(String numbers) {\n int[] numArray = Arrays.stream(numbers.split(\" \"))\n .mapToInt(Integer::parseInt)\n .toArray();\n \n int max = Arrays.stream(numArray).max().getAsInt();\n int min = Arrays.stream(numArray).min().getAsInt();\n \n return max + \" \" + min;\n }", "language": { "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" @@ -109,14 +159,160 @@ "$uuid": "09fabe32-7362-4bfb-ac05-b7bf854c6e0f" } }, + { + "_id": { + "$uuid" : "d6a5b2c1-9e8d-4f7c-a3b0-1e9f8c2d5a4b" + }, + "solution_text": "String sentence = \"Hello, world! This is a test.\";\n String[] words = sentence.split(\" \");\n String result = \"\";\n\n for (String word : words) {\n String firstLetter = word.substring(0, 1);\n String restOfWord = word.substring(1);\n result += restOfWord + firstLetter + \"ay \";\n }\n\n System.out.println(result.trim());", + "language": + { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + }, { "_id": { "$uuid" : "b3b2c8d7-4d0e-4f4d-b240-55d6a038d52e" }, - "solution_text": "public class HighLowNumbers {\n public static void main(String[] args) {\n String numbersString = \"4 5 29 54 4 0 -214 542 -64 1 -3 6 -6\";\n String result = findHighAndLow(numbersString);\n System.out.println(result);\n }\n\n public static String findHighAndLow(String numbersString) {\n String[] numbersArray = numbersString.split(\" \");\n\n int[] numbers = new int[numbersArray.length];\n for (int i = 0; i < numbersArray.length; i++) {\n numbers[i] = Integer.parseInt(numbersArray[i]);\n }\n\n int max = Arrays.stream(numbers).max().getAsInt();\n int min = Arrays.stream(numbers).min().getAsInt();\n\n return \"Max: \" + max + \", Min: \" + min;\n }\n}\n", + "solution_text": "Sed dictum. Proin eget odio. Aliquam vulputate ullamcorper magna. Sed eu eros. Nam consequat dolor vitae dolor. Donec fringilla. Donec", "language": { "$uuid": "09fabe32-7362-4bfb-ac05-b7bf854c6e0f" } + }, + { + "_id": { + "$uuid" : "e1a9f2b8-7c3d-4e9b-8a1f-99c6d5f17a83" + }, + "solution_text": "String input = \"Dermatoglyphics\";\n input = input.toLowerCase();\n boolean isIsogram = true;\n\n for (int i = 0; i < input.length() && isIsogram; i++) {\n for (int j = i + 1; j < input.length(); j++) {\n if (input.charAt(i) == input.charAt(j)) {\n isIsogram = false;\n }\n }\n }\n\n System.out.println(isIsogram);", + "language": + { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + }, + { + "_id": { + "$uuid": "36ffd264-9eca-48c1-8cdd-09f190d7adca" + }, + "solution_text": " int[][] testCases = {\n {255, 255, 255}, // \"FFFFFF\"\n {255, 255, 300}, // \"FFFFFF\"\n {0, 0, 0}, // \"000000\"\n {148, 0, 211} // \"9400D3\"\n };\n\n for (int[] testCase : testCases) {\n int r = testCase[0];\n int g = testCase[1];\n int b = testCase[2];\n \n r = Math.max(0, Math.min(255, r));\n g = Math.max(0, Math.min(255, g));\n b = Math.max(0, Math.min(255, b));\n \n String hex = String.format(\"%02X%02X%02X\", r, g, b);\n\n System.out.println(hex);\n }", + "language": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + }, + { + "_id": { + "$uuid": "9151e4cf-8195-4ad5-9363-b378aa322d31" + }, + "solution_text": "public static List filterList(List list) {\n List result = new ArrayList<>();\n for (Object item : list) {\n if (item instanceof Integer && (Integer) item >= 0) {\n result.add((Integer) item);\n }\n }\n return result;\n }", + "language": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + }, + { + "_id": { + "$uuid": "6ab78fab-642a-4e25-baf0-4890794dd8e2" + }, + "solution_text": "public static String getMiddleCharacter(String word) {\n int length = word.length();\n int middle = length / 2;\n\n if (length % 2 == 0) {\n return word.substring(middle - 1, middle + 1);\n } else {\n return String.valueOf(word.charAt(middle));\n }\n }", + "language": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + }, + { + "_id": { + "$uuid": "ce76eeb5-1a1f-4aa5-908a-dcf229c1f48f" + }, + "solution_text": "public static double calculateExpression(int n) {\n if (n < 1) {\n throw new IllegalArgumentException(\"n debe ser mayor o igual a 1\");\n }\n\n long factorialSum = 0;\n long factorial = 1;\n\n for (int i = 1; i <= n; i++) {\n factorial *= i;\n factorialSum += factorial;\n }\n\n return (double) factorialSum / nFactorial;\n }", + "language": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + }, + { + "_id": { + "$uuid": "d0f57f27-a5e0-49f6-8a72-24ad9a497b8d" + }, + "solution_text": "public static int calculatePerimeter(String[] arr) {\n int rows = arr.length;\n int cols = arr[0].length();\n int perimeter = 0;\n\n for (int i = 0; i < rows; i++) {\n for (int j = 0; j < cols; j++) {\n if (arr[i].charAt(j) == 'X') {\n if (i == 0 || arr[i - 1].charAt(j) == 'O') {\n perimeter++;\n }\n if (i == rows - 1 || arr[i + 1].charAt(j) == 'O') {\n perimeter++;\n }\n if (j == 0 || arr[i].charAt(j - 1) == 'O') {\n perimeter++;\n }\n if (j == cols - 1 || arr[i].charAt(j + 1) == 'O') {\n perimeter++;\n }\n }\n }\n }\n\n return perimeter;\n }", + "language": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + }, + { + "_id": { + "$uuid": "d624bae4-9a43-4515-8979-801c0d6fd88c" + }, + "solution_text": "String[] ejemplos = {\n \"aaabbbccc\",\n \"aabbccdd\",\n \"zzzzyyyyyx\",\n \"abcdeeffff\"\n };\n\n for (String input : ejemplos) {\n \n if (input == null || input.length() == 0) {\n System.out.println(input + \": \" + input);\n continue;\n }\n\n StringBuilder resultado = new StringBuilder();\n char currentChar = input.charAt(0);\n int count = 1;\n\n for (int i = 1; i < input.length(); i++) {\n if (input.charAt(i) == currentChar) {\n count++;\n } else {\n resultado.append(currentChar);\n if (count > 1) {\n resultado.append(count);\n }\n currentChar = input.charAt(i);\n count = 1;\n }\n }\n\n resultado.append(currentChar);\n if (count > 1) {\n resultado.append(count);\n }\n\n System.out.println(input + \": \" + resultado.toString());\n }", + "language": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + }, + { + "_id": { + "$uuid": "ea837e7d-3d39-42f1-a795-bfc1e928567b" + }, + "solution_text": "String[] ejemplos = {\n \"(2 + 3) * 4\",\n \"(2 + 3 * 4\",\n \"5 * (3 + (2 - 5))\",\n \"2 + )3 * 4(\",\n \"2 * 3\",\n \"2 & 3\",\n \"((3 + 4) * 2) / (5 - 2)\",\n \"((3 + 4) * 2 / (5 - 2\"\n };\n\n for (String expresion : ejemplos) {\n // Verificar paréntesis balanceados\n boolean paréntesisBalanceados = true;\n Stack stack = new Stack<>();\n for (char c : expresion.toCharArray()) {\n if (c == '(') {\n stack.push(c);\n } else if (c == ')') {\n if (stack.isEmpty()) {\n paréntesisBalanceados = false;\n break;\n }\n stack.pop();\n }\n }\n if (!stack.isEmpty()) {\n paréntesisBalanceados = false;\n }\n\n \n boolean operadoresValidos = true;\n String operadores = \"+-*/\";\n String validChars = \"0123456789+-*/() \";\n for (int i = 0; i < expresion.length(); i++) {\n char c = expresion.charAt(i);\n if (validChars.indexOf(c) == -1) {\n operadoresValidos = false;\n break;\n }\n\n if (operadores.indexOf(c) != -1) {\n if (i == 0 || i == expresion.length() - 1) {\n operadoresValidos = false; // Un operador no puede estar al principio o al final\n break;\n }\n char anterior = expresion.charAt(i - 1);\n char siguiente = expresion.charAt(i + 1);\n if (operadores.indexOf(anterior) != -1 || operadores.indexOf(siguiente) != -1) {\n operadoresValidos = false; // No puede haber dos operadores seguidos\n break;\n }\n }\n }\n\n \n boolean esValida = paréntesisBalanceados && operadoresValidos;\n System.out.println(expresion + \": \" + (esValida ? \"Válida\" : \"Inválida\"));\n }", + "language": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + }, + { + "_id": { + "$uuid": "429866e1-c489-4500-a458-d46ed62b26be" + }, + "solution_text": "public static int findEquilibriumIndex(int[] arr) {\n int totalSum = 0;\n int leftSum = 0;\n\n for (int num : arr) {\n totalSum += num;\n }\n\n for (int i = 0; i < arr.length; i++) {\n totalSum -= arr[i];\n\n if (leftSum == totalSum) {\n return i;\n }\n\n leftSum += arr[i];\n }\n\n return -1;\n }", + "language": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + }, + { + "_id": { + "$uuid": "a8e7d3f9-2b5c-4a6e-9d8f-6c1b0a4e3f8d" + }, + "solution_text": "int[] array = {2, 4, 1, 3, 5};\n int inversionCount = 0;\n for (int i = 0; i < array.length; i++) {\n for (int j = i + 1; j < array.length; j++) {\n if (array[i] > array[j]) {\n inversionCount++;\n }\n }\n }\n System.out.println(inversionCount);", + "language": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + }, + { + "_id": { + "$uuid": "edd8283a-3978-4657-b776-ff75536e231d" + }, + "solution_text": "String[] str1Array = {\"rkqodlw\", \"cedewaraaossoqqyt\", \"katas\", \"adios\"};\n String[] str2Array = {\"world\", \"codewars\", \"steak\", \"hola\"};\n\n for (int i = 0; i < str1Array.length; i++) {\n String str1 = str1Array[i];\n String str2 = str2Array[i];\n\n \n int[] count = new int[26]; // Hay 26 letras en el alfabeto inglés\n\n \n for (char c : str1.toCharArray()) {\n count[c - 'a']++;\n }\n\n \n boolean esValido = true;\n for (char c : str2.toCharArray()) {\n if (count[c - 'a'] == 0) {\n esValido = false; // No hay suficientes caracteres en str1 para formar str2\n break;\n }\n count[c - 'a']--;\n }\n\n \n System.out.println(str1 + \" / \" + str2 + \" - \" + (esValido ? \"True\" : \"False\"));\n }", + "language": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + }, + { + "_id": { + "$uuid": "046791ae-7355-4fc8-a696-4f9665eac927" + }, + "solution_text": " try {\n \n System.out.print(\"Introduce un número: \");\n StringBuilder inputBuilder = new StringBuilder();\n int ch;\n while ((ch = System.in.read()) != '\\n') {\n if (ch != '\\r') { // Ignorar los retornos de carro\n inputBuilder.append((char) ch);\n }\n }\n String input = inputBuilder.toString().trim();\n int N = Integer.parseInt(input);\n\n \n int ceros = 0;\n\n \n for (int i = 5; N / i >= 1; i *= 5) {\n ceros += N / i;\n }\n\n \n System.out.println(\"El número de ceros finales en \" + N + \"! es: \" + ceros);\n } catch (Exception e) {\n System.out.println(\"Error: \" + e.getMessage());\n }", + "language": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + }, + { + "_id": { + "$uuid": "396d1164-85c5-470a-8977-fc68b9b26fb1" + }, + "solution_text": "String[] testCases = {\"xxoo\", \"OxoO\", \"xxooxxoo\", \"xXoO\", \"abcd\"};\n\n for (String str : testCases) {\n // Inicializar contadores para 'x' y 'o'\n int countX = 0;\n int countO = 0;\n\n str = str.toLowerCase();\n \n for (int i = 0; i < str.length(); i++) {\n char c = str.charAt(i);\n if (c == 'x') {\n countX++;\n } else if (c == 'o') {\n countO++;\n }\n }\n \n boolean result = countX == countO;\n \n System.out.println( str + \": \" + result);\n }", + "language": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + }, + { + "_id": { + "$uuid": "6b1df7af-f32f-4f2b-8f97-7d7430874d34" + }, + "solution_text": " int[][] testCases = {\n {-2, 1, -3, 4, -1, 2, 1, -5, 4},\n {1, -2, 3, 5, -3, 2},\n {5, -3, 5},\n {0, -2, -3, -4, -1, -2, -3, -5, -4},\n {1, 2, 3, 4, 5},\n {-1, -2, -3, -4, -5},\n {2, -3, 4, -1, -2, 1, 5, -3},\n {1, -1, 1, -1, 1, -1, 1, -1}\n };\n\n for (int[] arr : testCases) {\n int maxSoFar = arr[0];\n int maxEndingHere = arr[0];\n int start = 0, end = 0, s = 0;\n\n for (int i = 1; i < arr.length; i++) {\n if (arr[i] > maxEndingHere + arr[i]) {\n maxEndingHere = arr[i];\n s = i;\n } else {\n maxEndingHere += arr[i];\n }\n\n if (maxEndingHere > maxSoFar) {\n maxSoFar = maxEndingHere;\n start = s;\n end = i;\n }\n }\n\n \n System.out.print(\"El subarray contiguo más grande es [\");\n for (int i = start; i <= end; i++) {\n System.out.print(arr[i] + (i < end ? \", \" : \"\"));\n }\n System.out.println(\"] con una suma de \" + maxSoFar);\n }", + "language": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } + }, + { + "_id": { + "$uuid": "2d423ff6-93fe-483d-bc86-9d8c58552942" + }, + "solution_text": "public static int[] findSmallestNumber(String numStr) {\n //String numStr = String.valueOf(n);\n int len = numStr.length();\n int[] result = {Integer.parseInt(numStr), 0, 0}; // Default result if no changes are needed\n\n for (int i = 0; i < len; i++) {\n for (int j = 0; j < len; j++) {\n if (i != j) {\n String newNumStr = moveDigit(numStr, i, j);\n int newNum = Integer.parseInt(newNumStr);\n if (newNum < result[0]) {\n result[0] = newNum;\n result[1] = i;\n result[2] = j;\n }\n }\n }\n }\n return result;\n }\n\n public static String moveDigit(String numStr, int i, int j) {\n StringBuilder sb = new StringBuilder(numStr);\n char digit = sb.charAt(i);\n sb.deleteCharAt(i);\n sb.insert(j, digit);\n return sb.toString();\n }", + "language": { + "$uuid": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + } } ] From 9b84f3aafbaf9adecc7441a52a052e590b4ab17c Mon Sep 17 00:00:00 2001 From: Marcos Pagliaruzza Date: Tue, 16 Jul 2024 09:56:53 +0200 Subject: [PATCH 10/21] Added getAllSolutionsByIdUser endpoint FIX Test#2 --- .../user/helper/ConverterDocumentToDto.java | 1 - .../helper/ConverterDocumentToDtoTest.java | 49 ++++++++++++++----- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/itachallenge-user/src/main/java/com/itachallenge/user/helper/ConverterDocumentToDto.java b/itachallenge-user/src/main/java/com/itachallenge/user/helper/ConverterDocumentToDto.java index 3378fb7f2..00da6afb1 100755 --- a/itachallenge-user/src/main/java/com/itachallenge/user/helper/ConverterDocumentToDto.java +++ b/itachallenge-user/src/main/java/com/itachallenge/user/helper/ConverterDocumentToDto.java @@ -33,5 +33,4 @@ public Flux fromUserSolutionDocumentToUserSolutionDto(UserSolut .solutionText(document.getSolutionDocument().get(0).getSolutionText()) .build()); } - } diff --git a/itachallenge-user/src/test/java/com/itachallenge/user/helper/ConverterDocumentToDtoTest.java b/itachallenge-user/src/test/java/com/itachallenge/user/helper/ConverterDocumentToDtoTest.java index c508f18bb..d2bac5b87 100755 --- a/itachallenge-user/src/test/java/com/itachallenge/user/helper/ConverterDocumentToDtoTest.java +++ b/itachallenge-user/src/test/java/com/itachallenge/user/helper/ConverterDocumentToDtoTest.java @@ -16,9 +16,9 @@ import reactor.core.publisher.Flux; import reactor.test.StepVerifier; +import java.util.Collections; import java.util.List; import java.util.UUID; -import java.util.stream.Collectors; @ExtendWith(SpringExtension.class) @SpringBootTest @@ -41,6 +41,9 @@ class ConverterDocumentToDtoTest { List solutionDocumentList = List.of(solutionDocument1, solutionDocument2, solutionDocument3); UserSolutionDocument userScoreDocument = new UserSolutionDocument(uuid_1, idUser, idChallenge, idLanguage, true, ChallengeStatus.STARTED, 90, solutionDocumentList); + SolutionDocument solutionDocument = new SolutionDocument(); + UserSolutionDocument userSolutionDocument = new UserSolutionDocument(); + @DisplayName("Convertir un objeto UserScoreDocument en un objeto UserScoreDto") @Test @@ -62,18 +65,38 @@ private boolean ValidateUserScoreDto(@NotNull UserScoreDto userScoreDto, @NotNul userScoreDto.getLanguageID().equals(userScoreDocument.getLanguageId()); } - public Flux fromUserSolutionDocumentToUserSolutionDto(UserSolutionDocument userSolutionDocument) { - return Flux.fromIterable( - userSolutionDocument.getSolutionDocument().stream() - .map(solution -> UserSolutionDto.builder() - .userId(userSolutionDocument.getUserId().toString()) - .challengeId(userSolutionDocument.getChallengeId().toString()) - .languageId(userSolutionDocument.getLanguageId().toString()) - .status(userSolutionDocument.getStatus().toString()) - .solutionText(solution.getSolutionText()) - .build()) - .collect(Collectors.toList()) - ); + @Test + public void testFromUserSolutionDocumentToUserSolutionDto() { + solutionDocument.setSolutionText("Sample Solution Text"); + + userSolutionDocument.setUserId(UUID.randomUUID()); + userSolutionDocument.setChallengeId(UUID.randomUUID()); + userSolutionDocument.setLanguageId(UUID.randomUUID()); + userSolutionDocument.setStatus(ChallengeStatus.STARTED); + userSolutionDocument.setSolutionDocument(Collections.singletonList(solutionDocument)); + + Flux userSolutionDtoFlux = fromUserSolutionDocumentToUserSolutionDto(userSolutionDocument); + + StepVerifier.create(userSolutionDtoFlux) + .expectNextMatches(dto -> + dto.getUserId().equals(userSolutionDocument.getUserId().toString()) && + dto.getChallengeId().equals(userSolutionDocument.getChallengeId().toString()) && + dto.getLanguageId().equals(userSolutionDocument.getLanguageId().toString()) && + dto.getStatus().equals(userSolutionDocument.getStatus().toString()) && // Convert status to string + dto.getSolutionText().equals(solutionDocument.getSolutionText()) + ) + .expectComplete() + .verify(); } + public Flux fromUserSolutionDocumentToUserSolutionDto(@NotNull UserSolutionDocument document) { + return Flux.just(UserSolutionDto.builder() + .userId(document.getUserId().toString()) + .challengeId(document.getChallengeId().toString()) + .languageId(document.getLanguageId().toString()) + .status(document.getStatus().toString()) + .solutionText(document.getSolutionDocument().get(0).getSolutionText()) + .build()); + } } + From 3d91e842fae3a731f2de97bad7dd02bd8f1069e3 Mon Sep 17 00:00:00 2001 From: Marcos Pagliaruzza Date: Tue, 16 Jul 2024 10:15:35 +0200 Subject: [PATCH 11/21] Added getAllSolutionsByIdUser endpoint FIX Test#3 --- .../itachallenge/user/helper/ConverterDocumentToDtoTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/itachallenge-user/src/test/java/com/itachallenge/user/helper/ConverterDocumentToDtoTest.java b/itachallenge-user/src/test/java/com/itachallenge/user/helper/ConverterDocumentToDtoTest.java index d2bac5b87..3d4b86412 100755 --- a/itachallenge-user/src/test/java/com/itachallenge/user/helper/ConverterDocumentToDtoTest.java +++ b/itachallenge-user/src/test/java/com/itachallenge/user/helper/ConverterDocumentToDtoTest.java @@ -65,6 +65,7 @@ private boolean ValidateUserScoreDto(@NotNull UserScoreDto userScoreDto, @NotNul userScoreDto.getLanguageID().equals(userScoreDocument.getLanguageId()); } + @DisplayName("Convert an object UserSolutionDocument to an object UserSolutionDocumentDto") @Test public void testFromUserSolutionDocumentToUserSolutionDto() { solutionDocument.setSolutionText("Sample Solution Text"); @@ -82,7 +83,7 @@ public void testFromUserSolutionDocumentToUserSolutionDto() { dto.getUserId().equals(userSolutionDocument.getUserId().toString()) && dto.getChallengeId().equals(userSolutionDocument.getChallengeId().toString()) && dto.getLanguageId().equals(userSolutionDocument.getLanguageId().toString()) && - dto.getStatus().equals(userSolutionDocument.getStatus().toString()) && // Convert status to string + dto.getStatus().equals(userSolutionDocument.getStatus().toString()) && dto.getSolutionText().equals(solutionDocument.getSolutionText()) ) .expectComplete() From feaf1106c10c2127ce69275db0bdb9fb6cac079e Mon Sep 17 00:00:00 2001 From: Marcos Pagliaruzza Date: Tue, 16 Jul 2024 10:29:55 +0200 Subject: [PATCH 12/21] Added getAllSolutionsByIdUser endpoint FIX Test#4 --- .../helper/ConverterDocumentToDtoTest.java | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/itachallenge-user/src/test/java/com/itachallenge/user/helper/ConverterDocumentToDtoTest.java b/itachallenge-user/src/test/java/com/itachallenge/user/helper/ConverterDocumentToDtoTest.java index 3d4b86412..df8c7e344 100755 --- a/itachallenge-user/src/test/java/com/itachallenge/user/helper/ConverterDocumentToDtoTest.java +++ b/itachallenge-user/src/test/java/com/itachallenge/user/helper/ConverterDocumentToDtoTest.java @@ -65,7 +65,7 @@ private boolean ValidateUserScoreDto(@NotNull UserScoreDto userScoreDto, @NotNul userScoreDto.getLanguageID().equals(userScoreDocument.getLanguageId()); } - @DisplayName("Convert an object UserSolutionDocument to an object UserSolutionDocumentDto") + @DisplayName("Convert an object UserSolutionDocument to an object UserSolutionDto") @Test public void testFromUserSolutionDocumentToUserSolutionDto() { solutionDocument.setSolutionText("Sample Solution Text"); @@ -76,28 +76,20 @@ public void testFromUserSolutionDocumentToUserSolutionDto() { userSolutionDocument.setStatus(ChallengeStatus.STARTED); userSolutionDocument.setSolutionDocument(Collections.singletonList(solutionDocument)); - Flux userSolutionDtoFlux = fromUserSolutionDocumentToUserSolutionDto(userSolutionDocument); + Flux userSolutionDtoFlux = converter.fromUserSolutionDocumentToUserSolutionDto(userSolutionDocument); StepVerifier.create(userSolutionDtoFlux) - .expectNextMatches(dto -> - dto.getUserId().equals(userSolutionDocument.getUserId().toString()) && - dto.getChallengeId().equals(userSolutionDocument.getChallengeId().toString()) && - dto.getLanguageId().equals(userSolutionDocument.getLanguageId().toString()) && - dto.getStatus().equals(userSolutionDocument.getStatus().toString()) && - dto.getSolutionText().equals(solutionDocument.getSolutionText()) - ) + .expectNextMatches(userSolutionDto -> validateUserSolutionDto(userSolutionDto, userSolutionDocument)) .expectComplete() .verify(); } - public Flux fromUserSolutionDocumentToUserSolutionDto(@NotNull UserSolutionDocument document) { - return Flux.just(UserSolutionDto.builder() - .userId(document.getUserId().toString()) - .challengeId(document.getChallengeId().toString()) - .languageId(document.getLanguageId().toString()) - .status(document.getStatus().toString()) - .solutionText(document.getSolutionDocument().get(0).getSolutionText()) - .build()); + private boolean validateUserSolutionDto(@NotNull UserSolutionDto userSolutionDto, @NotNull UserSolutionDocument userSolutionDocument) { + return userSolutionDto.getUserId().equals(userSolutionDocument.getUserId().toString()) && + userSolutionDto.getChallengeId().equals(userSolutionDocument.getChallengeId().toString()) && + userSolutionDto.getLanguageId().equals(userSolutionDocument.getLanguageId().toString()) && + userSolutionDto.getStatus().equals(userSolutionDocument.getStatus().toString()) && + userSolutionDto.getSolutionText().equals(userSolutionDocument.getSolutionDocument().get(0).getSolutionText()); } } From 69c057e5268b0cd3158ce22cfc534fc488f6621b Mon Sep 17 00:00:00 2001 From: DaniD Date: Sat, 20 Jul 2024 07:27:32 +0200 Subject: [PATCH 13/21] Added Test to function getChallengeById --- .../user/dtos/SolutionUserDto.java | 3 +- .../service/UserSolutionServiceImpTest.java | 35 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/itachallenge-user/src/main/java/com/itachallenge/user/dtos/SolutionUserDto.java b/itachallenge-user/src/main/java/com/itachallenge/user/dtos/SolutionUserDto.java index 98a32296b..b7131ba97 100755 --- a/itachallenge-user/src/main/java/com/itachallenge/user/dtos/SolutionUserDto.java +++ b/itachallenge-user/src/main/java/com/itachallenge/user/dtos/SolutionUserDto.java @@ -6,7 +6,8 @@ import org.springframework.stereotype.Component; @Component -@Getter @Setter +@Getter +@Setter @NoArgsConstructor public class SolutionUserDto { diff --git a/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java b/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java index 5b735b690..d6e8e89cb 100644 --- a/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java +++ b/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java @@ -2,10 +2,13 @@ import com.itachallenge.user.document.SolutionDocument; import com.itachallenge.user.document.UserSolutionDocument; +import com.itachallenge.user.dtos.SolutionUserDto; +import com.itachallenge.user.dtos.UserScoreDto; import com.itachallenge.user.dtos.UserSolutionDto; import com.itachallenge.user.dtos.UserSolutionScoreDto; import com.itachallenge.user.enums.ChallengeStatus; import com.itachallenge.user.exception.UnmodifiableSolutionException; +import com.itachallenge.user.helper.ConverterDocumentToDto; import com.itachallenge.user.repository.IUserSolutionRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -15,10 +18,12 @@ import org.junit.jupiter.params.provider.NullSource; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.mockito.InjectMocks; +import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -32,10 +37,13 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureWebTestClient @ExtendWith(SpringExtension.class) +@ExtendWith(MockitoExtension.class) class UserSolutionServiceImpTest { @Mock IUserSolutionRepository userSolutionRepository; + @Mock + ConverterDocumentToDto converterDocumentToDto; @InjectMocks UserSolutionServiceImp userSolutionService; @@ -46,6 +54,7 @@ class UserSolutionServiceImpTest { private int mockScore; private UserSolutionDto userSolutionDto; private UserSolutionDocument userSolutionDocument; + private ConverterDocumentToDto converter = new ConverterDocumentToDto(); @BeforeEach void setUp() { @@ -95,6 +104,32 @@ void markAsBookmarked() { } + @DisplayName("UserSolutionServiceImpTest - getChallengeById returns a SolutionUserDto when a valid document is found") + @Test + void getChallengeByIdValidDocument_test() { + + UserSolutionDocument userSolutionDocument = UserSolutionDocument.builder() + .userId(userUuid) + .challengeId(challengeUuid) + .languageId(languageUuid) + .status(ChallengeStatus.ENDED) + .solutionDocument(List.of(SolutionDocument.builder().solutionText(solutionText).build())) + .score(mockScore) + .build(); + when(userSolutionRepository.findByUserId(userUuid)).thenReturn(Flux.just(userSolutionDocument)); + UserSolutionServiceImp userSolutionServiceImp = new UserSolutionServiceImp(userSolutionRepository, converter); + + Mono> challengeById = userSolutionServiceImp.getChallengeById(userUuid.toString(), challengeUuid.toString(), languageUuid.toString()); + + assertNotNull(challengeById); + StepVerifier.create(challengeById) + .expectNextMatches(solutionUserDto -> solutionUserDto.getCount() == 1 + && solutionUserDto.getLimit() == 1 + && solutionUserDto.getOffset() == 0 + && solutionUserDto.getResults().length == 1) + .verifyComplete(); + } + @DisplayName("UserSolutionServiceImpTest - addSolution creates a new document when existing document can't be found and status is empty or ENDED") @ParameterizedTest @NullSource From 29c1de2fe4452a80ad2d47969a31c09510debb00 Mon Sep 17 00:00:00 2001 From: DaniD Date: Sat, 20 Jul 2024 07:38:19 +0200 Subject: [PATCH 14/21] Added Test to function getChallengeById --- .../user/controller/UserControllerTest.java | 313 ++++++++++++++++++ 1 file changed, 313 insertions(+) create mode 100644 itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java diff --git a/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java b/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java new file mode 100644 index 000000000..cbd6c37dd --- /dev/null +++ b/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java @@ -0,0 +1,313 @@ +package com.itachallenge.user.controller; + +import com.itachallenge.user.document.UserSolutionDocument; +import com.itachallenge.user.dtos.*; +import com.itachallenge.user.exception.UnmodifiableSolutionException; +import com.itachallenge.user.dtos.*; +import com.itachallenge.user.service.IServiceChallengeStatistics; +import com.itachallenge.user.service.IUserSolutionService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.core.env.Environment; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.reactive.server.WebTestClient; +import reactor.core.publisher.Mono; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureWebTestClient +@ExtendWith(SpringExtension.class) +@ActiveProfiles("test") +class UserControllerTest { + @Autowired + private WebTestClient webTestClient; + + @Autowired + UserController userController; + + @Autowired + Environment env; + + private static final String CONTROLLER_URL = "/itachallenge/api/v1/user"; + + @MockBean + IUserSolutionService userSolutionService; + @MockBean + IServiceChallengeStatistics statisticsService; + + @BeforeEach + public void setUp() { + } + + @Test + void testHello() { + String URI_TEST = "/test"; + + webTestClient.get() + .uri(CONTROLLER_URL + URI_TEST) + .accept(MediaType.APPLICATION_JSON) + .exchange() + .expectStatus().isEqualTo(HttpStatus.OK) + .expectBody(String.class) + .value(String::toString, equalTo("Hello from ITA User!!!")); + } + + //TODO: This test needs mocking. Is calling actual service + /* @Test + void getChallengeStatistics() { + String URI_TEST = "/statistics?"; + URI_TEST += queryCreation(10); + List response = webTestClient.get() + .uri(CONTROLLER_URL + URI_TEST) + .accept(MediaType.APPLICATION_JSON) + .exchange() + .expectStatus().isEqualTo(HttpStatus.OK) + .expectHeader().contentType(MediaType.APPLICATION_JSON) + .expectBodyList(ChallengeStatisticsDto.class) + .returnResult().getResponseBody(); + assertEquals(10, response.size()); + assertNotEquals(0, response.get(0).getPopularity()); + assertNotEquals(0, response.get(9).getPercentage()); + }*/ + + //TODO: This test needs mocking. Is calling actual service + @Test + void getChallengeStatistics_URLToLong() { + String URI_TEST = "/statistics?"; + + URI_TEST += queryCreation(100); + + webTestClient.get() + .uri(CONTROLLER_URL + URI_TEST) + .accept(MediaType.APPLICATION_JSON) + .exchange() + .expectStatus().isEqualTo(HttpStatus.URI_TOO_LONG); + } + + @Test + void getSolutionsByUserIdChallengeIdLanguageId (){ + + String URI_TEST = "/solution/user/{idUser}/challenge/{idChallenge}/language/{idLanguage}"; + + final String VALID_MONGO_UUID = "c3a92f9d-5d10-4f76-8c0b-6d884c549b1c"; + String userId = VALID_MONGO_UUID; + String idLanguage = VALID_MONGO_UUID; + String idChallenge = VALID_MONGO_UUID; + + UserScoreDto userScoreDto = new UserScoreDto(); + SolutionUserDto expectedSolutionUserDto = new SolutionUserDto<>(); + expectedSolutionUserDto.setInfo(0,1,1, new UserScoreDto[]{userScoreDto}); + + when(userSolutionService.getChallengeById(any(),any(),any())).thenReturn(Mono.just(expectedSolutionUserDto)); + + webTestClient.get() + .uri(CONTROLLER_URL + URI_TEST, userId,idLanguage,idChallenge) + .exchange() + .expectStatus().isOk() + .expectBody(SolutionUserDto.class) + .value(dto -> { + assert dto != null; + assert dto.getCount() == 1; + assert dto.getResults() != null; + assert dto.getResults().length == 1; + }); + } + + + //TODO: This test needs mocking. Is calling actual service + @Test + void getChallengeStatistics_EmptyUUIDList() { + String URI_TEST = "/statistics"; + + webTestClient.get() + .uri(uriBuilder -> uriBuilder + .path(CONTROLLER_URL + URI_TEST) + .queryParam("", Collections.EMPTY_LIST) + .build()) + .accept(MediaType.APPLICATION_JSON) + .exchange() + .expectStatus().isEqualTo(HttpStatus.BAD_REQUEST) + .expectBody(ChallengeStatisticsDto.class); + } + + @Test + void testGetBookmarkCountByIdChallenge() { + final UUID VALID_MONGO_UUID = UUID.fromString("5c1a97e5-1cca-4144-9981-2de1fb73b178"); + String URI_TEST = "/bookmarks/{idChallenge}"; + Long testCount = 1L; + + when(statisticsService.getBookmarkCountByIdChallenge(VALID_MONGO_UUID)) + .thenReturn(Mono.just(testCount)); + + webTestClient.get() + .uri(CONTROLLER_URL + URI_TEST, VALID_MONGO_UUID) + .exchange() + .expectStatus().isOk() + .expectBody() + .jsonPath("$.bookmarked").isEqualTo(testCount.intValue()); + } + + /** + * Method to create a query string link "challenge=UUID&", repeat 'numberUUID' times. + * + * @param numberUUID Number of tiems that repeat. + * @return String with query + */ + private String queryCreation(int numberUUID) { + String URI_TEST = String.format("challenge=%s", UUID.randomUUID()); + + for (int i = 1; i < numberUUID; i++) URI_TEST += String.format("&challenge=%s", UUID.randomUUID()); + + return URI_TEST; + } + + @Test + void markOrAddBookmark() { + + BookmarkRequestDto bookmarkRequestDto = new BookmarkRequestDto(); + bookmarkRequestDto.setUuid_challenge("b860f3eb-ef9f-43bf-8c3c-9a5318d26a90"); + bookmarkRequestDto.setUuid_user("26cbe8eb-be68-4eb4-96a6-796168e80ec9"); + bookmarkRequestDto.setUuid_language("df99bae8-4f7f-4054-a957-37a12aa16364"); + bookmarkRequestDto.setBookmarked(true); + when(userSolutionService.markAsBookmarked( + bookmarkRequestDto.getUuid_challenge(), + bookmarkRequestDto.getUuid_language(), + bookmarkRequestDto.getUuid_user(), + bookmarkRequestDto.isBookmarked())) + .thenAnswer(invocation -> { + + UserSolutionDocument userSolutionDocument = new UserSolutionDocument(); + + return Mono.just(userSolutionDocument); + } + + ); + + Mono> responseMono = userController.markOrAddBookmark(bookmarkRequestDto); + + ResponseEntity responseEntity = responseMono.block(); + + assertNotNull(responseEntity); + + assertEquals(HttpStatus.OK, responseEntity.getStatusCode()); + + assertEquals(bookmarkRequestDto, responseEntity.getBody()); + } + + @DisplayName("UserDocumentControllerTest - addSolution - create and return a new document with status 200 OK") + @Test + void addSolutionIfValidSolutionThenSolutionAdded_test() { + String URI_TEST = "/solution"; + UserSolutionDto userSolutionDto = new UserSolutionDto(); + userSolutionDto.setUserId("550e8400-e29b-41d4-a716-446655440001"); + userSolutionDto.setChallengeId("550e8400-e29b-41d4-a716-446655440002"); + userSolutionDto.setLanguageId("550e8400-e29b-41d4-a716-446655440003"); + userSolutionDto.setSolutionText("This is a test solution"); + + UserSolutionScoreDto expectedResponse = new UserSolutionScoreDto(userSolutionDto.getUserId(), + userSolutionDto.getChallengeId(), userSolutionDto.getLanguageId(), + userSolutionDto.getSolutionText(), 13); + + when(userSolutionService.addSolution(userSolutionDto)) + .thenReturn(Mono.just(expectedResponse)); + + webTestClient.put() + .uri(CONTROLLER_URL + URI_TEST) + .contentType(MediaType.APPLICATION_JSON) + .bodyValue(userSolutionDto) + .exchange() + .expectStatus().isEqualTo(HttpStatus.OK) + .expectBody(UserSolutionScoreDto.class) + .value(dto -> { + assert dto != null; + assert dto.getUserId() != null; + assert dto.getChallengeId() != null; + assert dto.getLanguageId() != null; + assert dto.getScore() >= 0; + + verify(userSolutionService).addSolution(userSolutionDto); + }); + } + @DisplayName("UserDocumentControllerTest - addSolution - return 400 BAD REQUEST and don't save if dto is invalid") + @Test + void addSolutionIfInvalidValuesThenBadRequest_test() { + String URI_TEST = "/solution"; + + List testCases = Arrays.asList( + new UserSolutionDto("invalid_uuid", "550e8400-e29b-41d4-a716-446655440002", "550e8400-e29b-41d4-a716-446655440003", null, "This is a test solution"), + new UserSolutionDto("550e8400-e29b-41d4-a716-446655440001", "invalid_uuid", "550e8400-e29b-41d4-a716-446655440003", null, "This is a test solution"), + new UserSolutionDto("550e8400-e29b-41d4-a716-446655440001", "550e8400-e29b-41d4-a716-446655440002", "invalid_uuid", null, "This is a test solution"), + new UserSolutionDto("550e8400-e29b-41d4-a716-446655440001", "550e8400-e29b-41d4-a716-446655440002", "550e8400-e29b-41d4-a716-446655440003", null, ""), + new UserSolutionDto() + ); + + for (UserSolutionDto testCase : testCases) { + webTestClient.put() + .uri(CONTROLLER_URL + URI_TEST) + .contentType(MediaType.APPLICATION_JSON) + .bodyValue(testCase) + .exchange() + .expectStatus().isBadRequest(); + + verifyNoInteractions(userSolutionService); + } + } + @DisplayName("UserDocumentControllerTest - addSolution - return 409 CONFLICT if Service returns UnmodifiableSolutionException") + @Test + void addSolutionServiceThrowsExceptionInternalServerError_test() { + String URI_TEST = "/solution"; + UserSolutionDto userSolutionDto = new UserSolutionDto(); + userSolutionDto.setUserId("550e8400-e29b-41d4-a716-446655440001"); + userSolutionDto.setChallengeId("550e8400-e29b-41d4-a716-446655440002"); + userSolutionDto.setLanguageId("550e8400-e29b-41d4-a716-446655440003"); + userSolutionDto.setStatus("ENDED"); + userSolutionDto.setSolutionText("This is a test solution"); + + when(userSolutionService.addSolution(userSolutionDto)) + .thenReturn(Mono.error(new UnmodifiableSolutionException("Invalid challenge status: status was already ENDED"))); + + webTestClient.put() + .uri(CONTROLLER_URL + URI_TEST) + .contentType(MediaType.APPLICATION_JSON) + .bodyValue(userSolutionDto) + .exchange() + .expectStatus().isEqualTo(HttpStatus.CONFLICT); + } + + @Test + void getVersionTest() { + String expectedVersion = env.getProperty("spring.application.version"); // Obtiene la versión desde el archivo application-test.yml + + webTestClient.get() + .uri("/itachallenge/api/v1/user/version") + .exchange() + .expectStatus().isOk() + .expectBody() + .jsonPath("$.application_name").isEqualTo("itachallenge-user") + .jsonPath("$.version").isEqualTo("1.0-SNAPSHOT"); + } + +} + From 4329eef9186e2c726e37e1de425539bbbdaea06e Mon Sep 17 00:00:00 2001 From: DaniD Date: Sun, 21 Jul 2024 06:44:00 +0200 Subject: [PATCH 15/21] Merge updates in branch feature#535 --- .../user/dtos/SolutionUserDto.java | 3 +- .../exception/GlobalExceptionHandler.java | 7 ++++- .../src/main/resources/application.yml | 6 ++++ .../user/controller/UserControllerTest.java | 31 +++++++++++++++++-- .../service/UserSolutionServiceImpTest.java | 6 ++-- 5 files changed, 45 insertions(+), 8 deletions(-) diff --git a/itachallenge-user/src/main/java/com/itachallenge/user/dtos/SolutionUserDto.java b/itachallenge-user/src/main/java/com/itachallenge/user/dtos/SolutionUserDto.java index b7131ba97..98a32296b 100755 --- a/itachallenge-user/src/main/java/com/itachallenge/user/dtos/SolutionUserDto.java +++ b/itachallenge-user/src/main/java/com/itachallenge/user/dtos/SolutionUserDto.java @@ -6,8 +6,7 @@ import org.springframework.stereotype.Component; @Component -@Getter -@Setter +@Getter @Setter @NoArgsConstructor public class SolutionUserDto { diff --git a/itachallenge-user/src/main/java/com/itachallenge/user/exception/GlobalExceptionHandler.java b/itachallenge-user/src/main/java/com/itachallenge/user/exception/GlobalExceptionHandler.java index 13de0505f..2754c6011 100755 --- a/itachallenge-user/src/main/java/com/itachallenge/user/exception/GlobalExceptionHandler.java +++ b/itachallenge-user/src/main/java/com/itachallenge/user/exception/GlobalExceptionHandler.java @@ -9,6 +9,7 @@ import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.multipart.MaxUploadSizeExceededException; import java.util.stream.Collectors; @@ -48,5 +49,9 @@ public ResponseEntity handleUnmodifiableSolutionException(Unmo public ResponseEntity handleChallengeNotFoundException(ChallengeNotFoundException e) { return ResponseEntity.status(HttpStatus.OK).body(new ErrorResponseDto(e.getMessage())); } +@ExceptionHandler(MaxUploadSizeExceededException.class) + public ResponseEntity handleMaxSizeException(MaxUploadSizeExceededException exc) { + return ResponseEntity.status(HttpStatus.PAYLOAD_TOO_LARGE).body("Payload too large!"); + } -} \ No newline at end of file +} diff --git a/itachallenge-user/src/main/resources/application.yml b/itachallenge-user/src/main/resources/application.yml index d8680d695..7417deaa5 100755 --- a/itachallenge-user/src/main/resources/application.yml +++ b/itachallenge-user/src/main/resources/application.yml @@ -11,6 +11,10 @@ spring: mongodb: uri: mongodb://admin_user:yxRG4sYBDjPFzbh5@localhost:27017/users?authSource=admin uuid-representation: standard + servlet: + multipart: + max-file-size: 2MB + max-request-size: 2MB springdoc: swagger-ui: @@ -22,6 +26,8 @@ springdoc: server: port: 8764 + tomcat: + max-http-form-post-size: 2MB management: endpoints: diff --git a/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java b/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java index a6d3fbbb4..7b42eae83 100644 --- a/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java +++ b/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java @@ -3,7 +3,6 @@ import com.itachallenge.user.document.UserSolutionDocument; import com.itachallenge.user.dtos.*; import com.itachallenge.user.exception.UnmodifiableSolutionException; -import com.itachallenge.user.dtos.*; import com.itachallenge.user.service.IServiceChallengeStatistics; import com.itachallenge.user.service.IUserSolutionService; import org.junit.jupiter.api.BeforeEach; @@ -11,7 +10,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -22,6 +20,7 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.web.multipart.MaxUploadSizeExceededException; import reactor.core.publisher.Mono; import java.util.Arrays; @@ -77,7 +76,9 @@ void testHello() { /* @Test void getChallengeStatistics() { String URI_TEST = "/statistics?"; + URI_TEST += queryCreation(10); + List response = webTestClient.get() .uri(CONTROLLER_URL + URI_TEST) .accept(MediaType.APPLICATION_JSON) @@ -86,6 +87,7 @@ void getChallengeStatistics() { .expectHeader().contentType(MediaType.APPLICATION_JSON) .expectBodyList(ChallengeStatisticsDto.class) .returnResult().getResponseBody(); + assertEquals(10, response.size()); assertNotEquals(0, response.get(0).getPopularity()); assertNotEquals(0, response.get(9).getPercentage()); @@ -327,5 +329,30 @@ void getVersionTest() { .jsonPath("$.version").isEqualTo("1.0-SNAPSHOT"); } + @Test + void addSolutionRequestBodyTooLarge_test() { + String URI_TEST = "/solution"; + + String largeSolutionText = "aLongText"; // 3MB de datos + UserSolutionDto userSolutionDto = new UserSolutionDto(); + userSolutionDto.setUserId("550e8400-e29b-41d4-a716-446655440001"); + userSolutionDto.setChallengeId("550e8400-e29b-41d4-a716-446655440002"); + userSolutionDto.setLanguageId("550e8400-e29b-41d4-a716-446655440003"); + userSolutionDto.setSolutionText(largeSolutionText); + + when(userSolutionService.addSolution(any())) + .thenReturn(Mono.error(new MaxUploadSizeExceededException(2 * 1024 * 1024))); + + webTestClient.put() + .uri(CONTROLLER_URL + URI_TEST) + .contentType(MediaType.APPLICATION_JSON) + .bodyValue(userSolutionDto) + .exchange() + .expectStatus().isEqualTo(HttpStatus.PAYLOAD_TOO_LARGE); + + verify(userSolutionService).addSolution(userSolutionDto); + } } + + diff --git a/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java b/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java index d6e8e89cb..6526307fa 100644 --- a/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java +++ b/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java @@ -124,9 +124,9 @@ void getChallengeByIdValidDocument_test() { assertNotNull(challengeById); StepVerifier.create(challengeById) .expectNextMatches(solutionUserDto -> solutionUserDto.getCount() == 1 - && solutionUserDto.getLimit() == 1 - && solutionUserDto.getOffset() == 0 - && solutionUserDto.getResults().length == 1) + && solutionUserDto.getLimit() == 1 + && solutionUserDto.getOffset() == 0 + && solutionUserDto.getResults().length == 1) .verifyComplete(); } From 6c5875a56ab608906779316d63abb883165c5756 Mon Sep 17 00:00:00 2001 From: DaniD Date: Sun, 21 Jul 2024 07:19:38 +0200 Subject: [PATCH 16/21] Fixing testing in UserSolutionServiceImpTest --- .../user/service/UserSolutionServiceImpTest.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java b/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java index 6526307fa..f378eb126 100644 --- a/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java +++ b/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java @@ -18,7 +18,6 @@ import org.junit.jupiter.params.provider.NullSource; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -37,13 +36,10 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureWebTestClient @ExtendWith(SpringExtension.class) -@ExtendWith(MockitoExtension.class) class UserSolutionServiceImpTest { @Mock IUserSolutionRepository userSolutionRepository; - @Mock - ConverterDocumentToDto converterDocumentToDto; @InjectMocks UserSolutionServiceImp userSolutionService; @@ -54,7 +50,6 @@ class UserSolutionServiceImpTest { private int mockScore; private UserSolutionDto userSolutionDto; private UserSolutionDocument userSolutionDocument; - private ConverterDocumentToDto converter = new ConverterDocumentToDto(); @BeforeEach void setUp() { @@ -108,6 +103,8 @@ void markAsBookmarked() { @Test void getChallengeByIdValidDocument_test() { + ConverterDocumentToDto converter = new ConverterDocumentToDto(); + UserSolutionDocument userSolutionDocument = UserSolutionDocument.builder() .userId(userUuid) .challengeId(challengeUuid) @@ -216,7 +213,7 @@ void addSolutionWithEndedStatusWhenInvalid_test() { StepVerifier.create(userSolutionService.addSolution(userSolutionDto)) .expectErrorMatches( throwable -> throwable instanceof UnmodifiableSolutionException - && throwable.getMessage().equals("Existing solution has status ENDED")).verify(); + && throwable.getMessage().equals("Existing solution has status ENDED")).verify(); verify(userSolutionRepository).findByUserIdAndChallengeIdAndLanguageId(userUuid, challengeUuid, languageUuid); verifyNoMoreInteractions(userSolutionRepository); } @@ -230,9 +227,9 @@ void addSolutionWithInvalidStatus_test(String status) { Mono resultMono = userSolutionService.addSolution(userSolutionDto); StepVerifier.create(resultMono) - .expectErrorMatches( - throwable -> throwable instanceof IllegalArgumentException - && throwable.getMessage().equals("Status not allowed")).verify(); + .expectErrorMatches( + throwable -> throwable instanceof IllegalArgumentException + && throwable.getMessage().equals("Status not allowed")).verify(); verifyNoInteractions(userSolutionRepository); } From df440f972dcac19a5d0a571a0da34eaa3f0159f8 Mon Sep 17 00:00:00 2001 From: DaniD Date: Sun, 21 Jul 2024 07:29:25 +0200 Subject: [PATCH 17/21] Fix issue --- .../itachallenge/user/service/UserSolutionServiceImpTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java b/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java index f378eb126..521e1db78 100644 --- a/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java +++ b/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java @@ -101,11 +101,11 @@ void markAsBookmarked() { @DisplayName("UserSolutionServiceImpTest - getChallengeById returns a SolutionUserDto when a valid document is found") @Test - void getChallengeByIdValidDocument_test() { + void getChallengeByIdTest() { ConverterDocumentToDto converter = new ConverterDocumentToDto(); - UserSolutionDocument userSolutionDocument = UserSolutionDocument.builder() + userSolutionDocument = UserSolutionDocument.builder() .userId(userUuid) .challengeId(challengeUuid) .languageId(languageUuid) From a0ccbc2eb5e1afc93b19b916e37a31da8529bf85 Mon Sep 17 00:00:00 2001 From: Jonatan Vicente Date: Mon, 22 Jul 2024 10:27:57 +0200 Subject: [PATCH 18/21] itachallenge-user-2.2.0-RELEASE --- .../java/com/itachallenge/user/controller/UserController.java | 2 +- itachallenge-user/src/main/resources/application.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/itachallenge-user/src/main/java/com/itachallenge/user/controller/UserController.java b/itachallenge-user/src/main/java/com/itachallenge/user/controller/UserController.java index 84f3cd947..c7f0b072b 100755 --- a/itachallenge-user/src/main/java/com/itachallenge/user/controller/UserController.java +++ b/itachallenge-user/src/main/java/com/itachallenge/user/controller/UserController.java @@ -175,7 +175,7 @@ public Mono>> getVersion() { } - @GetMapping(path = "/{idUser}/challenges") + @GetMapping(path = "/{idUser}/challenges/solutions") @Operation( summary = "Retrieves all user challenges solutions and their status.", description = "Retrieves all user-contributed solutions for all challenges and their status (whether they've finished completing them or not).", diff --git a/itachallenge-user/src/main/resources/application.yml b/itachallenge-user/src/main/resources/application.yml index d8680d695..1e0254c8c 100755 --- a/itachallenge-user/src/main/resources/application.yml +++ b/itachallenge-user/src/main/resources/application.yml @@ -1,7 +1,7 @@ spring: application: name: itachallenge-user - version: 2.1.0-RELEASE + version: 2.2.0-RELEASE autoconfigure: exclude: - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration From 01d7e3c6d23ac7af8dcd4f4576c2a4f7f2a2f2cd Mon Sep 17 00:00:00 2001 From: invictuzzzzz Date: Mon, 22 Jul 2024 12:05:00 +0200 Subject: [PATCH 19/21] clean branch and merge into develop --- .../user/exception/GlobalExceptionHandler.java | 7 +------ itachallenge-user/src/main/resources/application.yml | 6 ------ .../user/service/UserSolutionServiceImpTest.java | 8 ++++---- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/itachallenge-user/src/main/java/com/itachallenge/user/exception/GlobalExceptionHandler.java b/itachallenge-user/src/main/java/com/itachallenge/user/exception/GlobalExceptionHandler.java index 2754c6011..13de0505f 100755 --- a/itachallenge-user/src/main/java/com/itachallenge/user/exception/GlobalExceptionHandler.java +++ b/itachallenge-user/src/main/java/com/itachallenge/user/exception/GlobalExceptionHandler.java @@ -9,7 +9,6 @@ import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.multipart.MaxUploadSizeExceededException; import java.util.stream.Collectors; @@ -49,9 +48,5 @@ public ResponseEntity handleUnmodifiableSolutionException(Unmo public ResponseEntity handleChallengeNotFoundException(ChallengeNotFoundException e) { return ResponseEntity.status(HttpStatus.OK).body(new ErrorResponseDto(e.getMessage())); } -@ExceptionHandler(MaxUploadSizeExceededException.class) - public ResponseEntity handleMaxSizeException(MaxUploadSizeExceededException exc) { - return ResponseEntity.status(HttpStatus.PAYLOAD_TOO_LARGE).body("Payload too large!"); - } -} +} \ No newline at end of file diff --git a/itachallenge-user/src/main/resources/application.yml b/itachallenge-user/src/main/resources/application.yml index 681e78faf..1e0254c8c 100755 --- a/itachallenge-user/src/main/resources/application.yml +++ b/itachallenge-user/src/main/resources/application.yml @@ -11,10 +11,6 @@ spring: mongodb: uri: mongodb://admin_user:yxRG4sYBDjPFzbh5@localhost:27017/users?authSource=admin uuid-representation: standard - servlet: - multipart: - max-file-size: 2MB - max-request-size: 2MB springdoc: swagger-ui: @@ -26,8 +22,6 @@ springdoc: server: port: 8764 - tomcat: - max-http-form-post-size: 2MB management: endpoints: diff --git a/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java b/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java index da3c703f6..95da318cc 100644 --- a/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java +++ b/itachallenge-user/src/test/java/com/itachallenge/user/service/UserSolutionServiceImpTest.java @@ -216,7 +216,7 @@ void addSolutionWithEndedStatusWhenInvalid_test() { StepVerifier.create(userSolutionService.addSolution(userSolutionDto)) .expectErrorMatches( throwable -> throwable instanceof UnmodifiableSolutionException - && throwable.getMessage().equals("Existing solution has status ENDED")).verify(); + && throwable.getMessage().equals("Existing solution has status ENDED")).verify(); verify(userSolutionRepository).findByUserIdAndChallengeIdAndLanguageId(userUuid, challengeUuid, languageUuid); verifyNoMoreInteractions(userSolutionRepository); } @@ -230,9 +230,9 @@ void addSolutionWithInvalidStatus_test(String status) { Mono resultMono = userSolutionService.addSolution(userSolutionDto); StepVerifier.create(resultMono) - .expectErrorMatches( - throwable -> throwable instanceof IllegalArgumentException - && throwable.getMessage().equals("Status not allowed")).verify(); + .expectErrorMatches( + throwable -> throwable instanceof IllegalArgumentException + && throwable.getMessage().equals("Status not allowed")).verify(); verifyNoInteractions(userSolutionRepository); } From 2380fe763c9e0e25aa8d6a65e8b80072b9912f7d Mon Sep 17 00:00:00 2001 From: Jonatan Vicente Date: Mon, 22 Jul 2024 12:36:36 +0200 Subject: [PATCH 20/21] itachallenge-user-2.2.0-RELEASE --- .../com/itachallenge/user/controller/UserControllerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java b/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java index 68e3c05a9..100ccc14f 100755 --- a/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java +++ b/itachallenge-user/src/test/java/com/itachallenge/user/controller/UserControllerTest.java @@ -333,7 +333,7 @@ void getVersionTest() { @Test void getAllSolutionsByIdUser() { - String URI_TEST = "/{idUser}/challenges"; + String URI_TEST = "/{idUser}/challenges/solutions"; UUID userId = UUID.randomUUID(); UserSolutionDto userSolutionDto = UserSolutionDto.builder() From 0d2bab637921c175fcb45ee4270ae04cfff7eb7e Mon Sep 17 00:00:00 2001 From: Jonatan Vicente Date: Mon, 22 Jul 2024 12:53:15 +0200 Subject: [PATCH 21/21] Postman updated: latest version of User endpoints --- .../ITA-Challenges.postman_collection.json | 129 ++++++++++++------ 1 file changed, 90 insertions(+), 39 deletions(-) diff --git a/postman/ITA-Challenges.postman_collection.json b/postman/ITA-Challenges.postman_collection.json index f70109244..22a1714b5 100644 --- a/postman/ITA-Challenges.postman_collection.json +++ b/postman/ITA-Challenges.postman_collection.json @@ -70,13 +70,13 @@ "response": [] }, { - "name": "SSO - Users/me", + "name": "SSO - Admin Set ACTIVE", "request": { - "method": "POST", + "method": "PATCH", "header": [], "body": { "mode": "raw", - "raw": "{\n \"authToken\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InZjd2ZxOXE3ZWg2d3o1YW5ybnVxMDlrMiIsImlhdCI6MTcxMDc2MjQ2NSwiZXhwIjoxNzEwNzYzMzY1fQ.CqQRZ6ufQgVZuIphRt54IpKJYiPqV9Sds6gyeN8WiDA\"\n}", + "raw": "{\n \"authToken\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InZjd2ZxOXE3ZWg2d3o1YW5ybnVxMDlrMiIsImlhdCI6MTcxNTY4MDM1MCwiZXhwIjoxNzE1NjgxMjUwfQ.LcgIWJU5hTXdGlx-kUdHkYX3tyEQQZM7WD5XJHQb09U\",\n \"status\":\"ACTIVE\"\n}", "options": { "raw": { "language": "json" @@ -84,7 +84,7 @@ } }, "url": { - "raw": "https://{{dns}}/api/v1/users/me", + "raw": "https://{{dns}}/api/v1/users/b4xnst3qu7nmvacdo93qen71", "protocol": "https", "host": [ "{{dns}}" @@ -93,20 +93,20 @@ "api", "v1", "users", - "me" + "b4xnst3qu7nmvacdo93qen71" ] } }, "response": [] }, { - "name": "SSO - Users/me Copy", + "name": "SSO - Login", "request": { - "method": "PATCH", + "method": "POST", "header": [], "body": { "mode": "raw", - "raw": "{\n \"authToken\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InZjd2ZxOXE3ZWg2d3o1YW5ybnVxMDlrMiIsImlhdCI6MTcxMDc2Mzg3MywiZXhwIjoxNzEwNzY0NzczfQ.QLTLQmI6xqsJmN__jsGaWaQZ5tw0XoVX9hOnRlzexd0\",\n \"name\":\"Jonatan\"\n}", + "raw": "{\n \"dni\": \"84997685N\",\n \"password\": \"rU2GiuiTf3oj2RvQjMQX8EyozA7k2ehTp8YIUGSWOL3TdZcn7jaq7vG8z5ovfo6NMr77\"\n}", "options": { "raw": { "language": "json" @@ -114,7 +114,7 @@ } }, "url": { - "raw": "https://{{dns}}/api/v1/users/me?id=wig98drksz4se2wpgbnouu4w", + "raw": "https://{{dns}}/api/v1/auth/login", "protocol": "https", "host": [ "{{dns}}" @@ -122,27 +122,21 @@ "path": [ "api", "v1", - "users", - "me" - ], - "query": [ - { - "key": "id", - "value": "wig98drksz4se2wpgbnouu4w" - } + "auth", + "login" ] } }, "response": [] }, { - "name": "SSO - Login", + "name": "SSO - Validate", "request": { "method": "POST", "header": [], "body": { "mode": "raw", - "raw": "{\n \"dni\": \"32983483B\",\n \"password\": \"rU2GiuiTf3oj2RvQjMQX8EyozA7k2ehTp8YIUGSWOL3TdZcn7jaq7vG8z5ovfo6NMr77\"\n}", + "raw": "{\n \"authToken\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InZjd2ZxOXE3ZWg2d3o1YW5ybnVxMDlrMiIsImlhdCI6MTcxNTY3OTE3MiwiZXhwIjoxNzE2MjgzOTcyfQ.9Il2ZIcrxilL0IbUr1YwzPrY3zoZAjV6vl8STNxC9cw\"\n}", "options": { "raw": { "language": "json" @@ -150,7 +144,7 @@ } }, "url": { - "raw": "https://{{dns}}/api/v1/auth/login", + "raw": "https://{{dns}}/api/v1/tokens/validate", "protocol": "https", "host": [ "{{dns}}" @@ -158,8 +152,8 @@ "path": [ "api", "v1", - "auth", - "login" + "tokens", + "validate" ] } }, @@ -196,13 +190,13 @@ "response": [] }, { - "name": "SSO - Validate", + "name": "SSO - Users/me", "request": { "method": "POST", "header": [], "body": { "mode": "raw", - "raw": "{\n \"authToken\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InZjd2ZxOXE3ZWg2d3o1YW5ybnVxMDlrMiIsImlhdCI6MTcxNTY3OTE3MiwiZXhwIjoxNzE2MjgzOTcyfQ.9Il2ZIcrxilL0IbUr1YwzPrY3zoZAjV6vl8STNxC9cw\"\n}", + "raw": "{\n \"authToken\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InZjd2ZxOXE3ZWg2d3o1YW5ybnVxMDlrMiIsImlhdCI6MTcxOTMwNjk3MCwiZXhwIjoxNzE5MzA3ODcwfQ.7KvgUZh_OoxNGod4ELR2IwkGI0gXWGWpqn9-cdO4U4Q\"\n}", "options": { "raw": { "language": "json" @@ -210,7 +204,7 @@ } }, "url": { - "raw": "https://{{dns}}/api/v1/tokens/validate", + "raw": "https://{{dns}}/api/v1/users/me", "protocol": "https", "host": [ "{{dns}}" @@ -218,8 +212,8 @@ "path": [ "api", "v1", - "tokens", - "validate" + "users", + "me" ] } }, @@ -504,9 +498,16 @@ "item": [ { "name": "Challentes", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, "request": { "method": "GET", "header": [], + "body": { + "mode": "file", + "file": {} + }, "url": { "raw": "http://{{ip}}:{{challenge_port}}/itachallenge/api/v1/challenge/challenges", "protocol": "http", @@ -558,7 +559,7 @@ "method": "GET", "header": [], "url": { - "raw": "http://{{ip}}:{{challenge_port}}/itachallenge/api/v1/challenge/challenges/?idLanguage=660e1b18-0c0a-4262-a28a-85de9df6ac5f", + "raw": "http://{{ip}}:{{challenge_port}}/itachallenge/api/v1/challenge/challenges/?idLanguage=660e1b18-0c0a-4262-a28a-85de9df6ac5f&offset=1&limit=1", "protocol": "http", "host": [ "{{ip}}" @@ -576,6 +577,14 @@ { "key": "idLanguage", "value": "660e1b18-0c0a-4262-a28a-85de9df6ac5f" + }, + { + "key": "offset", + "value": "1" + }, + { + "key": "limit", + "value": "1" } ] } @@ -758,12 +767,12 @@ "response": [] }, { - "name": "Challentes/solutions", + "name": "Challenges/solutions", "request": { "method": "GET", "header": [], "url": { - "raw": "http://{{ip}}:{{challenge_port}}/itachallenge/api/v1/challenge/solution/dcacb291-b4aa-4029-8e9b-284c8ca80296/language/409c9fe8-74de-4db3-81a1-a55280cf92ef?limit=1", + "raw": "http://{{ip}}:{{challenge_port}}/itachallenge/api/v1/challenge/solution/dcacb291-b4aa-4029-8e9b-284c8ca80296/language/409c9fe8-74de-4db3-81a1-a55280cf92ef", "protocol": "http", "host": [ "{{ip}}" @@ -778,12 +787,6 @@ "dcacb291-b4aa-4029-8e9b-284c8ca80296", "language", "409c9fe8-74de-4db3-81a1-a55280cf92ef" - ], - "query": [ - { - "key": "limit", - "value": "1" - } ] } }, @@ -801,7 +804,7 @@ "header": [], "body": { "mode": "raw", - "raw": "{\n\"uuid_challenge\": \"5c1a97e5-1cca-4144-9981-2de1fb73b178\",\n\"uuid_language\": \"09fabe32-7362-4bfb-ac05-b7bf854c6e0f\",\n\"uuid_user\": \"442b8e6e-5d57-4d12-9be2-3ff4f26e7d79\",\n\"status\": \"\",\n\"solution_text\": \"PPPPPPPP\"\n}", + "raw": "{\n\"uuid_challenge\": \"5c1a97e5-1cca-4144-9981-2de1fb73b178\",\n\"uuid_language\": \"09fabe32-7362-4bfb-ac05-b7bf854c6e0f\",\n\"uuid_user\": \"442b8e6e-5d57-4d12-9be2-3ff4f26e7d79\",\n\"status\": \"ENDED\",\n\"solution_text\": \"ANOTHER SOLUTION\"\n}", "options": { "raw": { "language": "json" @@ -905,7 +908,7 @@ "response": [] }, { - "name": "User/statistics", + "name": "User/statistics/percent", "request": { "method": "GET", "header": [], @@ -981,6 +984,31 @@ } }, "response": [] + }, + { + "name": "User/challenges/solutions", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "http://{{ip}}:{{user_port}}/itachallenge/api/v1/user/c3a92f9d-5d10-4f76-8c0b-6d884c549b1c/challenges/solutions", + "protocol": "http", + "host": [ + "{{ip}}" + ], + "port": "{{user_port}}", + "path": [ + "itachallenge", + "api", + "v1", + "user", + "c3a92f9d-5d10-4f76-8c0b-6d884c549b1c", + "challenges", + "solutions" + ] + } + }, + "response": [] } ] }, @@ -1052,13 +1080,17 @@ "method": "GET", "header": [], "url": { - "raw": "http://{{ip}}:{{mock_port}}/test", + "raw": "http://{{ip}}:{{mock_port}}/itachallenge/api/v1/mock/test", "protocol": "http", "host": [ "{{ip}}" ], "port": "{{mock_port}}", "path": [ + "itachallenge", + "api", + "v1", + "mock", "test" ] } @@ -1171,6 +1203,25 @@ } }, "response": [] + }, + { + "name": "Doocument/version", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "http://{{ip}}:{{document_port}}/version", + "protocol": "http", + "host": [ + "{{ip}}" + ], + "port": "{{document_port}}", + "path": [ + "version" + ] + } + }, + "response": [] } ] }