-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[API] - Add search mocks api based on specified column
- search mocks based on the search query string and the search column such as name, description or route - #179
- Loading branch information
Showing
8 changed files
with
305 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
...end/src/main/java/com/arbindo/mimock/manage/mimocks/controller/SearchMocksController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package com.arbindo.mimock.manage.mimocks.controller; | ||
|
||
import com.arbindo.mimock.common.constants.UrlConfig; | ||
import com.arbindo.mimock.entities.Mock; | ||
import com.arbindo.mimock.manage.mimocks.mapper.ResponseModelMapper; | ||
import com.arbindo.mimock.manage.mimocks.models.response.ListMocksResponse; | ||
import com.arbindo.mimock.manage.mimocks.service.SearchMocksService; | ||
import io.swagger.v3.oas.annotations.Operation; | ||
import io.swagger.v3.oas.annotations.security.SecurityRequirement; | ||
import io.swagger.v3.oas.annotations.tags.Tag; | ||
import lombok.extern.log4j.Log4j2; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.data.domain.Sort; | ||
import org.springframework.data.web.SortDefault; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
@Log4j2 | ||
@RequestMapping(UrlConfig.MOCKS_PATH) | ||
@SecurityRequirement(name = UrlConfig.SWAGGER_BEARER_AUTH_KEY) | ||
@Tag(name = "Mock Management", description = "Handles operations related to mock resource.") | ||
public class SearchMocksController { | ||
|
||
@Autowired | ||
private SearchMocksService searchMocksService; | ||
|
||
@Operation(summary = "Search and List Mocks As Pageable", description = "Searches for mocks and lists them in " + | ||
"pageable format based on the search query provided", tags = {"Mock Management"}) | ||
@GetMapping(UrlConfig.MOCKS_SEARCH) | ||
public ResponseEntity<Page<ListMocksResponse>> searchMocks(@SortDefault(sort = "createdAt", | ||
direction = Sort.Direction.DESC) Pageable pageable, @RequestParam(required = true) String searchColumnString, | ||
@RequestParam(required = true) String searchQuery) { | ||
Page<Mock> mockPageable = searchMocksService.searchMocks(pageable, searchColumnString, searchQuery); | ||
if(mockPageable == null){ | ||
return ResponseEntity.badRequest().build(); | ||
} | ||
Page<ListMocksResponse> responsePage = mockPageable.map(ResponseModelMapper::map); | ||
return ResponseEntity.ok(responsePage); | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
mimock-backend/src/main/java/com/arbindo/mimock/manage/mimocks/enums/SearchColumn.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.arbindo.mimock.manage.mimocks.enums; | ||
|
||
public enum SearchColumn { | ||
NAME("NAME"), | ||
DESCRIPTION("DESCRIPTION"), | ||
ROUTE("ROUTE"); | ||
|
||
public final String value; | ||
|
||
private SearchColumn(String value) { | ||
this.value = value; | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
...k-backend/src/main/java/com/arbindo/mimock/manage/mimocks/service/SearchMocksService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.arbindo.mimock.manage.mimocks.service; | ||
|
||
import com.arbindo.mimock.entities.Mock; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
|
||
public interface SearchMocksService { | ||
|
||
Page<Mock> searchMocks(Pageable pageable, String searchColumnString, String searchQuery); | ||
} |
48 changes: 48 additions & 0 deletions
48
...ckend/src/main/java/com/arbindo/mimock/manage/mimocks/service/SearchMocksServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package com.arbindo.mimock.manage.mimocks.service; | ||
|
||
import com.arbindo.mimock.entities.Mock; | ||
import com.arbindo.mimock.manage.mimocks.enums.SearchColumn; | ||
import com.arbindo.mimock.repository.MocksRepository; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.extern.log4j.Log4j2; | ||
import org.apache.logging.log4j.Level; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Service | ||
@Log4j2 | ||
@Builder | ||
@AllArgsConstructor | ||
public class SearchMocksServiceImpl implements SearchMocksService{ | ||
|
||
@Autowired | ||
private MocksRepository mocksRepository; | ||
|
||
@Override | ||
public Page<Mock> searchMocks(Pageable pageable, String searchColumnString, String searchQuery) { | ||
try { | ||
SearchColumn searchColumn = SearchColumn.valueOf(searchColumnString); | ||
String sanitizedSearchQuery = searchQuery | ||
.replaceAll("\n", "") | ||
.replaceAll("\r", "") | ||
.trim(); | ||
switch (searchColumn){ | ||
case NAME: | ||
return mocksRepository.findAllByMockNameIgnoreCaseContaining(sanitizedSearchQuery, pageable); | ||
case DESCRIPTION: | ||
return mocksRepository.findAllByDescriptionIgnoreCaseContaining(sanitizedSearchQuery, pageable); | ||
case ROUTE: | ||
return mocksRepository.findAllByRouteIgnoreCaseContaining(sanitizedSearchQuery, pageable); | ||
default: | ||
return mocksRepository.findAll(pageable); | ||
} | ||
} catch(Exception e) { | ||
log.log(Level.DEBUG, e.getMessage()); | ||
} | ||
return null; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
105 changes: 105 additions & 0 deletions
105
...src/test/java/com/arbindo/mimock/manage/mimocks/controller/SearchMocksControllerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package com.arbindo.mimock.manage.mimocks.controller; | ||
|
||
import com.arbindo.mimock.common.constants.UrlConfig; | ||
import com.arbindo.mimock.entities.Mock; | ||
import com.arbindo.mimock.interceptor.DefaultHttpInterceptor; | ||
import com.arbindo.mimock.manage.mimocks.models.response.ListMocksResponse; | ||
import com.arbindo.mimock.manage.mimocks.service.SearchMocksService; | ||
import com.arbindo.mimock.security.JwtRequestFilter; | ||
import org.junit.jupiter.api.Test; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; | ||
import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration; | ||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; | ||
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; | ||
import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration; | ||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | ||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; | ||
import org.springframework.boot.test.mock.mockito.MockBean; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.jdbc.support.DatabaseStartupValidator; | ||
import org.springframework.security.core.userdetails.UserDetailsService; | ||
import org.springframework.test.web.servlet.MockMvc; | ||
import org.springframework.test.web.servlet.MvcResult; | ||
|
||
import javax.sql.DataSource; | ||
|
||
import static com.arbindo.mimock.helpers.entities.MocksGenerator.generateMocksPageable; | ||
import static com.arbindo.mimock.helpers.entities.MocksGenerator.getListMocksResponseInPageableFormat; | ||
import static com.arbindo.mimock.helpers.general.JsonMapper.convertObjectToJsonString; | ||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.mockito.ArgumentMatchers.any; | ||
import static org.mockito.Mockito.*; | ||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | ||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; | ||
|
||
@WebMvcTest(value = SearchMocksController.class, excludeAutoConfiguration = { | ||
SecurityAutoConfiguration.class, | ||
UserDetailsServiceAutoConfiguration.class, | ||
}) | ||
@AutoConfigureMockMvc(addFilters = false) | ||
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, JpaRepositoriesAutoConfiguration.class}) | ||
public class SearchMocksControllerTest { | ||
@Autowired | ||
MockMvc mockMvc; | ||
|
||
@MockBean | ||
SearchMocksService mockSearchService; | ||
|
||
@MockBean | ||
DataSource mockDataSource; | ||
|
||
@MockBean | ||
DatabaseStartupValidator mockDataStartupValidator; | ||
|
||
@MockBean | ||
DefaultHttpInterceptor defaultHttpInterceptor; | ||
|
||
@MockBean | ||
UserDetailsService userDetailsService; | ||
|
||
@MockBean | ||
JwtRequestFilter jwtRequestFilter; | ||
|
||
@Test | ||
void shouldReturnHttpOk_SearchMocks_ReturnMocksAsPageableForSearchQuery() throws Exception { | ||
// Arrange | ||
String route = UrlConfig.MOCKS_PATH + UrlConfig.MOCKS_SEARCH; | ||
String expectedContentType = "application/json"; | ||
Page<Mock> expectedMocksFromDB = generateMocksPageable(); | ||
Page<ListMocksResponse> expectedListMocksResponse = getListMocksResponseInPageableFormat(expectedMocksFromDB); | ||
String expectedResponseBody = convertObjectToJsonString(expectedListMocksResponse); | ||
|
||
lenient().when(mockSearchService.searchMocks(any(Pageable.class), anyString(), anyString())) | ||
.thenReturn(expectedMocksFromDB); | ||
|
||
// Act | ||
MvcResult result = mockMvc.perform(get(route) | ||
.param("searchColumnString", "NAME") | ||
.param("searchQuery", "randomQueryString")) | ||
.andExpect(status().isOk()) | ||
.andExpect(content().contentType(expectedContentType)) | ||
.andReturn(); | ||
|
||
// Assert | ||
assertEquals(expectedResponseBody, result.getResponse().getContentAsString()); | ||
} | ||
|
||
@Test | ||
void shouldReturnHttpBadRequest_SearchMocks_UnableToGetMocksDueToInvalidSearchColumn() throws Exception { | ||
// Arrange | ||
String route = UrlConfig.MOCKS_PATH + UrlConfig.MOCKS_SEARCH; | ||
|
||
lenient().when(mockSearchService.searchMocks(any(Pageable.class), anyString(), anyString())) | ||
.thenReturn(null); | ||
|
||
// Act & Assert | ||
MvcResult result = mockMvc.perform(get(route) | ||
.param("searchColumnString", "NAME") | ||
.param("searchQuery", "randomQueryString")) | ||
.andExpect(status().isBadRequest()) | ||
.andReturn(); | ||
|
||
} | ||
} |
78 changes: 78 additions & 0 deletions
78
...ckend/src/test/java/com/arbindo/mimock/manage/mimocks/service/SearchMocksServiceTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package com.arbindo.mimock.manage.mimocks.service; | ||
|
||
import com.arbindo.mimock.entities.Mock; | ||
import com.arbindo.mimock.repository.MocksRepository; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.EmptySource; | ||
import org.junit.jupiter.params.provider.NullSource; | ||
import org.junit.jupiter.params.provider.ValueSource; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
import org.springframework.boot.test.context.SpringBootTest; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
|
||
import static com.arbindo.mimock.helpers.entities.MocksGenerator.generateMocksPageable; | ||
import static org.junit.jupiter.api.Assertions.*; | ||
import static org.mockito.ArgumentMatchers.any; | ||
import static org.mockito.ArgumentMatchers.anyString; | ||
import static org.mockito.Mockito.lenient; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
@SpringBootTest | ||
public class SearchMocksServiceTest { | ||
|
||
@org.mockito.Mock | ||
MocksRepository mockRepository; | ||
|
||
SearchMocksService searchMocksService; | ||
|
||
@BeforeEach | ||
void setupMock(){ | ||
this.searchMocksService = SearchMocksServiceImpl.builder() | ||
.mocksRepository(mockRepository) | ||
.build(); | ||
} | ||
|
||
@ParameterizedTest | ||
@EmptySource | ||
@NullSource | ||
void shouldReturnNull_WhenSearchColumnStringIsNullOrEmpty(String searchColumnString) { | ||
// Act | ||
Page<Mock> result = searchMocksService.searchMocks(Pageable.unpaged(), searchColumnString, "randomQuery"); | ||
|
||
// Assert | ||
assertNull(result); | ||
} | ||
|
||
@ParameterizedTest | ||
@ValueSource(strings = {"Test", "UUID", "RandomString"}) | ||
void shouldReturnNull_WhenSearchColumnIsInvalid(String searchColumnString) { | ||
// Act | ||
Page<Mock> result = searchMocksService.searchMocks(Pageable.unpaged(), searchColumnString, "randomQuery"); | ||
|
||
// Assert | ||
assertNull(result); | ||
} | ||
|
||
@ParameterizedTest | ||
@ValueSource(strings = {"NAME", "DESCRIPTION", "ROUTE"}) | ||
void shouldReturnNull_WhenSearchColumnIsValid_ReturnMocksAsPageable(String searchColumnString) { | ||
// Arrange | ||
Page<Mock> expectedMocksFromDB = generateMocksPageable(); | ||
lenient().when(mockRepository.findAllByMockNameIgnoreCaseContaining(anyString(), any(Pageable.class))) | ||
.thenReturn(expectedMocksFromDB); | ||
lenient().when(mockRepository.findAllByDescriptionIgnoreCaseContaining(anyString(), any(Pageable.class))) | ||
.thenReturn(expectedMocksFromDB); | ||
lenient().when(mockRepository.findAllByRouteIgnoreCaseContaining(anyString(), any(Pageable.class))) | ||
.thenReturn(expectedMocksFromDB); | ||
|
||
// Act | ||
Page<Mock> result = searchMocksService.searchMocks(Pageable.unpaged(), searchColumnString, "randomQuery"); | ||
|
||
// Assert | ||
assertNotNull(result); | ||
assertEquals(expectedMocksFromDB, result); | ||
} | ||
} |