Skip to content

Commit 3800138

Browse files
ewanharrisOscmagevarkart
authored
feat: support name filter on ListStores API (#237)
* feat: support name filter on ListStores API * test: improve test coverage for ListStores --------- Co-authored-by: Oscmage <oscar.evertsson@gmail.com> Co-authored-by: varkart <44122128+varkart@users.noreply.github.com>
1 parent e45fc26 commit 3800138

File tree

8 files changed

+218
-19
lines changed

8 files changed

+218
-19
lines changed

docs/OpenFgaApi.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,7 +1156,7 @@ No authorization required
11561156

11571157
## listStores
11581158

1159-
> CompletableFuture<ListStoresResponse> listStores(pageSize, continuationToken)
1159+
> CompletableFuture<ListStoresResponse> listStores(pageSize, continuationToken, name)
11601160
11611161
List all stores
11621162

@@ -1181,8 +1181,9 @@ public class Example {
11811181
OpenFgaApi apiInstance = new OpenFgaApi(defaultClient);
11821182
Integer pageSize = 56; // Integer |
11831183
String continuationToken = "continuationToken_example"; // String |
1184+
String name = "name_example"; // String | The name parameter instructs the API to only include results that match that name.Multiple results may be returned. Only exact matches will be returned; substring matches and regexes will not be evaluated
11841185
try {
1185-
CompletableFuture<ListStoresResponse> result = apiInstance.listStores(pageSize, continuationToken);
1186+
CompletableFuture<ListStoresResponse> result = apiInstance.listStores(pageSize, continuationToken, name);
11861187
System.out.println(result.get());
11871188
} catch (ApiException e) {
11881189
System.err.println("Exception when calling OpenFgaApi#listStores");
@@ -1202,6 +1203,7 @@ public class Example {
12021203
|------------- | ------------- | ------------- | -------------|
12031204
| **pageSize** | **Integer**| | [optional] |
12041205
| **continuationToken** | **String**| | [optional] |
1206+
| **name** | **String**| The name parameter instructs the API to only include results that match that name.Multiple results may be returned. Only exact matches will be returned; substring matches and regexes will not be evaluated | [optional] |
12051207

12061208
### Return type
12071209

@@ -1231,7 +1233,7 @@ No authorization required
12311233

12321234
## listStoresWithHttpInfo
12331235

1234-
> CompletableFuture<ApiResponse<ListStoresResponse>> listStores listStoresWithHttpInfo(pageSize, continuationToken)
1236+
> CompletableFuture<ApiResponse<ListStoresResponse>> listStores listStoresWithHttpInfo(pageSize, continuationToken, name)
12351237
12361238
List all stores
12371239

@@ -1257,8 +1259,9 @@ public class Example {
12571259
OpenFgaApi apiInstance = new OpenFgaApi(defaultClient);
12581260
Integer pageSize = 56; // Integer |
12591261
String continuationToken = "continuationToken_example"; // String |
1262+
String name = "name_example"; // String | The name parameter instructs the API to only include results that match that name.Multiple results may be returned. Only exact matches will be returned; substring matches and regexes will not be evaluated
12601263
try {
1261-
CompletableFuture<ApiResponse<ListStoresResponse>> response = apiInstance.listStoresWithHttpInfo(pageSize, continuationToken);
1264+
CompletableFuture<ApiResponse<ListStoresResponse>> response = apiInstance.listStoresWithHttpInfo(pageSize, continuationToken, name);
12621265
System.out.println("Status code: " + response.get().getStatusCode());
12631266
System.out.println("Response headers: " + response.get().getHeaders());
12641267
System.out.println("Response body: " + response.get().getData());
@@ -1287,6 +1290,7 @@ public class Example {
12871290
|------------- | ------------- | ------------- | -------------|
12881291
| **pageSize** | **Integer**| | [optional] |
12891292
| **continuationToken** | **String**| | [optional] |
1293+
| **name** | **String**| The name parameter instructs the API to only include results that match that name.Multiple results may be returned. Only exact matches will be returned; substring matches and regexes will not be evaluated | [optional] |
12901294

12911295
### Return type
12921296

src/main/java/dev/openfga/sdk/api/OpenFgaApi.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -475,35 +475,37 @@ private CompletableFuture<ApiResponse<ListObjectsResponse>> listObjects(
475475
* Returns a paginated list of OpenFGA stores and a continuation token to get additional stores. The continuation token will be empty if there are no more stores.
476476
* @param pageSize (optional)
477477
* @param continuationToken (optional)
478+
* @param name The name parameter instructs the API to only include results that match that name.Multiple results may be returned. Only exact matches will be returned; substring matches and regexes will not be evaluated (optional)
478479
* @return CompletableFuture&lt;ApiResponse&lt;ListStoresResponse&gt;&gt;
479480
* @throws ApiException if fails to make API call
480481
*/
481-
public CompletableFuture<ApiResponse<ListStoresResponse>> listStores(Integer pageSize, String continuationToken)
482-
throws ApiException, FgaInvalidParameterException {
483-
return listStores(pageSize, continuationToken, this.configuration);
482+
public CompletableFuture<ApiResponse<ListStoresResponse>> listStores(
483+
Integer pageSize, String continuationToken, String name) throws ApiException, FgaInvalidParameterException {
484+
return listStores(pageSize, continuationToken, name, this.configuration);
484485
}
485486

486487
/**
487488
* List all stores
488489
* Returns a paginated list of OpenFGA stores and a continuation token to get additional stores. The continuation token will be empty if there are no more stores.
489490
* @param pageSize (optional)
490491
* @param continuationToken (optional)
492+
* @param name The name parameter instructs the API to only include results that match that name.Multiple results may be returned. Only exact matches will be returned; substring matches and regexes will not be evaluated (optional)
491493
* @param configurationOverride Override the {@link Configuration} this OpenFgaApi was constructed with
492494
* @return CompletableFuture&lt;ApiResponse&lt;ListStoresResponse&gt;&gt;
493495
* @throws ApiException if fails to make API call
494496
*/
495497
public CompletableFuture<ApiResponse<ListStoresResponse>> listStores(
496-
Integer pageSize, String continuationToken, ConfigurationOverride configurationOverride)
498+
Integer pageSize, String continuationToken, String name, ConfigurationOverride configurationOverride)
497499
throws ApiException, FgaInvalidParameterException {
498-
return listStores(pageSize, continuationToken, this.configuration.override(configurationOverride));
500+
return listStores(pageSize, continuationToken, name, this.configuration.override(configurationOverride));
499501
}
500502

501503
private CompletableFuture<ApiResponse<ListStoresResponse>> listStores(
502-
Integer pageSize, String continuationToken, Configuration configuration)
504+
Integer pageSize, String continuationToken, String name, Configuration configuration)
503505
throws ApiException, FgaInvalidParameterException {
504506

505507
String path = "/stores";
506-
path = pathWithParams(path, "page_size", pageSize, "continuation_token", continuationToken);
508+
path = pathWithParams(path, "page_size", pageSize, "continuation_token", continuationToken, "name", name);
507509

508510
Map<String, Object> methodParameters = new HashMap<>();
509511

src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public void setConfiguration(ClientConfiguration configuration) throws FgaInvali
8484
*/
8585
public CompletableFuture<ClientListStoresResponse> listStores() throws FgaInvalidParameterException {
8686
configuration.assertValid();
87-
return call(() -> api.listStores(null, null)).thenApply(ClientListStoresResponse::new);
87+
return call(() -> api.listStores(null, null, null)).thenApply(ClientListStoresResponse::new);
8888
}
8989

9090
/**
@@ -94,7 +94,8 @@ public CompletableFuture<ClientListStoresResponse> listStores(ClientListStoresOp
9494
throws FgaInvalidParameterException {
9595
configuration.assertValid();
9696
var overrides = new ConfigurationOverride().addHeaders(options);
97-
return call(() -> api.listStores(options.getPageSize(), options.getContinuationToken(), overrides))
97+
return call(() -> api.listStores(
98+
options.getPageSize(), options.getContinuationToken(), options.getName(), overrides))
9899
.thenApply(ClientListStoresResponse::new);
99100
}
100101

src/main/java/dev/openfga/sdk/api/configuration/ClientListStoresOptions.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public class ClientListStoresOptions implements AdditionalHeadersSupplier {
1818
private Map<String, String> additionalHeaders;
1919
private Integer pageSize;
2020
private String continuationToken;
21+
private String name;
2122

2223
public ClientListStoresOptions additionalHeaders(Map<String, String> additionalHeaders) {
2324
this.additionalHeaders = additionalHeaders;
@@ -46,4 +47,13 @@ public ClientListStoresOptions continuationToken(String continuationToken) {
4647
public String getContinuationToken() {
4748
return continuationToken;
4849
}
50+
51+
public ClientListStoresOptions name(String name) {
52+
this.name = name;
53+
return this;
54+
}
55+
56+
public String getName() {
57+
return name;
58+
}
4959
}

src/test-integration/java/dev/openfga/sdk/api/OpenFgaApiIntegrationTest.java

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public void deleteStore() throws Exception {
8484
api.deleteStore(storeId).get();
8585

8686
// Then
87-
ListStoresResponse response = api.listStores(100, null).get().getData();
87+
ListStoresResponse response = api.listStores(100, null, null).get().getData();
8888
boolean itWasDeleted = response.getStores().stream().map(Store::getId).noneMatch(storeId::equals);
8989
assertTrue(itWasDeleted, String.format("No stores should remain with the id %s.", storeId));
9090
}
@@ -115,7 +115,7 @@ public void listStores() throws Exception {
115115
}
116116

117117
// When
118-
ListStoresResponse response = api.listStores(100, null).get().getData();
118+
ListStoresResponse response = api.listStores(100, null, null).get().getData();
119119

120120
// Then
121121
for (String store : stores) {
@@ -124,6 +124,30 @@ public void listStores() throws Exception {
124124
}
125125
}
126126

127+
@Test
128+
public void listStoresWithNameFilter() throws Exception {
129+
// Given
130+
String testName = thisTestName();
131+
String targetStore = testName + "-target-store";
132+
String otherStore1 = testName + "-other-store-1";
133+
String otherStore2 = testName + "-other-store-2";
134+
135+
// Create multiple stores
136+
createStore(targetStore);
137+
createStore(otherStore1);
138+
createStore(otherStore2);
139+
140+
// When - Filter by name
141+
ListStoresResponse response =
142+
api.listStores(100, null, targetStore).get().getData();
143+
144+
// Then - Should only return the target store
145+
List<String> storeNames =
146+
response.getStores().stream().map(Store::getName).collect(java.util.stream.Collectors.toList());
147+
assertTrue(storeNames.contains(targetStore), "Target store should be in the filtered response");
148+
assertEquals(1, storeNames.size(), "Should return only one store when filtering by exact name");
149+
}
150+
127151
@Test
128152
public void readAuthModel() throws Exception {
129153
// Given

src/test-integration/java/dev/openfga/sdk/api/client/OpenFgaClientIntegrationTest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,32 @@ public void listStores() throws Exception {
141141
}
142142
}
143143

144+
@Test
145+
public void listStoresWithNameFilter() throws Exception {
146+
// Given
147+
String testName = thisTestName();
148+
String targetStore = testName + "-target";
149+
String otherStore1 = testName + "-other-1";
150+
String otherStore2 = testName + "-other-2";
151+
152+
// Create multiple stores
153+
createStore(targetStore);
154+
createStore(otherStore1);
155+
createStore(otherStore2);
156+
157+
ClientListStoresOptions options = new ClientListStoresOptions().name(targetStore);
158+
159+
// When - Filter by name using client options
160+
ClientListStoresResponse response = fga.listStores(options).get();
161+
162+
// Then - Should only return the target store
163+
assertNotNull(response.getStores());
164+
List<String> storeNames =
165+
response.getStores().stream().map(Store::getName).collect(java.util.stream.Collectors.toList());
166+
assertTrue(storeNames.contains(targetStore), "Target store should be in the filtered response");
167+
assertEquals(1, storeNames.size(), "Should return only one store when filtering by exact name");
168+
}
169+
144170
@Test
145171
public void readAuthModel() throws Exception {
146172
// Given

src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import static org.hamcrest.Matchers.*;
1616
import static org.junit.jupiter.api.Assertions.*;
17+
import static org.mockito.ArgumentMatchers.any;
1718
import static org.mockito.Mockito.*;
1819

1920
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -31,6 +32,7 @@
3132
import java.util.concurrent.ExecutionException;
3233
import org.junit.jupiter.api.BeforeEach;
3334
import org.junit.jupiter.api.Test;
35+
import org.mockito.ArgumentMatchers;
3436

3537
/**
3638
* API tests for OpenFgaApi.
@@ -74,6 +76,9 @@ public void beforeEachTest() throws Exception {
7476
when(mockConfiguration.getMaxRetries()).thenReturn(DEFAULT_MAX_RETRIES);
7577
when(mockConfiguration.getMinimumRetryDelay()).thenReturn(DEFAULT_RETRY_DELAY);
7678
when(mockConfiguration.getTelemetryConfiguration()).thenReturn(DEFAULT_TELEMETRY_CONFIG);
79+
when(mockConfiguration.override(ArgumentMatchers.any(ConfigurationOverride.class)))
80+
.thenReturn(mockConfiguration);
81+
doNothing().when(mockConfiguration).assertValid();
7782

7883
mockApiClient = mock(ApiClient.class);
7984
when(mockApiClient.getObjectMapper()).thenReturn(mapper);
@@ -96,7 +101,84 @@ public void listStoresTest() throws Exception {
96101
String continuationToken = null; // Input is optional
97102

98103
// When
99-
var response = fga.listStores(pageSize, continuationToken).get();
104+
var response = fga.listStores(pageSize, continuationToken, null).get();
105+
106+
// Then
107+
mockHttpClient.verify().get("https://api.fga.example/stores").called(1);
108+
assertNotNull(response.getData());
109+
assertNotNull(response.getData().getStores());
110+
var stores = response.getData().getStores();
111+
assertEquals(1, stores.size());
112+
assertEquals(DEFAULT_STORE_ID, stores.get(0).getId());
113+
assertEquals(DEFAULT_STORE_NAME, stores.get(0).getName());
114+
}
115+
116+
@Test
117+
public void listStoresTest_withNameFilter() throws Exception {
118+
// Given
119+
String storeName = "test-store-name";
120+
String responseBody =
121+
String.format("{\"stores\":[{\"id\":\"%s\",\"name\":\"%s\"}]}", DEFAULT_STORE_ID, storeName);
122+
mockHttpClient.onGet("https://api.fga.example/stores?name=" + storeName).doReturn(200, responseBody);
123+
Integer pageSize = null; // Input is optional
124+
String continuationToken = null; // Input is optional
125+
126+
// When
127+
var response = fga.listStores(pageSize, continuationToken, storeName).get();
128+
129+
// Then
130+
mockHttpClient
131+
.verify()
132+
.get("https://api.fga.example/stores?name=" + storeName)
133+
.called(1);
134+
assertNotNull(response.getData());
135+
assertNotNull(response.getData().getStores());
136+
var stores = response.getData().getStores();
137+
assertEquals(1, stores.size());
138+
assertEquals(DEFAULT_STORE_ID, stores.get(0).getId());
139+
assertEquals(storeName, stores.get(0).getName());
140+
}
141+
142+
@Test
143+
public void listStoresTest_withNameOnly() throws Exception {
144+
// Given
145+
String responseBody =
146+
String.format("{\"stores\":[{\"id\":\"%s\",\"name\":\"%s\"}]}", DEFAULT_STORE_ID, DEFAULT_STORE_NAME);
147+
String storeName = "test-store";
148+
String getUrl = String.format("https://api.fga.example/stores?name=%s", storeName);
149+
mockHttpClient.onGet(getUrl).doReturn(200, responseBody);
150+
Integer pageSize = null; // Input is optional
151+
String continuationToken = null; // Input is optional
152+
153+
// When - This covers the specific line: return listStores(pageSize, continuationToken, name,
154+
// this.configuration);
155+
var response = fga.listStores(pageSize, continuationToken, storeName).get();
156+
157+
// Then
158+
mockHttpClient.verify().get(getUrl).called(1);
159+
assertNotNull(response.getData());
160+
assertNotNull(response.getData().getStores());
161+
var stores = response.getData().getStores();
162+
assertEquals(1, stores.size());
163+
assertEquals(DEFAULT_STORE_ID, stores.get(0).getId());
164+
assertEquals(DEFAULT_STORE_NAME, stores.get(0).getName());
165+
}
166+
167+
@Test
168+
public void listStoresTest_withConfigurationOverride() throws Exception {
169+
// Given
170+
String responseBody =
171+
String.format("{\"stores\":[{\"id\":\"%s\",\"name\":\"%s\"}]}", DEFAULT_STORE_ID, DEFAULT_STORE_NAME);
172+
mockHttpClient.onGet("https://api.fga.example/stores").doReturn(200, responseBody);
173+
Integer pageSize = null; // Input is optional
174+
String continuationToken = null; // Input is optional
175+
String name = null;
176+
ConfigurationOverride configOverride = new ConfigurationOverride();
177+
178+
// When - This covers the specific line: return listStores(pageSize, continuationToken, null,
179+
// this.configuration.override(configurationOverride));
180+
var response = fga.listStores(pageSize, continuationToken, name, configOverride)
181+
.get();
100182

101183
// Then
102184
mockHttpClient.verify().get("https://api.fga.example/stores").called(1);
@@ -119,7 +201,7 @@ public void listStores_400() {
119201

120202
// When
121203
ExecutionException execException =
122-
assertThrows(ExecutionException.class, () -> fga.listStores(pageSize, continuationToken)
204+
assertThrows(ExecutionException.class, () -> fga.listStores(pageSize, continuationToken, null)
123205
.get());
124206

125207
// Then
@@ -142,7 +224,7 @@ public void listStores_404() throws Exception {
142224

143225
// When
144226
ExecutionException execException =
145-
assertThrows(ExecutionException.class, () -> fga.listStores(pageSize, continuationToken)
227+
assertThrows(ExecutionException.class, () -> fga.listStores(pageSize, continuationToken, null)
146228
.get());
147229

148230
// Then
@@ -164,7 +246,7 @@ public void listStores_500() throws Exception {
164246

165247
// When
166248
ExecutionException execException =
167-
assertThrows(ExecutionException.class, () -> fga.listStores(pageSize, continuationToken)
249+
assertThrows(ExecutionException.class, () -> fga.listStores(pageSize, continuationToken, null)
168250
.get());
169251

170252
// Then

0 commit comments

Comments
 (0)