diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/CategoriesResource.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/CategoriesResource.java
index 33b2f33ce41c..ccddc281c05e 100644
--- a/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/CategoriesResource.java
+++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/CategoriesResource.java
@@ -31,6 +31,7 @@
import com.dotmarketing.portlets.categories.business.CategoryAPI;
import com.dotmarketing.portlets.categories.business.PaginatedCategories;
import com.dotmarketing.portlets.categories.model.Category;
+import com.dotmarketing.portlets.categories.model.HierarchyShortCategory;
import com.dotmarketing.util.ActivityLogger;
import com.dotmarketing.util.Logger;
import com.dotmarketing.util.PageMode;
@@ -138,7 +139,6 @@ public CategoriesResource(final WebResource webresource, final PaginationUtil pa
*
per_page: limit of items to return
* ordeby: field to order by
* direction: asc for upward order and desc for downward order
- * showChildrenCount: true for including children categories count and false to exclude it
*
*
* Url example: /api/v1/categories?filter=&page=0&per_page=5&ordeby=category_name&direction=ASC&showChildrenCount=true
@@ -196,22 +196,30 @@ public final Response getCategories(@Context final HttpServletRequest httpReques
/**
* Return a list of {@link com.dotmarketing.portlets.categories.model.Category}, entity response
- * syntax:.
+ * Syntax:.
+ *
+ *
+ * {
+ * contentTypes: array of Category,
+ * total: total number of Categories
+ * }
+ *
*
- * { contentTypes: array of Category total: total number of Categories }
*
* Url syntax:
* api/v1/categories/children?filter=filter-string&page=page-number&per_page=per-page&orderby=order-field-name&direction=order-direction&inode=parentId
*
- * where:
*
- *
- * - filter-string: just return Category whose content this pattern into its name
- * - page: page to return
- * - per_page: limit of items to return
- * - ordeby: field to order by
- * - direction: asc for upward order and desc for downward order
- *
+ * Parameeters:
+ *
+ * - filter-string: Return categories whose names contain this pattern.
+ * - page: The page number to return.
+ * - per_page: The limit of items to return.
+ * - orderby: The field to order by.
+ * - direction: Sorting direction, asc for ascending and desc for descending.
+ * - showChildrenCount: true to include the count of child categories, false to exclude it.
+ * - allLevels: A Boolean value. If TRUE, the search will include categories at any level, ignoring the childrenCategories parameter. If showChildrenCount is TRUE, this parameter is ignored.
+ *
*
* Url example: v1/categories/children?filter=test&page=0&per_page=5&orderby=category_name
*
@@ -276,6 +284,79 @@ public final Response getChildren(@Context final HttpServletRequest httpRequest,
return response;
}
+ /**
+ * Response with the list of parents for a specific set of {@link Category}.
+ *
+ * This ned point receive a list the {@link Category}'s endpoint as follow:
+ *
+ *
+ * {
+ * "inodes": ["352ca17e238357ce12e9dff10afc8516", "c0ab974897f8d37c98afa4bba74ef9f1"]
+ * }
+ *
+ *
+ * The output is going to be something like:
+ *
+ *
+ * {
+ * entity: [
+ * {
+ * "inode": "352ca17e238357ce12e9dff10afc8516",
+ * "parentList": [
+ * {
+ * 'categoryName': 'Grand Parent Name',
+ * 'key': 'Grand Parent Key',
+ * 'inode': 'Grand Parent inode'
+ * },
+ * {
+ * 'categoryName': 'Parent Name',
+ * 'key': 'Parent Key',
+ * 'inode': 'Parent inode'
+ * }
+ * ]
+ * },
+ * {
+ * "inode": "c0ab974897f8d37c98afa4bba74ef9f1",
+ * "parentList": [
+ * {
+ * 'categoryName': 'Category name value',
+ * 'key': 'Key value',
+ * 'inode': 'inode value'
+ * }
+ * ]
+ * }
+ * ]
+ * }
+ *
+ *
+ * parentList is the list of parents where the 0 is the more top level parent and the last one is the direct
+ * parent.
+ *
+ * @param httpRequest
+ * @param httpResponse
+ * @param form
+ * @return
+ * @throws DotDataException
+ * @throws DotSecurityException
+ */
+ @GET
+ @Path(("/hierarchy"))
+ @JSONP
+ @NoCache
+ @Produces({MediaType.APPLICATION_JSON})
+ public final Response getHierarchy(@Context final HttpServletRequest httpRequest,
+ @Context final HttpServletResponse httpResponse,
+ final CategoryInodesForm form) throws DotDataException, DotSecurityException {
+
+ Logger.debug(this, () -> "Getting the List of Parents for the follow categories: " +
+ form.getInodes().stream().collect(Collectors.joining(",")));
+
+ webResource.init(null, httpRequest, httpResponse, true, null);
+
+ return Response.ok(
+ new HierarchyShortCategoriesResponseView(categoryAPI.findHierarchy(form.getInodes()))).build();
+ }
+
/**
* Lookup operation. Categories can be retrieved by category id or key
* @param httpRequest
diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/CategoryInodesForm.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/CategoryInodesForm.java
new file mode 100644
index 000000000000..4a71b43d8f71
--- /dev/null
+++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/CategoryInodesForm.java
@@ -0,0 +1,41 @@
+package com.dotcms.rest.api.v1.categories;
+
+import com.dotcms.repackage.javax.validation.constraints.NotNull;
+import com.dotcms.rest.api.Validated;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+
+import java.util.List;
+
+/**
+ * Category Input Form
+ */
+@JsonDeserialize(builder = CategoryInodesForm.Builder.class)
+public class CategoryInodesForm extends Validated {
+
+ private List inodes;
+
+ private CategoryInodesForm(final Builder builder) {
+
+ this.inodes = builder.inodes;
+ }
+
+ public List getInodes() {
+ return inodes;
+ }
+
+ public static final class Builder {
+
+ @JsonProperty
+ private List inodes;
+
+ public void setInodes(List inodes) {
+ this.inodes = inodes;
+ }
+
+ public CategoryInodesForm build() {
+
+ return new CategoryInodesForm(this);
+ }
+ }
+}
diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/HierarchyShortCategoriesResponseView.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/HierarchyShortCategoriesResponseView.java
new file mode 100644
index 000000000000..8e418e80b8ae
--- /dev/null
+++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/categories/HierarchyShortCategoriesResponseView.java
@@ -0,0 +1,13 @@
+package com.dotcms.rest.api.v1.categories;
+
+import com.dotcms.experiments.model.Experiment;
+import com.dotcms.rest.ResponseEntityView;
+import com.dotmarketing.portlets.categories.model.HierarchyShortCategory;
+
+import java.util.List;
+
+public class HierarchyShortCategoriesResponseView extends ResponseEntityView> {
+ public HierarchyShortCategoriesResponseView(final List categories) {
+ super(categories);
+ }
+}
\ No newline at end of file
diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPI.java b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPI.java
index 8ff3f200b8da..44b0558d25a5 100644
--- a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPI.java
+++ b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPI.java
@@ -5,8 +5,11 @@
import com.dotmarketing.exception.DotDataException;
import com.dotmarketing.exception.DotSecurityException;
import com.dotmarketing.portlets.categories.model.Category;
+import com.dotmarketing.portlets.categories.model.HierarchyShortCategory;
import com.dotmarketing.portlets.contentlet.model.Contentlet;
import com.liferay.portal.model.User;
+
+import java.util.Collection;
import java.util.HashMap;
import java.util.List;
/**
@@ -496,4 +499,38 @@ Category findByVariable(final String variable, final User user,
*/
PaginatedCategories findAll(final CategorySearchCriteria searchCriteria, final User user, boolean respectFrontendRoles)
throws DotDataException, DotSecurityException;
+
+ /**
+ * Find Categories by inodes and calculate its Hierarchy.
+ *
+ * For Example if you have the follows categories:
+ *
+ *
+ * | Inode | Name | key |Parent |
+ * |--------|-------------|-------------|----------------|
+ * | 1 | Top Category| top | null |
+ * | 2 | Child | child | Top Category |
+ * | 3 | Grand Child | grand_child | Child |
+ *
+ * And you search by inode 3 then you got:
+ *
+ * Inode: 3
+ * parentList [
+ * {
+ * 'categoryName':'Top Category',
+ * 'key': 'top',
+ * 'inode': '1'
+ * },
+ * {
+ * 'categoryName':'Child',
+ * 'key': 'child',
+ * 'inode': '2'
+ * }
+ * ]
+ *
+ * @param inodes List of inodes to search
+ * @return
+ * @throws DotDataException
+ */
+ List findHierarchy(final Collection inodes) throws DotDataException;
}
diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPIImpl.java b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPIImpl.java
index fab12f505b88..2e30d0ff6b44 100644
--- a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPIImpl.java
+++ b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPIImpl.java
@@ -17,6 +17,7 @@
import com.dotmarketing.exception.DotDataException;
import com.dotmarketing.exception.DotSecurityException;
import com.dotmarketing.portlets.categories.model.Category;
+import com.dotmarketing.portlets.categories.model.HierarchyShortCategory;
import com.dotmarketing.portlets.contentlet.model.Contentlet;
import com.dotmarketing.util.ActivityLogger;
import com.dotmarketing.util.InodeUtils;
@@ -25,14 +26,8 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.liferay.portal.model.User;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Objects;
-import java.util.UUID;
+
+import java.util.*;
import java.util.stream.Collectors;
/**
@@ -978,4 +973,18 @@ public PaginatedCategories findAll(final CategorySearchCriteria searchCriteria,
return getCategoriesSubList(searchCriteria.offset, searchCriteria.limit, categories, null);
}
+ /**
+ * Default implementation of {@link CategoryAPI}
+ *
+ * @param inodes List of inodes to search
+ * @return
+ *
+ * @throws DotDataException
+ */
+ @CloseDBIfOpened
+ @Override
+ public List findHierarchy(final Collection inodes) throws DotDataException {
+ Logger.debug(this, "Getting parentList for the follow Categories: " + inodes);
+ return categoryFactory.findHierarchy(inodes);
+ }
}
diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactory.java b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactory.java
index d113529ee09a..332376eef471 100644
--- a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactory.java
+++ b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactory.java
@@ -1,11 +1,13 @@
package com.dotmarketing.portlets.categories.business;
+import java.util.Collection;
import java.util.List;
import com.dotmarketing.exception.DotDataException;
import com.dotmarketing.portlets.categories.model.Category;
import com.dotmarketing.portlets.categories.model.HierarchedCategory;
+import com.dotmarketing.portlets.categories.model.HierarchyShortCategory;
/**
@@ -286,4 +288,38 @@ public abstract class CategoryFactory {
* @return List of Category filteredx
*/
public abstract List findAll(final CategorySearchCriteria searchCriteria) throws DotDataException;
+
+ /**
+ * Find Categories by inodes and calculate its Hierarchy.
+ *
+ * For Example if you have the follows categories:
+ *
+ *
+ * | Inode | Name | key |Parent |
+ * |--------|-------------|-------------|----------------|
+ * | 1 | Top Category| top | null |
+ * | 2 | Child | child | Top Category |
+ * | 3 | Grand Child | grand_child | Child |
+ *
+ * And you search by inode 3 then you got:
+ *
+ * Inode: 3
+ * parentList [
+ * {
+ * 'categoryName':'Top Category',
+ * 'key': 'top',
+ * 'inode': '1'
+ * },
+ * {
+ * 'categoryName':'Child',
+ * 'key': 'child',
+ * 'inode': '2'
+ * }
+ * ]
+ *
+ * @param inodes List of inodes to search
+ * @return
+ * @throws DotDataException
+ */
+ public abstract List findHierarchy(final Collection inodes) throws DotDataException;
}
diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactoryImpl.java b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactoryImpl.java
index 31e8aeb46a1b..d821386218dd 100644
--- a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactoryImpl.java
+++ b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactoryImpl.java
@@ -17,24 +17,24 @@
import com.dotmarketing.common.util.SQLUtil;
import com.dotmarketing.db.DbConnectionFactory;
import com.dotmarketing.exception.DotDataException;
+import com.dotmarketing.exception.DotRuntimeException;
import com.dotmarketing.factories.TreeFactory;
import com.dotmarketing.portlets.categories.model.Category;
import com.dotmarketing.portlets.categories.model.HierarchedCategory;
+import com.dotmarketing.portlets.categories.model.HierarchyShortCategory;
import com.dotmarketing.portlets.categories.model.ShortCategory;
import com.dotmarketing.util.InodeUtils;
import com.dotmarketing.util.Logger;
import com.dotmarketing.util.UtilMethods;
import com.dotmarketing.util.VelocityUtil;
import com.liferay.util.StringPool;
+import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.io.Serializable;
import java.sql.*;
-import java.util.ArrayList;
+import java.util.*;
import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
import java.util.stream.Collectors;
/**
@@ -633,22 +633,12 @@ private List convertForHierarchedCategories(final List
+ *
+ * @param parentsASJsonArray
+ * @return
+ */
+ private static List getShortCategories(String parentsASJsonArray) {
+ try {
+ return ((List>) JsonUtil.getObjectFromJson(parentsASJsonArray, List.class))
+ .stream()
+ .map(map -> new ShortCategory.Builder()
+ .setCategoryName(map.get("categoryName"))
+ .setKey(map.get("key"))
+ .setInode(map.get(INODE))
+ .build()
+ )
+ .collect(Collectors.toList());
+ } catch (IOException e) {
+ throw new DotRuntimeException(e);
+ }
+ }
+
private Category convertForCategory(final Map sqlResult) {
return convertForCategory(sqlResult, Category.class);
}
@@ -949,4 +972,54 @@ private void updateCache(List extends Category> categories) throws DotDataExce
}
}
+ /**
+ * Default implementation of {@link CategoryFactory#findHierarchy(Collection)}
+ *
+ * @param inodes list of inodes to search
+ * @return
+ * @throws DotDataException
+ */
+ @Override
+ public List findHierarchy(final Collection inodes) throws DotDataException {
+
+ if (inodes == null || inodes.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ final String queryTemplate = "WITH RECURSIVE CategoryHierarchy AS ( SELECT " +
+ "c.inode," +
+ "c.inode AS root_inode," +
+ "1 AS level," +
+ "json_build_object('inode', c.inode, 'categoryName', c.category_name, 'key', c.category_key)::varchar AS path " +
+ "FROM Category c " +
+ "WHERE c.inode IN (%s) " +
+ "UNION ALL " +
+ "SELECT " +
+ "c.inode, " +
+ "ch.root_inode AS root_inode, " +
+ "ch.level + 1 AS level, " +
+ "CONCAT(json_build_object('inode', c.inode, 'categoryName', c.category_name, 'key', c.category_key)::varchar, ',', ch.path) AS path " +
+ "FROM Category c JOIN tree t ON c.inode = t.parent JOIN CategoryHierarchy ch ON t.child = ch.inode " +
+ ")," +
+ "MaxLevels AS (SELECT root_inode, MAX(level) AS max_level FROM CategoryHierarchy GROUP BY root_inode) " +
+ "SELECT " +
+ "ch.root_inode as inode, " +
+ "CONCAT('[', path, ']')::jsonb as path " +
+ "FROM CategoryHierarchy ch JOIN MaxLevels ml ON ch.root_inode = ml.root_inode AND ch.level = ml.max_level;";
+
+
+ final DotConnect dc = new DotConnect()
+ .setSQL(String.format(queryTemplate, DotConnect.createParametersPlaceholder(inodes.size())));
+
+ inodes.forEach(dc::addParam);
+
+ return dc.loadObjectResults().stream().map(row -> {
+ final List parentList = getShortCategories(row.get("path").toString());
+
+ return new HierarchyShortCategory(row.get(INODE).toString(), parentList.subList(0, parentList.size() - 1));
+ }).collect(Collectors.toList());
+ }
+
+
+
}
diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/model/HierarchyShortCategory.java b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/model/HierarchyShortCategory.java
new file mode 100644
index 000000000000..f2c5db0869b3
--- /dev/null
+++ b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/model/HierarchyShortCategory.java
@@ -0,0 +1,25 @@
+package com.dotmarketing.portlets.categories.model;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * Represents a HierarchyCategory but just include the parentList and the inode
+ */
+public class HierarchyShortCategory implements Serializable {
+ private final String inode;
+ private final List parentList;
+
+ public HierarchyShortCategory(final String inode, final List parentList) {
+ this.inode = inode;
+ this.parentList = parentList;
+ }
+
+ public String getInode() {
+ return inode;
+ }
+
+ public List getParentList() {
+ return parentList;
+ }
+}
diff --git a/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryAPITest.java b/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryAPITest.java
index 8df95b568119..0e9d36b3a2d1 100644
--- a/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryAPITest.java
+++ b/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryAPITest.java
@@ -8,8 +8,7 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
import com.dotcms.IntegrationTestBase;
import com.dotcms.contenttype.business.ContentTypeAPIImpl;
@@ -35,6 +34,7 @@
import com.dotmarketing.exception.DotSecurityException;
import com.dotmarketing.portlets.categories.model.Category;
import com.dotmarketing.portlets.categories.model.HierarchedCategory;
+import com.dotmarketing.portlets.categories.model.HierarchyShortCategory;
import com.dotmarketing.portlets.contentlet.business.ContentletAPI;
import com.dotmarketing.portlets.contentlet.business.HostAPI;
import com.dotmarketing.portlets.contentlet.model.Contentlet;
@@ -1661,4 +1661,38 @@ public void getAllCategoriesFilteredWithPagination() throws DotDataException, Do
assertEquals(4, secondPage.getCategories().size());
assertTrue(list(category6, category7, category8, category9).containsAll(secondPage.getCategories()));
}
+
+ /**
+ * Method to test: {@link CategoryAPIImpl#findAll(CategorySearchCriteria, User, boolean)}
+ * When: Call the API method
+ * Should: it should
+ * - Use the {@link CategoryFactoryImpl#findAll(CategorySearchCriteria)} to search the {@link Category}
+ * - Use the {@link PermissionAPI#filterCollection(List, int, boolean, User)} method to check permission
+ */
+ @Test
+ public void findHierarchy() throws DotDataException, DotSecurityException {
+ final String inode = new RandomString().nextString();
+
+ final HierarchyShortCategory category1 = mock(HierarchyShortCategory.class);
+ when(category1.getInode()).thenReturn(inode);
+
+ final HierarchyShortCategory category2 = mock(HierarchyShortCategory.class);
+ final HierarchyShortCategory category3 = mock(HierarchyShortCategory.class);
+
+ final List categoriesAExpected = list(category2, category3);
+
+ final List inodes = list(category1.getInode());
+ final CategoryFactory categoryFactory = mock();
+ when(categoryFactory.findHierarchy(inodes)).thenReturn(categoriesAExpected);
+
+ final PermissionAPI permissionAPI = mock(PermissionAPI.class);
+
+ final CategoryAPI categoryAPI = new CategoryAPIImpl(categoryFactory, permissionAPI);
+ final List hierarchy = categoryAPI.findHierarchy(inodes);
+
+ assertEquals(categoriesAExpected.size(), hierarchy.size());
+ assertTrue(categoriesAExpected.containsAll(hierarchy));
+
+ verify(categoryFactory).findHierarchy(inodes);
+ }
}
diff --git a/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryFactoryTest.java b/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryFactoryTest.java
index a6c0903f41d0..92b07f52751c 100644
--- a/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryFactoryTest.java
+++ b/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryFactoryTest.java
@@ -20,14 +20,12 @@
import com.dotmarketing.exception.DotSecurityException;
import com.dotmarketing.portlets.categories.model.Category;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.dotmarketing.portlets.categories.model.HierarchedCategory;
+import com.dotmarketing.portlets.categories.model.HierarchyShortCategory;
import com.dotmarketing.portlets.categories.model.ShortCategory;
import com.liferay.util.StringUtil;
import com.tngtech.java.junit.dataprovider.DataProvider;
@@ -640,4 +638,56 @@ public String transformToSearch(){
return transformToSearch.apply(filter);
}
}
+
+ /**
+ * Method to test: {@link com.dotmarketing.portlets.categories.model.HierarchyShortCategory}
+ * when: Create 4 Category each is a child of the previous one and find for the great grand child and the grand child
+ * should: Return the great grand child we all the parent list
+ * @throws DotDataException
+ */
+ @Test
+ public void findHierarchy() throws DotDataException {
+ final Category topLevelCategory = new CategoryDataGen().setCategoryName("Top Level Category")
+ .setKey("top_level")
+ .setCategoryVelocityVarName("top_level_categoria")
+ .nextPersisted();
+
+ final Category childCategory = new CategoryDataGen().setCategoryName("Child Category")
+ .setKey("child")
+ .setCategoryVelocityVarName("child_category")
+ .parent(topLevelCategory)
+ .nextPersisted();
+
+ final Category grandChildCategory = new CategoryDataGen().setCategoryName("Grand Child Category")
+ .setKey("grand_child")
+ .setCategoryVelocityVarName("grand_child_category")
+ .parent(childCategory)
+ .nextPersisted();
+
+ final Category greatGrandchildCategory = new CategoryDataGen().setCategoryName("Great Grand Child Category")
+ .setKey("great_grand_child")
+ .setCategoryVelocityVarName("great_grand_child_category")
+ .parent(grandChildCategory)
+ .nextPersisted();
+
+ final List categories = FactoryLocator.getCategoryFactory()
+ .findHierarchy(list(grandChildCategory.getInode(), greatGrandchildCategory.getInode()));
+
+ assertEquals(2, categories.size());
+
+ for (final HierarchyShortCategory category : categories) {
+ if (grandChildCategory.getInode().equals(category.getInode())) {
+ assertEquals(2, category.getParentList().size());
+ assertEquals("Top Level Category", category.getParentList().get(0).getCategoryName());
+ assertEquals("Child Category", category.getParentList().get(1).getCategoryName());
+ } else if (greatGrandchildCategory.getInode().equals(category.getInode())) {
+ assertEquals(3, category.getParentList().size());
+ assertEquals("Top Level Category", category.getParentList().get(0).getCategoryName());
+ assertEquals("Child Category", category.getParentList().get(1).getCategoryName());
+ assertEquals("Grand Child Category", category.getParentList().get(2).getCategoryName());
+ } else {
+ throw new AssertionError("Unexpected Category");
+ }
+ }
+ }
}
diff --git a/dotcms-postman/src/main/resources/postman/Category.postman_collection.json b/dotcms-postman/src/main/resources/postman/Category.postman_collection.json
index 1b9b85825f59..5b9d409ca5ab 100644
--- a/dotcms-postman/src/main/resources/postman/Category.postman_collection.json
+++ b/dotcms-postman/src/main/resources/postman/Category.postman_collection.json
@@ -1,6 +1,6 @@
{
"info": {
- "_postman_id": "d13b8154-b0c4-46eb-afcd-902105508f76",
+ "_postman_id": "12554162-5748-4f0b-a315-85639e82d87b",
"name": "Category",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_exporter_id": "30436704"
@@ -2890,7 +2890,7 @@
"method": "GET",
"header": [],
"url": {
- "raw": "{{serverURL}}/api/v1/categories/children?filter=PostmanTest&allLevels=true&inode={{topCategoryInode}}",
+ "raw": "{{serverURL}}/api/v1/categories/children?filter=PostmanTest&allLevels=true&inode={{topCategoryInode}}&per_page=7000&direction=ASC",
"host": [
"{{serverURL}}"
],
@@ -2912,14 +2912,591 @@
{
"key": "inode",
"value": "{{topCategoryInode}}"
+ },
+ {
+ "key": "showChildrenCount",
+ "value": "true",
+ "disabled": true
+ },
+ {
+ "key": "per_page",
+ "value": "7000"
+ },
+ {
+ "key": "direction",
+ "value": "ASC"
+ }
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Get categories by filter AND looking on the entire tree (Enabled showChildrenCount)",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code should be ok 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "var jsonData = pm.response.json();",
+ "",
+ "pm.test(\"Fetch successfully without errors\", function () {",
+ " pm.expect(jsonData.errors).to.have.lengthOf(0);",
+ "});",
+ "",
+ "pm.expect(2).to.have.equals(jsonData.entity.length);",
+ "",
+ "pm.test('get the right categories', () => { ",
+ " let data = [];",
+ "",
+ " for (let i = 0; i < jsonData.entity.length; i++)",
+ " { ",
+ " data.push(jsonData.entity[i]['categoryName']); ",
+ "",
+ " if (i === 0) {",
+ " pm.expect('PostmanTest Child 1').to.have.equals(jsonData.entity[i].categoryName);",
+ " pm.expect(jsonData.entity[i].parentList).to.be.undefined;",
+ " } else if (i === 1) {",
+ " pm.expect('PostmanTest Child 2').to.have.equals(jsonData.entity[i].categoryName);",
+ " pm.expect(jsonData.entity[i].parentList).to.be.undefined;",
+ " } ",
+ " }",
+ "",
+ " data.includes(\"PostmanTest Child 1\");",
+ " data.includes(\"PostmanTest Child 2\");",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "auth": {
+ "type": "bearer",
+ "bearer": [
+ {
+ "key": "token",
+ "value": "{{jwt}}",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "{{serverURL}}/api/v1/categories/children?filter=PostmanTest&allLevels=true&inode={{topCategoryInode}}&showChildrenCount=true&per_page=7000&direction=ASC",
+ "host": [
+ "{{serverURL}}"
+ ],
+ "path": [
+ "api",
+ "v1",
+ "categories",
+ "children"
+ ],
+ "query": [
+ {
+ "key": "filter",
+ "value": "PostmanTest"
+ },
+ {
+ "key": "allLevels",
+ "value": "true"
+ },
+ {
+ "key": "inode",
+ "value": "{{topCategoryInode}}"
+ },
+ {
+ "key": "showChildrenCount",
+ "value": "true"
+ },
+ {
+ "key": "per_page",
+ "value": "7000"
+ },
+ {
+ "key": "direction",
+ "value": "ASC"
+ }
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Get categories by filter AND looking just in children",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code should be ok 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "var jsonData = pm.response.json();",
+ "",
+ "pm.test(\"Fetch successfully without errors\", function () {",
+ " pm.expect(jsonData.errors).to.have.lengthOf(0);",
+ "});",
+ "",
+ "pm.expect(2).to.have.equals(jsonData.entity.length);",
+ "",
+ "pm.test('get the right categories', () => { ",
+ " let data = [];",
+ "",
+ " for (let i = 0; i < jsonData.entity.length; i++)",
+ " { ",
+ " data.push(jsonData.entity[i]['categoryName']); ",
+ " }",
+ "",
+ " data.includes(\"PostmanTest Child 1\");",
+ " data.includes(\"PostmanTest Child 2\");",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "auth": {
+ "type": "bearer",
+ "bearer": [
+ {
+ "key": "token",
+ "value": "{{jwt}}",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "{{serverURL}}/api/v1/categories/children?filter=PostmanTest&inode={{topCategoryInode}}",
+ "host": [
+ "{{serverURL}}"
+ ],
+ "path": [
+ "api",
+ "v1",
+ "categories",
+ "children"
+ ],
+ "query": [
+ {
+ "key": "filter",
+ "value": "PostmanTest"
+ },
+ {
+ "key": "inode",
+ "value": "{{topCategoryInode}}"
+ }
+ ]
+ }
+ },
+ "response": []
+ }
+ ],
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "type": "text/javascript",
+ "packages": {},
+ "exec": [
+ ""
+ ]
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "type": "text/javascript",
+ "packages": {},
+ "exec": [
+ ""
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "name": "Getting Category Hierarchy",
+ "item": [
+ {
+ "name": "Create Top Level category",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code should be ok 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "",
+ "var jsonData = pm.response.json();",
+ "",
+ "pm.test(\"Information Saved Correctly\", function () {",
+ " ",
+ " pm.expect(jsonData.entity.categoryName).to.eql(\"Hierarchy Top level Category\");",
+ "});",
+ "",
+ "pm.collectionVariables.set(\"topCategoryInodeHierarchy\", jsonData.entity.inode);",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "auth": {
+ "type": "bearer",
+ "bearer": [
+ {
+ "key": "token",
+ "value": "{{jwt}}",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"key\":\"Hierarchy_TOP_LEVEL\",\n \"categoryName\" : \"Hierarchy Top level Category\",\n \"categoryVelocityVarName\" : \"hierarchy_childrenTopLevel\",\n \"sortOrder\" : 1\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "{{serverURL}}/api/v1/categories",
+ "host": [
+ "{{serverURL}}"
+ ],
+ "path": [
+ "api",
+ "v1",
+ "categories"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Create First child Category",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code should be ok 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "var jsonData = pm.response.json();",
+ "",
+ "pm.test(\"Information Saved Correctly\", function () {",
+ " ",
+ " pm.expect(jsonData.entity.categoryName).to.eql(\"Hierarchy Child 1\");",
+ "});",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "auth": {
+ "type": "bearer",
+ "bearer": [
+ {
+ "key": "token",
+ "value": "{{jwt}}",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"key\":\"Hierarchy Child 1\",\n \"categoryName\" : \"Hierarchy Child 1\",\n \"keywords\":\"This is a child test category\",\n \"categoryVelocityVarName\" : \"Hierarchy_ChildTestKey_1\",\n \"parent\" : \"{{topCategoryInodeHierarchy}}\"\n}\n\n",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "{{serverURL}}/api/v1/categories",
+ "host": [
+ "{{serverURL}}"
+ ],
+ "path": [
+ "api",
+ "v1",
+ "categories"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Create Second child Category",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code should be ok 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "var jsonData = pm.response.json();",
+ "",
+ "pm.test(\"Information Saved Correctly\", function () {",
+ " ",
+ " pm.expect(jsonData.entity.categoryName).to.eql(\"Hierarchy Child 2\");",
+ "});",
+ "",
+ "pm.collectionVariables.set(\"child2CategoryInodeHierarchy\", jsonData.entity.inode);"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "auth": {
+ "type": "bearer",
+ "bearer": [
+ {
+ "key": "token",
+ "value": "{{jwt}}",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"key\":\"Hierarchy Child 2\",\n \"categoryName\" : \"Hierarchy Child 2\",\n \"keywords\":\"This is a child test category\",\n \"categoryVelocityVarName\" : \"Hierarchy_ChildTestKey_2\",\n \"parent\" : \"{{topCategoryInodeHierarchy}}\"\n}\n\n",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "{{serverURL}}/api/v1/categories",
+ "host": [
+ "{{serverURL}}"
+ ],
+ "path": [
+ "api",
+ "v1",
+ "categories"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Create Third child Category",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code should be ok 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "var jsonData = pm.response.json();",
+ "",
+ "pm.test(\"Information Saved Correctly\", function () {",
+ " ",
+ " pm.expect(jsonData.entity.categoryName).to.eql(\"Hierarchy Child 3\");",
+ "});",
+ "",
+ "",
+ "pm.collectionVariables.set(\"child3CategoryInodeHierarchy\", jsonData.entity.inode);"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "auth": {
+ "type": "bearer",
+ "bearer": [
+ {
+ "key": "token",
+ "value": "{{jwt}}",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"key\":\"Hierarchy_Child_3\",\n \"categoryName\" : \"Hierarchy Child 3\",\n \"keywords\":\"This is a child test category\",\n \"categoryVelocityVarName\" : \"Hierarchy_ChildTestKey_3\",\n \"parent\" : \"{{topCategoryInodeHierarchy}}\"\n}\n\n",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "{{serverURL}}/api/v1/categories",
+ "host": [
+ "{{serverURL}}"
+ ],
+ "path": [
+ "api",
+ "v1",
+ "categories"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Create Grandchild Category",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code should be ok 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "var jsonData = pm.response.json();",
+ "",
+ "pm.test(\"Information Saved Correctly\", function () {",
+ " ",
+ " pm.expect(jsonData.entity.categoryName).to.eql(\"Hierarchy Grandchild 1\");",
+ "});",
+ "",
+ "pm.collectionVariables.set(\"grantChildCategoryInodeHierarchy\", jsonData.entity.inode);",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "auth": {
+ "type": "bearer",
+ "bearer": [
+ {
+ "key": "token",
+ "value": "{{jwt}}",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"key\":\"Hierarchy ChiGrandchildld 1\",\n \"categoryName\" : \"Hierarchy Grandchild 1\",\n \"keywords\":\"This is a child test category\",\n \"categoryVelocityVarName\" : \"Hierarchy_GrandcßhildTestKey_1\",\n \"parent\" : \"{{child3CategoryInodeHierarchy}}\"\n}\n\n",
+ "options": {
+ "raw": {
+ "language": "json"
}
+ }
+ },
+ "url": {
+ "raw": "{{serverURL}}/api/v1/categories",
+ "host": [
+ "{{serverURL}}"
+ ],
+ "path": [
+ "api",
+ "v1",
+ "categories"
]
}
},
"response": []
},
{
- "name": "Get categories by filter AND looking just in children",
+ "name": "Create Second Top Level category",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code should be ok 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "auth": {
+ "type": "bearer",
+ "bearer": [
+ {
+ "key": "token",
+ "value": "{{jwt}}",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"key\":\"Hierarchy Second TOP_LEVEL\",\n \"categoryName\" : \"Hierarchy Second Top level Category\",\n \"categoryVelocityVarName\" : \"hierarchy_second_childrenTopLevel\",\n \"sortOrder\" : 1\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "{{serverURL}}/api/v1/categories",
+ "host": [
+ "{{serverURL}}"
+ ],
+ "path": [
+ "api",
+ "v1",
+ "categories"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Get categories hierarchy",
"event": [
{
"listen": "test",
@@ -2935,6 +3512,9 @@
" pm.expect(jsonData.errors).to.have.lengthOf(0);",
"});",
"",
+ "var child2CategoryInodeHierarchy = pm.collectionVariables.get(\"child2CategoryInodeHierarchy\"); ",
+ "var grantChildCategoryInodeHierarchy = pm.collectionVariables.get(\"grantChildCategoryInodeHierarchy\"); ;",
+ "",
"pm.expect(2).to.have.equals(jsonData.entity.length);",
"",
"pm.test('get the right categories', () => { ",
@@ -2942,11 +3522,122 @@
"",
" for (let i = 0; i < jsonData.entity.length; i++)",
" { ",
- " data.push(jsonData.entity[i]['categoryName']); ",
+ "",
+ " if (jsonData.entity[i]['inode'] === child2CategoryInodeHierarchy) {",
+ " pm.expect(1).to.have.equals(jsonData.entity[i].parentList.length);",
+ " pm.expect('Hierarchy Top level Category').to.have.equals(jsonData.entity[i].parentList[0].categoryName);",
+ " pm.expect(pm.collectionVariables.get(\"topCategoryInodeHierarchy\")).to.have.equals(jsonData.entity[i].parentList[0].inode);",
+ " pm.expect('Hierarchy_TOP_LEVEL').to.have.equals(jsonData.entity[i].parentList[0].key);",
+ " } else if (jsonData.entity[i]['inode'] === grantChildCategoryInodeHierarchy) {",
+ " pm.expect(2).to.have.equals(jsonData.entity[i].parentList.length);",
+ "",
+ " pm.expect('Hierarchy Top level Category').to.have.equals(jsonData.entity[i].parentList[0].categoryName);",
+ " pm.expect(pm.collectionVariables.get(\"topCategoryInodeHierarchy\")).to.have.equals(jsonData.entity[i].parentList[0].inode);",
+ " pm.expect('Hierarchy_TOP_LEVEL').to.have.equals(jsonData.entity[i].parentList[0].key);",
+ "",
+ " pm.expect(\"Hierarchy Child 3\").to.have.equals(jsonData.entity[i].parentList[1].categoryName);",
+ " pm.expect(pm.collectionVariables.get(\"child3CategoryInodeHierarchy\")).to.have.equals(jsonData.entity[i].parentList[1].inode);",
+ " pm.expect(\"Hierarchy_Child_3\").to.have.equals(jsonData.entity[i].parentList[1].key);",
+ " } else {",
+ " pm.expect(true).to.be.equals(false);",
+ " } ",
+ " }",
+ "",
+ "});"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "protocolProfileBehavior": {
+ "disableBodyPruning": true
+ },
+ "request": {
+ "auth": {
+ "type": "bearer",
+ "bearer": [
+ {
+ "key": "token",
+ "value": "{{jwt}}",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "GET",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"inodes\": [\"{{grantChildCategoryInodeHierarchy}}\", \"{{child2CategoryInodeHierarchy}}\"]\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "{{serverURL}}/api/v1/categories/hierarchy",
+ "host": [
+ "{{serverURL}}"
+ ],
+ "path": [
+ "api",
+ "v1",
+ "categories",
+ "hierarchy"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Get categories hierarchy with no valid category",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code should be ok 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "var jsonData = pm.response.json();",
+ "",
+ "pm.test(\"Fetch successfully without errors\", function () {",
+ " pm.expect(jsonData.errors).to.have.lengthOf(0);",
+ "});",
+ "",
+ "var child2CategoryInodeHierarchy = pm.collectionVariables.get(\"child2CategoryInodeHierarchy\"); ",
+ "var grantChildCategoryInodeHierarchy = pm.collectionVariables.get(\"grantChildCategoryInodeHierarchy\"); ;",
+ "",
+ "pm.expect(2).to.have.equals(jsonData.entity.length);",
+ "",
+ "pm.test('get the right categories', () => { ",
+ " let data = [];",
+ "",
+ " for (let i = 0; i < jsonData.entity.length; i++)",
+ " { ",
+ "",
+ " if (jsonData.entity[i]['inode'] === child2CategoryInodeHierarchy) {",
+ " pm.expect(1).to.have.equals(jsonData.entity[i].parentList.length);",
+ " pm.expect('Hierarchy Top level Category').to.have.equals(jsonData.entity[i].parentList[0].categoryName);",
+ " pm.expect(pm.collectionVariables.get(\"topCategoryInodeHierarchy\")).to.have.equals(jsonData.entity[i].parentList[0].inode);",
+ " pm.expect('Hierarchy_TOP_LEVEL').to.have.equals(jsonData.entity[i].parentList[0].key);",
+ " } else if (jsonData.entity[i]['inode'] === grantChildCategoryInodeHierarchy) {",
+ " pm.expect(2).to.have.equals(jsonData.entity[i].parentList.length);",
+ "",
+ " pm.expect('Hierarchy Top level Category').to.have.equals(jsonData.entity[i].parentList[0].categoryName);",
+ " pm.expect(pm.collectionVariables.get(\"topCategoryInodeHierarchy\")).to.have.equals(jsonData.entity[i].parentList[0].inode);",
+ " pm.expect('Hierarchy_TOP_LEVEL').to.have.equals(jsonData.entity[i].parentList[0].key);",
+ "",
+ " pm.expect(\"Hierarchy Child 3\").to.have.equals(jsonData.entity[i].parentList[1].categoryName);",
+ " pm.expect(pm.collectionVariables.get(\"child3CategoryInodeHierarchy\")).to.have.equals(jsonData.entity[i].parentList[1].inode);",
+ " pm.expect(\"Hierarchy_Child_3\").to.have.equals(jsonData.entity[i].parentList[1].key);",
+ " } else {",
+ " pm.expect(true).to.be.equals(false);",
+ " } ",
" }",
"",
- " data.includes(\"PostmanTest Child 1\");",
- " data.includes(\"PostmanTest Child 2\");",
"});",
""
],
@@ -2955,6 +3646,9 @@
}
}
],
+ "protocolProfileBehavior": {
+ "disableBodyPruning": true
+ },
"request": {
"auth": {
"type": "bearer",
@@ -2968,8 +3662,17 @@
},
"method": "GET",
"header": [],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"inodes\": [\"{{grantChildCategoryInodeHierarchy}}\", \"{{child2CategoryInodeHierarchy}}\", \"not_valid_category\"]\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
"url": {
- "raw": "{{serverURL}}/api/v1/categories/children?filter=PostmanTest&inode={{topCategoryInode}}",
+ "raw": "{{serverURL}}/api/v1/categories/hierarchy",
"host": [
"{{serverURL}}"
],
@@ -2977,17 +3680,72 @@
"api",
"v1",
"categories",
- "children"
- ],
- "query": [
- {
- "key": "filter",
- "value": "PostmanTest"
- },
+ "hierarchy"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Get categories hierarchy with empty array of inodes",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "pm.test(\"Status code should be ok 200\", function () {",
+ " pm.response.to.have.status(200);",
+ "});",
+ "",
+ "",
+ "var jsonData = pm.response.json();",
+ "",
+ "pm.test(\"Fetch successfully without errors\", function () {",
+ " pm.expect(jsonData.errors).to.have.lengthOf(0);",
+ "});",
+ "",
+ "pm.expect(0).to.have.equals(jsonData.entity.length);"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "protocolProfileBehavior": {
+ "disableBodyPruning": true
+ },
+ "request": {
+ "auth": {
+ "type": "bearer",
+ "bearer": [
{
- "key": "inode",
- "value": "{{topCategoryInode}}"
+ "key": "token",
+ "value": "{{jwt}}",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "GET",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"inodes\": []\n}",
+ "options": {
+ "raw": {
+ "language": "json"
}
+ }
+ },
+ "url": {
+ "raw": "{{serverURL}}/api/v1/categories/hierarchy",
+ "host": [
+ "{{serverURL}}"
+ ],
+ "path": [
+ "api",
+ "v1",
+ "categories",
+ "hierarchy"
]
}
},
@@ -3001,44 +3759,7 @@
"type": "text/javascript",
"packages": {},
"exec": [
- "if (!pm.environment.get('jwt')) {",
- " const serverURL = pm.environment.get('serverURL'); // Get the server URL from the environment variable",
- " const apiUrl = `${serverURL}/api/v1/apitoken`; // Construct the full API URL",
- "",
- " if (!pm.environment.get('jwt')) {",
- " const username = 'admin@dotcms.com';",
- " const password = 'admin';",
- " const basicAuth = btoa(`${username}:${password}`);",
- "",
- " const requestOptions = {",
- " url: apiUrl,",
- " method: \"POST\",",
- " header: {",
- " \"accept\": \"*/*\",",
- " \"content-type\": \"application/json\",",
- " \"Authorization\": `Basic ${basicAuth}`",
- " },",
- " body: {",
- " mode: \"raw\",",
- " raw: JSON.stringify({",
- " \"expirationSeconds\": 7200,",
- " \"userId\": \"dotcms.org.1\",",
- " \"network\": \"0.0.0.0/0\",",
- " \"claims\": {\"label\": \"postman-tests\"}",
- " })",
- " }",
- " };",
- "",
- " pm.sendRequest(requestOptions, function (err, response) {",
- " if (err) {",
- " console.log(err);",
- " } else {",
- " const jwt = response.json().entity.jwt;",
- " pm.environment.set('jwt', jwt);",
- " }",
- " });",
- " }",
- "}"
+ ""
]
}
},
@@ -5350,6 +6071,67 @@
"response": []
}
],
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "type": "text/javascript",
+ "packages": {},
+ "exec": [
+ " const serverURL = pm.environment.get('serverURL'); // Get the server URL from the environment variable",
+ " const apiUrl = `${serverURL}/api/v1/apitoken`; // Construct the full API URL",
+ "",
+ "// If we are unable to get the JWT we need to generate a new one",
+ " if (!pm.environment.get('jwt')) {",
+ " const username = pm.environment.get(\"user\");",
+ " const password = pm.environment.get(\"password\");",
+ " const basicAuth = Buffer.from(`${username}:${password}`).toString('base64');",
+ "",
+ "",
+ " const requestOptions = {",
+ " url: apiUrl,",
+ " method: \"POST\",",
+ " header: {",
+ " \"accept\": \"*/*\",",
+ " \"content-type\": \"application/json\",",
+ " \"Authorization\": `Basic ${basicAuth}`",
+ " },",
+ " body: {",
+ " mode: \"raw\",",
+ " raw: JSON.stringify({",
+ " \"expirationSeconds\": 7200,",
+ " \"userId\": \"dotcms.org.1\",",
+ " \"network\": \"0.0.0.0/0\",",
+ " \"claims\": {\"label\": \"postman-tests\"}",
+ " })",
+ " }",
+ " };",
+ "",
+ "",
+ " pm.sendRequest(requestOptions, function (err, response) {",
+ " if (err) {",
+ " console.log(err);",
+ " } else {",
+ " const jwt = response.json().entity.jwt;",
+ " pm.environment.set('jwt', jwt);",
+ " console.log(jwt);",
+ " }",
+ " });",
+ " }"
+ ]
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "type": "text/javascript",
+ "packages": {},
+ "exec": [
+ ""
+ ]
+ }
+ }
+ ],
"variable": [
{
"key": "templateIdToEdit",
@@ -5402,6 +6184,22 @@
{
"key": "child3Inode",
"value": ""
+ },
+ {
+ "key": "topCategoryInodeHierarchy",
+ "value": ""
+ },
+ {
+ "key": "child2CategoryInodeHierarchy",
+ "value": ""
+ },
+ {
+ "key": "child3CategoryInodeHierarchy",
+ "value": ""
+ },
+ {
+ "key": "grantChildCategoryInodeHierarchy",
+ "value": ""
}
]
}
\ No newline at end of file