From 75ee2ccff3d4b2ca25b5977fe07271a95fb9a3a9 Mon Sep 17 00:00:00 2001 From: Vimal290704 Date: Tue, 18 Nov 2025 21:28:44 +0530 Subject: [PATCH 1/4] feat: support Meilisearch 1.18 (queryVector, rename index, swap-index rename) --- .code-samples.meilisearch.yaml | 2 + src/main/java/com/meilisearch/sdk/Client.java | 130 ++++++++++-------- .../com/meilisearch/sdk/IndexesHandler.java | 26 +++- .../meilisearch/sdk/model/SearchResult.java | 1 + .../sdk/model/SearchResultPaginated.java | 1 + .../sdk/model/SwapIndexesParams.java | 8 +- 6 files changed, 102 insertions(+), 66 deletions(-) diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index ed73f5b5..8cbd8c91 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -854,3 +854,5 @@ export_post_1: |- client.export(request); compact_index_1: |- client.index("INDEX_NAME").compact(); +rename_an_index_1: |- + client.updateIndex("indexA", null, "indexB"); diff --git a/src/main/java/com/meilisearch/sdk/Client.java b/src/main/java/com/meilisearch/sdk/Client.java index 3a871eb8..1f5f2cf1 100644 --- a/src/main/java/com/meilisearch/sdk/Client.java +++ b/src/main/java/com/meilisearch/sdk/Client.java @@ -10,13 +10,12 @@ import com.meilisearch.sdk.model.*; import com.meilisearch.sdk.model.batch.req.BatchesQuery; import com.meilisearch.sdk.model.batch.res.Batch; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.TimeZone; -import java.util.UUID; -/** Meilisearch client */ +import java.util.*; + +/** + * Meilisearch client + */ public class Client { private Config config; private IndexesHandler indexesHandler; @@ -46,7 +45,7 @@ public Client(Config config) { * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TaskInfo createIndex(String uid) throws MeilisearchException { return this.createIndex(uid, null); @@ -55,12 +54,12 @@ public TaskInfo createIndex(String uid) throws MeilisearchException { /** * Creates an index with a unique identifier * - * @param uid Unique identifier for the index to create + * @param uid Unique identifier for the index to create * @param primaryKey The primary key of the documents in that index * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TaskInfo createIndex(String uid, String primaryKey) throws MeilisearchException { return this.indexesHandler.createIndex(uid, primaryKey); @@ -72,7 +71,7 @@ public TaskInfo createIndex(String uid, String primaryKey) throws MeilisearchExc * @return Results containing a list of indexes from the Meilisearch API * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Results getIndexes() throws MeilisearchException { Results indexes = this.indexesHandler.getIndexes(); @@ -89,7 +88,7 @@ public Results getIndexes() throws MeilisearchException { * @return Results containing a list of indexes from the Meilisearch API * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Results getIndexes(IndexesQuery params) throws MeilisearchException { Results indexes = this.indexesHandler.getIndexes(params); @@ -105,7 +104,7 @@ public Results getIndexes(IndexesQuery params) throws MeilisearchExceptio * @return List of indexes from the Meilisearch API as String * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public String getRawIndexes() throws MeilisearchException { return this.indexesHandler.getRawIndexes(); @@ -118,7 +117,7 @@ public String getRawIndexes() throws MeilisearchException { * @return List of indexes from the Meilisearch API as String * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public String getRawIndexes(IndexesQuery params) throws MeilisearchException { return this.indexesHandler.getRawIndexes(params); @@ -147,7 +146,7 @@ public Index index(String uid) throws MeilisearchException { * @return Meilisearch API response as Index instance * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Index getIndex(String uid) throws MeilisearchException { Index index = this.indexesHandler.getIndex(uid); @@ -158,17 +157,28 @@ public Index getIndex(String uid) throws MeilisearchException { /** * Updates the primary key of an index * - * @param uid Unique identifier of the index to update + * @param uid Unique identifier of the index to update * @param primaryKey Primary key of the documents in the index * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TaskInfo updateIndex(String uid, String primaryKey) throws MeilisearchException { return this.indexesHandler.updatePrimaryKey(uid, primaryKey); } + /** + * Update an index: either update primary key or rename the index by passing indexUid. + */ + public TaskInfo updateIndex(String uid, String primaryKey, String indexUid) throws MeilisearchException { + if (indexUid != null) { + return this.indexesHandler.updateIndexUid(uid, indexUid); + } + return this.indexesHandler.updatePrimaryKey(uid, primaryKey); + } + + /** * Deletes single index by its unique identifier * @@ -176,7 +186,7 @@ public TaskInfo updateIndex(String uid, String primaryKey) throws MeilisearchExc * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TaskInfo deleteIndex(String uid) throws MeilisearchException { return this.indexesHandler.deleteIndex(uid); @@ -189,7 +199,7 @@ public TaskInfo deleteIndex(String uid) throws MeilisearchException { * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TaskInfo swapIndexes(SwapIndexesParams[] param) throws MeilisearchException { return config.httpClient.post("/swap-indexes", param, TaskInfo.class); @@ -201,7 +211,7 @@ public TaskInfo swapIndexes(SwapIndexesParams[] param) throws MeilisearchExcepti * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TaskInfo createDump() throws MeilisearchException { return config.httpClient.post("/dumps", "", TaskInfo.class); @@ -234,10 +244,10 @@ public TaskInfo export(ExportRequest request) throws MeilisearchException { * Gets the status and availability of a Meilisearch instance * * @return String containing the status of the Meilisearch instance from Meilisearch API - * response + * response * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public String health() throws MeilisearchException { return this.instanceHandler.health(); @@ -249,7 +259,7 @@ public String health() throws MeilisearchException { * @return True if the Meilisearch instance is available or false if it is not * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Boolean isHealthy() throws MeilisearchException { return this.instanceHandler.isHealthy(); @@ -261,7 +271,7 @@ public Boolean isHealthy() throws MeilisearchException { * @return Stats instance from Meilisearch API response * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Stats getStats() throws MeilisearchException { return this.instanceHandler.getStats(); @@ -273,7 +283,7 @@ public Stats getStats() throws MeilisearchException { * @return Meilisearch API response * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public String getVersion() throws MeilisearchException { return this.instanceHandler.getVersion(); @@ -286,7 +296,7 @@ public String getVersion() throws MeilisearchException { * @return Meilisearch API response as Task Instance * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Task getTask(int uid) throws MeilisearchException { return this.tasksHandler.getTask(uid); @@ -298,7 +308,7 @@ public Task getTask(int uid) throws MeilisearchException { * @return TasksResults containing a list of tasks from the Meilisearch API * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TasksResults getTasks() throws MeilisearchException { return this.tasksHandler.getTasks(); @@ -311,7 +321,7 @@ public TasksResults getTasks() throws MeilisearchException { * @return TasksResults containing a list of tasks from the Meilisearch API * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TasksResults getTasks(TasksQuery param) throws MeilisearchException { return this.tasksHandler.getTasks(param); @@ -324,7 +334,7 @@ public TasksResults getTasks(TasksQuery param) throws MeilisearchException { * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TaskInfo cancelTasks(CancelTasksQuery param) throws MeilisearchException { return this.tasksHandler.cancelTasks(param); @@ -337,7 +347,7 @@ public TaskInfo cancelTasks(CancelTasksQuery param) throws MeilisearchException * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TaskInfo deleteTasks(DeleteTasksQuery param) throws MeilisearchException { return this.tasksHandler.deleteTasks(param); @@ -372,7 +382,7 @@ public Batch getBatch(int uid) throws MeilisearchException { * @throws MeilisearchException If an error occurs during the request. */ public CursorResults getAllBatches(BatchesQuery batchesQuery) - throws MeilisearchException { + throws MeilisearchException { return this.tasksHandler.getAllBatches(batchesQuery); } @@ -383,7 +393,7 @@ public CursorResults getAllBatches(BatchesQuery batchesQuery) * @return Meilisearch API response as Key Instance * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Key getKey(String uid) throws MeilisearchException { return this.keysHandler.getKey(uid); @@ -395,7 +405,7 @@ public Key getKey(String uid) throws MeilisearchException { * @return Results containing a list of Key from the Meilisearch API * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Results getKeys() throws MeilisearchException { return this.keysHandler.getKeys(); @@ -408,7 +418,7 @@ public Results getKeys() throws MeilisearchException { * @return Results containing a list of Key from the Meilisearch API * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Results getKeys(KeysQuery params) throws MeilisearchException { return this.keysHandler.getKeys(params); @@ -421,7 +431,7 @@ public Results getKeys(KeysQuery params) throws MeilisearchException { * @return Meilisearch API response as Key Instance * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Key createKey(Key options) throws MeilisearchException { return this.keysHandler.createKey(options); @@ -430,12 +440,12 @@ public Key createKey(Key options) throws MeilisearchException { /** * Updates a key * - * @param key String containing the key + * @param key String containing the key * @param options String containing the options to update * @return Meilisearch API response as Key Instance * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Key updateKey(String key, KeyUpdate options) throws MeilisearchException { return this.keysHandler.updateKey(key, options); @@ -447,7 +457,7 @@ public Key updateKey(String key, KeyUpdate options) throws MeilisearchException * @param key String containing the key * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public void deleteKey(String key) throws MeilisearchException { this.keysHandler.deleteKey(key); @@ -457,8 +467,8 @@ public void deleteKey(String key) throws MeilisearchException { * Method overloading the multi search method to add federation parameter */ public MultiSearchResult multiSearch( - MultiSearchRequest search, MultiSearchFederation federation) - throws MeilisearchException { + MultiSearchRequest search, MultiSearchFederation federation) + throws MeilisearchException { Map payload = new HashMap<>(); payload.put("queries", search.getQueries()); payload.put("federation", federation); @@ -466,9 +476,9 @@ public MultiSearchResult multiSearch( } public Results multiSearch(MultiSearchRequest search) - throws MeilisearchException { + throws MeilisearchException { return this.config.httpClient.post( - "/multi-search", search, Results.class, MultiSearchResult.class); + "/multi-search", search, Results.class, MultiSearchResult.class); } public void experimentalFeatures(Map features) { @@ -476,29 +486,29 @@ public void experimentalFeatures(Map features) { } public String generateTenantToken(String apiKeyUid, Map searchRules) - throws MeilisearchException { + throws MeilisearchException { return this.generateTenantToken(apiKeyUid, searchRules, new TenantTokenOptions()); } /** * Generate a tenant token * - * @param apiKeyUid Uid of a signing API key. + * @param apiKeyUid Uid of a signing API key. * @param searchRules A Map of string, object which contains the rules to be enforced at search - * time for all or specific accessible indexes for the signing API Key. - * @param options A TenantTokenOptions, the following fileds are accepted: - apiKey: String - * containing the API key parent of the token. If you leave it empty the client API Key will - * be used. - expiresAt: A DateTime when the key will expire. Note that if an expiresAt - * value is included it should be in UTC time. + * time for all or specific accessible indexes for the signing API Key. + * @param options A TenantTokenOptions, the following fileds are accepted: - apiKey: String + * containing the API key parent of the token. If you leave it empty the client API Key will + * be used. - expiresAt: A DateTime when the key will expire. Note that if an expiresAt + * value is included it should be in UTC time. * @return String containing the tenant token * @throws MeilisearchException if an error occurs * @see Meilisearch - * Tenant Tokens + * href="https://www.meilisearch.com/docs/learn/security/tenant_tokens#multitenancy-and-tenant-tokens">Meilisearch + * Tenant Tokens */ public String generateTenantToken( - String apiKeyUid, Map searchRules, TenantTokenOptions options) - throws MeilisearchException { + String apiKeyUid, Map searchRules, TenantTokenOptions options) + throws MeilisearchException { // Validate all fields Date now = new Date(); String secret; @@ -514,15 +524,15 @@ public String generateTenantToken( } if (secret == null || secret == "" || secret.length() <= 8) { throw new MeilisearchException( - "An api key is required in the client or should be passed as an argument and this key cannot be the master key."); + "An api key is required in the client or should be passed as an argument and this key cannot be the master key."); } if (searchRules == null) { throw new MeilisearchException( - "The searchRules field is mandatory and should be defined."); + "The searchRules field is mandatory and should be defined."); } if (apiKeyUid == "" || apiKeyUid == null || !isValidUUID(apiKeyUid)) { throw new MeilisearchException( - "The uid used for the token generation must exist and comply to uuid4 format"); + "The uid used for the token generation must exist and comply to uuid4 format"); } // Encrypt the key @@ -530,11 +540,11 @@ public String generateTenantToken( // Create JWT String jwtToken = - JWT.create() - .withClaim("searchRules", searchRules) - .withClaim("apiKeyUid", apiKeyUid) - .withExpiresAt(options.getExpiresAt()) - .sign(algorithm); + JWT.create() + .withClaim("searchRules", searchRules) + .withClaim("apiKeyUid", apiKeyUid) + .withExpiresAt(options.getExpiresAt()) + .sign(algorithm); return jwtToken; } diff --git a/src/main/java/com/meilisearch/sdk/IndexesHandler.java b/src/main/java/com/meilisearch/sdk/IndexesHandler.java index 9a9996f5..444861ec 100644 --- a/src/main/java/com/meilisearch/sdk/IndexesHandler.java +++ b/src/main/java/com/meilisearch/sdk/IndexesHandler.java @@ -5,6 +5,7 @@ import com.meilisearch.sdk.model.IndexesQuery; import com.meilisearch.sdk.model.Results; import com.meilisearch.sdk.model.TaskInfo; + import java.util.HashMap; /** @@ -39,7 +40,7 @@ TaskInfo createIndex(String uid) throws MeilisearchException { /** * Creates an index with a unique identifier * - * @param uid Unique identifier of the index + * @param uid Unique identifier of the index * @param primaryKey Field to use as the primary key for documents in that index * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs @@ -82,7 +83,7 @@ Results getIndexes() throws MeilisearchException { */ Results getIndexes(IndexesQuery params) throws MeilisearchException { return httpClient.get( - indexesPath().addQuery(params.toQuery()).getURL(), Results.class, Index.class); + indexesPath().addQuery(params.toQuery()).getURL(), Results.class, Index.class); } /** @@ -109,7 +110,7 @@ String getRawIndexes(IndexesQuery params) throws MeilisearchException { /** * Updates the primary key of an index in the Meilisearch instance * - * @param uid Unique identifier of the index to update + * @param uid Unique identifier of the index to update * @param primaryKey New primary key field to use for documents in that index * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs @@ -121,6 +122,21 @@ TaskInfo updatePrimaryKey(String uid, String primaryKey) throws MeilisearchExcep return httpClient.patch(indexesPath().addSubroute(uid).getURL(), index, TaskInfo.class); } + /** + * Rename an index by changing its uid. + * + * @param uid Unique identifier of the index to rename + * @param indexUid New unique identifier for the index + * @return Meilisearch API response as TaskInfo + * @throws MeilisearchException if an error occurs + */ + TaskInfo updateIndexUid(String uid, String indexUid) throws MeilisearchException { + HashMap body = new HashMap<>(); + body.put("indexUid", indexUid); + return httpClient.patch(indexesPath().addSubroute(uid).getURL(), body, TaskInfo.class); + } + + /** * Deletes an index in the Meilisearch instance * @@ -132,7 +148,9 @@ TaskInfo deleteIndex(String uid) throws MeilisearchException { return httpClient.delete(indexesPath().addSubroute(uid).getURL(), TaskInfo.class); } - /** Creates an URLBuilder for the constant route indexes */ + /** + * Creates an URLBuilder for the constant route indexes + */ private URLBuilder indexesPath() { return new URLBuilder("/indexes"); } diff --git a/src/main/java/com/meilisearch/sdk/model/SearchResult.java b/src/main/java/com/meilisearch/sdk/model/SearchResult.java index ef8c424a..0640d4d2 100644 --- a/src/main/java/com/meilisearch/sdk/model/SearchResult.java +++ b/src/main/java/com/meilisearch/sdk/model/SearchResult.java @@ -18,6 +18,7 @@ public class SearchResult implements Searchable { Object facetDistribution; HashMap facetStats; int processingTimeMs; + ArrayList queryVector; String query; int offset; int limit; diff --git a/src/main/java/com/meilisearch/sdk/model/SearchResultPaginated.java b/src/main/java/com/meilisearch/sdk/model/SearchResultPaginated.java index 239077f5..474ba742 100644 --- a/src/main/java/com/meilisearch/sdk/model/SearchResultPaginated.java +++ b/src/main/java/com/meilisearch/sdk/model/SearchResultPaginated.java @@ -23,6 +23,7 @@ public class SearchResultPaginated implements Searchable { Object facetDistribution; HashMap facetStats; int processingTimeMs; + ArrayList queryVector; String query; public SearchResultPaginated() {} diff --git a/src/main/java/com/meilisearch/sdk/model/SwapIndexesParams.java b/src/main/java/com/meilisearch/sdk/model/SwapIndexesParams.java index 53229791..6dff30bb 100644 --- a/src/main/java/com/meilisearch/sdk/model/SwapIndexesParams.java +++ b/src/main/java/com/meilisearch/sdk/model/SwapIndexesParams.java @@ -4,12 +4,16 @@ import lombok.Setter; import lombok.experimental.Accessors; -/** Swap Indexes Params data structure */ +/** + * Swap Indexes Params data structure + */ @Getter @Setter @Accessors(chain = true) public class SwapIndexesParams { protected String[] indexes; + protected Boolean rename; - public SwapIndexesParams() {} + public SwapIndexesParams() { + } } From a6bf5077ac813ca807997ee8c65329b456c4f980 Mon Sep 17 00:00:00 2001 From: Vimal290704 Date: Tue, 18 Nov 2025 22:08:47 +0530 Subject: [PATCH 2/4] feat: support Meilisearch 1.18 (queryVector + rename index + swap index) --- data.ms/VERSION | 1 + data.ms/auth/data.mdb | Bin 0 -> 57344 bytes data.ms/auth/lock.mdb | Bin 0 -> 8128 bytes data.ms/instance-uid | 1 + data.ms/tasks/data.mdb | Bin 0 -> 196608 bytes data.ms/tasks/lock.mdb | Bin 0 -> 8128 bytes src/main/java/com/meilisearch/sdk/Client.java | 121 +++++++++--------- .../com/meilisearch/sdk/IndexesHandler.java | 14 +- .../sdk/model/SwapIndexesParams.java | 7 +- .../com/meilisearch/sdk/IndexRenameTest.java | 81 ++++++++++++ .../sdk/SearchResultQueryVectorTest.java | 32 +++++ .../meilisearch/sdk/SwapIndexRenameTest.java | 84 ++++++++++++ 12 files changed, 264 insertions(+), 77 deletions(-) create mode 100644 data.ms/VERSION create mode 100644 data.ms/auth/data.mdb create mode 100644 data.ms/auth/lock.mdb create mode 100644 data.ms/instance-uid create mode 100644 data.ms/tasks/data.mdb create mode 100644 data.ms/tasks/lock.mdb create mode 100644 src/test/java/com/meilisearch/sdk/IndexRenameTest.java create mode 100644 src/test/java/com/meilisearch/sdk/SearchResultQueryVectorTest.java create mode 100644 src/test/java/com/meilisearch/sdk/SwapIndexRenameTest.java diff --git a/data.ms/VERSION b/data.ms/VERSION new file mode 100644 index 00000000..bc584045 --- /dev/null +++ b/data.ms/VERSION @@ -0,0 +1 @@ +1.26.0 \ No newline at end of file diff --git a/data.ms/auth/data.mdb b/data.ms/auth/data.mdb new file mode 100644 index 0000000000000000000000000000000000000000..75c5e13967464df997f9c56aa5ec98181b891505 GIT binary patch literal 57344 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 WFzyl86tQqZTvJj5%BeswApakM@f$Dz literal 0 HcmV?d00001 diff --git a/data.ms/tasks/lock.mdb b/data.ms/tasks/lock.mdb new file mode 100644 index 0000000000000000000000000000000000000000..f9ead87713ef7de99eec0f4b05d9b5360d7ad464 GIT binary patch literal 8128 zcmeIup$&sz5C+hOBJfPW6h$x!!%&C7F#-#80>TO`(4-SE0;J&=nDdBt=5qPIGw-`> zbJmqb^*HC5cDIhNPe1+A8LmCezcAEcEex*z`8%wI!S%mw!kT~p0RjXF5FkK+009C7 a2oNAZfB*pk1PBlyK!5-N0t5)$THpX+T_UXj literal 0 HcmV?d00001 diff --git a/src/main/java/com/meilisearch/sdk/Client.java b/src/main/java/com/meilisearch/sdk/Client.java index 1f5f2cf1..888a52dd 100644 --- a/src/main/java/com/meilisearch/sdk/Client.java +++ b/src/main/java/com/meilisearch/sdk/Client.java @@ -10,12 +10,9 @@ import com.meilisearch.sdk.model.*; import com.meilisearch.sdk.model.batch.req.BatchesQuery; import com.meilisearch.sdk.model.batch.res.Batch; - import java.util.*; -/** - * Meilisearch client - */ +/** Meilisearch client */ public class Client { private Config config; private IndexesHandler indexesHandler; @@ -45,7 +42,7 @@ public Client(Config config) { * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TaskInfo createIndex(String uid) throws MeilisearchException { return this.createIndex(uid, null); @@ -54,12 +51,12 @@ public TaskInfo createIndex(String uid) throws MeilisearchException { /** * Creates an index with a unique identifier * - * @param uid Unique identifier for the index to create + * @param uid Unique identifier for the index to create * @param primaryKey The primary key of the documents in that index * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TaskInfo createIndex(String uid, String primaryKey) throws MeilisearchException { return this.indexesHandler.createIndex(uid, primaryKey); @@ -71,7 +68,7 @@ public TaskInfo createIndex(String uid, String primaryKey) throws MeilisearchExc * @return Results containing a list of indexes from the Meilisearch API * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Results getIndexes() throws MeilisearchException { Results indexes = this.indexesHandler.getIndexes(); @@ -88,7 +85,7 @@ public Results getIndexes() throws MeilisearchException { * @return Results containing a list of indexes from the Meilisearch API * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Results getIndexes(IndexesQuery params) throws MeilisearchException { Results indexes = this.indexesHandler.getIndexes(params); @@ -104,7 +101,7 @@ public Results getIndexes(IndexesQuery params) throws MeilisearchExceptio * @return List of indexes from the Meilisearch API as String * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public String getRawIndexes() throws MeilisearchException { return this.indexesHandler.getRawIndexes(); @@ -117,7 +114,7 @@ public String getRawIndexes() throws MeilisearchException { * @return List of indexes from the Meilisearch API as String * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public String getRawIndexes(IndexesQuery params) throws MeilisearchException { return this.indexesHandler.getRawIndexes(params); @@ -146,7 +143,7 @@ public Index index(String uid) throws MeilisearchException { * @return Meilisearch API response as Index instance * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Index getIndex(String uid) throws MeilisearchException { Index index = this.indexesHandler.getIndex(uid); @@ -157,28 +154,26 @@ public Index getIndex(String uid) throws MeilisearchException { /** * Updates the primary key of an index * - * @param uid Unique identifier of the index to update + * @param uid Unique identifier of the index to update * @param primaryKey Primary key of the documents in the index * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TaskInfo updateIndex(String uid, String primaryKey) throws MeilisearchException { return this.indexesHandler.updatePrimaryKey(uid, primaryKey); } - /** - * Update an index: either update primary key or rename the index by passing indexUid. - */ - public TaskInfo updateIndex(String uid, String primaryKey, String indexUid) throws MeilisearchException { + /** Update an index: either update primary key or rename the index by passing indexUid. */ + public TaskInfo updateIndex(String uid, String primaryKey, String indexUid) + throws MeilisearchException { if (indexUid != null) { return this.indexesHandler.updateIndexUid(uid, indexUid); } return this.indexesHandler.updatePrimaryKey(uid, primaryKey); } - /** * Deletes single index by its unique identifier * @@ -186,7 +181,7 @@ public TaskInfo updateIndex(String uid, String primaryKey, String indexUid) thro * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TaskInfo deleteIndex(String uid) throws MeilisearchException { return this.indexesHandler.deleteIndex(uid); @@ -199,7 +194,7 @@ public TaskInfo deleteIndex(String uid) throws MeilisearchException { * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TaskInfo swapIndexes(SwapIndexesParams[] param) throws MeilisearchException { return config.httpClient.post("/swap-indexes", param, TaskInfo.class); @@ -211,7 +206,7 @@ public TaskInfo swapIndexes(SwapIndexesParams[] param) throws MeilisearchExcepti * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TaskInfo createDump() throws MeilisearchException { return config.httpClient.post("/dumps", "", TaskInfo.class); @@ -244,10 +239,10 @@ public TaskInfo export(ExportRequest request) throws MeilisearchException { * Gets the status and availability of a Meilisearch instance * * @return String containing the status of the Meilisearch instance from Meilisearch API - * response + * response * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public String health() throws MeilisearchException { return this.instanceHandler.health(); @@ -259,7 +254,7 @@ public String health() throws MeilisearchException { * @return True if the Meilisearch instance is available or false if it is not * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Boolean isHealthy() throws MeilisearchException { return this.instanceHandler.isHealthy(); @@ -271,7 +266,7 @@ public Boolean isHealthy() throws MeilisearchException { * @return Stats instance from Meilisearch API response * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Stats getStats() throws MeilisearchException { return this.instanceHandler.getStats(); @@ -283,7 +278,7 @@ public Stats getStats() throws MeilisearchException { * @return Meilisearch API response * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public String getVersion() throws MeilisearchException { return this.instanceHandler.getVersion(); @@ -296,7 +291,7 @@ public String getVersion() throws MeilisearchException { * @return Meilisearch API response as Task Instance * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Task getTask(int uid) throws MeilisearchException { return this.tasksHandler.getTask(uid); @@ -308,7 +303,7 @@ public Task getTask(int uid) throws MeilisearchException { * @return TasksResults containing a list of tasks from the Meilisearch API * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TasksResults getTasks() throws MeilisearchException { return this.tasksHandler.getTasks(); @@ -321,7 +316,7 @@ public TasksResults getTasks() throws MeilisearchException { * @return TasksResults containing a list of tasks from the Meilisearch API * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TasksResults getTasks(TasksQuery param) throws MeilisearchException { return this.tasksHandler.getTasks(param); @@ -334,7 +329,7 @@ public TasksResults getTasks(TasksQuery param) throws MeilisearchException { * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TaskInfo cancelTasks(CancelTasksQuery param) throws MeilisearchException { return this.tasksHandler.cancelTasks(param); @@ -347,7 +342,7 @@ public TaskInfo cancelTasks(CancelTasksQuery param) throws MeilisearchException * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public TaskInfo deleteTasks(DeleteTasksQuery param) throws MeilisearchException { return this.tasksHandler.deleteTasks(param); @@ -382,7 +377,7 @@ public Batch getBatch(int uid) throws MeilisearchException { * @throws MeilisearchException If an error occurs during the request. */ public CursorResults getAllBatches(BatchesQuery batchesQuery) - throws MeilisearchException { + throws MeilisearchException { return this.tasksHandler.getAllBatches(batchesQuery); } @@ -393,7 +388,7 @@ public CursorResults getAllBatches(BatchesQuery batchesQuery) * @return Meilisearch API response as Key Instance * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Key getKey(String uid) throws MeilisearchException { return this.keysHandler.getKey(uid); @@ -405,7 +400,7 @@ public Key getKey(String uid) throws MeilisearchException { * @return Results containing a list of Key from the Meilisearch API * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Results getKeys() throws MeilisearchException { return this.keysHandler.getKeys(); @@ -418,7 +413,7 @@ public Results getKeys() throws MeilisearchException { * @return Results containing a list of Key from the Meilisearch API * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Results getKeys(KeysQuery params) throws MeilisearchException { return this.keysHandler.getKeys(params); @@ -431,7 +426,7 @@ public Results getKeys(KeysQuery params) throws MeilisearchException { * @return Meilisearch API response as Key Instance * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Key createKey(Key options) throws MeilisearchException { return this.keysHandler.createKey(options); @@ -440,12 +435,12 @@ public Key createKey(Key options) throws MeilisearchException { /** * Updates a key * - * @param key String containing the key + * @param key String containing the key * @param options String containing the options to update * @return Meilisearch API response as Key Instance * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public Key updateKey(String key, KeyUpdate options) throws MeilisearchException { return this.keysHandler.updateKey(key, options); @@ -457,7 +452,7 @@ public Key updateKey(String key, KeyUpdate options) throws MeilisearchException * @param key String containing the key * @throws MeilisearchException if an error occurs * @see API - * specification + * specification */ public void deleteKey(String key) throws MeilisearchException { this.keysHandler.deleteKey(key); @@ -467,8 +462,8 @@ public void deleteKey(String key) throws MeilisearchException { * Method overloading the multi search method to add federation parameter */ public MultiSearchResult multiSearch( - MultiSearchRequest search, MultiSearchFederation federation) - throws MeilisearchException { + MultiSearchRequest search, MultiSearchFederation federation) + throws MeilisearchException { Map payload = new HashMap<>(); payload.put("queries", search.getQueries()); payload.put("federation", federation); @@ -476,9 +471,9 @@ public MultiSearchResult multiSearch( } public Results multiSearch(MultiSearchRequest search) - throws MeilisearchException { + throws MeilisearchException { return this.config.httpClient.post( - "/multi-search", search, Results.class, MultiSearchResult.class); + "/multi-search", search, Results.class, MultiSearchResult.class); } public void experimentalFeatures(Map features) { @@ -486,29 +481,29 @@ public void experimentalFeatures(Map features) { } public String generateTenantToken(String apiKeyUid, Map searchRules) - throws MeilisearchException { + throws MeilisearchException { return this.generateTenantToken(apiKeyUid, searchRules, new TenantTokenOptions()); } /** * Generate a tenant token * - * @param apiKeyUid Uid of a signing API key. + * @param apiKeyUid Uid of a signing API key. * @param searchRules A Map of string, object which contains the rules to be enforced at search - * time for all or specific accessible indexes for the signing API Key. - * @param options A TenantTokenOptions, the following fileds are accepted: - apiKey: String - * containing the API key parent of the token. If you leave it empty the client API Key will - * be used. - expiresAt: A DateTime when the key will expire. Note that if an expiresAt - * value is included it should be in UTC time. + * time for all or specific accessible indexes for the signing API Key. + * @param options A TenantTokenOptions, the following fileds are accepted: - apiKey: String + * containing the API key parent of the token. If you leave it empty the client API Key will + * be used. - expiresAt: A DateTime when the key will expire. Note that if an expiresAt + * value is included it should be in UTC time. * @return String containing the tenant token * @throws MeilisearchException if an error occurs * @see Meilisearch - * Tenant Tokens + * href="https://www.meilisearch.com/docs/learn/security/tenant_tokens#multitenancy-and-tenant-tokens">Meilisearch + * Tenant Tokens */ public String generateTenantToken( - String apiKeyUid, Map searchRules, TenantTokenOptions options) - throws MeilisearchException { + String apiKeyUid, Map searchRules, TenantTokenOptions options) + throws MeilisearchException { // Validate all fields Date now = new Date(); String secret; @@ -524,15 +519,15 @@ public String generateTenantToken( } if (secret == null || secret == "" || secret.length() <= 8) { throw new MeilisearchException( - "An api key is required in the client or should be passed as an argument and this key cannot be the master key."); + "An api key is required in the client or should be passed as an argument and this key cannot be the master key."); } if (searchRules == null) { throw new MeilisearchException( - "The searchRules field is mandatory and should be defined."); + "The searchRules field is mandatory and should be defined."); } if (apiKeyUid == "" || apiKeyUid == null || !isValidUUID(apiKeyUid)) { throw new MeilisearchException( - "The uid used for the token generation must exist and comply to uuid4 format"); + "The uid used for the token generation must exist and comply to uuid4 format"); } // Encrypt the key @@ -540,11 +535,11 @@ public String generateTenantToken( // Create JWT String jwtToken = - JWT.create() - .withClaim("searchRules", searchRules) - .withClaim("apiKeyUid", apiKeyUid) - .withExpiresAt(options.getExpiresAt()) - .sign(algorithm); + JWT.create() + .withClaim("searchRules", searchRules) + .withClaim("apiKeyUid", apiKeyUid) + .withExpiresAt(options.getExpiresAt()) + .sign(algorithm); return jwtToken; } diff --git a/src/main/java/com/meilisearch/sdk/IndexesHandler.java b/src/main/java/com/meilisearch/sdk/IndexesHandler.java index 444861ec..fdaa0b0f 100644 --- a/src/main/java/com/meilisearch/sdk/IndexesHandler.java +++ b/src/main/java/com/meilisearch/sdk/IndexesHandler.java @@ -5,7 +5,6 @@ import com.meilisearch.sdk.model.IndexesQuery; import com.meilisearch.sdk.model.Results; import com.meilisearch.sdk.model.TaskInfo; - import java.util.HashMap; /** @@ -40,7 +39,7 @@ TaskInfo createIndex(String uid) throws MeilisearchException { /** * Creates an index with a unique identifier * - * @param uid Unique identifier of the index + * @param uid Unique identifier of the index * @param primaryKey Field to use as the primary key for documents in that index * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs @@ -83,7 +82,7 @@ Results getIndexes() throws MeilisearchException { */ Results getIndexes(IndexesQuery params) throws MeilisearchException { return httpClient.get( - indexesPath().addQuery(params.toQuery()).getURL(), Results.class, Index.class); + indexesPath().addQuery(params.toQuery()).getURL(), Results.class, Index.class); } /** @@ -110,7 +109,7 @@ String getRawIndexes(IndexesQuery params) throws MeilisearchException { /** * Updates the primary key of an index in the Meilisearch instance * - * @param uid Unique identifier of the index to update + * @param uid Unique identifier of the index to update * @param primaryKey New primary key field to use for documents in that index * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs @@ -125,7 +124,7 @@ TaskInfo updatePrimaryKey(String uid, String primaryKey) throws MeilisearchExcep /** * Rename an index by changing its uid. * - * @param uid Unique identifier of the index to rename + * @param uid Unique identifier of the index to rename * @param indexUid New unique identifier for the index * @return Meilisearch API response as TaskInfo * @throws MeilisearchException if an error occurs @@ -136,7 +135,6 @@ TaskInfo updateIndexUid(String uid, String indexUid) throws MeilisearchException return httpClient.patch(indexesPath().addSubroute(uid).getURL(), body, TaskInfo.class); } - /** * Deletes an index in the Meilisearch instance * @@ -148,9 +146,7 @@ TaskInfo deleteIndex(String uid) throws MeilisearchException { return httpClient.delete(indexesPath().addSubroute(uid).getURL(), TaskInfo.class); } - /** - * Creates an URLBuilder for the constant route indexes - */ + /** Creates an URLBuilder for the constant route indexes */ private URLBuilder indexesPath() { return new URLBuilder("/indexes"); } diff --git a/src/main/java/com/meilisearch/sdk/model/SwapIndexesParams.java b/src/main/java/com/meilisearch/sdk/model/SwapIndexesParams.java index 6dff30bb..bc8c5c2b 100644 --- a/src/main/java/com/meilisearch/sdk/model/SwapIndexesParams.java +++ b/src/main/java/com/meilisearch/sdk/model/SwapIndexesParams.java @@ -4,9 +4,7 @@ import lombok.Setter; import lombok.experimental.Accessors; -/** - * Swap Indexes Params data structure - */ +/** Swap Indexes Params data structure */ @Getter @Setter @Accessors(chain = true) @@ -14,6 +12,5 @@ public class SwapIndexesParams { protected String[] indexes; protected Boolean rename; - public SwapIndexesParams() { - } + public SwapIndexesParams() {} } diff --git a/src/test/java/com/meilisearch/sdk/IndexRenameTest.java b/src/test/java/com/meilisearch/sdk/IndexRenameTest.java new file mode 100644 index 00000000..524ecd3c --- /dev/null +++ b/src/test/java/com/meilisearch/sdk/IndexRenameTest.java @@ -0,0 +1,81 @@ +package com.meilisearch.sdk; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.Mockito.*; + +import com.meilisearch.sdk.http.CustomOkHttpClient; +import com.meilisearch.sdk.http.request.HttpMethod; +import com.meilisearch.sdk.http.request.HttpRequest; +import com.meilisearch.sdk.http.response.HttpResponse; +import java.util.ArrayDeque; +import okhttp3.*; +import okhttp3.internal.connection.RealCall; +import okio.Buffer; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class IndexRenameTest { + + private final Config config = new Config("http://localhost:7700", "masterKey"); + private final OkHttpClient ok = mock(OkHttpClient.class); + private final CustomOkHttpClient http = new CustomOkHttpClient(config, ok); + + private final ArrayDeque requestQueue = new ArrayDeque<>(); + private final ArrayDeque responseQueue = new ArrayDeque<>(); + + private final MediaType JSON = MediaType.get("application/json; charset=utf-8"); + + @BeforeEach + void setUp() throws Exception { + RealCall call = mock(RealCall.class); + + when(ok.newCall(any())) + .thenAnswer( + inv -> { + Request req = inv.getArgument(0); + requestQueue.push(req); + + Response resp = + new Response.Builder() + .request(req) + .protocol(Protocol.HTTP_1_1) + .code(200) + .message("OK") + .body( + ResponseBody.create( + "{\"status\":\"enqueued\"}", JSON)) + .build(); + + responseQueue.push(resp); + return call; + }); + + when(call.execute()).then(inv -> responseQueue.poll()); + } + + @Test + void testRenameIndex() throws Exception { + // Build the PATCH request the same way IndexesHandler does: + String body = "{\"indexUid\":\"indexB\"}"; + HttpRequest request = + new HttpRequest(HttpMethod.PATCH, "/indexes/indexA", config.getHeaders(), body); + + HttpResponse resp = http.patch(request); + + assertThat(resp.getStatusCode(), equalTo(200)); + + Request okReq = requestQueue.poll(); + + assertThat(okReq.method(), equalTo("PATCH")); + assertThat(okReq.url().toString(), equalTo("http://localhost:7700/indexes/indexA")); + assertThat(read(okReq.body()), containsString("\"indexUid\":\"indexB\"")); + } + + private String read(RequestBody body) throws Exception { + Buffer buf = new Buffer(); + body.writeTo(buf); + return buf.readUtf8(); + } +} diff --git a/src/test/java/com/meilisearch/sdk/SearchResultQueryVectorTest.java b/src/test/java/com/meilisearch/sdk/SearchResultQueryVectorTest.java new file mode 100644 index 00000000..b1590a2b --- /dev/null +++ b/src/test/java/com/meilisearch/sdk/SearchResultQueryVectorTest.java @@ -0,0 +1,32 @@ +package com.meilisearch.sdk; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +import com.meilisearch.sdk.json.GsonJsonHandler; +import com.meilisearch.sdk.model.SearchResult; +import org.junit.jupiter.api.Test; + +class SearchResultQueryVectorTest { + + @Test + void testQueryVectorIsMapped() throws Exception { + String json = + "{" + + "\"hits\": []," + + "\"processingTimeMs\": 1," + + "\"query\": \"hello\"," + + "\"queryVector\": [0.1, 0.2, 0.3]" + + "}"; + + GsonJsonHandler handler = new GsonJsonHandler(); + SearchResult result = handler.decode(json, SearchResult.class); + + assertThat(result, is(notNullValue())); + assertThat(result.getQueryVector(), is(notNullValue())); + assertThat(result.getQueryVector().size(), is(3)); + assertThat(result.getQueryVector().get(0), equalTo(0.1F)); + assertThat(result.getQueryVector().get(1), equalTo(0.2F)); + assertThat(result.getQueryVector().get(2), equalTo(0.3F)); + } +} diff --git a/src/test/java/com/meilisearch/sdk/SwapIndexRenameTest.java b/src/test/java/com/meilisearch/sdk/SwapIndexRenameTest.java new file mode 100644 index 00000000..52f85302 --- /dev/null +++ b/src/test/java/com/meilisearch/sdk/SwapIndexRenameTest.java @@ -0,0 +1,84 @@ +package com.meilisearch.sdk; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.Mockito.*; + +import com.meilisearch.sdk.http.CustomOkHttpClient; +import com.meilisearch.sdk.http.request.HttpMethod; +import com.meilisearch.sdk.http.request.HttpRequest; +import com.meilisearch.sdk.model.SwapIndexesParams; +import java.util.ArrayDeque; +import okhttp3.*; +import okhttp3.internal.connection.RealCall; +import okio.Buffer; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class SwapIndexesRenameTest { + + private final Config config = new Config("http://localhost:7700", "masterKey"); + private final OkHttpClient ok = mock(OkHttpClient.class); + private final CustomOkHttpClient http = new CustomOkHttpClient(config, ok); + + private final ArrayDeque reqQ = new ArrayDeque<>(); + private final ArrayDeque resQ = new ArrayDeque<>(); + + private final MediaType JSON = MediaType.get("application/json; charset=utf-8"); + + @BeforeEach + void setUp() throws Exception { + RealCall call = mock(RealCall.class); + + when(ok.newCall(any())) + .thenAnswer( + inv -> { + Request req = inv.getArgument(0); + reqQ.push(req); + + Response resp = + new Response.Builder() + .request(req) + .protocol(Protocol.HTTP_1_1) + .code(200) + .message("OK") + .body( + ResponseBody.create( + "{\"status\":\"enqueued\"}", JSON)) + .build(); + + resQ.push(resp); + + return call; + }); + + when(call.execute()).then(inv -> resQ.poll()); + } + + @Test + void testSwapIndexesWithRename() throws Exception { + SwapIndexesParams[] params = { + new SwapIndexesParams().setIndexes(new String[] {"indexA", "indexB"}).setRename(true) + }; + + String json = "[{\"indexes\":[\"indexA\",\"indexB\"],\"rename\":true}]"; + + HttpRequest req = + new HttpRequest(HttpMethod.POST, "/swap-indexes", config.getHeaders(), json); + + http.post(req); + + Request okReq = reqQ.poll(); + + assertThat(okReq.method(), equalTo("POST")); + assertThat(okReq.url().toString(), equalTo("http://localhost:7700/swap-indexes")); + assertThat(read(okReq.body()), containsString("\"rename\":true")); + } + + private String read(RequestBody b) throws Exception { + Buffer buf = new Buffer(); + b.writeTo(buf); + return buf.readUtf8(); + } +} From 2a5ec2fb6a6d6074d701a15ebcee0f8411e151bc Mon Sep 17 00:00:00 2001 From: Vimal290704 Date: Wed, 19 Nov 2025 01:32:00 +0530 Subject: [PATCH 3/4] fix: refactor index rename and swap tests to use SDK public API --- build.gradle | 2 + .../com/meilisearch/sdk/IndexRenameTest.java | 118 ++++++++-------- .../meilisearch/sdk/SwapIndexRenameTest.java | 84 ----------- .../sdk/SwapIndexesRenameTest.java | 133 ++++++++++++++++++ 4 files changed, 194 insertions(+), 143 deletions(-) delete mode 100644 src/test/java/com/meilisearch/sdk/SwapIndexRenameTest.java create mode 100644 src/test/java/com/meilisearch/sdk/SwapIndexesRenameTest.java diff --git a/build.gradle b/build.gradle index 2cb1e515..702c7316 100644 --- a/build.gradle +++ b/build.gradle @@ -63,6 +63,8 @@ dependencies { testImplementation 'com.squareup.okhttp3:okhttp:4.12.0' testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.19.0' + testImplementation 'com.squareup.okhttp3:mockwebserver:4.12.0' + // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind compileOnly group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.19.0' diff --git a/src/test/java/com/meilisearch/sdk/IndexRenameTest.java b/src/test/java/com/meilisearch/sdk/IndexRenameTest.java index 524ecd3c..bc45052e 100644 --- a/src/test/java/com/meilisearch/sdk/IndexRenameTest.java +++ b/src/test/java/com/meilisearch/sdk/IndexRenameTest.java @@ -1,81 +1,81 @@ package com.meilisearch.sdk; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -import static org.mockito.Mockito.*; - -import com.meilisearch.sdk.http.CustomOkHttpClient; -import com.meilisearch.sdk.http.request.HttpMethod; -import com.meilisearch.sdk.http.request.HttpRequest; -import com.meilisearch.sdk.http.response.HttpResponse; -import java.util.ArrayDeque; -import okhttp3.*; -import okhttp3.internal.connection.RealCall; -import okio.Buffer; +import com.meilisearch.sdk.model.TaskInfo; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -class IndexRenameTest { +import java.io.IOException; - private final Config config = new Config("http://localhost:7700", "masterKey"); - private final OkHttpClient ok = mock(OkHttpClient.class); - private final CustomOkHttpClient http = new CustomOkHttpClient(config, ok); +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; - private final ArrayDeque requestQueue = new ArrayDeque<>(); - private final ArrayDeque responseQueue = new ArrayDeque<>(); +public class IndexRenameTest { - private final MediaType JSON = MediaType.get("application/json; charset=utf-8"); + private MockWebServer mockServer; + private Config config; + private IndexesHandler handler; @BeforeEach - void setUp() throws Exception { - RealCall call = mock(RealCall.class); - - when(ok.newCall(any())) - .thenAnswer( - inv -> { - Request req = inv.getArgument(0); - requestQueue.push(req); - - Response resp = - new Response.Builder() - .request(req) - .protocol(Protocol.HTTP_1_1) - .code(200) - .message("OK") - .body( - ResponseBody.create( - "{\"status\":\"enqueued\"}", JSON)) - .build(); - - responseQueue.push(resp); - return call; - }); - - when(call.execute()).then(inv -> responseQueue.poll()); + void setUp() throws IOException { + mockServer = new MockWebServer(); + mockServer.start(); + + String baseUrl = mockServer.url("").toString(); + if (baseUrl.endsWith("/")) { + baseUrl = baseUrl.substring(0, baseUrl.length() - 1); + } + config = new Config(baseUrl, "masterKey"); + handler = new IndexesHandler(config); + } + + @AfterEach + void tearDown() throws IOException { + mockServer.shutdown(); } @Test void testRenameIndex() throws Exception { - // Build the PATCH request the same way IndexesHandler does: - String body = "{\"indexUid\":\"indexB\"}"; - HttpRequest request = - new HttpRequest(HttpMethod.PATCH, "/indexes/indexA", config.getHeaders(), body); + String responseJson = "{\"taskUid\":123,\"indexUid\":\"indexB\",\"status\":\"enqueued\",\"type\":\"indexUpdate\",\"enqueuedAt\":\"2024-01-01T00:00:00Z\"}"; + mockServer.enqueue(new MockResponse() + .setResponseCode(202) + .setBody(responseJson) + .addHeader("Content-Type", "application/json")); - HttpResponse resp = http.patch(request); + TaskInfo result = handler.updateIndexUid("indexA", "indexB"); - assertThat(resp.getStatusCode(), equalTo(200)); + assertThat(result, is(notNullValue())); + assertThat(result.getTaskUid(), is(equalTo(123))); - Request okReq = requestQueue.poll(); + RecordedRequest request = mockServer.takeRequest(); + assertThat(request.getMethod(), equalTo("PATCH")); + assertThat(request.getPath(), equalTo("/indexes/indexA")); + assertThat(request.getHeader("Authorization"), equalTo("Bearer masterKey")); - assertThat(okReq.method(), equalTo("PATCH")); - assertThat(okReq.url().toString(), equalTo("http://localhost:7700/indexes/indexA")); - assertThat(read(okReq.body()), containsString("\"indexUid\":\"indexB\"")); + String requestBody = request.getBody().readUtf8(); + assertThat(requestBody, containsString("\"indexUid\":\"indexB\"")); } - private String read(RequestBody body) throws Exception { - Buffer buf = new Buffer(); - body.writeTo(buf); - return buf.readUtf8(); + @Test + void testRenameIndexWithDifferentNames() throws Exception { + String responseJson = "{\"taskUid\":456,\"indexUid\":\"newIndex\",\"status\":\"enqueued\",\"type\":\"indexUpdate\",\"enqueuedAt\":\"2024-01-02T00:00:00Z\"}"; + mockServer.enqueue(new MockResponse() + .setResponseCode(202) + .setBody(responseJson) + .addHeader("Content-Type", "application/json")); + + TaskInfo result = handler.updateIndexUid("oldIndex", "newIndex"); + + assertThat(result, is(notNullValue())); + assertThat(result.getTaskUid(), is(equalTo(456))); + + RecordedRequest request = mockServer.takeRequest(); + assertThat(request.getPath(), equalTo("/indexes/oldIndex")); + + String requestBody = request.getBody().readUtf8(); + assertThat(requestBody, containsString("\"indexUid\":\"newIndex\"")); } } diff --git a/src/test/java/com/meilisearch/sdk/SwapIndexRenameTest.java b/src/test/java/com/meilisearch/sdk/SwapIndexRenameTest.java deleted file mode 100644 index 52f85302..00000000 --- a/src/test/java/com/meilisearch/sdk/SwapIndexRenameTest.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.meilisearch.sdk; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -import static org.mockito.Mockito.*; - -import com.meilisearch.sdk.http.CustomOkHttpClient; -import com.meilisearch.sdk.http.request.HttpMethod; -import com.meilisearch.sdk.http.request.HttpRequest; -import com.meilisearch.sdk.model.SwapIndexesParams; -import java.util.ArrayDeque; -import okhttp3.*; -import okhttp3.internal.connection.RealCall; -import okio.Buffer; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class SwapIndexesRenameTest { - - private final Config config = new Config("http://localhost:7700", "masterKey"); - private final OkHttpClient ok = mock(OkHttpClient.class); - private final CustomOkHttpClient http = new CustomOkHttpClient(config, ok); - - private final ArrayDeque reqQ = new ArrayDeque<>(); - private final ArrayDeque resQ = new ArrayDeque<>(); - - private final MediaType JSON = MediaType.get("application/json; charset=utf-8"); - - @BeforeEach - void setUp() throws Exception { - RealCall call = mock(RealCall.class); - - when(ok.newCall(any())) - .thenAnswer( - inv -> { - Request req = inv.getArgument(0); - reqQ.push(req); - - Response resp = - new Response.Builder() - .request(req) - .protocol(Protocol.HTTP_1_1) - .code(200) - .message("OK") - .body( - ResponseBody.create( - "{\"status\":\"enqueued\"}", JSON)) - .build(); - - resQ.push(resp); - - return call; - }); - - when(call.execute()).then(inv -> resQ.poll()); - } - - @Test - void testSwapIndexesWithRename() throws Exception { - SwapIndexesParams[] params = { - new SwapIndexesParams().setIndexes(new String[] {"indexA", "indexB"}).setRename(true) - }; - - String json = "[{\"indexes\":[\"indexA\",\"indexB\"],\"rename\":true}]"; - - HttpRequest req = - new HttpRequest(HttpMethod.POST, "/swap-indexes", config.getHeaders(), json); - - http.post(req); - - Request okReq = reqQ.poll(); - - assertThat(okReq.method(), equalTo("POST")); - assertThat(okReq.url().toString(), equalTo("http://localhost:7700/swap-indexes")); - assertThat(read(okReq.body()), containsString("\"rename\":true")); - } - - private String read(RequestBody b) throws Exception { - Buffer buf = new Buffer(); - b.writeTo(buf); - return buf.readUtf8(); - } -} diff --git a/src/test/java/com/meilisearch/sdk/SwapIndexesRenameTest.java b/src/test/java/com/meilisearch/sdk/SwapIndexesRenameTest.java new file mode 100644 index 00000000..915a2823 --- /dev/null +++ b/src/test/java/com/meilisearch/sdk/SwapIndexesRenameTest.java @@ -0,0 +1,133 @@ +package com.meilisearch.sdk; + +import com.meilisearch.sdk.model.SwapIndexesParams; +import com.meilisearch.sdk.model.TaskInfo; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class SwapIndexesRenameTest { + + private MockWebServer mockServer; + private Config config; + private Client client; + + @BeforeEach + void setUp() throws IOException { + mockServer = new MockWebServer(); + mockServer.start(); + + String baseUrl = mockServer.url("").toString(); + if (baseUrl.endsWith("/")) { + baseUrl = baseUrl.substring(0, baseUrl.length() - 1); + } + config = new Config(baseUrl, "masterKey"); + client = new Client(config); + } + + @AfterEach + void tearDown() throws IOException { + mockServer.shutdown(); + } + + @Test + void testSwapIndexesWithRename() throws Exception { + String responseJson = "{\"taskUid\":789,\"status\":\"enqueued\",\"type\":\"indexSwap\",\"enqueuedAt\":\"2024-01-01T00:00:00Z\"}"; + mockServer.enqueue(new MockResponse() + .setResponseCode(202) + .setBody(responseJson) + .addHeader("Content-Type", "application/json")); + + SwapIndexesParams[] params = { + new SwapIndexesParams() + .setIndexes(new String[]{"indexA", "indexB"}) + .setRename(true) + }; + + TaskInfo result = client.swapIndexes(params); + + assertThat(result, is(notNullValue())); + assertThat(result.getTaskUid(), is(equalTo(789))); + + RecordedRequest request = mockServer.takeRequest(); + assertThat(request.getMethod(), equalTo("POST")); + assertThat(request.getPath(), equalTo("/swap-indexes")); + assertThat(request.getHeader("Authorization"), equalTo("Bearer masterKey")); + + String requestBody = request.getBody().readUtf8(); + assertThat(requestBody, containsString("\"rename\":true")); + assertThat(requestBody, containsString("\"indexes\"")); + assertThat(requestBody, containsString("\"indexA\"")); + assertThat(requestBody, containsString("\"indexB\"")); + } + + @Test + void testSwapIndexesWithoutRename() throws Exception { + String responseJson = "{\"taskUid\":790,\"status\":\"enqueued\",\"type\":\"indexSwap\",\"enqueuedAt\":\"2024-01-02T00:00:00Z\"}"; + mockServer.enqueue(new MockResponse() + .setResponseCode(202) + .setBody(responseJson) + .addHeader("Content-Type", "application/json")); + + SwapIndexesParams[] params = { + new SwapIndexesParams() + .setIndexes(new String[]{"indexC", "indexD"}) + .setRename(false) + }; + + TaskInfo result = client.swapIndexes(params); + + assertThat(result, is(notNullValue())); + assertThat(result.getTaskUid(), is(equalTo(790))); + + RecordedRequest request = mockServer.takeRequest(); + assertThat(request.getMethod(), equalTo("POST")); + assertThat(request.getPath(), equalTo("/swap-indexes")); + + String requestBody = request.getBody().readUtf8(); + assertThat(requestBody, containsString("\"rename\":false")); + assertThat(requestBody, containsString("\"indexC\"")); + assertThat(requestBody, containsString("\"indexD\"")); + } + + @Test + void testSwapMultipleIndexPairs() throws Exception { + String responseJson = "{\"taskUid\":791,\"status\":\"enqueued\",\"type\":\"indexSwap\",\"enqueuedAt\":\"2024-01-03T00:00:00Z\"}"; + mockServer.enqueue(new MockResponse() + .setResponseCode(202) + .setBody(responseJson) + .addHeader("Content-Type", "application/json")); + + SwapIndexesParams[] params = { + new SwapIndexesParams() + .setIndexes(new String[]{"indexA", "indexB"}) + .setRename(true), + new SwapIndexesParams() + .setIndexes(new String[]{"indexC", "indexD"}) + .setRename(false) + }; + + TaskInfo result = client.swapIndexes(params); + + assertThat(result, is(notNullValue())); + assertThat(result.getTaskUid(), is(equalTo(791))); + + RecordedRequest request = mockServer.takeRequest(); + String requestBody = request.getBody().readUtf8(); + + assertThat(requestBody, containsString("\"indexA\"")); + assertThat(requestBody, containsString("\"indexB\"")); + assertThat(requestBody, containsString("\"indexC\"")); + assertThat(requestBody, containsString("\"indexD\"")); + assertThat(requestBody, startsWith("[")); + assertThat(requestBody, endsWith("]")); + } +} From 9a991c4282fff27f032dbec3e56a9f237311e665 Mon Sep 17 00:00:00 2001 From: Vimal290704 Date: Wed, 19 Nov 2025 01:48:45 +0530 Subject: [PATCH 4/4] fix: add comprehensive assertions to index rename and swap tests --- src/test/java/com/meilisearch/sdk/IndexRenameTest.java | 4 +++- .../java/com/meilisearch/sdk/SwapIndexesRenameTest.java | 9 +++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/meilisearch/sdk/IndexRenameTest.java b/src/test/java/com/meilisearch/sdk/IndexRenameTest.java index bc45052e..edd7d52d 100644 --- a/src/test/java/com/meilisearch/sdk/IndexRenameTest.java +++ b/src/test/java/com/meilisearch/sdk/IndexRenameTest.java @@ -13,7 +13,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; -public class IndexRenameTest { +class IndexRenameTest { private MockWebServer mockServer; private Config config; @@ -73,7 +73,9 @@ void testRenameIndexWithDifferentNames() throws Exception { assertThat(result.getTaskUid(), is(equalTo(456))); RecordedRequest request = mockServer.takeRequest(); + assertThat(request.getMethod(), equalTo("PATCH")); assertThat(request.getPath(), equalTo("/indexes/oldIndex")); + assertThat(request.getHeader("Authorization"), equalTo("Bearer masterKey")); String requestBody = request.getBody().readUtf8(); assertThat(requestBody, containsString("\"indexUid\":\"newIndex\"")); diff --git a/src/test/java/com/meilisearch/sdk/SwapIndexesRenameTest.java b/src/test/java/com/meilisearch/sdk/SwapIndexesRenameTest.java index 915a2823..9c3b3317 100644 --- a/src/test/java/com/meilisearch/sdk/SwapIndexesRenameTest.java +++ b/src/test/java/com/meilisearch/sdk/SwapIndexesRenameTest.java @@ -91,6 +91,7 @@ void testSwapIndexesWithoutRename() throws Exception { RecordedRequest request = mockServer.takeRequest(); assertThat(request.getMethod(), equalTo("POST")); assertThat(request.getPath(), equalTo("/swap-indexes")); + assertThat(request.getHeader("Authorization"), equalTo("Bearer masterKey")); String requestBody = request.getBody().readUtf8(); assertThat(requestBody, containsString("\"rename\":false")); @@ -127,7 +128,11 @@ void testSwapMultipleIndexPairs() throws Exception { assertThat(requestBody, containsString("\"indexB\"")); assertThat(requestBody, containsString("\"indexC\"")); assertThat(requestBody, containsString("\"indexD\"")); - assertThat(requestBody, startsWith("[")); - assertThat(requestBody, endsWith("]")); + assertThat(requestBody, containsString("\"rename\":true")); + assertThat(requestBody, containsString("\"rename\":false")); + + String trimmedBody = requestBody.trim(); + assertThat(trimmedBody, startsWith("[")); + assertThat(trimmedBody, endsWith("]")); } }