diff --git a/docker-compose.yml b/docker-compose.yml index 6b63e3a..9542e87 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3.8' - services: dancer: @@ -13,7 +11,7 @@ services: environment: # https://ckinan.com/blog/remote-debug-spring-boot-docker-intellij/: - SPRING_DATASOURCE_URL=jdbc:postgresql://dancer-db:5432/dancer - - SPRING_PROFILES_ACTIVE="dev" + - SPRING_PROFILES_ACTIVE=dev - JAVA_TOOL_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 dancer-db: image: postgres:14 @@ -40,6 +38,8 @@ services: prometheus: image: prom/prometheus + depends_on: + - dancer ports: - "9090:9090" volumes: @@ -70,6 +70,8 @@ services: kafka-ui: container_name: kafka-ui image: tchiotludo/akhq:latest + depends_on: + - kafka healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/ui"] interval: 10s diff --git a/src/main/java/net/dancier/dancer/core/dto/DancerSearchRequestDto.java b/src/main/java/net/dancier/dancer/core/dto/DancerSearchRequestDto.java new file mode 100644 index 0000000..d9c8126 --- /dev/null +++ b/src/main/java/net/dancier/dancer/core/dto/DancerSearchRequestDto.java @@ -0,0 +1,10 @@ +package net.dancier.dancer.core.dto; + +import lombok.Data; +import net.dancier.dancer.core.model.Gender; + +@Data +public class DancerSearchRequestDto { + private Gender gender; + private int range = 20; +} diff --git a/src/main/java/net/dancier/dancer/core/model/Gender.java b/src/main/java/net/dancier/dancer/core/model/Gender.java index e0d7091..78ba946 100644 --- a/src/main/java/net/dancier/dancer/core/model/Gender.java +++ b/src/main/java/net/dancier/dancer/core/model/Gender.java @@ -2,7 +2,7 @@ public enum Gender { MALE, - DIVERS, + DIVERSE, FEMALE, NA } diff --git a/src/main/java/net/dancier/dancer/dancers/DancerController.java b/src/main/java/net/dancier/dancer/dancers/DancerController.java index 40382aa..21cb1be 100644 --- a/src/main/java/net/dancier/dancer/dancers/DancerController.java +++ b/src/main/java/net/dancier/dancer/dancers/DancerController.java @@ -1,10 +1,11 @@ package net.dancier.dancer.dancers; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import net.dancier.dancer.chat.dto.DancerDto; import net.dancier.dancer.chat.dto.DancerIdsDto; +import net.dancier.dancer.core.dto.DancerSearchRequestDto; import net.dancier.dancer.core.dto.PublicProfileDto; -import net.dancier.dancer.core.model.Gender; import net.dancier.dancer.security.AuthenticatedUser; import net.dancier.dancer.security.CurrentUser; import org.slf4j.Logger; @@ -29,11 +30,9 @@ public class DancerController { @Secured(ROLE_USER) public ResponseEntity> get( @CurrentUser AuthenticatedUser authenticatedUser, - @RequestParam Gender gender, - @RequestParam(defaultValue = "20") int range - ) { - log.info("Fetching list of dancers in {} km range with gender {} for user {}", range, gender, authenticatedUser.getUserId()); - return ResponseEntity.ok(dancerService.getDancerList(authenticatedUser, gender, range)); + @Valid DancerSearchRequestDto searchRequest) { + log.info("Fetching list of dancers in {} km range with gender {} for user {}", searchRequest.getRange(), searchRequest.getGender(), authenticatedUser.getUserId()); + return ResponseEntity.ok(dancerService.getDancerList(authenticatedUser, searchRequest.getGender(), searchRequest.getRange())); } @PostMapping("") diff --git a/src/main/java/net/dancier/dancer/dancers/DancerRepository.java b/src/main/java/net/dancier/dancer/dancers/DancerRepository.java index abcb9a6..bd05b1a 100644 --- a/src/main/java/net/dancier/dancer/dancers/DancerRepository.java +++ b/src/main/java/net/dancier/dancer/dancers/DancerRepository.java @@ -22,4 +22,11 @@ List findFirst500ByGenderAndLongitudeBetweenAndLatitudeBetween( double upperLatitude ); + List findFirst500ByLongitudeBetweenAndLatitudeBetween( + double lowerLongitude, + double upperLongitude, + double lowerLatitude, + double upperLatitude + ); + } diff --git a/src/main/java/net/dancier/dancer/dancers/DancerService.java b/src/main/java/net/dancier/dancer/dancers/DancerService.java index 8803e7b..8f14785 100644 --- a/src/main/java/net/dancier/dancer/dancers/DancerService.java +++ b/src/main/java/net/dancier/dancer/dancers/DancerService.java @@ -54,8 +54,14 @@ public List getDancerList(AuthenticatedUser authenticatedUser, double upperLongitude = dancer.getLongitude() + longitudeRange; double lowerLongitude = dancer.getLongitude() - longitudeRange; - List resultList = dancerRepository.findFirst500ByGenderAndLongitudeBetweenAndLatitudeBetween( - gender, lowerLongitude, upperLongitude, lowerLatitude, upperLatitude); + List resultList; + if (gender == null) { + resultList = dancerRepository.findFirst500ByLongitudeBetweenAndLatitudeBetween( + lowerLongitude, upperLongitude, lowerLatitude, upperLatitude); + } else { + resultList = dancerRepository.findFirst500ByGenderAndLongitudeBetweenAndLatitudeBetween( + gender, lowerLongitude, upperLongitude, lowerLatitude, upperLatitude); + } return resultList.stream() .map(PublicProfileDto::of) diff --git a/src/test/java/net/dancier/dancer/core/EndToEndProfileTest.java b/src/test/java/net/dancier/dancer/core/EndToEndProfileTest.java index 37c4e7e..975645e 100644 --- a/src/test/java/net/dancier/dancer/core/EndToEndProfileTest.java +++ b/src/test/java/net/dancier/dancer/core/EndToEndProfileTest.java @@ -16,7 +16,6 @@ import org.springframework.test.web.servlet.ResultActions; import java.time.LocalDate; -import java.util.Date; import java.util.Set; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -68,7 +67,7 @@ void fromVirginProfileToPopulatedProfile() throws Exception { danceProfileDto.setLeading(Leading.FOLLOW); - profileOfCurrentUserDto.setGender(Gender.DIVERS); + profileOfCurrentUserDto.setGender(Gender.DIVERSE); profileOfCurrentUserDto.setBirthDate(LocalDate.now()); profileOfCurrentUserDto.setAbleTo(Set.of(danceProfileDto)); profileOfCurrentUserDto.setWantsTo(Set.of(danceProfileDto)); diff --git a/src/test/java/net/dancier/dancer/dancers/DancerControllerTest.java b/src/test/java/net/dancier/dancer/dancers/DancerControllerTest.java index b427b37..c7b59f0 100644 --- a/src/test/java/net/dancier/dancer/dancers/DancerControllerTest.java +++ b/src/test/java/net/dancier/dancer/dancers/DancerControllerTest.java @@ -1,12 +1,13 @@ package net.dancier.dancer.dancers; import net.dancier.dancer.AbstractPostgreSQLEnabledTest; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.security.test.context.support.WithUserDetails; import org.springframework.test.context.jdbc.Sql; import java.util.List; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.isA; + +import static org.hamcrest.Matchers.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -61,9 +62,35 @@ void getDancersUsingDefaultRange() throws Exception { @Test @WithUserDetails("user-with-a-profile@dancier.net") - void shouldFailIfGenderIsNotSet() throws Exception { - mockMvc .perform(get("/dancers") - .param("range", "20") - ).andExpect(status().isBadRequest()); + @DisplayName("Search with no specified gender should return all genders") + void getDancers_whenGenderIsOmitted_shouldReturnAllGenders() throws Exception { + mockMvc.perform(get("/dancers") + .param("range", "20") + ) + .andExpect(status().isOk()) + .andExpect(jsonPath("$", hasSize(2))) + .andExpect(jsonPath("$[*].gender", containsInAnyOrder("FEMALE", "MALE"))); + } + + @Test + @WithUserDetails("user-with-a-profile@dancier.net") + @DisplayName("Search that matches no dancers should return an empty list") + void getDancers_whenNoDancersMatch_shouldReturnEmptyList() throws Exception { + mockMvc.perform(get("/dancers") + .param("range", "200") + .param("gender", "DIVERSE") // Assuming no DIVERSE dancers are in the data.sql + ) + .andExpect(status().isOk()) + .andExpect(jsonPath("$", hasSize(0))); + } + + @Test + @DisplayName("Search without authentication should be rejected") + void getDancers_whenNotAuthenticated_shouldReturnUnauthorized() throws Exception { + mockMvc.perform(get("/dancers") + .param("range", "20") + .param("gender", "FEMALE") + ) + .andExpect(status().isForbidden()); } }