From 444f92c0957816e40a3bad021a6041fe8fbcc6bd Mon Sep 17 00:00:00 2001 From: reeshika-h Date: Tue, 6 Jan 2026 15:37:49 +0530 Subject: [PATCH 1/6] Update dependencies in pom.xml: bump rxjava-source to 3.1.12, loggin to 5.3.2, jackson-databind to 2.20.1, and okhttp to 5.3.2. --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index f3317c31..819e6f1f 100644 --- a/pom.xml +++ b/pom.xml @@ -20,9 +20,9 @@ 3.3.1 3.4.1 3.0.0 - 3.1.10 + 3.1.12 2.11.0 - 5.1.0 + 5.3.2 0.8.5 1.18.36 5.11.4 @@ -177,7 +177,7 @@ com.fasterxml.jackson.core jackson-databind - 2.18.2 + 2.20.1 com.slack.api @@ -192,7 +192,7 @@ com.squareup.okhttp3 okhttp - 5.1.0 + 5.3.2 org.slf4j From d40f88b54be3530e4fcdca72effff69e61012157 Mon Sep 17 00:00:00 2001 From: reeshika-h Date: Tue, 6 Jan 2026 15:41:29 +0530 Subject: [PATCH 2/6] Update dependency version for annotations in pom.xml from 24.0.1 to 26.0.2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 819e6f1f..8edefc9c 100644 --- a/pom.xml +++ b/pom.xml @@ -187,7 +187,7 @@ org.jetbrains annotations - 24.0.1 + 26.0.2 com.squareup.okhttp3 From 751a721d1527fd108ad9ca33c1d1a59d73b2b18a Mon Sep 17 00:00:00 2001 From: reeshika-h Date: Tue, 6 Jan 2026 15:55:34 +0530 Subject: [PATCH 3/6] Update retrofit-source version in pom.xml from 2.11.0 to 3.0.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8edefc9c..d55d54db 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 3.4.1 3.0.0 3.1.12 - 2.11.0 + 3.0.0 5.3.2 0.8.5 1.18.36 From fc533f19c59c4fb93ee7d4e21969eeed25ea6e0b Mon Sep 17 00:00:00 2001 From: reeshika-h Date: Wed, 11 Feb 2026 13:19:02 +0530 Subject: [PATCH 4/6] chore: Update dependencies in pom.xml and modify test fixture in TestEntryModel.java --- pom.xml | 15 ++++++--------- .../java/com/contentstack/sdk/TestEntryModel.java | 6 +++--- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/pom.xml b/pom.xml index ea5fca09..4c79771b 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ 3.0.0 5.3.2 0.8.5 - 1.18.36 + 1.18.42 5.11.4 5.8.0-M1 2.8.8 @@ -33,17 +33,14 @@ 1.5 3.8.1 1.6.13 - 20250107 + 20250517 0.8.11 2.5.3 1.2.15 - - org.sonatype.oss - oss-parent - 7 - + + https://github.com/contentstack/contentstack-java @@ -184,12 +181,12 @@ com.fasterxml.jackson.core jackson-databind - 2.20.1 + 2.21.0 com.slack.api bolt - 1.45.3 + 1.46.0 org.jetbrains diff --git a/src/test/java/com/contentstack/sdk/TestEntryModel.java b/src/test/java/com/contentstack/sdk/TestEntryModel.java index cbf9fbe2..f0a33237 100644 --- a/src/test/java/com/contentstack/sdk/TestEntryModel.java +++ b/src/test/java/com/contentstack/sdk/TestEntryModel.java @@ -254,8 +254,8 @@ void testConstructorWithPublishDetails() { JSONObject publishDetails = new JSONObject(); publishDetails.put("environment", "production"); publishDetails.put("time", "2024-01-01T00:00:00.000Z"); - // file deepcode ignore NoHardcodedCredentials/test: - publishDetails.put("user", "user123"); + // Test fixture: user is a non-secret publish-detail field (not a credential) + publishDetails.put("user", "test_publisher_uid"); JSONObject json = new JSONObject(); json.put("uid", "published_entry"); @@ -267,7 +267,7 @@ void testConstructorWithPublishDetails() { assertNotNull(model.publishDetails); assertEquals("production", model.environment); assertEquals("2024-01-01T00:00:00.000Z", model.time); - assertEquals("user123", model.user); + assertEquals("test_publisher_uid", model.user); // Verify metadata is populated assertNotNull(model.metadata); From cc3918a720b787c8868dfa5088a0384932b80d11 Mon Sep 17 00:00:00 2001 From: reeshika-h Date: Thu, 12 Feb 2026 18:10:09 +0530 Subject: [PATCH 5/6] feat: Implement assetFields method across multiple classes for enhanced asset querying --- .gitignore | 1 + src/main/java/com/contentstack/sdk/Asset.java | 14 ++ .../com/contentstack/sdk/AssetLibrary.java | 17 ++- .../contentstack/sdk/CSHttpConnection.java | 6 +- src/main/java/com/contentstack/sdk/Entry.java | 13 ++ src/main/java/com/contentstack/sdk/Query.java | 13 ++ .../java/com/contentstack/sdk/TestAsset.java | 127 ++++++++++++++++++ .../contentstack/sdk/TestAssetLibrary.java | 102 ++++++++++++++ .../sdk/TestCSHttpConnection.java | 27 ++++ .../java/com/contentstack/sdk/TestEntry.java | 101 ++++++++++++++ .../java/com/contentstack/sdk/TestQuery.java | 103 ++++++++++++++ 11 files changed, 521 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 80376521..a043cab6 100644 --- a/.gitignore +++ b/.gitignore @@ -274,3 +274,4 @@ src/main/resources/ /.vscode/ /docs/ INTEGRATION-TESTS-GUIDE.md +src/main/java/com/demo/* \ No newline at end of file diff --git a/src/main/java/com/contentstack/sdk/Asset.java b/src/main/java/com/contentstack/sdk/Asset.java index e281f53c..9f498245 100644 --- a/src/main/java/com/contentstack/sdk/Asset.java +++ b/src/main/java/com/contentstack/sdk/Asset.java @@ -1,6 +1,7 @@ package com.contentstack.sdk; import org.jetbrains.annotations.NotNull; +import org.json.JSONArray; import org.json.JSONObject; import retrofit2.Retrofit; import lombok.Getter; @@ -544,6 +545,19 @@ public Asset includeMetadata() { return this; } + public Asset assetFields(String... fields) { + if (fields != null && fields.length > 0) { + JSONArray array = new JSONArray(); + for (String field : fields) { + array.put(field); + } + if (!array.isEmpty()) { + urlQueries.put("asset_fields[]", array); + } + } + return this; + } + /** * Fetch. * diff --git a/src/main/java/com/contentstack/sdk/AssetLibrary.java b/src/main/java/com/contentstack/sdk/AssetLibrary.java index e005955f..29fd0c4b 100644 --- a/src/main/java/com/contentstack/sdk/AssetLibrary.java +++ b/src/main/java/com/contentstack/sdk/AssetLibrary.java @@ -2,6 +2,7 @@ import org.jetbrains.annotations.NotNull; import org.json.JSONObject; +import org.json.JSONArray; import java.util.*; import java.util.logging.Logger; @@ -33,7 +34,8 @@ protected void setStackInstance(@NotNull Stack stack) { //Sanitization of keys private boolean isValidKey(String key) { - return key.matches("^[a-zA-Z0-9_.]+$"); + // Fixed regex: allow alphanumeric, underscore, dot, and square brackets at the end, escaped properly + return key.matches("^[a-zA-Z0-9_.]+(\\[\\])?$"); } //Sanitization of values @@ -265,6 +267,19 @@ public AssetLibrary limit (@NotNull int number) { return this; } + public AssetLibrary assetFields(String... fields) { + if (fields != null && fields.length > 0) { + JSONArray array = new JSONArray(); + for (String field : fields) { + array.put(field); + } + if (!array.isEmpty()) { + urlQueries.put("asset_fields[]", array); + } + } + return this; + } + /** * Fetch all. * diff --git a/src/main/java/com/contentstack/sdk/CSHttpConnection.java b/src/main/java/com/contentstack/sdk/CSHttpConnection.java index 9635dbf5..b60532db 100644 --- a/src/main/java/com/contentstack/sdk/CSHttpConnection.java +++ b/src/main/java/com/contentstack/sdk/CSHttpConnection.java @@ -102,7 +102,9 @@ public String setFormParamsGET(HashMap params) { if (params != null && params.size() > 0) { String urlParams = null; urlParams = info.equalsIgnoreCase(Constants.REQUEST_CONTROLLER.QUERY.name()) - || info.equalsIgnoreCase(Constants.REQUEST_CONTROLLER.ENTRY.name()) ? getParams(params) : null; + || info.equalsIgnoreCase(Constants.REQUEST_CONTROLLER.ENTRY.name()) + || info.equalsIgnoreCase(Constants.REQUEST_CONTROLLER.ASSET.name()) + || info.equalsIgnoreCase(Constants.REQUEST_CONTROLLER.ASSETLIBRARY.name()) ? getParams(params) : null; if (urlParams == null) { for (Map.Entry e : params.entrySet()) { if (urlParams == null) { @@ -124,7 +126,7 @@ private String getParams(HashMap params) { Object value = e.getValue(); try { if (key.equalsIgnoreCase("include[]") || key.equalsIgnoreCase("only[BASE][]") - || key.equalsIgnoreCase("except[BASE][]")) { + || key.equalsIgnoreCase("except[BASE][]") || key.equalsIgnoreCase("asset_fields[]")) { urlParams = convertUrlParam(urlParams, value, key); } else if (key.equalsIgnoreCase("only")) { JSONObject onlyJSON = (JSONObject) value; diff --git a/src/main/java/com/contentstack/sdk/Entry.java b/src/main/java/com/contentstack/sdk/Entry.java index ab24592e..14cb47eb 100644 --- a/src/main/java/com/contentstack/sdk/Entry.java +++ b/src/main/java/com/contentstack/sdk/Entry.java @@ -904,6 +904,19 @@ public Entry exceptWithReferenceUid(@NotNull List fieldUid, @NotNull Str return this; } + + public Entry assetFields(String... fields) { + if (fields != null && fields.length > 0) { + JSONArray array = new JSONArray(); + for (String field : fields) { + array.put(field); + } + if (!array.isEmpty()) { + params.put("asset_fields[]", array); + } + } + return this; + } /** * Fetches the latest version of the entries from Contentstack.com content stack * diff --git a/src/main/java/com/contentstack/sdk/Query.java b/src/main/java/com/contentstack/sdk/Query.java index fdc1f521..52b6851c 100644 --- a/src/main/java/com/contentstack/sdk/Query.java +++ b/src/main/java/com/contentstack/sdk/Query.java @@ -1146,6 +1146,19 @@ public Query search(@NotNull String value) { return this; } + public Query assetFields(String... fields) { + if (fields != null && fields.length > 0) { + JSONArray array = new JSONArray(); + for (String field : fields) { + array.put(field); + } + if (!array.isEmpty()) { + urlQueries.put("asset_fields[]", array); + } + } + return this; + } + /** * Execute a Query and Caches its result (Optional) * diff --git a/src/test/java/com/contentstack/sdk/TestAsset.java b/src/test/java/com/contentstack/sdk/TestAsset.java index ac460463..715c3777 100644 --- a/src/test/java/com/contentstack/sdk/TestAsset.java +++ b/src/test/java/com/contentstack/sdk/TestAsset.java @@ -182,6 +182,133 @@ void testIncludeMetadata() { assertEquals(true, asset.urlQueries.get("include_metadata")); } + // ========== ASSET FIELDS TESTS (CDA asset_fields[] parameter) ========== + + @Test + void testAssetFieldsWithSupportedValues() { + Asset result = asset.assetFields("user_defined_fields", "embedded", "ai_suggested", "visual_markups"); + assertSame(asset, result); + assertTrue(asset.urlQueries.has("asset_fields[]")); + Object val = asset.urlQueries.get("asset_fields[]"); + assertTrue(val instanceof JSONArray); + JSONArray arr = (JSONArray) val; + assertEquals(4, arr.length()); + assertEquals("user_defined_fields", arr.get(0)); + assertEquals("embedded", arr.get(1)); + assertEquals("ai_suggested", arr.get(2)); + assertEquals("visual_markups", arr.get(3)); + } + + @Test + void testAssetFieldsReturnsThis() { + Asset result = asset.assetFields("user_defined_fields"); + assertSame(asset, result); + } + + @Test + void testAssetFieldsWithNoArgsDoesNotSetParam() { + asset.assetFields(); + assertFalse(asset.urlQueries.has("asset_fields[]")); + } + + @Test + void testAssetFieldsWithNullDoesNotSetParam() { + asset.assetFields((String[]) null); + assertFalse(asset.urlQueries.has("asset_fields[]")); + } + + @Test + void testAssetFieldsChainingWithOtherMethods() { + Asset result = asset.assetFields("embedded", "visual_markups") + .includeMetadata() + .includeDimension(); + assertSame(asset, result); + assertTrue(asset.urlQueries.has("asset_fields[]")); + assertTrue(asset.urlQueries.has("include_metadata")); + assertTrue(asset.urlQueries.has("include_dimension")); + JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]"); + assertEquals(2, arr.length()); + assertEquals("embedded", arr.get(0)); + assertEquals("visual_markups", arr.get(1)); + } + + /** + * Usage: stack.asset(assetUid).assetFields(...).fetch() + * Verifies the full chain sets asset_fields[] on the asset before fetch. + */ + @Test + void testUsageSingleAssetFetchWithAssetFields() throws IllegalAccessException { + Stack stack = Contentstack.stack("api_key", "delivery_token", "env"); + Asset asset = stack.asset("asset_uid_123") + .assetFields("embedded", "visual_markups"); + assertTrue(asset.urlQueries.has("asset_fields[]")); + JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]"); + assertEquals(2, arr.length()); + assertEquals("embedded", arr.get(0)); + assertEquals("visual_markups", arr.get(1)); + } + + + @Test + void testAssetFieldsSingleField() { + asset.assetFields("embedded"); + assertTrue(asset.urlQueries.has("asset_fields[]")); + JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]"); + assertEquals(1, arr.length()); + assertEquals("embedded", arr.get(0)); + } + + @Test + void testAssetFieldsEmptyVarargsArrayDoesNotSetParam() { + asset.assetFields(new String[0]); + assertFalse(asset.urlQueries.has("asset_fields[]")); + } + + @Test + void testAssetFieldsDuplicateValuesAllowed() { + asset.assetFields("embedded", "embedded"); + JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]"); + assertEquals(2, arr.length()); + assertEquals("embedded", arr.get(0)); + assertEquals("embedded", arr.get(1)); + } + + @Test + void testAssetFieldsSecondCallOverwrites() { + asset.assetFields("user_defined_fields", "embedded"); + asset.assetFields("ai_suggested"); + JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]"); + assertEquals(1, arr.length()); + assertEquals("ai_suggested", arr.get(0)); + } + + @Test + void testAssetFieldsWithEmptyStringInArray() { + asset.assetFields("valid", "", "embedded"); + JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]"); + assertEquals(3, arr.length()); + assertEquals("valid", arr.get(0)); + assertEquals("", arr.get(1)); + assertEquals("embedded", arr.get(2)); + } + + @Test + void testAssetFieldsWithNullInArray() { + asset.assetFields("valid", null, "embedded"); + JSONArray arr = asset.urlQueries.getJSONArray("asset_fields[]"); + assertEquals(3, arr.length()); + assertEquals("valid", arr.get(0)); + assertEquals("embedded", arr.get(2)); + } + + @Test + void testAssetFieldsSingleEmptyStringSetsParam() { + asset.assetFields(""); + assertTrue(asset.urlQueries.has("asset_fields[]")); + assertEquals(1, asset.urlQueries.getJSONArray("asset_fields[]").length()); + assertEquals("", asset.urlQueries.getJSONArray("asset_fields[]").get(0)); + } + // ========== CHAINING TESTS ========== @Test diff --git a/src/test/java/com/contentstack/sdk/TestAssetLibrary.java b/src/test/java/com/contentstack/sdk/TestAssetLibrary.java index c9e5348e..9092c4f1 100644 --- a/src/test/java/com/contentstack/sdk/TestAssetLibrary.java +++ b/src/test/java/com/contentstack/sdk/TestAssetLibrary.java @@ -1,5 +1,6 @@ package com.contentstack.sdk; +import org.json.JSONArray; import org.json.JSONObject; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -135,6 +136,107 @@ void testIncludeMetadata() { assertEquals(true, assetLibrary.urlQueries.get("include_metadata")); } + // ========== ASSET FIELDS TESTS (CDA asset_fields[] parameter) ========== + + @Test + void testAssetFieldsWithSupportedValues() { + AssetLibrary result = assetLibrary.assetFields("user_defined_fields", "embedded", "ai_suggested", "visual_markups"); + assertSame(assetLibrary, result); + assertTrue(assetLibrary.urlQueries.has("asset_fields[]")); + Object val = assetLibrary.urlQueries.get("asset_fields[]"); + assertTrue(val instanceof JSONArray); + JSONArray arr = (JSONArray) val; + assertEquals(4, arr.length()); + assertEquals("user_defined_fields", arr.get(0)); + assertEquals("embedded", arr.get(1)); + assertEquals("ai_suggested", arr.get(2)); + assertEquals("visual_markups", arr.get(3)); + } + + @Test + void testAssetFieldsReturnsThis() { + AssetLibrary result = assetLibrary.assetFields("embedded"); + assertSame(assetLibrary, result); + } + + @Test + void testAssetFieldsWithNoArgsDoesNotSetParam() { + assetLibrary.assetFields(); + assertFalse(assetLibrary.urlQueries.has("asset_fields[]")); + } + + @Test + void testAssetFieldsWithNullDoesNotSetParam() { + assetLibrary.assetFields((String[]) null); + assertFalse(assetLibrary.urlQueries.has("asset_fields[]")); + } + + @Test + void testAssetFieldsChainingWithIncludeMetadata() { + AssetLibrary result = assetLibrary.assetFields("user_defined_fields").includeMetadata().includeCount(); + assertSame(assetLibrary, result); + assertTrue(assetLibrary.urlQueries.has("asset_fields[]")); + assertTrue(assetLibrary.urlQueries.has("include_metadata")); + assertTrue(assetLibrary.urlQueries.has("include_count")); + } + + /** + * Usage: stack.assetLibrary().assetFields(...).fetchAll() + * (AssetQuery / query assets - in this SDK use assetLibrary(), not asset().find()) + * Verifies the full chain sets asset_fields[] on the asset library before fetchAll. + */ + @Test + void testUsageAssetLibraryFetchAllWithAssetFields() throws IllegalAccessException { + Stack stack = Contentstack.stack("api_key", "delivery_token", "env"); + AssetLibrary lib = stack.assetLibrary() + .assetFields("user_defined_fields", "embedded"); + assertTrue(lib.urlQueries.has("asset_fields[]")); + JSONArray arr = lib.urlQueries.getJSONArray("asset_fields[]"); + assertEquals(2, arr.length()); + assertEquals("user_defined_fields", arr.get(0)); + assertEquals("embedded", arr.get(1)); + } + + @Test + void testAssetFieldsSingleField() { + assetLibrary.assetFields("visual_markups"); + JSONArray arr = assetLibrary.urlQueries.getJSONArray("asset_fields[]"); + assertEquals(1, arr.length()); + assertEquals("visual_markups", arr.get(0)); + } + + @Test + void testAssetFieldsEmptyVarargsArrayDoesNotSetParam() { + assetLibrary.assetFields(new String[0]); + assertFalse(assetLibrary.urlQueries.has("asset_fields[]")); + } + + @Test + void testAssetFieldsSecondCallOverwrites() { + assetLibrary.assetFields("user_defined_fields", "embedded"); + assetLibrary.assetFields("ai_suggested"); + JSONArray arr = assetLibrary.urlQueries.getJSONArray("asset_fields[]"); + assertEquals(1, arr.length()); + assertEquals("ai_suggested", arr.get(0)); + } + + @Test + void testAssetFieldsDuplicateValuesAllowed() { + assetLibrary.assetFields("embedded", "embedded"); + JSONArray arr = assetLibrary.urlQueries.getJSONArray("asset_fields[]"); + assertEquals(2, arr.length()); + assertEquals("embedded", arr.get(0)); + assertEquals("embedded", arr.get(1)); + } + + @Test + void testAssetFieldsWithEmptyStringInArray() { + assetLibrary.assetFields("valid", "", "visual_markups"); + JSONArray arr = assetLibrary.urlQueries.getJSONArray("asset_fields[]"); + assertEquals(3, arr.length()); + assertEquals("", arr.get(1)); + } + @Test void testMultipleIncludes() { assetLibrary.includeCount() diff --git a/src/test/java/com/contentstack/sdk/TestCSHttpConnection.java b/src/test/java/com/contentstack/sdk/TestCSHttpConnection.java index 754e96f6..bf2a097e 100644 --- a/src/test/java/com/contentstack/sdk/TestCSHttpConnection.java +++ b/src/test/java/com/contentstack/sdk/TestCSHttpConnection.java @@ -399,6 +399,33 @@ void testGetParamsWithMultipleTypes() throws Exception { assertTrue(result.contains("environment=staging")); } + @Test + void testGetParamsWithAssetFieldsArray() throws Exception { + connection.setInfo("ENTRY"); + + HashMap params = new HashMap<>(); + params.put("environment", "production"); + + JSONArray assetFieldsArray = new JSONArray(); + assetFieldsArray.put("user_defined_fields"); + assetFieldsArray.put("embedded"); + assetFieldsArray.put("ai_suggested"); + assetFieldsArray.put("visual_markups"); + params.put("asset_fields[]", assetFieldsArray); + + Method getParamsMethod = CSHttpConnection.class.getDeclaredMethod("getParams", HashMap.class); + getParamsMethod.setAccessible(true); + + String result = (String) getParamsMethod.invoke(connection, params); + + assertNotNull(result); + assertTrue(result.contains("environment=production")); + assertTrue(result.contains("user_defined_fields")); + assertTrue(result.contains("embedded")); + assertTrue(result.contains("ai_suggested")); + assertTrue(result.contains("visual_markups")); + } + // ========== CONVERT URL PARAM TESTS ========== @Test diff --git a/src/test/java/com/contentstack/sdk/TestEntry.java b/src/test/java/com/contentstack/sdk/TestEntry.java index 4cf7ac2d..827cfabc 100644 --- a/src/test/java/com/contentstack/sdk/TestEntry.java +++ b/src/test/java/com/contentstack/sdk/TestEntry.java @@ -1,5 +1,6 @@ package com.contentstack.sdk; +import org.json.JSONArray; import org.json.JSONObject; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -251,6 +252,106 @@ void testIncludeMetadata() { assertEquals(true, entry.params.get("include_metadata")); } + // ========== ASSET FIELDS TESTS (CDA asset_fields[] parameter) ========== + + @Test + void testAssetFieldsWithSupportedValues() { + Entry result = entry.assetFields("user_defined_fields", "embedded", "ai_suggested", "visual_markups"); + assertSame(entry, result); + assertTrue(entry.params.has("asset_fields[]")); + Object val = entry.params.get("asset_fields[]"); + assertTrue(val instanceof JSONArray); + JSONArray arr = (JSONArray) val; + assertEquals(4, arr.length()); + assertEquals("user_defined_fields", arr.get(0)); + assertEquals("embedded", arr.get(1)); + assertEquals("ai_suggested", arr.get(2)); + assertEquals("visual_markups", arr.get(3)); + } + + @Test + void testAssetFieldsReturnsThis() { + Entry result = entry.assetFields("embedded"); + assertSame(entry, result); + } + + @Test + void testAssetFieldsWithNoArgsDoesNotSetParam() { + entry.assetFields(); + assertFalse(entry.params.has("asset_fields[]")); + } + + @Test + void testAssetFieldsWithNullDoesNotSetParam() { + entry.assetFields((String[]) null); + assertFalse(entry.params.has("asset_fields[]")); + } + + @Test + void testAssetFieldsChainingWithIncludeMetadata() { + Entry result = entry.assetFields("user_defined_fields", "visual_markups").includeMetadata().setLocale("en-us"); + assertSame(entry, result); + assertTrue(entry.params.has("asset_fields[]")); + assertTrue(entry.params.has("include_metadata")); + assertTrue(entry.params.has("locale")); + } + + /** + * Usage: stack.contentType(ctUid).entry(entryUid).assetFields(...).fetch() + * Verifies the full chain sets asset_fields[] on the entry before fetch. + */ + @Test + void testUsageSingleEntryFetchWithAssetFields() throws IllegalAccessException { + Stack stack = Contentstack.stack("api_key", "delivery_token", "env"); + Entry entry = stack.contentType("blog").entry("entry_123") + .assetFields("user_defined_fields", "embedded"); + assertTrue(entry.params.has("asset_fields[]")); + JSONArray arr = entry.params.getJSONArray("asset_fields[]"); + assertEquals(2, arr.length()); + assertEquals("user_defined_fields", arr.get(0)); + assertEquals("embedded", arr.get(1)); + } + + @Test + void testAssetFieldsSingleField() { + entry.assetFields("embedded"); + JSONArray arr = entry.params.getJSONArray("asset_fields[]"); + assertEquals(1, arr.length()); + assertEquals("embedded", arr.get(0)); + } + + @Test + void testAssetFieldsEmptyVarargsArrayDoesNotSetParam() { + entry.assetFields(new String[0]); + assertFalse(entry.params.has("asset_fields[]")); + } + + @Test + void testAssetFieldsSecondCallOverwrites() { + entry.assetFields("user_defined_fields", "embedded"); + entry.assetFields("ai_suggested"); + JSONArray arr = entry.params.getJSONArray("asset_fields[]"); + assertEquals(1, arr.length()); + assertEquals("ai_suggested", arr.get(0)); + } + + @Test + void testAssetFieldsDuplicateValuesAllowed() { + entry.assetFields("embedded", "embedded"); + JSONArray arr = entry.params.getJSONArray("asset_fields[]"); + assertEquals(2, arr.length()); + assertEquals("embedded", arr.get(0)); + assertEquals("embedded", arr.get(1)); + } + + @Test + void testAssetFieldsWithEmptyStringInArray() { + entry.assetFields("valid", "", "visual_markups"); + JSONArray arr = entry.params.getJSONArray("asset_fields[]"); + assertEquals(3, arr.length()); + assertEquals("", arr.get(1)); + } + // ========== ONLY/EXCEPT FIELD TESTS ========== @Test diff --git a/src/test/java/com/contentstack/sdk/TestQuery.java b/src/test/java/com/contentstack/sdk/TestQuery.java index 065ef3d1..667fdf1b 100644 --- a/src/test/java/com/contentstack/sdk/TestQuery.java +++ b/src/test/java/com/contentstack/sdk/TestQuery.java @@ -550,6 +550,109 @@ void testIncludeMetadata() { assertNotNull(query.urlQueries); } + // ========== ASSET FIELDS TESTS (CDA asset_fields[] parameter) ========== + + @Test + void testAssetFieldsWithSupportedValues() { + Query result = query.assetFields("user_defined_fields", "embedded", "ai_suggested", "visual_markups"); + assertSame(query, result); + assertTrue(query.urlQueries.has("asset_fields[]")); + Object val = query.urlQueries.get("asset_fields[]"); + assertTrue(val instanceof JSONArray); + JSONArray arr = (JSONArray) val; + assertEquals(4, arr.length()); + assertEquals("user_defined_fields", arr.get(0)); + assertEquals("embedded", arr.get(1)); + assertEquals("ai_suggested", arr.get(2)); + assertEquals("visual_markups", arr.get(3)); + } + + @Test + void testAssetFieldsReturnsThis() { + Query result = query.assetFields("embedded"); + assertSame(query, result); + } + + @Test + void testAssetFieldsWithNoArgsDoesNotSetParam() { + query.assetFields(); + assertFalse(query.urlQueries.has("asset_fields[]")); + } + + @Test + void testAssetFieldsWithNullDoesNotSetParam() { + query.assetFields((String[]) null); + assertFalse(query.urlQueries.has("asset_fields[]")); + } + + @Test + void testAssetFieldsChainingWithIncludeMetadata() { + Query result = query.assetFields("ai_suggested", "visual_markups").includeMetadata().includeCount(); + assertSame(query, result); + assertTrue(query.urlQueries.has("asset_fields[]")); + assertTrue(query.urlQueries.has("include_count")); + JSONArray arr = query.urlQueries.getJSONArray("asset_fields[]"); + assertEquals(2, arr.length()); + assertEquals("ai_suggested", arr.get(0)); + assertEquals("visual_markups", arr.get(1)); + } + + /** + * Usage: stack.contentType(ctUid).query().assetFields(...).find() + * Verifies the full chain sets asset_fields[] on the query before find. + */ + @Test + void testUsageQueryEntriesFindWithAssetFields() throws IllegalAccessException { + Stack stack = Contentstack.stack("api_key", "delivery_token", "env"); + Query query = stack.contentType("blog").query() + .assetFields("ai_suggested", "visual_markups"); + assertTrue(query.urlQueries.has("asset_fields[]")); + JSONArray arr = query.urlQueries.getJSONArray("asset_fields[]"); + assertEquals(2, arr.length()); + assertEquals("ai_suggested", arr.get(0)); + assertEquals("visual_markups", arr.get(1)); + } + + @Test + void testAssetFieldsSingleField() { + query.assetFields("user_defined_fields"); + JSONArray arr = query.urlQueries.getJSONArray("asset_fields[]"); + assertEquals(1, arr.length()); + assertEquals("user_defined_fields", arr.get(0)); + } + + @Test + void testAssetFieldsEmptyVarargsArrayDoesNotSetParam() { + query.assetFields(new String[0]); + assertFalse(query.urlQueries.has("asset_fields[]")); + } + + @Test + void testAssetFieldsSecondCallOverwrites() { + query.assetFields("user_defined_fields", "embedded"); + query.assetFields("visual_markups"); + JSONArray arr = query.urlQueries.getJSONArray("asset_fields[]"); + assertEquals(1, arr.length()); + assertEquals("visual_markups", arr.get(0)); + } + + @Test + void testAssetFieldsDuplicateValuesAllowed() { + query.assetFields("ai_suggested", "ai_suggested"); + JSONArray arr = query.urlQueries.getJSONArray("asset_fields[]"); + assertEquals(2, arr.length()); + assertEquals("ai_suggested", arr.get(0)); + assertEquals("ai_suggested", arr.get(1)); + } + + @Test + void testAssetFieldsWithEmptyStringInArray() { + query.assetFields("valid", "", "embedded"); + JSONArray arr = query.urlQueries.getJSONArray("asset_fields[]"); + assertEquals(3, arr.length()); + assertEquals("", arr.get(1)); + } + @Test void testMultipleIncludeMethods() { query.includeFallback() From 4c6be0bdd7ed0a537e7235240352155eaff6604d Mon Sep 17 00:00:00 2001 From: reeshika-h Date: Thu, 12 Feb 2026 18:14:36 +0530 Subject: [PATCH 6/6] version bump --- CHANGELOG.md | 5 +++++ pom.xml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 001a9d56..d2fa8498 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## v2.5.0 + +### Feb 12, 2026 +- Enhancement: assetFields method added + ## v2.4.0 ### Feb 02, 2026 diff --git a/pom.xml b/pom.xml index 41ea6079..d8aa684b 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.contentstack.sdk java - 2.4.0 + 2.5.0 jar contentstack-java Java SDK for Contentstack Content Delivery API