Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/main/java/org/folio/edge/rtac/client/RtacCacheClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ String searchRtacCacheHoldings(@PathVariable("instanceId") String instanceId,
@RequestParam String query,
@RequestParam(required = false) Boolean available,
@RequestParam Integer limit,
@RequestParam Integer offset);
@RequestParam Integer offset,
@RequestParam(required = false) String sort);

@GetMapping(value = "/rtac-cache/{instanceId}", consumes = MediaType.APPLICATION_JSON_VALUE)
String rtacCacheById(@PathVariable String instanceId, @RequestParam Integer limit, @RequestParam Integer offset);
String rtacCacheById(@PathVariable String instanceId,
@RequestParam Integer limit, @RequestParam Integer offset,
@RequestParam(required = false) String sort);

@PostMapping(value = "/rtac-cache/batch", consumes = MediaType.APPLICATION_JSON_VALUE)
String rtacCacheBatch(@RequestBody RtacRequest rtacRequest);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,23 @@ public ResponseEntity<String> searchRtacCacheHoldings(String instanceId,
Boolean available,
Integer limit,
Integer offset,
String sort,
String authorization,
String apiKey) {
var holdings = rtacCacheService.searchRtacCacheHoldings(instanceId, query, available, limit, offset);
var holdings = rtacCacheService.searchRtacCacheHoldings(instanceId, query, available, limit, offset, sort);
return ResponseEntity.ok(holdings);
}


@Override
public ResponseEntity<String> getRtacCacheHoldingsById(String instanceId,
Integer limit,
Integer offset,
String sort,
String authorization,
String apiKey) {
var holdings = rtacCacheService.getRtacCacheHoldingsById(instanceId, limit, offset);
String apiKey
) {
var holdings = rtacCacheService.getRtacCacheHoldingsById(instanceId, limit, offset, sort);
return ResponseEntity.ok(holdings);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ public class RtacCacheService {
private final RtacCacheClient rtacCacheClient;

public String searchRtacCacheHoldings(String instanceId, String query, Boolean available,
Integer limit, Integer offset) {
return rtacCacheClient.searchRtacCacheHoldings(instanceId, query, available, limit, offset);
Integer limit, Integer offset, String sort) {
return rtacCacheClient.searchRtacCacheHoldings(instanceId, query, available, limit, offset, sort);
}

public String getRtacCacheHoldingsById(String instanceId, Integer limit, Integer offset) {
return rtacCacheClient.rtacCacheById(instanceId, limit, offset);
public String getRtacCacheHoldingsById(String instanceId, Integer limit, Integer offset, String sort) {
return rtacCacheClient.rtacCacheById(instanceId, limit, offset, sort);
}

public String getRtacCacheBatchHoldings(RtacRequest rtacRequest) {
Expand Down
11 changes: 11 additions & 0 deletions src/main/resources/swagger.api/edge-rtac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ paths:
- $ref: '#/components/parameters/available-parameter'
- $ref: '#/components/parameters/limit'
- $ref: '#/components/parameters/offset'
- $ref: '#/components/parameters/sort'
- $ref: '#/components/parameters/authorization'
- $ref: '#/components/parameters/apiKey'
responses:
Expand Down Expand Up @@ -126,6 +127,7 @@ paths:
- $ref: '#/components/parameters/instance-id-path'
- $ref: '#/components/parameters/limit'
- $ref: '#/components/parameters/offset'
- $ref: '#/components/parameters/sort'
- $ref: '#/components/parameters/authorization'
- $ref: '#/components/parameters/apiKey'
responses:
Expand Down Expand Up @@ -321,6 +323,15 @@ components:
required: false
schema:
type: boolean
sort:
name: sort
in: query
description: |
Sort criteria in the format: `property,direction` (e.g., `locationName,asc`).
Supported properties are: effectiveShelvingOrder, libraryName, locationName, status.
The default sort order is effectiveShelvingOrder, libraryName, locationName, status (ascending).
schema:
type: string

responses:
healthCheckResponse:
Expand Down
7 changes: 7 additions & 0 deletions src/test/java/org/folio/edge/rtac/BaseIntegrationTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer;
import java.util.List;
import java.util.Map;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.folio.edge.rtac.config.RtacClientRequestInterceptor;
Expand Down Expand Up @@ -92,6 +93,12 @@ protected static ResultActions doGetWithParam(MockMvc mockMvc, String url, Strin
.accept(acceptType));
}

protected static ResultActions doGetWithParams(MockMvc mockMvc, String url, Map<String, String> params) throws Exception {
var request = get(url).headers(defaultHeaders());
params.forEach(request::param);
return mockMvc.perform(request);
}

private static HttpHeaders defaultHeaders() {
final HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(APPLICATION_JSON);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import java.util.Map;
import org.folio.edge.rtac.BaseIntegrationTests;
import org.folio.edge.rtac.TestConstants;
import org.folio.edge.rtac.TestUtil;
Expand All @@ -34,6 +35,15 @@ void searchInstanceRtacCache_shouldReturnCachedHoldings() throws Exception {
.andExpect(jsonPath("$.totalRecords", equalTo(2)));
}

@Test
void searchInstanceRtacCache_shouldReturnCachedHoldings_withSortParameter() throws Exception {
doGetWithParams(mockMvc, RTAC_CACHE_SEARCH_URL + INSTANCE_UUID, Map.of(QUERY_PARAM, QUERY_PARAM_VALUE, "sort", "locationName,asc"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.instanceId", equalTo(INSTANCE_UUID)))
.andExpect(jsonPath("$.holdings", notNullValue()))
.andExpect(jsonPath("$.totalRecords", equalTo(2)));
}

@Test
void searchInstanceRtacCache_shouldReturnNotFound_whenInstanceDoesNotExist() throws Exception {
doGetWithParam(mockMvc, RTAC_CACHE_SEARCH_URL + NON_EXISTENT_INSTANCE_UUID, QUERY_PARAM, QUERY_PARAM_VALUE)
Expand Down
27 changes: 17 additions & 10 deletions src/test/java/org/folio/edge/rtac/service/RtacCacheServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class RtacCacheServiceTest {
private static final Integer OFFSET_0 = 0;
private static final Integer LIMIT_5 = 5;
private static final Integer OFFSET_2 = 2;
private static final String SORT_BY_LOCATION = "locationName,asc";
private static final String SORT_BY_STATUS = "status,desc";

@InjectMocks
private RtacCacheService rtacCacheService;
Expand All @@ -35,28 +37,28 @@ class RtacCacheServiceTest {
@Test
void searchRtacCacheHoldings_shouldDelegateToClient_andReturnResult() {
// given
when(rtacCacheClient.searchRtacCacheHoldings(INSTANCE_ID_1, QUERY_TITLE_FOO, AVAILABLE_TRUE, LIMIT_10, OFFSET_0))
when(rtacCacheClient.searchRtacCacheHoldings(INSTANCE_ID_1, QUERY_TITLE_FOO, AVAILABLE_TRUE, LIMIT_10, OFFSET_0, SORT_BY_LOCATION))
.thenReturn("search-response");

// when
String result = rtacCacheService.searchRtacCacheHoldings(INSTANCE_ID_1, QUERY_TITLE_FOO, AVAILABLE_TRUE, LIMIT_10, OFFSET_0);
String result = rtacCacheService.searchRtacCacheHoldings(INSTANCE_ID_1, QUERY_TITLE_FOO, AVAILABLE_TRUE, LIMIT_10, OFFSET_0, SORT_BY_LOCATION);

// then
assertThat(result).isNotNull();
assertSearchDelegation(INSTANCE_ID_1, QUERY_TITLE_FOO, AVAILABLE_TRUE, LIMIT_10, OFFSET_0);
assertSearchDelegation(INSTANCE_ID_1, QUERY_TITLE_FOO, AVAILABLE_TRUE, LIMIT_10, OFFSET_0, SORT_BY_LOCATION);
}

@Test
void getRtacCacheHoldingsById_shouldDelegateToClient_andReturnResult() {
// given
when(rtacCacheClient.rtacCacheById(INSTANCE_ID_2, LIMIT_5, OFFSET_2)).thenReturn("single-response");
when(rtacCacheClient.rtacCacheById(INSTANCE_ID_2, LIMIT_5, OFFSET_2, SORT_BY_STATUS)).thenReturn("single-response");

// when
String result = rtacCacheService.getRtacCacheHoldingsById(INSTANCE_ID_2, LIMIT_5, OFFSET_2);
String result = rtacCacheService.getRtacCacheHoldingsById(INSTANCE_ID_2, LIMIT_5, OFFSET_2, SORT_BY_STATUS);

// then
assertThat(result).isNotNull();
assertByIdDelegation(INSTANCE_ID_2, LIMIT_5, OFFSET_2);
assertByIdDelegation(INSTANCE_ID_2, LIMIT_5, OFFSET_2, SORT_BY_STATUS);
}

@Test
Expand All @@ -73,38 +75,43 @@ void getRtacCacheBatchHoldings_shouldDelegateToClient_andReturnResult() {
assertBatchDelegation(request);
}

private void assertSearchDelegation(String instanceId, String query, Boolean available, Integer limit, Integer offset) {
private void assertSearchDelegation(String instanceId, String query, Boolean available, Integer limit, Integer offset, String sort) {
ArgumentCaptor<String> instanceCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<String> queryCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<Boolean> availableCaptor = ArgumentCaptor.forClass(Boolean.class);
ArgumentCaptor<Integer> limitCaptor = ArgumentCaptor.forClass(Integer.class);
ArgumentCaptor<Integer> offsetCaptor = ArgumentCaptor.forClass(Integer.class);
ArgumentCaptor<String> sortCaptor = ArgumentCaptor.forClass(String.class);

verify(rtacCacheClient).searchRtacCacheHoldings(
instanceCaptor.capture(),
queryCaptor.capture(),
availableCaptor.capture(),
limitCaptor.capture(),
offsetCaptor.capture()
offsetCaptor.capture(),
sortCaptor.capture()
);

assertThat(instanceCaptor.getValue()).isEqualTo(instanceId);
assertThat(queryCaptor.getValue()).isEqualTo(query);
assertThat(availableCaptor.getValue()).isEqualTo(available);
assertThat(limitCaptor.getValue()).isEqualTo(limit);
assertThat(offsetCaptor.getValue()).isEqualTo(offset);
assertThat(sortCaptor.getValue()).isEqualTo(sort);
}

private void assertByIdDelegation(String instanceId, Integer limit, Integer offset) {
private void assertByIdDelegation(String instanceId, Integer limit, Integer offset, String sort) {
ArgumentCaptor<String> instanceCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<Integer> limitCaptor = ArgumentCaptor.forClass(Integer.class);
ArgumentCaptor<Integer> offsetCaptor = ArgumentCaptor.forClass(Integer.class);
ArgumentCaptor<String> sortCaptor = ArgumentCaptor.forClass(String.class);

verify(rtacCacheClient).rtacCacheById(instanceCaptor.capture(), limitCaptor.capture(), offsetCaptor.capture());
verify(rtacCacheClient).rtacCacheById(instanceCaptor.capture(), limitCaptor.capture(), offsetCaptor.capture(), sortCaptor.capture());

assertThat(instanceCaptor.getValue()).isEqualTo(instanceId);
assertThat(limitCaptor.getValue()).isEqualTo(limit);
assertThat(offsetCaptor.getValue()).isEqualTo(offset);
assertThat(sortCaptor.getValue()).isEqualTo(sort);
}

private void assertBatchDelegation(RtacRequest request) {
Expand Down
27 changes: 24 additions & 3 deletions src/test/resources/mappings/rtac-cache-search.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,32 @@
{
"mappings": [
{
"priority": 1,
"request": {
"method": "GET",
"urlPath": "/rtac-cache/search/83034b0a-bf71-4495-b642-2e998f721e5d"
"urlPath": "/rtac-cache/search/83034b0a-bf71-4495-b642-2e998f721e5d",
"queryParameters": {
"sort": {
"equalTo": "locationName,asc"
}
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"bodyFileName": "rtac-cache/rtac-cache-response.json"
}
},
{
"request": {
"method": "GET",
"urlPath": "/rtac-cache/search/83034b0a-bf71-4495-b642-2e998f721e5d",
"queryParameters": {
"sort": {
"absent": true
}
}
},
"response": {
"status": 200,
Expand All @@ -15,7 +37,6 @@
}
},
{
"priority": 2,
"request": {
"method": "GET",
"urlPath": "/rtac-cache/search/a826719e-4ed2-4681-95ca-d3de6bbdec66"
Expand Down