Skip to content

Commit

Permalink
created new endpoint for getting habits by different parameters (#5846)
Browse files Browse the repository at this point in the history
* created new endpoint for getting habits by different parameters

* added tests for more cases in HabitControllerTest

* added tests for more cases in HabitControllerTest

* renamed method in CustomExceptionHandler

* changed CustomExceptionHandler, HabitController, HabitControllerTest

* added test for one more case in HabitControllerTest

* added isValid method in HabitController
changed method getAllByDifferentParameters in HabitServiceImpl
changed parameters in getAllByDifferentParametersArguments in HabitServiceImplTest

* fixed code smell

* changed getAllByDifferentParameters in HabitServiceImplTest

* created private method createPageRequest() in HabitControllerTest
and changed SQL querys into HQL querys
  • Loading branch information
LiliaMokhnatska committed May 30, 2023
1 parent 2dd3afa commit c668bb6
Show file tree
Hide file tree
Showing 9 changed files with 576 additions and 5 deletions.
1 change: 1 addition & 0 deletions core/src/main/java/greencity/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ protected void configure(HttpSecurity http) throws Exception {
"/habit/assign/allUserAndCustomShoppingListsInprogress",
"/habit/assign/{habitAssignId}",
"/habit/tags/search",
"/habit/search",
"/habit/{habitId}/friends/profile-pictures")
.hasAnyRole(USER, ADMIN, MODERATOR, UBS_EMPLOYEE)
.antMatchers(HttpMethod.POST,
Expand Down
52 changes: 52 additions & 0 deletions core/src/main/java/greencity/controller/HabitController.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import greencity.dto.habittranslation.HabitTranslationDto;
import greencity.dto.user.UserProfilePictureDto;
import greencity.dto.user.UserVO;
import greencity.exception.exceptions.BadRequestException;
import greencity.service.HabitService;
import greencity.service.TagsService;
import io.swagger.annotations.ApiOperation;
Expand All @@ -25,6 +26,9 @@
import java.security.Principal;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.Set;

import lombok.AllArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
Expand Down Expand Up @@ -138,6 +142,54 @@ public ResponseEntity<PageableDto<HabitDto>> getAllByTagsAndLanguageCode(
habitService.getAllByTagsAndLanguageCode(pageable, tags, locale.getLanguage()));
}

/**
* Method finds all habits by tags, isCustomHabit, complexity and language code.
*
* @param locale {@link Locale} with needed language code.
* @param pageable {@link Pageable} instance.
* @param tags {@link Set} of {@link String}
* @param isCustomHabit {@link Boolean} value.
* @param complexity {@link Integer} value.
* @return Pageable of {@link HabitDto} instance.
*/
@ApiOperation(value = "Find all habits by tags, isCustomHabit, complexity.")
@ApiResponses(value = {
@ApiResponse(code = 200, message = HttpStatuses.OK),
@ApiResponse(code = 400, message = HttpStatuses.BAD_REQUEST),
@ApiResponse(code = 401, message = HttpStatuses.UNAUTHORIZED)
})
@GetMapping("/search")
@ApiPageableWithLocale
public ResponseEntity<PageableDto<HabitDto>> getAllByDifferentParameters(
@ApiIgnore @ValidLanguage Locale locale,
@RequestParam(required = false, name = "tags") Optional<List<String>> tags,
@RequestParam(required = false, name = "isCustomHabit") Optional<Boolean> isCustomHabit,
@RequestParam(required = false, name = "complexity") Optional<Integer> complexity,
@ApiIgnore Pageable pageable) throws BadRequestException {
if (isValid(tags, isCustomHabit, complexity)) {
return ResponseEntity.status(HttpStatus.OK).body(
habitService.getAllByDifferentParameters(pageable, tags,
isCustomHabit, complexity, locale.getLanguage()));
} else {
throw new BadRequestException("You should enter at least one parameter");
}
}

/**
* Method checks if at least one of the input parameters (tags, isCustomHabit,
* complexity) is present.
*
* @param tags {@link Set} of {@link String}
* @param isCustomHabit {@link Boolean} value.
* @param complexity {@link Integer} value.
*
* @author Lilia Mokhnatska
*/
private boolean isValid(Optional<List<String>> tags, Optional<Boolean> isCustomHabit,
Optional<Integer> complexity) {
return ((tags.isPresent() && !tags.get().isEmpty()) || isCustomHabit.isPresent() || complexity.isPresent());
}

/**
* The method which returns all habit's tags.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

/**
Expand Down
156 changes: 156 additions & 0 deletions core/src/test/java/greencity/controller/HabitControllerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,25 @@
import com.google.gson.Gson;
import greencity.ModelUtils;
import greencity.dto.habit.AddCustomHabitDtoRequest;
import greencity.exception.handler.CustomExceptionHandler;
import greencity.service.HabitService;

import java.security.Principal;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

import java.util.Optional;

import greencity.service.TagsService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
Expand All @@ -31,6 +36,7 @@
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.validation.Validator;

@ExtendWith(MockitoExtension.class)
class HabitControllerTest {
Expand All @@ -46,14 +52,23 @@ class HabitControllerTest {
@InjectMocks
HabitController habitController;

@Mock
private Validator mockValidator;

private static final String habitLink = "/habit";

private final Principal principal = getPrincipal();

private final ErrorAttributes errorAttributes = new DefaultErrorAttributes();

private final ObjectMapper objectMapper = new ObjectMapper();

@BeforeEach
void setUp() {
this.mockMvc = MockMvcBuilders.standaloneSetup(habitController)
.setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver())
.setControllerAdvice(new CustomExceptionHandler(errorAttributes, objectMapper))
.setValidator(mockValidator)
.build();
}

Expand Down Expand Up @@ -99,6 +114,147 @@ void findAllHabitsTags() throws Exception {
verify(tagsService).findAllHabitsTags(locale.getLanguage());
}

private Pageable createPageRequest() {
int pageNumber = 0;
int pageSize = 20;
return PageRequest.of(pageNumber, pageSize);
}

@Test
void findByDifferentParameters() throws Exception {
Locale locale = new Locale("en");
Gson gson = new Gson();

mockMvc.perform(get(habitLink + "/search")
.param("tags", "reusable")
.param("complexity", "1")
.param("isCustomHabit", "true")
.content(gson.toJson(locale))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
verify(habitService).getAllByDifferentParameters(createPageRequest(), Optional.of(List.of("reusable")),
Optional.of(true),
Optional.of(1),
locale.getLanguage());
}

@Test
void findByDifferentParametersWithComplexityAndTags() throws Exception {
Locale locale = new Locale("en");
Gson gson = new Gson();

mockMvc.perform(get(habitLink + "/search")
.param("tags", "reusable")
.param("complexity", "1")
.content(gson.toJson(locale))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
verify(habitService).getAllByDifferentParameters(createPageRequest(), Optional.of(List.of("reusable")),
Optional.empty(),
Optional.of(1),
locale.getLanguage());
}

@Test
void findByDifferentParametersWithComplexityAndIsCustomHabit() throws Exception {
Locale locale = new Locale("en");
Gson gson = new Gson();

mockMvc.perform(get(habitLink + "/search")
.param("complexity", "1")
.param("isCustomHabit", "true")
.content(gson.toJson(locale))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
verify(habitService).getAllByDifferentParameters(createPageRequest(), Optional.empty(), Optional.of(true),
Optional.of(1),
locale.getLanguage());
}

@Test
void findByDifferentParametersWithTagsAndIsCustomHabit() throws Exception {
Locale locale = new Locale("en");
Gson gson = new Gson();

mockMvc.perform(get(habitLink + "/search")
.param("tags", "reusable")
.param("isCustomHabit", "true")
.content(gson.toJson(locale))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
verify(habitService).getAllByDifferentParameters(createPageRequest(), Optional.of(List.of("reusable")),
Optional.of(true),
Optional.empty(),
locale.getLanguage());
}

@Test
void findByDifferentParametersWithComplexity() throws Exception {
Locale locale = new Locale("en");
Gson gson = new Gson();

mockMvc.perform(get(habitLink + "/search")
.param("complexity", "1")
.content(gson.toJson(locale))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
verify(habitService).getAllByDifferentParameters(createPageRequest(), Optional.empty(), Optional.empty(),
Optional.of(1),
locale.getLanguage());
}

@Test
void findByDifferentParametersWithIsCustomHabit() throws Exception {
Locale locale = new Locale("en");
Gson gson = new Gson();

mockMvc.perform(get(habitLink + "/search")
.param("isCustomHabit", "true")
.content(gson.toJson(locale))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
verify(habitService).getAllByDifferentParameters(createPageRequest(), Optional.empty(), Optional.of(true),
Optional.empty(),
locale.getLanguage());
}

@Test
void findByDifferentParametersWithTags() throws Exception {
Locale locale = new Locale("en");
Gson gson = new Gson();

mockMvc.perform(get(habitLink + "/search")
.param("tags", "reusable")
.content(gson.toJson(locale))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
verify(habitService).getAllByDifferentParameters(createPageRequest(), Optional.of(List.of("reusable")),
Optional.empty(),
Optional.empty(),
locale.getLanguage());
}

@Test
void findByDifferentParametersBadRequest() throws Exception {
Locale locale = new Locale("en");
Gson gson = new Gson();
mockMvc.perform(get(habitLink + "/search")
.content(gson.toJson(locale))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isBadRequest());
}

@Test
void findByDifferentParametersBadRequestWithEmptyList() throws Exception {
Locale locale = new Locale("en");
Gson gson = new Gson();
mockMvc.perform(get(habitLink + "/search")
.param("tags", "")
.content(gson.toJson(locale))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isBadRequest());
}

@Test
void getHabitById() throws Exception {

Expand Down
Loading

0 comments on commit c668bb6

Please sign in to comment.