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/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..417ea1a3 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
@@ -20,11 +20,11 @@
3.3.1
3.4.1
3.0.0
- 3.1.11
+ 3.1.12
3.0.0
- 5.1.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.19.2
+ 2.21.0
com.slack.api
bolt
- 1.45.3
+ 1.46.0
org.jetbrains
@@ -199,7 +196,7 @@
com.squareup.okhttp3
okhttp
- 5.1.0
+ 5.3.2
org.slf4j
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/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);
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()