diff --git a/sdm/src/main/java/com/sap/cds/sdm/constants/SDMConstants.java b/sdm/src/main/java/com/sap/cds/sdm/constants/SDMConstants.java index 500ef4bb..b4fb45fc 100644 --- a/sdm/src/main/java/com/sap/cds/sdm/constants/SDMConstants.java +++ b/sdm/src/main/java/com/sap/cds/sdm/constants/SDMConstants.java @@ -1,7 +1,10 @@ package com.sap.cds.sdm.constants; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; public class SDMConstants { private SDMConstants() { @@ -23,7 +26,6 @@ private SDMConstants() { "The following files could not be renamed as they already exist:\n%s\n"; public static final String COULD_NOT_UPDATE_THE_ATTACHMENT = "Could not update the attachment"; public static final String ATTACHMENT_NOT_FOUND = "Attachment not found"; - public static final String DUPLICATE_FILES_ERROR = "%s already exists."; public static final String GENERIC_ERROR = "Could not %s the document."; public static final String VERSIONED_REPO_ERROR = "Upload not supported for versioned repositories."; @@ -140,45 +142,46 @@ private SDMConstants() { "Failed to parse repository response"; public static final String ERROR_IN_SETTING_TIMEOUT_MESSAGE = "Error in setting timeout"; public static final String FAILED_TO_CREATE_FOLDER = "Failed to create folder"; + public static final String FILENAME_WHITESPACE_ERROR_MESSAGE = + "The object name cannot be empty or consist entirely of space characters. Enter a value."; + public static final String SINGLE_RESTRICTED_CHARACTER_IN_FILE = + "\"%s\" contains unsupported characters (‘/’ or ‘\\’). Rename and try again."; + public static final String SINGLE_DUPLICATE_FILENAME = + "An object named \"%s\" already exists. Rename the object and try again."; - public static String nameConstraintMessage( - List fileNameWithRestrictedCharacters, String operation) { - // Create the base message - String prefixMessage = - "%s unsuccessful. The following filename(s) contain unsupported characters (/, \\). \n\n"; - - // Create the formatted prefix message - String formattedPrefixMessage = String.format(prefixMessage, operation); - - // Initialize the StringBuilder with the formatted message prefix - StringBuilder bulletPoints = new StringBuilder(formattedPrefixMessage); - - // Append each unsupported file name to the StringBuilder - for (String file : fileNameWithRestrictedCharacters) { - bulletPoints.append(String.format("\t• %s%n", file)); + // Helper Methods to create error/warning messages + public static String buildErrorMessage( + Collection filenames, StringBuilder prefixTemplate, String closingRemark) { + for (String file : filenames) { + prefixTemplate.append(String.format("\t• %s%n", file)); } - bulletPoints.append("\nRename the files and try again."); - return bulletPoints.toString(); + if (closingRemark != null && !closingRemark.isEmpty()) + prefixTemplate.append("\n ").append(closingRemark); + return prefixTemplate.toString(); } - public static String linkNameConstraintMessage( - List fileNameWithRestrictedCharacters, String operation) { - // Create the base message - String prefixMessage = - "Link could not be %s. The following name(s) contain unsupported characters (/, \\). \n\n"; - - // Create the formatted prefix message - String formattedPrefixMessage = String.format(prefixMessage, operation); - - // Initialize the StringBuilder with the formatted message prefix - StringBuilder bulletPoints = new StringBuilder(formattedPrefixMessage); + // Restricted characters: / and \ + public static String nameConstraintMessage(List invalidFileNames) { + // if only 1 restricted character is there in file, so different error will throw + if (invalidFileNames.size() == 1) { + return String.format(SINGLE_RESTRICTED_CHARACTER_IN_FILE, invalidFileNames.iterator().next()); + } + StringBuilder prefix = new StringBuilder(); + prefix.append( + "The following names contain unsupported characters (‘/’ or ‘\\’). Rename and try again:\n\n"); + return buildErrorMessage(invalidFileNames, prefix, null); + } - // Append each unsupported file name to the StringBuilder - for (String file : fileNameWithRestrictedCharacters) { - bulletPoints.append(String.format("\t• %s%n", file)); + // Duplicate file names error message + public static String duplicateFilenameFormat(Set duplicateFileNames) { + // if only 1 duplicate file, so different error will throw + if (duplicateFileNames.size() == 1) { + return String.format(SINGLE_DUPLICATE_FILENAME, duplicateFileNames.iterator().next()); } - bulletPoints.append("\nRename the link and try again."); - return bulletPoints.toString(); + StringBuilder prefix = new StringBuilder(); + prefix.append("Objects with the following names already exist:\n\n"); + String closingRemark = "Rename the objects and try again"; + return buildErrorMessage(duplicateFileNames, prefix, closingRemark); } public static String fileNotFound(List fileNameNotFound) { @@ -253,7 +256,9 @@ public static String unsupportedPropertiesMessage(List propertiesList) { } public static String getDuplicateFilesError(String filename) { - return String.format(DUPLICATE_FILES_ERROR, filename); + Set filenames = new HashSet<>(); + filenames.add(filename); + return duplicateFilenameFormat(filenames); } public static String getGenericError(String event) { diff --git a/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMCreateAttachmentsHandler.java b/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMCreateAttachmentsHandler.java index b21a1b3c..60e29365 100644 --- a/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMCreateAttachmentsHandler.java +++ b/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMCreateAttachmentsHandler.java @@ -74,13 +74,9 @@ public void updateName( Map propertyTitles = new HashMap<>(); Map secondaryPropertiesWithInvalidDefinitions = new HashMap<>(); String targetEntity = context.getTarget().getQualifiedName(); - Set duplicateFilenames = - SDMUtils.isFileNameDuplicateInDrafts(data, attachmentCompositionName, targetEntity); - if (!duplicateFilenames.isEmpty()) { - handleDuplicateFilenames(context, duplicateFilenames); - } else { - List fileNameWithRestrictedCharacters = new ArrayList<>(); - List duplicateFileNameList = new ArrayList<>(); + Boolean isError = false; + isError = SDMUtils.validateFileNames(context, data, attachmentCompositionName); + if (!isError) { List filesNotFound = new ArrayList<>(); List filesWithUnsupportedProperties = new ArrayList<>(); Map badRequest = new HashMap<>(); @@ -89,19 +85,22 @@ public void updateName( List> attachments = AttachmentsHandlerUtils.fetchAttachments( targetEntity, entity, attachmentCompositionName); + if (attachments == null || attachments.isEmpty()) { + logger.info( + "No attachments found for composition [{}] in entity [{}]. Skipping processing.", + attachmentCompositionName, + targetEntity); + continue; + } Optional attachmentEntity = context.getModel().findEntity(attachmentCompositionDefinition); - if (attachments != null && !attachments.isEmpty()) { - propertyTitles = SDMUtils.getPropertyTitles(attachmentEntity, attachments.get(0)); - secondaryPropertiesWithInvalidDefinitions = - SDMUtils.getSecondaryPropertiesWithInvalidDefinition( - attachmentEntity, attachments.get(0)); - } + propertyTitles = SDMUtils.getPropertyTitles(attachmentEntity, attachments.get(0)); + secondaryPropertiesWithInvalidDefinitions = + SDMUtils.getSecondaryPropertiesWithInvalidDefinition( + attachmentEntity, attachments.get(0)); processEntity( context, entity, - fileNameWithRestrictedCharacters, - duplicateFileNameList, filesNotFound, filesWithUnsupportedProperties, badRequest, @@ -112,8 +111,6 @@ public void updateName( attachmentCompositionName); handleWarnings( context, - fileNameWithRestrictedCharacters, - duplicateFileNameList, filesNotFound, filesWithUnsupportedProperties, badRequest, @@ -123,21 +120,9 @@ public void updateName( } } - private void handleDuplicateFilenames( - CdsCreateEventContext context, Set duplicateFilenames) { - context - .getMessages() - .error( - String.format( - SDMConstants.DUPLICATE_FILE_IN_DRAFT_ERROR_MESSAGE, - String.join(", ", duplicateFilenames))); - } - private void processEntity( CdsCreateEventContext context, Map entity, - List fileNameWithRestrictedCharacters, - List duplicateFileNameList, List filesNotFound, List filesWithUnsupportedProperties, Map badRequest, @@ -155,8 +140,6 @@ private void processEntity( processAttachment( context, attachment, - fileNameWithRestrictedCharacters, - duplicateFileNameList, filesNotFound, filesWithUnsupportedProperties, badRequest, @@ -175,8 +158,6 @@ private void processEntity( private void processAttachment( CdsCreateEventContext context, Map attachment, - List fileNameWithRestrictedCharacters, - List duplicateFileNameList, List filesNotFound, List filesWithUnsupportedProperties, Map badRequest, @@ -226,81 +207,53 @@ private void processAttachment( secondaryTypeProperties, propertiesInDB); - if (Boolean.TRUE.equals(SDMUtils.isRestrictedCharactersInName(filenameInRequest))) { - fileNameWithRestrictedCharacters.add(filenameInRequest); - replacePropertiesInAttachment( - attachment, - fileNameInSDM, - propertiesInDB, - secondaryTypeProperties); // In this case we immediately stop the processing (Request - // isn't sent to SDM) - } else { - CmisDocument cmisDocument = new CmisDocument(); - cmisDocument.setFileName(filenameInRequest); - cmisDocument.setObjectId(objectId); - if (fileNameInDB - == null) { // If the file name in DB is null, it means that the file is being created for - // the first time - if (filenameInRequest != null) { - updatedSecondaryProperties.put("filename", filenameInRequest); - } else { - throw new ServiceException("Filename cannot be empty"); - } - } else { - if (filenameInRequest == null) { - throw new ServiceException("Filename cannot be empty"); - } else if (!fileNameInDB.equals( - filenameInRequest)) { // If the file name in DB is not equal to the file name in - // request, it means that the file name has been modified - updatedSecondaryProperties.put("filename", filenameInRequest); - } - } - try { - int responseCode = - sdmService.updateAttachments( - sdmCredentials, - cmisDocument, - updatedSecondaryProperties, - secondaryPropertiesWithInvalidDefinitions, - context.getUserInfo().isSystemUser()); - switch (responseCode) { - case 403: - // SDM Roles for user are missing - noSDMRoles.add(fileNameInSDM); - replacePropertiesInAttachment( - attachment, fileNameInSDM, propertiesInDB, secondaryTypeProperties); - break; - case 409: - duplicateFileNameList.add(filenameInRequest); - replacePropertiesInAttachment( - attachment, fileNameInSDM, propertiesInDB, secondaryTypeProperties); - break; - case 404: - filesNotFound.add(filenameInRequest); - replacePropertiesInAttachment( - attachment, filenameInRequest, propertiesInDB, secondaryTypeProperties); - break; - case 200: - case 201: - // Success cases, do nothing - break; + CmisDocument cmisDocument = new CmisDocument(); + cmisDocument.setFileName(filenameInRequest); + cmisDocument.setObjectId(objectId); + if (fileNameInDB == null || !fileNameInDB.equals(filenameInRequest)) { + updatedSecondaryProperties.put("filename", filenameInRequest); + } - default: - throw new ServiceException(SDMConstants.SDM_ROLES_ERROR_MESSAGE, null); - } - } catch (ServiceException e) { - // This exception is thrown when there are unsupported properties in the request - if (e.getMessage().startsWith(SDMConstants.UNSUPPORTED_PROPERTIES)) { - String unsupportedDetails = - e.getMessage().substring(SDMConstants.UNSUPPORTED_PROPERTIES.length()).trim(); - filesWithUnsupportedProperties.add(unsupportedDetails); + try { + int responseCode = + sdmService.updateAttachments( + sdmCredentials, + cmisDocument, + updatedSecondaryProperties, + secondaryPropertiesWithInvalidDefinitions, + context.getUserInfo().isSystemUser()); + switch (responseCode) { + case 403: + // SDM Roles for user are missing + noSDMRoles.add(fileNameInSDM); replacePropertiesInAttachment( attachment, fileNameInSDM, propertiesInDB, secondaryTypeProperties); - } else { - badRequest.put(filenameInRequest, e.getMessage()); + break; + case 404: + filesNotFound.add(filenameInRequest); replacePropertiesInAttachment( attachment, filenameInRequest, propertiesInDB, secondaryTypeProperties); - } + break; + case 200: + case 201: + // Success cases, do nothing + break; + + default: + throw new ServiceException(SDMConstants.SDM_ROLES_ERROR_MESSAGE, null); + } + } catch (ServiceException e) { + // This exception is thrown when there are unsupported properties in the request + if (e.getMessage().startsWith(SDMConstants.UNSUPPORTED_PROPERTIES)) { + String unsupportedDetails = + e.getMessage().substring(SDMConstants.UNSUPPORTED_PROPERTIES.length()).trim(); + filesWithUnsupportedProperties.add(unsupportedDetails); + replacePropertiesInAttachment( + attachment, fileNameInSDM, propertiesInDB, secondaryTypeProperties); + } else { + badRequest.put(filenameInRequest, e.getMessage()); + replacePropertiesInAttachment( + attachment, filenameInRequest, propertiesInDB, secondaryTypeProperties); } } } @@ -333,26 +286,11 @@ private void replacePropertiesInAttachment( private void handleWarnings( CdsCreateEventContext context, - List fileNameWithRestrictedCharacters, - List duplicateFileNameList, List filesNotFound, List filesWithUnsupportedProperties, Map badRequest, Map propertyTitles, List noSDMRoles) { - if (!fileNameWithRestrictedCharacters.isEmpty()) { - context - .getMessages() - .warn(SDMConstants.nameConstraintMessage(fileNameWithRestrictedCharacters, "Rename")); - } - if (!duplicateFileNameList.isEmpty()) { - context - .getMessages() - .warn( - String.format( - SDMConstants.FILES_RENAME_WARNING_MESSAGE, - String.join(", ", duplicateFileNameList))); - } if (!filesNotFound.isEmpty()) { context.getMessages().warn(SDMConstants.fileNotFound(filesNotFound)); } diff --git a/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMUpdateAttachmentsHandler.java b/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMUpdateAttachmentsHandler.java index 34b70204..faa61d75 100644 --- a/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMUpdateAttachmentsHandler.java +++ b/sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMUpdateAttachmentsHandler.java @@ -65,17 +65,9 @@ public void updateName( String attachmentCompositionDefinition, String attachmentCompositionName) throws IOException { - String targetEntity = context.getTarget().getQualifiedName(); - Set duplicateFilenames = - SDMUtils.isFileNameDuplicateInDrafts(data, attachmentCompositionName, targetEntity); - if (!duplicateFilenames.isEmpty()) { - context - .getMessages() - .error( - String.format( - SDMConstants.DUPLICATE_FILE_IN_DRAFT_ERROR_MESSAGE, - String.join(", ", duplicateFilenames))); - } else { + Boolean isError = false; + isError = SDMUtils.validateFileNames(context, data, attachmentCompositionName); + if (!isError) { Optional attachmentEntity = context.getModel().findEntity(attachmentCompositionDefinition); renameDocument( @@ -94,9 +86,7 @@ private void renameDocument( String attachmentCompositionDefinition, String attachmentCompositionName) throws IOException { - List duplicateFileNameList = new ArrayList<>(); Map secondaryPropertiesWithInvalidDefinitions; - List fileNameWithRestrictedCharacters = new ArrayList<>(); List filesNotFound = new ArrayList<>(); List filesWithUnsupportedProperties = new ArrayList<>(); Map badRequest = new HashMap<>(); @@ -125,8 +115,6 @@ private void renameDocument( attachmentEntity, context, attachments, - duplicateFileNameList, - fileNameWithRestrictedCharacters, filesNotFound, filesWithUnsupportedProperties, badRequest, @@ -136,8 +124,6 @@ private void renameDocument( } handleWarnings( context, - duplicateFileNameList, - fileNameWithRestrictedCharacters, filesNotFound, filesWithUnsupportedProperties, badRequest, @@ -149,8 +135,6 @@ private void processAttachments( Optional attachmentEntity, CdsUpdateEventContext context, List> attachments, - List duplicateFileNameList, - List fileNameWithRestrictedCharacters, List filesNotFound, List filesWithUnsupportedProperties, Map badRequest, @@ -164,8 +148,6 @@ private void processAttachments( attachmentEntity, context, attachment, - duplicateFileNameList, - fileNameWithRestrictedCharacters, filesNotFound, filesWithUnsupportedProperties, badRequest, @@ -184,8 +166,6 @@ public void processAttachment( Optional attachmentEntity, CdsUpdateEventContext context, Map attachment, - List duplicateFileNameList, - List fileNameWithRestrictedCharacters, List filesNotFound, List filesWithUnsupportedProperties, Map badRequest, @@ -225,15 +205,6 @@ public void processAttachment( String filenameInRequest = (String) attachment.get("fileName"); String objectId = (String) attachment.get("objectId"); - if (Boolean.TRUE.equals( - SDMUtils.isRestrictedCharactersInName( - filenameInRequest))) { // Check if the filename contains restricted characters and stop - // further processing if it does (Request not sent to SDM) - fileNameWithRestrictedCharacters.add(filenameInRequest); - replacePropertiesInAttachment( - attachment, fileNameInDB, propertiesInDB, secondaryTypeProperties); - return; - } CmisDocument cmisDocument = new CmisDocument(); cmisDocument.setFileName(filenameInRequest); cmisDocument.setObjectId(objectId); @@ -266,11 +237,6 @@ public void processAttachment( replacePropertiesInAttachment( attachment, fileNameInDB, propertiesInDB, secondaryTypeProperties); break; - case 409: - duplicateFileNameList.add(filenameInRequest); - replacePropertiesInAttachment( - attachment, fileNameInDB, propertiesInDB, secondaryTypeProperties); - break; case 404: filesNotFound.add(fileNameInDB); replacePropertiesInAttachment( @@ -329,26 +295,11 @@ private void replacePropertiesInAttachment( private void handleWarnings( CdsUpdateEventContext context, - List duplicateFileNameList, - List fileNameWithRestrictedCharacters, List filesNotFound, List filesWithUnsupportedProperties, Map badRequest, Map propertyTitles, List noSDMRoles) { - if (!fileNameWithRestrictedCharacters.isEmpty()) { - context - .getMessages() - .warn(SDMConstants.nameConstraintMessage(fileNameWithRestrictedCharacters, "Rename")); - } - if (!duplicateFileNameList.isEmpty()) { - context - .getMessages() - .warn( - String.format( - SDMConstants.FILES_RENAME_WARNING_MESSAGE, - String.join(", ", duplicateFileNameList))); - } if (!filesNotFound.isEmpty()) { context.getMessages().warn(SDMConstants.fileNotFound(filesNotFound)); } diff --git a/sdm/src/main/java/com/sap/cds/sdm/service/handler/SDMAttachmentsServiceHandler.java b/sdm/src/main/java/com/sap/cds/sdm/service/handler/SDMAttachmentsServiceHandler.java index bd1fe98f..86795bdb 100644 --- a/sdm/src/main/java/com/sap/cds/sdm/service/handler/SDMAttachmentsServiceHandler.java +++ b/sdm/src/main/java/com/sap/cds/sdm/service/handler/SDMAttachmentsServiceHandler.java @@ -252,9 +252,12 @@ private void checkAttachmentConstraints( private void validateFileName(String filename, Result result, Map attachmentIds) throws ServiceException { - if (SDMUtils.isRestrictedCharactersInName(filename)) { + if (filename == null || filename.isBlank()) { + throw new ServiceException(SDMConstants.FILENAME_WHITESPACE_ERROR_MESSAGE); + } + if (SDMUtils.hasRestrictedCharactersInName(filename)) { throw new ServiceException( - SDMConstants.nameConstraintMessage(Collections.singletonList(filename), "Upload")); + SDMConstants.nameConstraintMessage(Collections.singletonList(filename))); } String fileid = (String) attachmentIds.get("ID"); if (duplicateCheck(filename, fileid, result)) { diff --git a/sdm/src/main/java/com/sap/cds/sdm/service/handler/SDMServiceGenericHandler.java b/sdm/src/main/java/com/sap/cds/sdm/service/handler/SDMServiceGenericHandler.java index 74a1898f..b121f13f 100644 --- a/sdm/src/main/java/com/sap/cds/sdm/service/handler/SDMServiceGenericHandler.java +++ b/sdm/src/main/java/com/sap/cds/sdm/service/handler/SDMServiceGenericHandler.java @@ -282,9 +282,12 @@ private void checkAttachmentConstraints( } private void validateLinkName(String filename, Result result) throws ServiceException { - if (SDMUtils.isRestrictedCharactersInName(filename)) { + if (filename == null || filename.isBlank()) { + throw new ServiceException(SDMConstants.FILENAME_WHITESPACE_ERROR_MESSAGE); + } + if (SDMUtils.hasRestrictedCharactersInName(filename)) { throw new ServiceException( - SDMConstants.linkNameConstraintMessage(Collections.singletonList(filename), "created")); + SDMConstants.nameConstraintMessage(Collections.singletonList(filename))); } if (duplicateCheck(filename, result)) { throw new ServiceException(SDMConstants.getDuplicateFilesError(filename)); diff --git a/sdm/src/main/java/com/sap/cds/sdm/utilities/SDMUtils.java b/sdm/src/main/java/com/sap/cds/sdm/utilities/SDMUtils.java index c6896b2d..035c373d 100644 --- a/sdm/src/main/java/com/sap/cds/sdm/utilities/SDMUtils.java +++ b/sdm/src/main/java/com/sap/cds/sdm/utilities/SDMUtils.java @@ -8,6 +8,7 @@ import com.sap.cds.sdm.constants.SDMConstants; import com.sap.cds.sdm.handler.applicationservice.helper.AttachmentsHandlerUtils; import com.sap.cds.sdm.model.AttachmentInfo; +import com.sap.cds.services.EventContext; import com.sap.cds.services.persistence.PersistenceService; import java.io.IOException; import java.util.ArrayList; @@ -33,6 +34,56 @@ private SDMUtils() { // Doesn't do anything } + public static Boolean validateFileNames( + EventContext context, List data, String composition) { + Boolean isError = false; + String targetEntity = context.getTarget().getQualifiedName(); + + // Validation for file names + Set whitespaceFilenames = isFileNameContainsWhitespace(data, composition, targetEntity); + List restrictedFileNames = + isFileNameContainsRestrictedCharaters(data, composition, targetEntity); + Set duplicateFilenames = isFileNameDuplicateInDrafts(data, composition, targetEntity); + + // Collecting all the errors + if (whitespaceFilenames != null && !whitespaceFilenames.isEmpty()) { + context.getMessages().error(SDMConstants.FILENAME_WHITESPACE_ERROR_MESSAGE); + isError = true; + } + if (restrictedFileNames != null && !restrictedFileNames.isEmpty()) { + context.getMessages().error(SDMConstants.nameConstraintMessage(restrictedFileNames)); + isError = true; + } + if (duplicateFilenames != null && !duplicateFilenames.isEmpty()) { + String formattedMessage = + String.format(SDMConstants.duplicateFilenameFormat(duplicateFilenames)); + context.getMessages().error(formattedMessage); + isError = true; + } + // returning the error message + return isError; + } + + public static Set isFileNameContainsWhitespace( + List data, String composition, String targetEntity) { + Set filenamesWithWhitespace = new HashSet<>(); + for (Map entity : data) { + List> attachments = + AttachmentsHandlerUtils.fetchAttachments(targetEntity, entity, composition); + if (attachments != null) { + Iterator> iterator = attachments.iterator(); + while (iterator.hasNext()) { + Map attachment = iterator.next(); + String filenameInRequest = (String) attachment.get("fileName"); + if (filenameInRequest == null || filenameInRequest.isBlank()) { + filenamesWithWhitespace.add("Whitespace/null"); + } + } + } + } + return filenamesWithWhitespace; + } + public static Set isFileNameDuplicateInDrafts( List data, String composition, String targetEntity) { Set uniqueFilenames = new HashSet<>(); @@ -45,10 +96,12 @@ public static Set isFileNameDuplicateInDrafts( while (iterator.hasNext()) { Map attachment = iterator.next(); String filenameInRequest = (String) attachment.get("fileName"); - String repositoryInRequest = (String) attachment.get("repositoryId"); - String fileRepositorySpecific = filenameInRequest + "#" + repositoryInRequest; - if (!uniqueFilenames.add(fileRepositorySpecific)) { - duplicateFilenames.add(filenameInRequest); + if (filenameInRequest != null && !filenameInRequest.isBlank()) { + String repositoryInRequest = (String) attachment.get("repositoryId"); + String fileRepositorySpecific = filenameInRequest + "#" + repositoryInRequest; + if (!uniqueFilenames.add(fileRepositorySpecific)) { + duplicateFilenames.add(filenameInRequest); + } } } } @@ -56,16 +109,18 @@ public static Set isFileNameDuplicateInDrafts( return duplicateFilenames; } - public static List isFileNameContainsRestrictedCharaters(List data) { - List restrictedFilenames = new ArrayList(); + public static List isFileNameContainsRestrictedCharaters( + List data, String composition, String targetEntity) { + List restrictedFilenames = new ArrayList<>(); for (Map entity : data) { - List> attachments = (List>) entity.get("attachments"); + List> attachments = + AttachmentsHandlerUtils.fetchAttachments(targetEntity, entity, composition); if (attachments != null) { Iterator> iterator = attachments.iterator(); while (iterator.hasNext()) { Map attachment = iterator.next(); String filenameInRequest = (String) attachment.get("fileName"); - if (isRestrictedCharactersInName(filenameInRequest)) { + if (hasRestrictedCharactersInName(filenameInRequest)) { restrictedFilenames.add(filenameInRequest); } } @@ -74,7 +129,10 @@ public static List isFileNameContainsRestrictedCharaters(List d return restrictedFilenames; } - public static boolean isRestrictedCharactersInName(String cmisName) { + public static boolean hasRestrictedCharactersInName(String cmisName) { + if (cmisName == null || cmisName.isEmpty()) { + return false; + } String regex = "[/\\\\]"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(cmisName); diff --git a/sdm/src/test/java/integration/com/sap/cds/sdm/IntegrationTest_MultipleFacet.java b/sdm/src/test/java/integration/com/sap/cds/sdm/IntegrationTest_MultipleFacet.java index 1c43ddaa..d8a9f0f4 100644 --- a/sdm/src/test/java/integration/com/sap/cds/sdm/IntegrationTest_MultipleFacet.java +++ b/sdm/src/test/java/integration/com/sap/cds/sdm/IntegrationTest_MultipleFacet.java @@ -237,7 +237,7 @@ private boolean checkDuplicateCreation(String facetType, List createResp return false; } else { String expectedJson = - "{\"error\":{\"code\":\"500\",\"message\":\"sample.pdf already exists.\"}}"; + "{\"error\":{\"code\":\"500\",\"message\":\"An object named \\\"sample.pdf\\\" already exists. Rename the object and try again.\"}}"; ObjectMapper objectMapper = new ObjectMapper(); JsonNode actualJsonNode = objectMapper.readTree(creationCheck); JsonNode expectedJsonNode = objectMapper.readTree(expectedJson); @@ -572,13 +572,13 @@ void testCreateEntitiesWithUnsupportedCharacter() throws IOException { response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID); String expected = - "[{\"code\":\"\",\"message\":\"Rename unsuccessful. The following filename(s) contain unsupported " - + "characters (/, \\\\). \\n\\n\\t\\u2022 a/\\bc.pdf\\n\\nRename the files and try again.\",\"numericSeverity" - + "\":3},{\"code\":\"\",\"message\":\"Rename unsuccessful. The following filename(s) contain unsupported characters " - + "(/, \\\\). \\n\\n\\t\\u2022 a/\\bc.pdf\\n\\nRename the files and try again.\",\"numericSeverity\":3},{\"code\":\"\"," - + "\"message\":\"Rename unsuccessful. The following filename(s) contain unsupported characters (/, \\\\). \\n\\n\\t\\u2022 " - + "a/\\bc.pdf\\n\\nRename the files and try again.\",\"numericSeverity\":3}]"; + "{\"error\":{\"code\":\"400\",\"message\":\"\\\"a/\\bc.pdf\\\" contains unsupported characters (‘/’ or ‘\\\\’). Rename and try again.\",\"details\":[{\"code\":\"\",\"message\":\"\\\"a/\\bc.pdf\\\" contains unsupported characters (‘/’ or ‘\\\\’). Rename and try again.\",\"@Common.numericSeverity\":4},{\"code\":\"\",\"message\":\"\\\"a/\\bc.pdf\\\" contains unsupported characters (‘/’ or ‘\\\\’). Rename and try again.\",\"@Common.numericSeverity\":4}]}}"; if (response.equals(expected)) { + for (int i = 0; i < facet.length; i++) { + response = + api.renameAttachment(appUrl, entityName, facet[i], entityID, ID4[i], "sample.pdf"); + } + response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID); testStatus = true; } @@ -604,10 +604,13 @@ void testRenameEntitiesWithUnsupportedCharacter() { counter = -1; // Reset counter for the next check response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID); String expected = - "[{\"code\":\"\",\"message\":\"Rename unsuccessful. The following filename(s) contain unsupported characters (/, \\\\). \\n\\n\\t\\u2022 reference1/234\\n\\nRename the files and try again.\",\"numericSeverity\":3}," - + "{\"code\":\"\",\"message\":\"Rename unsuccessful. The following filename(s) contain unsupported characters (/, \\\\). \\n\\n\\t\\u2022 sample/1234\\n\\nRename the files and try again.\",\"numericSeverity\":3}," - + "{\"code\":\"\",\"message\":\"Rename unsuccessful. The following filename(s) contain unsupported characters (/, \\\\). \\n\\n\\t\\u2022 footnote1/234\\n\\nRename the files and try again.\",\"numericSeverity\":3}]"; + "{\"error\":{\"code\":\"400\",\"message\":\"\\\"reference1/234\\\" contains unsupported characters (‘/’ or ‘\\\\’). Rename and try again.\",\"details\":[{\"code\":\"\",\"message\":\"\\\"sample/1234\\\" contains unsupported characters (‘/’ or ‘\\\\’). Rename and try again.\",\"@Common.numericSeverity\":4},{\"code\":\"\",\"message\":\"\\\"footnote1/234\\\" contains unsupported characters (‘/’ or ‘\\\\’). Rename and try again.\",\"@Common.numericSeverity\":4}]}}"; if (response.equals(expected)) { + for (int i = 0; i < facet.length; i++) { + response = + api.renameAttachment(appUrl, entityName, facet[i], entityID, ID3[i], "sample.pdf"); + } + response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID); testStatus = true; } } else { @@ -668,11 +671,7 @@ void testRenameSingleDuplicate() { response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID); String expected = String.format( - "{\"error\":{\"code\":\"400\",\"message\":\"The file(s) %s have been added multiple times. Please rename and try again.\"," - + "\"details\":[" - + "{\"code\":\"\",\"message\":\"The file(s) %s have been added multiple times. Please rename and try again.\",\"@Common.numericSeverity\":4}," - + "{\"code\":\"\",\"message\":\"The file(s) %s have been added multiple times. Please rename and try again.\",\"@Common.numericSeverity\":4}" - + "]}}", + "{\"error\":{\"code\":\"400\",\"message\":\"An object named \\\"%s\\\" already exists. Rename the object and try again.\",\"details\":[{\"code\":\"\",\"message\":\"An object named \\\"%s\\\" already exists. Rename the object and try again.\",\"@Common.numericSeverity\":4},{\"code\":\"\",\"message\":\"An object named \\\"%s\\\" already exists. Rename the object and try again.\",\"@Common.numericSeverity\":4}]}}", name[1], name[0], name[2]); if (response.equals(expected)) { for (int i = 0; i < facet.length; i++) { @@ -719,10 +718,14 @@ void testRenameMultipleEntitiesWithOneUnsupportedCharacter() { if (successCount >= 2) { response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID); String expected = - "[{\"code\":\"\",\"message\":\"Rename unsuccessful. The following filename(s) contain unsupported characters" - + " (/, \\\\). \\n\\n\\t\\u2022 note/invalid\\n\\nRename the files and try again.\",\"numericSeverity\":3}]"; + "{\"error\":{\"code\":\"400\",\"message\":\"\\\"note/invalid\\\" contains unsupported characters (‘/’ or ‘\\\\’). Rename and try again.\"}}"; if (response.equals(expected)) { - testStatus = true; + response = + api.renameAttachment(appUrl, entityName, facet[2], entityID, ID3[2], "note_valid"); + if (response.equals("Renamed")) { + response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID); + if (response.equals("Saved")) testStatus = true; + } } } else { api.saveEntityDraft(appUrl, entityName, srvpath, entityID); @@ -736,8 +739,66 @@ void testRenameMultipleEntitiesWithOneUnsupportedCharacter() { @Test @Order(14) + void testRenameToValidateNames() throws IOException { + System.out.println("Test (14) : Rename attachments to validate names"); + String[] generatedIDs = new String[3]; + String[] duplicateIDs = new String[1]; + Boolean testStatus = false, allRenamedSuccessfully = true; + String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); + if (!response.equals("Could not create entity")) { + entityID3 = response; + + String[] invalidNames = {"Restricted/Character", " ", "duplicateName.pdf"}; + String duplicateName = "duplicateName.pdf"; + + ClassLoader classLoader = getClass().getClassLoader(); + Map postData = new HashMap<>(); + postData.put("up__ID", entityID3); + postData.put("mimeType", "application/pdf"); + postData.put("createdAt", new Date().toString()); + postData.put("createdBy", "test@test.com"); + postData.put("modifiedBy", "test@test.com"); + + // Creation of attachment, reference and footnote + for (int i = 0; i < facet.length; i++) { + File file = new File(classLoader.getResource("sample2.pdf").getFile()); + generatedIDs[i] = + CreateandReturnFacetID( + appUrl, serviceName, entityName, facet[i], entityID3, postData, file); + response = + api.renameAttachment( + appUrl, entityName, facet[i], entityID3, generatedIDs[i], invalidNames[i]); + allRenamedSuccessfully &= "Renamed".equals(response); + } + File file = new File(classLoader.getResource("sample.pdf").getFile()); + // Creating duplicate name for last facet + duplicateIDs[0] = + CreateandReturnFacetID( + appUrl, serviceName, entityName, facet[2], entityID3, postData, file); + String response2 = + api.renameAttachment( + appUrl, entityName, facet[2], entityID3, duplicateIDs[0], duplicateName); + + if (allRenamedSuccessfully && "Renamed".equals(response2)) { + response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID3); + String expected = + "{\"error\":{\"code\":\"400\",\"message\":\"The object name cannot be empty or consist entirely of space characters. Enter a value.\",\"details\":[{\"code\":\"\",\"message\":\"\\\"Restricted/Character\\\" contains unsupported characters (‘/’ or ‘\\\\’). Rename and try again.\",\"@Common.numericSeverity\":4},{\"code\":\"\",\"message\":\"An object named \\\"duplicateName.pdf\\\" already exists. Rename the object and try again.\",\"@Common.numericSeverity\":4}]}}"; + if (response.equals(expected)) { + response = api.deleteEntityDraft(appUrl, entityName, entityID3); + if (response.equals("Entity Draft Deleted")) testStatus = true; + } + } + if (!testStatus) fail("Could not create entity"); + } else { + fail("Could not create entity"); + return; + } + } + + @Test + @Order(15) void testRenameEntitiesWithoutSDMRole() throws IOException { - System.out.println("Test (14) : Rename attachments where user don't have SDM-Roles"); + System.out.println("Test (15) : Rename attachments where user don't have SDM-Roles"); boolean testStatus = true; try { String apiResponse = apiNoRoles.editEntityDraft(appUrl, entityName, srvpath, entityID); @@ -794,9 +855,9 @@ void testRenameEntitiesWithoutSDMRole() throws IOException { } @Test - @Order(15) + @Order(16) void testDeleteSingleAttachment() throws IOException { - System.out.println("Test (15) : Delete single attachment, reference, and footnote"); + System.out.println("Test (16) : Delete single attachment, reference, and footnote"); Boolean testStatus = false; counter = -1; @@ -822,9 +883,9 @@ void testDeleteSingleAttachment() throws IOException { } @Test - @Order(16) + @Order(17) void testDeleteMultipleAttachmentsReferencesFootnotes() throws IOException { - System.out.println("Test (16) : Delete multiple attachments, references, and footnotes"); + System.out.println("Test (17) : Delete multiple attachments, references, and footnotes"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID); if (response.equals("Entity in draft mode")) { @@ -850,9 +911,9 @@ void testDeleteMultipleAttachmentsReferencesFootnotes() throws IOException { } @Test - @Order(17) + @Order(18) void testUploadBlockedMimeType() throws IOException { - System.out.println("Test (17) : Upload blocked mimeType .rtf"); + System.out.println("Test (18) : Upload blocked mimeType .rtf"); Boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -897,9 +958,9 @@ void testUploadBlockedMimeType() throws IOException { } @Test - @Order(18) + @Order(19) void testDeleteEntity() { - System.out.println("Test (18) : Delete entity"); + System.out.println("Test (19) : Delete entity"); Boolean testStatus = false; String response = api.deleteEntity(appUrl, entityName, entityID); String response2 = api.deleteEntity(appUrl, entityName, entityID2); @@ -908,9 +969,9 @@ void testDeleteEntity() { } @Test - @Order(19) + @Order(20) void testUpdateValidSecondaryProperty_beforeEntityIsSaved_single() throws IOException { - System.out.println("Test (19) : Rename & Update secondary property before entity is saved"); + System.out.println("Test (20) : Rename & Update secondary property before entity is saved"); System.out.println("Creating entity"); Boolean testStatus = false; @@ -1007,9 +1068,9 @@ void testUpdateValidSecondaryProperty_beforeEntityIsSaved_single() throws IOExce } @Test - @Order(20) + @Order(21) void testUpdateValidSecondaryProperty_afterEntityIsSaved_single() { - System.out.println("Test (20): Rename & Update secondary property after entity is saved"); + System.out.println("Test (21): Rename & Update secondary property after entity is saved"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID3); System.out.println("Editing entity"); @@ -1075,10 +1136,10 @@ void testUpdateValidSecondaryProperty_afterEntityIsSaved_single() { } @Test - @Order(21) + @Order(22) void testUpdateInvalidSecondaryProperty_beforeEntityIsSaved_single() throws IOException { System.out.println( - "Test (21): Rename & Update invalid secondary property before entity is saved"); + "Test (22): Rename & Update invalid secondary property before entity is saved"); System.out.println("Creating entity"); Boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -1194,10 +1255,10 @@ void testUpdateInvalidSecondaryProperty_beforeEntityIsSaved_single() throws IOEx } @Test - @Order(22) + @Order(23) void testUpdateInvalidSecondaryProperty_afterEntityIsSaved_single() throws IOException { System.out.println( - "Test (22): Rename & Update invalid secondary property after entity is saved"); + "Test (23): Rename & Update invalid secondary property after entity is saved"); System.out.println("Editing entity"); Boolean testStatus = false; @@ -1302,11 +1363,11 @@ void testUpdateInvalidSecondaryProperty_afterEntityIsSaved_single() throws IOExc } @Test - @Order(23) + @Order(24) void testUpdateValidSecondaryProperty_beforeEntityIsSaved_multipleAttachments() throws IOException { System.out.println( - "Test (23): Rename & Update valid secondary properties for multiple facets before entity is saved"); + "Test (24): Rename & Update valid secondary properties for multiple facets before entity is saved"); System.out.println("Creating entity"); Boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -1475,10 +1536,10 @@ void testUpdateValidSecondaryProperty_beforeEntityIsSaved_multipleAttachments() } @Test - @Order(24) + @Order(25) void testUpdateValidSecondaryProperty_afterEntityIsSaved_multipleAttachments() { System.out.println( - "Test (24): Rename & Update valid secondary properties for multiple facets after entity is saved"); + "Test (25): Rename & Update valid secondary properties for multiple facets after entity is saved"); System.out.println("Editing entity"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID3); @@ -1615,11 +1676,11 @@ void testUpdateValidSecondaryProperty_afterEntityIsSaved_multipleAttachments() { } @Test - @Order(25) + @Order(26) void testUpdateInvalidSecondaryProperty_beforeEntityIsSaved_multipleAttachments() throws IOException { System.out.println( - "Test (25): Rename & Update invalid and valid secondary properties for multiple facets before entity is saved"); + "Test (26): Rename & Update invalid and valid secondary properties for multiple facets before entity is saved"); System.out.println("Creating entity"); Boolean testStatus = false; @@ -1845,11 +1906,11 @@ void testUpdateInvalidSecondaryProperty_beforeEntityIsSaved_multipleAttachments( } @Test - @Order(26) + @Order(27) void testUpdateInvalidSecondaryProperty_afterEntityIsSaved_multipleAttachments() throws IOException { System.out.println( - "Test (26): Rename & Update invalid and valid secondary properties for multiple attachments after entity is saved"); + "Test (27): Rename & Update invalid and valid secondary properties for multiple attachments after entity is saved"); System.out.println("Editing entity"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID3); @@ -2049,10 +2110,10 @@ void testUpdateInvalidSecondaryProperty_afterEntityIsSaved_multipleAttachments() } @Test - @Order(27) + @Order(28) void testNAttachments_NewEntity() throws IOException { System.out.println( - "Test (27): Creating new entity and checking only max 4 attachments are allowed to be uploaded"); + "Test (28): Creating new entity and checking only max 4 attachments are allowed to be uploaded"); System.out.println("Creating entity"); Boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -2166,9 +2227,9 @@ void testNAttachments_NewEntity() throws IOException { } @Test - @Order(28) + @Order(29) void testUploadNAttachments() throws IOException { - System.out.println("Test (28): Upload maximum 4 attachments in an exsisting entity"); + System.out.println("Test (29): Upload maximum 4 attachments in an exsisting entity"); ClassLoader classLoader = getClass().getClassLoader(); File originalFile = new File(classLoader.getResource("sample.exe").getFile()); @@ -2225,9 +2286,9 @@ void testUploadNAttachments() throws IOException { } @Test - @Order(29) + @Order(30) void testDiscardDraftWithoutAttachments() { - System.out.println("Test (29) : Discard draft without adding attachments"); + System.out.println("Test (30) : Discard draft without adding attachments"); Boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -2244,9 +2305,9 @@ void testDiscardDraftWithoutAttachments() { } @Test - @Order(30) + @Order(31) void testDiscardDraftWithAttachments() throws IOException { - System.out.println("Test (30): Discard draft with attachments, references, and footnotes"); + System.out.println("Test (31): Discard draft with attachments, references, and footnotes"); boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -2281,9 +2342,9 @@ void testDiscardDraftWithAttachments() throws IOException { } @Test - @Order(31) + @Order(32) void testDraftUpdateUploadTwoDeleteOneAndCreate() throws IOException { - System.out.println("Test (31): Upload to all facets, delete one, and create entity"); + System.out.println("Test (32): Upload to all facets, delete one, and create entity"); boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -2351,9 +2412,9 @@ void testDraftUpdateUploadTwoDeleteOneAndCreate() throws IOException { } @Test - @Order(32) + @Order(33) void testUpdateEntityDraft() throws IOException { - System.out.println("Test (32): Update entity draft with new facet content"); + System.out.println("Test (33): Update entity draft with new facet content"); boolean testStatus = false; ClassLoader classLoader = getClass().getClassLoader(); @@ -2396,9 +2457,9 @@ void testUpdateEntityDraft() throws IOException { } @Test - @Order(33) + @Order(34) void testUploadAttachmentWithoutSDMRole() throws IOException { - System.out.println("Test (33): Upload attachment across facets without SDM role"); + System.out.println("Test (34): Upload attachment across facets without SDM role"); boolean testStatus = true; String response = apiNoRoles.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -2436,9 +2497,9 @@ void testUploadAttachmentWithoutSDMRole() throws IOException { } @Test - @Order(34) + @Order(35) void testCopyAttachmentsSuccessNewEntity() throws IOException { - System.out.println("Test (34): Copy attachments from one entity to another new entity"); + System.out.println("Test (35): Copy attachments from one entity to another new entity"); List> attachments = new ArrayList<>(); for (int i = 0; i < 3; i++) { attachments.add(new ArrayList<>()); @@ -2560,10 +2621,10 @@ void testCopyAttachmentsSuccessNewEntity() throws IOException { } @Test - @Order(35) + @Order(36) void testCopyAttachmentsUnsuccessfulNewEntity() throws IOException { System.out.println( - "Test (35): Copy incorrect attachments from one entity to another new entity"); + "Test (36): Copy incorrect attachments from one entity to another new entity"); String editResponse1 = api.editEntityDraft(appUrl, entityName, srvpath, copyAttachmentSourceEntity); copyAttachmentTargetEntityEmpty = @@ -2607,9 +2668,9 @@ void testCopyAttachmentsUnsuccessfulNewEntity() throws IOException { } @Test - @Order(36) + @Order(37) void testCopyAttachmentsSuccessExistingEntity() throws IOException { - System.out.println("Test (36): Copy attachments from one entity to another existing entity"); + System.out.println("Test (37): Copy attachments from one entity to another existing entity"); List> attachments = new ArrayList<>(); for (int i = 0; i < 3; i++) { attachments.add(new ArrayList<>()); @@ -2743,9 +2804,9 @@ void testCopyAttachmentsSuccessExistingEntity() throws IOException { } @Test - @Order(37) + @Order(38) void testCopyAttachmentsUnsuccessfulExistingEntity() throws IOException { - System.out.println("Test (37): Copy attachments from one entity to another new entity"); + System.out.println("Test (38): Copy attachments from one entity to another new entity"); String editResponse1 = api.editEntityDraft(appUrl, entityName, srvpath, copyAttachmentSourceEntity); String editResponse2 = @@ -2782,9 +2843,9 @@ void testCopyAttachmentsUnsuccessfulExistingEntity() throws IOException { } @Test - @Order(38) + @Order(39) void testCreateLinkSuccess() throws IOException { - System.out.println("Test (38): Create link in entity"); + System.out.println("Test (39): Create link in entity"); List attachments = new ArrayList<>(); createLinkEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -2828,9 +2889,9 @@ void testCreateLinkSuccess() throws IOException { } @Test - @Order(39) + @Order(40) void testCreateLinkDifferentEntity() throws IOException { - System.out.println("Test (39): Create link with same name in different entity"); + System.out.println("Test (40): Create link with same name in different entity"); String createLinkDifferentEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -2861,9 +2922,9 @@ void testCreateLinkDifferentEntity() throws IOException { } @Test - @Order(40) + @Order(41) void testCreateLinkFailure() throws IOException { - System.out.println("Test (40): Create link fails due to invalid URL and name"); + System.out.println("Test (41): Create link fails due to invalid URL and name"); String editEntityResponse = api.editEntityDraft(appUrl, entityName, srvpath, createLinkEntity); if (editEntityResponse.equals("Could not edit entity")) { fail("Could not edit entity"); @@ -2900,9 +2961,7 @@ void testCreateLinkFailure() throws IOException { String errorCode = json.getJSONObject("error").getString("code"); String errorMessage = json.getJSONObject("error").getString("message"); String expected = - "Link could not be created. The following name(s) contain unsupported characters (/, \\).\n\n" - + " • sample//\n\n" - + "Rename the link and try again."; + "\"sample//\" contains unsupported characters (‘/’ or ‘\\’). Rename and try again."; assertEquals("500", errorCode); assertEquals( expected.replaceAll("\\s+", " ").trim(), errorMessage.replaceAll("\\s+", " ").trim()); @@ -2933,7 +2992,9 @@ void testCreateLinkFailure() throws IOException { String errorCode = json.getJSONObject("error").getString("code"); String errorMessage = json.getJSONObject("error").getString("message"); assertEquals("500", errorCode); - assertEquals("sample already exists.", errorMessage); + assertEquals( + "An object named \"sample\" already exists. Rename the object and try again.", + errorMessage); } try { for (int i = 2; i < 6; i++) { @@ -2972,9 +3033,9 @@ void testCreateLinkFailure() throws IOException { } @Test - @Order(41) + @Order(42) void testCreateLinkNoSDMRoles() throws IOException { - System.out.println("Test (41): Create link fails due to no SDM roles assigned"); + System.out.println("Test (42): Create link fails due to no SDM roles assigned"); String createLinkEntityNoSDMRoles = apiNoRoles.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -3016,9 +3077,9 @@ void testCreateLinkNoSDMRoles() throws IOException { } @Test - @Order(42) + @Order(43) void testDeleteLink() throws IOException { - System.out.println("Test (42): Delete link in entity"); + System.out.println("Test (43): Delete link in entity"); List> attachments = new ArrayList<>(); String createLinkEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -3094,9 +3155,9 @@ void testDeleteLink() throws IOException { } @Test - @Order(43) + @Order(44) void testRenameLinkSuccess() throws IOException { - System.out.println("Test (43): Rename link in entity"); + System.out.println("Test (44): Rename link in entity"); List> attachments = new ArrayList<>(); createLinkEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -3156,9 +3217,9 @@ void testRenameLinkSuccess() throws IOException { } @Test - @Order(44) + @Order(45) void testRenameLinkDuplicate() throws IOException { - System.out.println("Test (44): Rename link in entity fails due to duplicate error"); + System.out.println("Test (45): Rename link in entity fails due to duplicate error"); List attachments = new ArrayList<>(); String editEntityResponse = api.editEntityDraft(appUrl, entityName, srvpath, createLinkEntity); @@ -3215,7 +3276,7 @@ void testRenameLinkDuplicate() throws IOException { String saveError = api.saveEntityDraft(appUrl, entityName, srvpath, createLinkEntity); String expectedWarning = - "{\"error\":{\"code\":\"400\",\"message\":\"The file(s) sampleRenamed have been added multiple times. Please rename and try again.\",\"details\":[{\"code\":\"\",\"message\":\"The file(s) sampleRenamed have been added multiple times. Please rename and try again.\",\"@Common.numericSeverity\":4},{\"code\":\"\",\"message\":\"The file(s) sampleRenamed have been added multiple times. Please rename and try again.\",\"@Common.numericSeverity\":4}]}}"; + "{\"error\":{\"code\":\"400\",\"message\":\"An object named \\\"sampleRenamed\\\" already exists. Rename the object and try again.\",\"details\":[{\"code\":\"\",\"message\":\"An object named \\\"sampleRenamed\\\" already exists. Rename the object and try again.\",\"@Common.numericSeverity\":4},{\"code\":\"\",\"message\":\"An object named \\\"sampleRenamed\\\" already exists. Rename the object and try again.\",\"@Common.numericSeverity\":4}]}}"; ObjectMapper mapper = new ObjectMapper(); assertEquals(mapper.readTree(expectedWarning), mapper.readTree(saveError)); @@ -3226,10 +3287,10 @@ void testRenameLinkDuplicate() throws IOException { } @Test - @Order(45) + @Order(46) void testRenameLinkUnsupportedCharacters() throws IOException { System.out.println( - "Test (45): Rename link in entity fails due to unsupported characters in name"); + "Test (46): Rename link in entity fails due to unsupported characters in name"); List> attachments = new ArrayList<>(); createLinkEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -3278,14 +3339,16 @@ void testRenameLinkUnsupportedCharacters() throws IOException { index += 1; } - String warning = + String error = saveEntityResponse = api.saveEntityDraft(appUrl, entityName, srvpath, createLinkEntity); - String expectedWarning = - "[{\"code\":\"\",\"message\":\"Rename unsuccessful. The following filename(s) contain unsupported characters (/, \\\\). \\n\\n\\t• sampleRenamed//\\n\\nRename the files and try again.\",\"numericSeverity\":3}," - + "{\"code\":\"\",\"message\":\"Rename unsuccessful. The following filename(s) contain unsupported characters (/, \\\\). \\n\\n\\t• sampleRenamed//\\n\\nRename the files and try again.\",\"numericSeverity\":3}," - + "{\"code\":\"\",\"message\":\"Rename unsuccessful. The following filename(s) contain unsupported characters (/, \\\\). \\n\\n\\t• sampleRenamed//\\n\\nRename the files and try again.\",\"numericSeverity\":3}]"; + String expectedError = + "{\"error\":{\"code\":\"400\",\"message\":\"\\\"sampleRenamed//\\\" contains unsupported characters (‘/’ or ‘\\\\’). Rename and try again.\"," + + "\"details\":[" + + "{\"code\":\"\",\"message\":\"\\\"sampleRenamed//\\\" contains unsupported characters (‘/’ or ‘\\\\’). Rename and try again.\",\"@Common.numericSeverity\":4}," + + "{\"code\":\"\",\"message\":\"\\\"sampleRenamed//\\\" contains unsupported characters (‘/’ or ‘\\\\’). Rename and try again.\",\"@Common.numericSeverity\":4}" + + "]}}"; ObjectMapper mapper = new ObjectMapper(); - assertEquals(mapper.readTree(expectedWarning), mapper.readTree(warning)); + assertEquals(mapper.readTree(expectedError), mapper.readTree(error)); String deleteEntityResponse = api.deleteEntity(appUrl, entityName, createLinkEntity); if (!deleteEntityResponse.equals("Entity Deleted")) { @@ -3294,9 +3357,9 @@ void testRenameLinkUnsupportedCharacters() throws IOException { } @Test - @Order(46) + @Order(47) void testEditLinkSuccess() throws IOException { - System.out.println("Test (46): Edit existing link in entity"); + System.out.println("Test (47): Edit existing link in entity"); List> attachmentsPerFacet = new ArrayList<>(); editLinkEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -3365,9 +3428,9 @@ void testEditLinkSuccess() throws IOException { } @Test - @Order(47) + @Order(48) void testEditLinkFailureInvalidURL() throws IOException { - System.out.println("Test (47): Edit existing link with invalid url"); + System.out.println("Test (48): Edit existing link with invalid url"); List> attachmentsPerFacet = new ArrayList<>(); String editEntityResponse = api.editEntityDraft(appUrl, entityName, srvpath, editLinkEntity); @@ -3416,9 +3479,9 @@ void testEditLinkFailureInvalidURL() throws IOException { } @Test - @Order(48) + @Order(49) void testEditLinkFailureEmptyURL() throws IOException { - System.out.println("Test (48): Edit existing link with an empty url"); + System.out.println("Test (49): Edit existing link with an empty url"); List> attachmentsPerFacet = new ArrayList<>(); String editEntityResponse = api.editEntityDraft(appUrl, entityName, srvpath, editLinkEntity); @@ -3464,9 +3527,9 @@ void testEditLinkFailureEmptyURL() throws IOException { } @Test - @Order(49) + @Order(50) void testEditLinkNoSDMRoles() throws IOException { - System.out.println("Test (49): Edit link fails due to no SDM roles assigned"); + System.out.println("Test (50): Edit link fails due to no SDM roles assigned"); Boolean testStatus = false; @@ -3536,9 +3599,9 @@ void testEditLinkNoSDMRoles() throws IOException { } @Test - @Order(50) + @Order(51) void testCopyLinkSuccessNewEntity() throws IOException { - System.out.println("Test (50): Copy link from one entity to another new entity"); + System.out.println("Test (51): Copy link from one entity to another new entity"); List> attachmentsByFacet = new ArrayList<>(); String linkUrl = "https://www.example.com"; for (int i = 0; i < facet.length; i++) { @@ -3643,10 +3706,10 @@ void testCopyLinkSuccessNewEntity() throws IOException { } @Test - @Order(51) + @Order(52) void testCopyLinkUnsuccessfulNewEntity() throws IOException { System.out.println( - "Test (51): Copy invalid type of link from one entity to another new entity"); + "Test (52): Copy invalid type of link from one entity to another new entity"); String editResponse = api.editEntityDraft(appUrl, entityName, srvpath, copyLinkSourceEntity); copyLinkTargetEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -3670,9 +3733,9 @@ void testCopyLinkUnsuccessfulNewEntity() throws IOException { } @Test - @Order(52) + @Order(53) void testCopyLinkFromNewEntityToExistingEntity() throws IOException { - System.out.println("Test (52): Copy link from a new entity to an existing target entity"); + System.out.println("Test (53): Copy link from a new entity to an existing target entity"); List> attachmentsByFacet = new ArrayList<>(); String linkUrl = "https://www.example.com"; @@ -3767,10 +3830,10 @@ void testCopyLinkFromNewEntityToExistingEntity() throws IOException { } @Test - @Order(53) + @Order(54) void testCopyInvalidLinkFromNewEntityToExistingEntity() throws IOException { System.out.println( - "Test (53): Copy invalid type of link from new entity to existing target entity"); + "Test (54): Copy invalid type of link from new entity to existing target entity"); String linkUrl = "https://www.example.com"; copyLinkSourceEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -3807,9 +3870,9 @@ void testCopyInvalidLinkFromNewEntityToExistingEntity() throws IOException { } @Test - @Order(54) + @Order(55) void testCopyLinkSuccessNewEntityDraft() throws IOException { - System.out.println("Test (54): Copy link from one entity to another new entity draft mode"); + System.out.println("Test (55): Copy link from one entity to another new entity draft mode"); List> attachmentsByFacet = new ArrayList<>(); String linkUrl = "https://www.example.com"; for (int i = 0; i < facet.length; i++) { @@ -3912,10 +3975,10 @@ void testCopyLinkSuccessNewEntityDraft() throws IOException { } @Test - @Order(55) + @Order(56) void testCopyAttachmentsSuccessNewEntityDraft() throws IOException { System.out.println( - "Test (55): Copy attachments from one entity to another new entity draft mode"); + "Test (56): Copy attachments from one entity to another new entity draft mode"); List> attachments = new ArrayList<>(); for (int i = 0; i < 3; i++) { attachments.add(new ArrayList<>()); diff --git a/sdm/src/test/java/integration/com/sap/cds/sdm/IntegrationTest_SingleFacet.java b/sdm/src/test/java/integration/com/sap/cds/sdm/IntegrationTest_SingleFacet.java index 8e481be2..d25b16fa 100644 --- a/sdm/src/test/java/integration/com/sap/cds/sdm/IntegrationTest_SingleFacet.java +++ b/sdm/src/test/java/integration/com/sap/cds/sdm/IntegrationTest_SingleFacet.java @@ -404,7 +404,7 @@ void testUploadSingleAttachmentPDFDuplicate() throws IOException { response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID); if (response.equals("Saved")) { String expectedJson = - "{\"error\":{\"code\":\"500\",\"message\":\"sample.pdf already exists.\"}}"; + "{\"error\":{\"code\":\"500\",\"message\":\"An object named \\\"sample.pdf\\\" already exists. Rename the object and try again.\"}}"; ObjectMapper objectMapper = new ObjectMapper(); JsonNode actualJsonNode = objectMapper.readTree(check); JsonNode expectedJsonNode = objectMapper.readTree(expectedJson); @@ -454,7 +454,7 @@ void testUploadSingleAttachmentPDFDuplicateDifferentEntity() throws IOException List createResponse = api.createAttachment(appUrl, entityName, facetName, entityID2, srvpath, postData, file); String check = createResponse.get(0); - if (check.equals(facetName + " created")) { + if (check.equals("Attachment created")) { attachmentID4 = createResponse.get(1); response = api.readAttachmentDraft(appUrl, entityName, facetName, entityID2, attachmentID4); if (response.equals("OK")) { @@ -510,10 +510,12 @@ void testCreateAttachmentWithRestrictedCharacterInFilename() throws IOException if (response.equals("Renamed")) { response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID); String expected = - "[{\"code\":\"\",\"message\":\"Rename unsuccessful. The following filename(s) contain unsupported " - + "characters (/, \\\\). \\n\\n\\t\\u2022 a/\\bc.pdf\\n\\nRename the files and try again.\",\"numericSeverity\":3}]"; + "{\"error\":{\"code\":\"400\",\"message\":\"\\\"a/\\bc.pdf\\\" contains unsupported characters (‘/’ or ‘\\\\’). Rename and try again.\"}}"; if (response.equals(expected)) { - testStatus = true; + api.renameAttachment( + appUrl, entityName, facetName, entityID, attachmentID6, "sample3.pdf"); + response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID); + if ("Saved".equals(response)) testStatus = true; } } else { api.saveEntityDraft(appUrl, entityName, srvpath, entityID); @@ -650,10 +652,11 @@ void testRenameAttachmentWithUnsupportedCharacter() { if (response.equals("Renamed")) { response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID); String expected = - "[{\"code\":\"\",\"message\":\"Rename unsuccessful. The following filename(s) contain unsupported characters " - + "(/, \\\\). \\n\\n\\t\\u2022 invalid/name\\n\\nRename the files and try again.\",\"numericSeverity\":3}]"; + "{\"error\":{\"code\":\"400\",\"message\":\"\\\"invalid/name\\\" contains unsupported characters (‘/’ or ‘\\\\’). Rename and try again.\"}}"; if (response.equals(expected)) { - testStatus = true; + api.renameAttachment(appUrl, entityName, facetName, entityID, attachmentID1, "sample123"); + response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID); + if ("Saved".equals(response)) testStatus = true; } } else { api.saveEntityDraft(appUrl, entityName, srvpath, entityID); @@ -704,8 +707,7 @@ void testRenameSingleAttachmentDuplicate() { if (response.equals("Renamed")) { response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID); String expected = - "{\"error\":{\"code\":\"400\",\"message\":\"The file(s) sample123 have been added " - + "multiple times. Please rename and try again.\"}}"; + "{\"error\":{\"code\":\"400\",\"message\":\"An object named \\\"sample123\\\" already exists. Rename the object and try again.\"}}"; if (response.equals(expected)) { response = api.renameAttachment(appUrl, entityName, facetName, entityID, attachmentID3, name2); @@ -747,10 +749,12 @@ void testRenameMultipleAttachmentsWithOneUnsupportedCharacter() { if (renameResponse1.equals("Renamed") && renameResponse2.equals("Renamed")) { response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID); String expected = - "[{\"code\":\"\",\"message\":\"Rename unsuccessful. The following filename(s) contain unsupported characters" - + " (/, \\\\). \\n\\n\\t\\u2022 invalid/attachment2.pdf\\n\\nRename the files and try again.\",\"numericSeverity\":3}]"; + "{\"error\":{\"code\":\"400\",\"message\":\"\\\"invalid/attachment2.pdf\\\" contains unsupported characters (‘/’ or ‘\\\\’). Rename and try again.\"}}"; if (response.equals(expected)) { - testStatus = true; + api.renameAttachment( + appUrl, entityName, facetName, entityID, attachmentID2, "sample1234"); + response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID); + if ("Saved".equals(response)) testStatus = true; } } else { api.saveEntityDraft(appUrl, entityName, srvpath, entityID); @@ -798,8 +802,53 @@ void testRenameSingleAttachmentWithoutSDMRole() throws IOException { @Test @Order(18) + void testRenameToValidateNames() throws IOException { + System.out.println("Test (18) : Rename attachments to validate names"); + boolean testStatus = false, successCount = true; + String generatedID = ""; + String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); + if (!response.equals("Could not create entity")) { + entityID3 = response; + String[] filetoUpload = {"sample.pdf", "sample.txt", "sample.exe", "sample2.pdf"}; + String[] names = {"Restricted/Character", " ", "duplicateName.pdf", "duplicateName.pdf"}; + + ClassLoader classLoader = getClass().getClassLoader(); + Map postData = new HashMap<>(); + postData.put("up__ID", entityID3); + postData.put("mimeType", "application/pdf"); + postData.put("createdAt", new Date().toString()); + postData.put("createdBy", "test@test.com"); + postData.put("modifiedBy", "test@test.com"); + + for (int i = 0; i < filetoUpload.length; i++) { + File file = new File(classLoader.getResource(filetoUpload[i]).getFile()); + List createResponse = + api.createAttachment(appUrl, entityName, facetName, entityID3, srvpath, postData, file); + generatedID = createResponse.get(1); + response = + api.renameAttachment(appUrl, entityName, facetName, entityID3, generatedID, names[i]); + successCount &= "Renamed".equals(response); + } + if (successCount) { + response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID3); + String expected = + "{\"error\":{\"code\":\"400\",\"message\":\"The object name cannot be empty or consist entirely of space characters. Enter a value.\",\"details\":[{\"code\":\"\",\"message\":\"\\\"Restricted/Character\\\" contains unsupported characters (‘/’ or ‘\\\\’). Rename and try again.\",\"@Common.numericSeverity\":4},{\"code\":\"\",\"message\":\"An object named \\\"duplicateName.pdf\\\" already exists. Rename the object and try again.\",\"@Common.numericSeverity\":4}]}}"; + if (response.equals(expected)) { + response = api.deleteEntityDraft(appUrl, entityName, entityID3); + if (response.equals("Entity Draft Deleted")) testStatus = true; + } + } + if (!testStatus) fail("Could not create entity"); + } else { + fail("Could not create entity"); + return; + } + } + + @Test + @Order(19) void testDeleteSingleAttachment() throws IOException { - System.out.println("Test (18) : Delete single attachment"); + System.out.println("Test (19) : Delete single attachment"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID); if (response == "Entity in draft mode") { @@ -820,9 +869,9 @@ void testDeleteSingleAttachment() throws IOException { } @Test - @Order(19) + @Order(20) void testDeleteMultipleAttachments() throws IOException { - System.out.println("Test (19) : Delete multiple attachments"); + System.out.println("Test (20) : Delete multiple attachments"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID); if (response == "Entity in draft mode") { @@ -848,9 +897,9 @@ void testDeleteMultipleAttachments() throws IOException { } @Test - @Order(20) + @Order(21) void testUploadBlockedMimeType() throws IOException { - System.out.println("Test (20): Upload blocked mimeType .rtf"); + System.out.println("Test (21): Upload blocked mimeType .rtf"); Boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); if (!"Could not create entity".equals(response)) { @@ -887,9 +936,9 @@ void testUploadBlockedMimeType() throws IOException { } @Test - @Order(21) + @Order(22) void testDeleteEntity() { - System.out.println("Test (21) : Delete entity"); + System.out.println("Test (22) : Delete entity"); Boolean testStatus = false; String response = api.deleteEntity(appUrl, entityName, entityID); String response2 = api.deleteEntity(appUrl, entityName, entityID2); @@ -902,9 +951,9 @@ void testDeleteEntity() { } @Test - @Order(22) + @Order(23) void testUpdateValidSecondaryProperty_beforeEntityIsSaved_singleAttachment() throws IOException { - System.out.println("Test (22): Rename & Update secondary property before entity is saved"); + System.out.println("Test (23): Rename & Update secondary property before entity is saved"); System.out.println("Creating entity"); Boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -989,9 +1038,9 @@ void testUpdateValidSecondaryProperty_beforeEntityIsSaved_singleAttachment() thr } @Test - @Order(23) + @Order(24) void testUpdateValidSecondaryProperty_afterEntityIsSaved_singleAttachment() { - System.out.println("Test (23): Rename & Update secondary property after entity is saved"); + System.out.println("Test (24): Rename & Update secondary property after entity is saved"); System.out.println("Editing entity"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID3); @@ -1060,11 +1109,11 @@ void testUpdateValidSecondaryProperty_afterEntityIsSaved_singleAttachment() { } @Test - @Order(24) + @Order(25) void testUpdateInvalidSecondaryProperty_beforeEntityIsSaved_singleAttachment() throws IOException { System.out.println( - "Test (24): Rename & Update invalid secondary property before entity is saved"); + "Test (25): Rename & Update invalid secondary property before entity is saved"); System.out.println("Creating entity"); Boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -1189,10 +1238,10 @@ void testUpdateInvalidSecondaryProperty_beforeEntityIsSaved_singleAttachment() } @Test - @Order(25) + @Order(26) void testUpdateInvalidSecondaryProperty_afterEntityIsSaved_singleAttachment() throws IOException { System.out.println( - "Test (25): Rename & Update invalid secondary property after entity is saved"); + "Test (26): Rename & Update invalid secondary property after entity is saved"); System.out.println("Editing entity"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID3); @@ -1287,11 +1336,11 @@ void testUpdateInvalidSecondaryProperty_afterEntityIsSaved_singleAttachment() th } @Test - @Order(26) + @Order(27) void testUpdateValidSecondaryProperty_beforeEntityIsSaved_multipleAttachments() throws IOException { System.out.println( - "Test (26): Rename & Update valid secondary properties for multiple attachments before entity is saved"); + "Test (27): Rename & Update valid secondary properties for multiple attachments before entity is saved"); System.out.println("Creating entity"); Boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -1475,10 +1524,10 @@ void testUpdateValidSecondaryProperty_beforeEntityIsSaved_multipleAttachments() } @Test - @Order(27) + @Order(28) void testUpdateValidSecondaryProperty_afterEntityIsSaved_multipleAttachments() { System.out.println( - "Test (27): Rename & Update valid secondary properties for multiple attachments after entity is saved"); + "Test (28): Rename & Update valid secondary properties for multiple attachments after entity is saved"); System.out.println("Editing entity"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID3); @@ -1607,11 +1656,11 @@ void testUpdateValidSecondaryProperty_afterEntityIsSaved_multipleAttachments() { } @Test - @Order(28) + @Order(29) void testUpdateInvalidSecondaryProperty_beforeEntityIsSaved_multipleAttachments() throws IOException { System.out.println( - "Test (28): Rename & Update invalid and valid secondary properties for multiple attachments before entity is saved"); + "Test (29): Rename & Update invalid and valid secondary properties for multiple attachments before entity is saved"); System.out.println("Creating entity"); Boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -1828,11 +1877,11 @@ void testUpdateInvalidSecondaryProperty_beforeEntityIsSaved_multipleAttachments( } @Test - @Order(29) + @Order(30) void testUpdateInvalidSecondaryProperty_afterEntityIsSaved_multipleAttachments() throws IOException { System.out.println( - "Test (29): Rename & Update invalid and valid secondary properties for multiple attachments after entity is saved"); + "Test (30): Rename & Update invalid and valid secondary properties for multiple attachments after entity is saved"); System.out.println("Editing entity"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID3); @@ -1992,10 +2041,10 @@ void testUpdateInvalidSecondaryProperty_afterEntityIsSaved_multipleAttachments() } @Test - @Order(30) + @Order(31) void testNAttachments_NewEntity() throws IOException { System.out.println( - "Test (30): Creating new entity and checking only max 4 attachments are allowed to be uploaded"); + "Test (31): Creating new entity and checking only max 4 attachments are allowed to be uploaded"); System.out.println("Creating entity"); Boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -2109,9 +2158,9 @@ void testNAttachments_NewEntity() throws IOException { } @Test - @Order(31) + @Order(32) void testUploadNAttachments() throws IOException { - System.out.println("Test (31): Upload maximum 4 attachments in an exsisting entity"); + System.out.println("Test (32): Upload maximum 4 attachments in an exsisting entity"); ClassLoader classLoader = getClass().getClassLoader(); File originalFile = new File(classLoader.getResource("sample.exe").getFile()); @@ -2168,9 +2217,9 @@ void testUploadNAttachments() throws IOException { } @Test - @Order(32) + @Order(33) void testDiscardDraftWithoutAttachments() { - System.out.println("Test (32) : Discard draft without adding attachments"); + System.out.println("Test (33) : Discard draft without adding attachments"); String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -2185,9 +2234,9 @@ void testDiscardDraftWithoutAttachments() { } @Test - @Order(33) + @Order(34) void testDiscardDraftWithAttachments() throws IOException { - System.out.println("Test (33) : Discard draft with attachments"); + System.out.println("Test (34) : Discard draft with attachments"); boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); if (!response.equals("Could not create entity")) { @@ -2221,9 +2270,9 @@ void testDiscardDraftWithAttachments() throws IOException { } @Test - @Order(34) + @Order(35) void testCopyAttachmentsSuccessNewEntity() throws IOException { - System.out.println("Test (34): Copy attachments from one entity to another new entity"); + System.out.println("Test (35): Copy attachments from one entity to another new entity"); List attachments = new ArrayList<>(); copyAttachmentSourceEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); copyAttachmentTargetEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -2316,9 +2365,9 @@ void testCopyAttachmentsSuccessNewEntity() throws IOException { } @Test - @Order(35) + @Order(36) void testCopyAttachmentsUnsuccessfulNewEntity() throws IOException { - System.out.println("Test (35): Copy attachments from one entity to another new entity"); + System.out.println("Test (36): Copy attachments from one entity to another new entity"); String editResponse1 = api.editEntityDraft(appUrl, entityName, srvpath, copyAttachmentSourceEntity); copyAttachmentTargetEntityEmpty = @@ -2353,9 +2402,9 @@ void testCopyAttachmentsUnsuccessfulNewEntity() throws IOException { } @Test - @Order(36) + @Order(37) void testCopyAttachmentsSuccessExistingEntity() throws IOException { - System.out.println("Test (36): Copy attachments from one entity to another existing entity"); + System.out.println("Test (37): Copy attachments from one entity to another existing entity"); List attachments = new ArrayList<>(); ClassLoader classLoader = getClass().getClassLoader(); List files = new ArrayList<>(); @@ -2461,9 +2510,9 @@ void testCopyAttachmentsSuccessExistingEntity() throws IOException { } @Test - @Order(37) + @Order(38) void testCopyAttachmentsUnsuccessfulExistingEntity() throws IOException { - System.out.println("Test (37): Copy attachments from one entity to another new entity"); + System.out.println("Test (38): Copy attachments from one entity to another new entity"); String editResponse1 = api.editEntityDraft(appUrl, entityName, srvpath, copyAttachmentSourceEntity); String editResponse2 = @@ -2491,9 +2540,9 @@ void testCopyAttachmentsUnsuccessfulExistingEntity() throws IOException { } @Test - @Order(38) + @Order(39) void testCreateLinkSuccess() throws IOException { - System.out.println("Test (38): Create link in entity"); + System.out.println("Test (39): Create link in entity"); List attachments = new ArrayList<>(); createLinkEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); if (!createLinkEntity.equals("Could not create entity")) { @@ -2534,9 +2583,9 @@ void testCreateLinkSuccess() throws IOException { } @Test - @Order(39) + @Order(40) void testCreateLinkDifferentEntity() throws IOException { - System.out.println("Test (39): Create link with same name in different entity"); + System.out.println("Test (40): Create link with same name in different entity"); String createLinkDifferentEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); if (!createLinkDifferentEntity.equals("Could not edit entity")) { @@ -2562,9 +2611,9 @@ void testCreateLinkDifferentEntity() throws IOException { } @Test - @Order(40) + @Order(41) void testCreateLinkFailure() throws IOException { - System.out.println("Test (40): Create link fails due to invalid URL and name"); + System.out.println("Test (41): Create link fails due to invalid URL and name"); String editEntityResponse = api.editEntityDraft(appUrl, entityName, srvpath, createLinkEntity); if (!editEntityResponse.equals("Could not edit entity")) { String linkName = "sample"; @@ -2597,9 +2646,7 @@ void testCreateLinkFailure() throws IOException { String errorCode = json.getJSONObject("error").getString("code"); String errorMessage = json.getJSONObject("error").getString("message"); String expected = - "Link could not be created. The following name(s) contain unsupported characters (/, \\).\n\n" - + " • sample//\n\n" - + "Rename the link and try again."; + "\"sample//\" contains unsupported characters (‘/’ or ‘\\’). Rename and try again."; assertEquals("500", errorCode); assertEquals( expected.replaceAll("\\s+", " ").trim(), errorMessage.replaceAll("\\s+", " ").trim()); @@ -2630,7 +2677,9 @@ void testCreateLinkFailure() throws IOException { String errorCode = json.getJSONObject("error").getString("code"); String errorMessage = json.getJSONObject("error").getString("message"); assertEquals("500", errorCode); - assertEquals("sample already exists.", errorMessage); + assertEquals( + "An object named \"sample\" already exists. Rename the object and try again.", + errorMessage); } try { for (int i = 2; i < 5; i++) { @@ -2662,9 +2711,9 @@ void testCreateLinkFailure() throws IOException { } @Test - @Order(41) + @Order(42) void testCreateLinkNoSDMRoles() throws IOException { - System.out.println("Test (41): Create link fails due to no SDM roles assigned"); + System.out.println("Test (42): Create link fails due to no SDM roles assigned"); String createLinkEntityNoSDMRoles = apiNoRoles.createEntityDraft(appUrl, entityName, entityName2, srvpath); if (!createLinkEntityNoSDMRoles.equals("Could not edit entity")) { @@ -2701,9 +2750,9 @@ void testCreateLinkNoSDMRoles() throws IOException { } @Test - @Order(42) + @Order(43) void testDeleteLink() throws IOException { - System.out.println("Test (42): Delete link in entity"); + System.out.println("Test (43): Delete link in entity"); List attachments = new ArrayList<>(); String createLinkEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); if (!createLinkEntity.equals("Could not create entity")) { @@ -2760,9 +2809,9 @@ void testDeleteLink() throws IOException { } @Test - @Order(43) + @Order(44) void testRenameLinkSuccess() throws IOException { - System.out.println("Test (43): Rename link in entity"); + System.out.println("Test (44): Rename link in entity"); List attachments = new ArrayList<>(); createLinkEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -2807,9 +2856,9 @@ void testRenameLinkSuccess() throws IOException { } @Test - @Order(44) + @Order(45) void testRenameLinkDuplicate() throws IOException { - System.out.println("Test (44): Rename link in entity fails due to duplicate error"); + System.out.println("Test (45): Rename link in entity fails due to duplicate error"); List attachments = new ArrayList<>(); String editEntityResponse = api.editEntityDraft(appUrl, entityName, srvpath, createLinkEntity); @@ -2848,7 +2897,7 @@ void testRenameLinkDuplicate() throws IOException { String saveError = saveEntityResponse = api.saveEntityDraft(appUrl, entityName, srvpath, createLinkEntity); String expectedWarning = - "{\"error\":{\"code\":\"400\",\"message\":\"The file(s) sampleRenamed have been added multiple times. Please rename and try again.\"}}"; + "{\"error\":{\"code\":\"400\",\"message\":\"An object named \\\"sampleRenamed\\\" already exists. Rename the object and try again.\"}}"; ObjectMapper mapper = new ObjectMapper(); assertEquals(mapper.readTree(expectedWarning), mapper.readTree(saveError)); @@ -2859,10 +2908,10 @@ void testRenameLinkDuplicate() throws IOException { } @Test - @Order(45) + @Order(46) void testRenameLinkUnsupportedCharacters() throws IOException { System.out.println( - "Test (45): Rename link in entity fails due to unsupported characters in name"); + "Test (46): Rename link in entity fails due to unsupported characters in name"); List attachments = new ArrayList<>(); String editEntityResponse = api.editEntityDraft(appUrl, entityName, srvpath, createLinkEntity); @@ -2901,7 +2950,7 @@ void testRenameLinkUnsupportedCharacters() throws IOException { String warning = saveEntityResponse = api.saveEntityDraft(appUrl, entityName, srvpath, createLinkEntity); String expectedWarning = - "[{\"code\":\"\",\"message\":\"Rename unsuccessful. The following filename(s) contain unsupported characters (/, \\\\). \\n\\n\\t• sampleRenamed//\\n\\nRename the files and try again.\",\"numericSeverity\":3}]"; + "{\"error\":{\"code\":\"400\",\"message\":\"\\\"sampleRenamed//\\\" contains unsupported characters (‘/’ or ‘\\\\’). Rename and try again.\"}}"; ObjectMapper mapper = new ObjectMapper(); assertEquals(mapper.readTree(expectedWarning), mapper.readTree(warning)); @@ -2912,9 +2961,9 @@ void testRenameLinkUnsupportedCharacters() throws IOException { } @Test - @Order(46) + @Order(47) void testEditLinkSuccess() throws IOException { - System.out.println("Test (46): Edit existing link in entity"); + System.out.println("Test (47): Edit existing link in entity"); List attachments = new ArrayList<>(); editLinkEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -2969,9 +3018,9 @@ void testEditLinkSuccess() throws IOException { } @Test - @Order(47) + @Order(48) void testEditLinkFailureInvalidURL() throws IOException { - System.out.println("Test (47): Edit existing link with invalid url"); + System.out.println("Test (48): Edit existing link with invalid url"); Boolean testStatus = false; List attachments = new ArrayList<>(); @@ -3016,9 +3065,9 @@ void testEditLinkFailureInvalidURL() throws IOException { } @Test - @Order(48) + @Order(49) void testEditLinkFailureEmptyURL() throws IOException { - System.out.println("Test (48): Edit existing link with an empty url"); + System.out.println("Test (49): Edit existing link with an empty url"); Boolean testStatus = false; List attachments = new ArrayList<>(); @@ -3059,9 +3108,9 @@ void testEditLinkFailureEmptyURL() throws IOException { } @Test - @Order(49) + @Order(50) void testEditLinkNoSDMRoles() throws IOException { - System.out.println("Test (49): Edit link fails due to no SDM roles assigned"); + System.out.println("Test (50): Edit link fails due to no SDM roles assigned"); Boolean testStatus = false; List attachments = new ArrayList<>(); @@ -3105,9 +3154,9 @@ void testEditLinkNoSDMRoles() throws IOException { } @Test - @Order(50) + @Order(51) void testCopyLinkSuccessNewEntity() throws IOException { - System.out.println("Test (50): Copy link from one entity to another new entity"); + System.out.println("Test (51): Copy link from one entity to another new entity"); List> attachmentsMetadata = new ArrayList<>(); copyLinkSourceEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -3184,10 +3233,10 @@ void testCopyLinkSuccessNewEntity() throws IOException { } @Test - @Order(51) + @Order(52) void testCopyLinkUnsuccessfulNewEntity() throws IOException { System.out.println( - "Test (51): Copy invalid type of link from one entity to another new entity"); + "Test (52): Copy invalid type of link from one entity to another new entity"); copyLinkSourceEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); copyLinkTargetEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -3219,9 +3268,9 @@ void testCopyLinkUnsuccessfulNewEntity() throws IOException { } @Test - @Order(52) + @Order(53) void testCopyLinkFromNewEntityToExistingEntity() throws IOException { - System.out.println("Test (52): Copy link from a new entity to an existing target entity"); + System.out.println("Test (53): Copy link from a new entity to an existing target entity"); List> attachmentsMetadata = new ArrayList<>(); copyLinkSourceEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -3306,10 +3355,10 @@ void testCopyLinkFromNewEntityToExistingEntity() throws IOException { } @Test - @Order(53) + @Order(54) void testCopyInvalidLinkFromNewEntityToExistingEntity() throws IOException { System.out.println( - "Test (53): Copy invalid type of link from new entity to existing target entity"); + "Test (54): Copy invalid type of link from new entity to existing target entity"); copyLinkSourceEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); if (copyLinkSourceEntity.equals("Could not create entity")) { @@ -3359,9 +3408,9 @@ void testCopyInvalidLinkFromNewEntityToExistingEntity() throws IOException { } @Test - @Order(54) + @Order(55) void testCopyLinkSuccessNewEntityDraft() throws IOException { - System.out.println("Test (54): Copy link from one entity to another new entity draft mode"); + System.out.println("Test (55): Copy link from one entity to another new entity draft mode"); copyLinkSourceEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); copyLinkTargetEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -3433,10 +3482,10 @@ void testCopyLinkSuccessNewEntityDraft() throws IOException { } @Test - @Order(55) + @Order(56) void testCopyAttachmentsSuccessNewEntityDraft() throws IOException { System.out.println( - "Test (55): Copy attachments from one entity to another new entity draft mode"); + "Test (56): Copy attachments from one entity to another new entity draft mode"); List attachments = new ArrayList<>(); copyAttachmentSourceEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); copyAttachmentTargetEntity = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); diff --git a/sdm/src/test/java/unit/com/sap/cds/sdm/handler/applicationservice/SDMCreateAttachmentsHandlerTest.java b/sdm/src/test/java/unit/com/sap/cds/sdm/handler/applicationservice/SDMCreateAttachmentsHandlerTest.java index dd0b4711..bf943570 100644 --- a/sdm/src/test/java/unit/com/sap/cds/sdm/handler/applicationservice/SDMCreateAttachmentsHandlerTest.java +++ b/sdm/src/test/java/unit/com/sap/cds/sdm/handler/applicationservice/SDMCreateAttachmentsHandlerTest.java @@ -1,7 +1,5 @@ package unit.com.sap.cds.sdm.handler.applicationservice; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyString; @@ -10,6 +8,7 @@ import com.sap.cds.CdsData; import com.sap.cds.reflect.*; import com.sap.cds.sdm.caching.CacheConfig; +import com.sap.cds.sdm.constants.SDMConstants; import com.sap.cds.sdm.handler.TokenHandler; import com.sap.cds.sdm.handler.applicationservice.SDMCreateAttachmentsHandler; import com.sap.cds.sdm.handler.applicationservice.helper.AttachmentsHandlerUtils; @@ -17,7 +16,6 @@ import com.sap.cds.sdm.persistence.DBQuery; import com.sap.cds.sdm.service.SDMService; import com.sap.cds.sdm.utilities.SDMUtils; -import com.sap.cds.services.ServiceException; import com.sap.cds.services.authentication.AuthenticationInfo; import com.sap.cds.services.authentication.JwtTokenAuthenticationInfo; import com.sap.cds.services.cds.CdsCreateEventContext; @@ -122,18 +120,31 @@ public void testUpdateNameWithDuplicateFilenames() throws IOException { CdsEntity targetEntity = mock(CdsEntity.class); when(targetEntity.getQualifiedName()).thenReturn("TestEntity"); when(context.getTarget()).thenReturn(targetEntity); - + // Make validateFileName execute its real implementation, and stub helper methods + sdmUtilsMockedStatic + .when(() -> SDMUtils.isFileNameContainsWhitespace(anyList(), anyString(), anyString())) + .thenCallRealMethod(); + sdmUtilsMockedStatic + .when( + () -> + SDMUtils.isFileNameContainsRestrictedCharaters( + anyList(), anyString(), anyString())) + .thenReturn(Collections.emptyList()); sdmUtilsMockedStatic .when(() -> SDMUtils.isFileNameDuplicateInDrafts(data, "compositionName", "TestEntity")) .thenReturn(duplicateFilenames); + sdmUtilsMockedStatic + .when(() -> SDMUtils.validateFileNames(any(), anyList(), anyString())) + .thenCallRealMethod(); // Act handler.updateName(context, data, "compositionDefinition", "compositionName"); - // Assert + // Assert: validateFileName should have logged an error for duplicate filenames verify(messages, times(1)) .error( - "The file(s) file1.txt, file2.txt have been added multiple times. Please rename and try again."); + org.mockito.ArgumentMatchers.contains( + "Objects with the following names already exist")); } } @@ -484,7 +495,7 @@ public void testUpdateNameWithEmptyFilename() throws IOException { // Mock restricted character sdmUtilsMockedStatic - .when(() -> SDMUtils.isRestrictedCharactersInName("fileNameInRequest")) + .when(() -> SDMUtils.hasRestrictedCharactersInName("fileNameInRequest")) .thenReturn(false); when(dbQuery.getAttachmentForID(attachmentDraftEntity, persistenceService, "test-id")) @@ -495,19 +506,94 @@ public void testUpdateNameWithEmptyFilename() throws IOException { attachmentDraftEntity, persistenceService, "test-id", secondaryTypeProperties)) .thenReturn(updatedSecondaryProperties); - // Act & Assert - ServiceException exception = - assertThrows( - ServiceException.class, - () -> - handler.updateName(context, data, "compositionDefinition", "compositionName")); + // Make validateFileName execute its real implementation so it logs the error + sdmUtilsMockedStatic + .when(() -> SDMUtils.isFileNameContainsWhitespace(anyList(), anyString(), anyString())) + .thenCallRealMethod(); + sdmUtilsMockedStatic + .when(() -> SDMUtils.isFileNameDuplicateInDrafts(anyList(), anyString(), anyString())) + .thenReturn(new HashSet<>()); + sdmUtilsMockedStatic + .when(() -> SDMUtils.validateFileNames(any(), anyList(), anyString())) + .thenCallRealMethod(); - // Assert that the correct exception message is returned - assertEquals("Filename cannot be empty", exception.getMessage()); + // Act + handler.updateName(context, data, "compositionDefinition", "compositionName"); + + // Assert: since validation logs an error instead of throwing, ensure the message was logged + verify(messages, times(1)).error(SDMConstants.FILENAME_WHITESPACE_ERROR_MESSAGE); } // Close AttachmentsHandlerUtils mock } } + @Test + public void testUpdateNameWithRestrictedCharacters() throws IOException { + try (MockedStatic cacheConfigMockedStatic = mockStatic(CacheConfig.class)) { + Cache mockCache = mock(Cache.class); + cacheConfigMockedStatic.when(CacheConfig::getSecondaryPropertiesCache).thenReturn(mockCache); + + // Arrange + List data = new ArrayList<>(); + Map entity = new HashMap<>(); + List> attachments = new ArrayList<>(); + + Map attachment = new HashMap<>(); + attachment.put("ID", "test-id"); + attachment.put("fileName", "file/1.txt"); // Restricted character + attachment.put("objectId", "test-object-id"); + attachments.add(attachment); + + entity.put("composition", attachments); + + CdsData cdsDataEntity = CdsData.create(entity); + data.add(cdsDataEntity); + + when(context.getMessages()).thenReturn(messages); + + // Mock attachment entity and model + CdsEntity attachmentDraftEntity = mock(CdsEntity.class); + when(attachmentDraftEntity.getQualifiedName()).thenReturn("some.qualified.Name"); + when(context.getTarget()).thenReturn(attachmentDraftEntity); + when(context.getModel()).thenReturn(model); + when(model.findEntity("compositionDefinition")) + .thenReturn(Optional.of(attachmentDraftEntity)); + + // Stub the validation helper methods so validateFileName runs and detects the restricted char + sdmUtilsMockedStatic + .when(() -> SDMUtils.isFileNameContainsWhitespace(anyList(), anyString(), anyString())) + .thenReturn(Collections.emptySet()); + sdmUtilsMockedStatic + .when(() -> SDMUtils.isFileNameDuplicateInDrafts(anyList(), anyString(), anyString())) + .thenReturn(Collections.emptySet()); + sdmUtilsMockedStatic + .when( + () -> + SDMUtils.isFileNameContainsRestrictedCharaters( + data, "compositionName", "some.qualified.Name")) + .thenReturn(Arrays.asList("file/1.txt")); + sdmUtilsMockedStatic + .when(() -> SDMUtils.validateFileNames(any(), anyList(), anyString())) + .thenCallRealMethod(); + + try (MockedStatic attachmentsHandlerUtilsMocked = + mockStatic(AttachmentsHandlerUtils.class)) { + attachmentsHandlerUtilsMocked + .when( + () -> + AttachmentsHandlerUtils.fetchAttachments( + "some.qualified.Name", entity, "compositionName")) + .thenReturn(attachments); + + // Act + handler.updateName(context, data, "compositionDefinition", "compositionName"); + + // Assert: proper restricted-character error was logged + verify(messages, times(1)) + .error(SDMConstants.nameConstraintMessage(Arrays.asList("file/1.txt"))); + } + } + } + // @Test // public void testUpdateNameWithMultipleAttachments() throws IOException { // // Arrange diff --git a/sdm/src/test/java/unit/com/sap/cds/sdm/handler/applicationservice/SDMUpdateAttachmentsHandlerTest.java b/sdm/src/test/java/unit/com/sap/cds/sdm/handler/applicationservice/SDMUpdateAttachmentsHandlerTest.java index 30a55023..6ec5ae63 100644 --- a/sdm/src/test/java/unit/com/sap/cds/sdm/handler/applicationservice/SDMUpdateAttachmentsHandlerTest.java +++ b/sdm/src/test/java/unit/com/sap/cds/sdm/handler/applicationservice/SDMUpdateAttachmentsHandlerTest.java @@ -1,6 +1,5 @@ package unit.com.sap.cds.sdm.handler.applicationservice; -import static com.sap.cds.sdm.utilities.SDMUtils.isFileNameDuplicateInDrafts; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; @@ -113,12 +112,28 @@ public void testProcessBefore() throws IOException { @Test public void testRenameWithDuplicateFilenames() throws IOException { - try (MockedStatic cacheConfigMockedStatic = mockStatic(CacheConfig.class)) { + try (MockedStatic cacheConfigMockedStatic = mockStatic(CacheConfig.class); + MockedStatic attachmentsMockedStatic = + mockStatic(AttachmentsHandlerUtils.class)) { Cache mockCache = mock(Cache.class); cacheConfigMockedStatic.when(CacheConfig::getSecondaryPropertiesCache).thenReturn(mockCache); + // Prepare a data list with a mocked CdsData element (CdsData implements Map) List data = new ArrayList<>(); - Set duplicateFilenames = new HashSet<>(Arrays.asList("file1.txt", "file2.txt")); + CdsData mockCdsData = mock(CdsData.class); + data.add(mockCdsData); + + // Prepare attachments that contain duplicate file names + List> attachments = new ArrayList<>(); + Map attachment1 = new HashMap<>(); + attachment1.put("fileName", "file1.txt"); + attachment1.put("repositoryId", SDMConstants.REPOSITORY_ID); + Map attachment2 = new HashMap<>(); + attachment2.put("fileName", "file1.txt"); + attachment2.put("repositoryId", SDMConstants.REPOSITORY_ID); + attachments.add(attachment1); + attachments.add(attachment2); + when(context.getMessages()).thenReturn(messages); // Mock the target entity @@ -126,16 +141,21 @@ public void testRenameWithDuplicateFilenames() throws IOException { when(targetEntity.getQualifiedName()).thenReturn("TestEntity"); when(context.getTarget()).thenReturn(targetEntity); - sdmUtilsMockedStatic = mockStatic(SDMUtils.class); - sdmUtilsMockedStatic - .when(() -> isFileNameDuplicateInDrafts(data, "compositionName", "TestEntity")) - .thenReturn(duplicateFilenames); + // Make AttachmentsHandlerUtils.fetchAttachments return our attachments for any entity + attachmentsMockedStatic + .when( + () -> + AttachmentsHandlerUtils.fetchAttachments( + anyString(), any(Map.class), eq("compositionName"))) + .thenReturn(attachments); + // Call the method under test; SDMUtils.validateFileName will detect duplicates and call + // context.getMessages().error(...) handler.updateName(context, data, "compositionDefinition", "compositionName"); - verify(messages, times(1)) - .error( - "The file(s) file1.txt, file2.txt have been added multiple times. Please rename and try again."); + Set expected = new HashSet<>(); + expected.add("file1.txt"); + verify(messages, times(1)).error(SDMConstants.duplicateFilenameFormat(expected)); } } @@ -323,7 +343,7 @@ public void testRenameWithNoSDMRoles() throws IOException { .thenReturn(secondaryProperties); sdmUtilsMock - .when(() -> SDMUtils.isRestrictedCharactersInName(anyString())) + .when(() -> SDMUtils.hasRestrictedCharactersInName(anyString())) .thenReturn(false); // Call the method diff --git a/sdm/src/test/java/unit/com/sap/cds/sdm/service/handler/SDMAttachmentsServiceHandlerTest.java b/sdm/src/test/java/unit/com/sap/cds/sdm/service/handler/SDMAttachmentsServiceHandlerTest.java index 5d76393e..a873291c 100644 --- a/sdm/src/test/java/unit/com/sap/cds/sdm/service/handler/SDMAttachmentsServiceHandlerTest.java +++ b/sdm/src/test/java/unit/com/sap/cds/sdm/service/handler/SDMAttachmentsServiceHandlerTest.java @@ -439,7 +439,7 @@ public void testCreateNonVersionedDIDuplicate() throws IOException { // Mock SDMUtils.isRestrictedCharactersInName sdmUtilsMockedStatic - .when(() -> SDMUtils.isRestrictedCharactersInName(anyString())) + .when(() -> SDMUtils.hasRestrictedCharactersInName(anyString())) .thenReturn(false); // Return false to indicate no restricted characters when(mockContext.getAttachmentEntity()).thenReturn(mockDraftEntity); @@ -674,6 +674,10 @@ public void testCreateNonVersionedDIUnauthorizedI18n() throws IOException { .thenReturn(SDMConstants.USER_NOT_AUTHORISED_ERROR); when(mockContext.getParameterInfo()).thenReturn(parameterInfo); when(parameterInfo.getHeaders()).thenReturn(headers); + // Ensure filename is present so handler's own validateFileName doesn't throw whitespace error + when(mockContext.getData()).thenReturn(mockMediaData); + when(mockMediaData.get("fileName")).thenReturn("test.txt"); + when(mockMediaData.getFileName()).thenReturn("test.txt"); // Mock the behavior of createDocument and other dependencies when(documentUploadService.createDocument(any(), any(), anyBoolean())) @@ -691,6 +695,9 @@ public void testCreateNonVersionedDIUnauthorizedI18n() throws IOException { sdmUtilsMockedStatic .when(() -> SDMUtils.getAttachmentCountAndMessage(anyList(), any())) .thenReturn("10__null"); + sdmUtilsMockedStatic + .when(() -> SDMUtils.validateFileNames(any(), any(), any())) + .thenReturn(false); // Assert that a ServiceException is thrown and verify its message ServiceException thrown = @@ -710,8 +717,11 @@ public void testCreateNonVersionedDIUnauthorized() throws IOException { mockAttachmentIds.put("up__ID", "upid"); mockAttachmentIds.put("ID", "id"); mockAttachmentIds.put("repositoryId", "repo1"); + mockAttachmentIds.put("fileName", "test.txt"); MediaData mockMediaData = mock(MediaData.class); + when(mockMediaData.get("fileName")).thenReturn("test.txt"); + when(mockMediaData.getFileName()).thenReturn("test.txt"); Result mockResult = mock(Result.class); List nonEmptyRowList = List.of(mock(Row.class)); CdsEntity mockDraftEntity = mock(CdsEntity.class); @@ -719,6 +729,8 @@ public void testCreateNonVersionedDIUnauthorized() throws IOException { CdsElement mockAssociationElement = mock(CdsElement.class); CdsAssociationType mockAssociationType = mock(CdsAssociationType.class); CqnElementRef mockCqnElementRef = mock(CqnElementRef.class); + byte[] byteArray = "Test content".getBytes(); + InputStream contentStream = new ByteArrayInputStream(byteArray); // Set up the JSON response for the "unauthorized" case JSONObject mockCreateResult = new JSONObject(); @@ -746,6 +758,10 @@ public void testCreateNonVersionedDIUnauthorized() throws IOException { .thenReturn("Unauthorised error german"); when(mockContext.getParameterInfo()).thenReturn(parameterInfo); when(parameterInfo.getHeaders()).thenReturn(headers); + when(mockMediaData.getContent()).thenReturn(contentStream); + when(mockContext.getAuthenticationInfo()).thenReturn(mockAuthInfo); + when(mockAuthInfo.as(JwtTokenAuthenticationInfo.class)).thenReturn(mockJwtTokenInfo); + when(mockJwtTokenInfo.getToken()).thenReturn("mockedJwtToken"); // Mock the behavior of createDocument and other dependencies when(documentUploadService.createDocument(any(), any(), anyBoolean())) @@ -762,7 +778,13 @@ public void testCreateNonVersionedDIUnauthorized() throws IOException { try (MockedStatic sdmUtilsMockedStatic = mockStatic(SDMUtils.class)) { sdmUtilsMockedStatic .when(() -> SDMUtils.getAttachmentCountAndMessage(anyList(), any())) - .thenReturn("10__null"); + .thenReturn("0__null"); + sdmUtilsMockedStatic + .when(() -> SDMUtils.hasRestrictedCharactersInName(anyString())) + .thenReturn(false); + sdmUtilsMockedStatic + .when(() -> SDMUtils.validateFileNames(any(), any(), any())) + .thenReturn(true); // Assert that a ServiceException is thrown and verify its message ServiceException thrown = @@ -782,8 +804,11 @@ public void testCreateNonVersionedDIBlocked() throws IOException { mockAttachmentIds.put("up__ID", "upid"); mockAttachmentIds.put("ID", "id"); mockAttachmentIds.put("repositoryId", "repo1"); + mockAttachmentIds.put("fileName", "test.txt"); MediaData mockMediaData = mock(MediaData.class); + when(mockMediaData.get("fileName")).thenReturn("test.txt"); + when(mockMediaData.getFileName()).thenReturn("test.txt"); Result mockResult = mock(Result.class); List nonEmptyRowList = List.of(mock(Row.class)); CdsEntity mockDraftEntity = mock(CdsEntity.class); @@ -791,6 +816,8 @@ public void testCreateNonVersionedDIBlocked() throws IOException { CdsElement mockAssociationElement = mock(CdsElement.class); CdsAssociationType mockAssociationType = mock(CdsAssociationType.class); CqnElementRef mockCqnElementRef = mock(CqnElementRef.class); + byte[] byteArray = "Test content".getBytes(); + InputStream contentStream = new ByteArrayInputStream(byteArray); // Set up the JSON response for the "blocked" case JSONObject mockCreateResult = new JSONObject(); @@ -812,6 +839,7 @@ public void testCreateNonVersionedDIBlocked() throws IOException { when(userInfo.getTenant()).thenReturn("t1"); when(sdmService.checkRepositoryType(anyString(), anyString())).thenReturn(repoValue); when(mockContext.getData()).thenReturn(mockMediaData); + when(mockMediaData.getContent()).thenReturn(contentStream); when(mockContext.getAttachmentEntity()).thenReturn(mockDraftEntity); when(mockDraftEntity.getQualifiedName()).thenReturn("some.qualified.name"); when(mockContext.getCdsRuntime()).thenReturn(cdsRuntime); @@ -819,6 +847,9 @@ public void testCreateNonVersionedDIBlocked() throws IOException { .thenReturn(SDMConstants.MIMETYPE_INVALID_ERROR); when(mockContext.getParameterInfo()).thenReturn(parameterInfo); when(parameterInfo.getHeaders()).thenReturn(headers); + when(mockContext.getAuthenticationInfo()).thenReturn(mockAuthInfo); + when(mockAuthInfo.as(JwtTokenAuthenticationInfo.class)).thenReturn(mockJwtTokenInfo); + when(mockJwtTokenInfo.getToken()).thenReturn("mockedJwtToken"); // Mock the behavior of createDocument and other dependencies when(documentUploadService.createDocument(any(), any(), anyBoolean())) @@ -835,7 +866,13 @@ public void testCreateNonVersionedDIBlocked() throws IOException { try (MockedStatic sdmUtilsMockedStatic = mockStatic(SDMUtils.class)) { sdmUtilsMockedStatic .when(() -> SDMUtils.getAttachmentCountAndMessage(anyList(), any())) - .thenReturn("10__null"); + .thenReturn("0__null"); + sdmUtilsMockedStatic + .when(() -> SDMUtils.hasRestrictedCharactersInName(anyString())) + .thenReturn(false); + sdmUtilsMockedStatic + .when(() -> SDMUtils.validateFileNames(any(), any(), any())) + .thenReturn(true); // Assert that a ServiceException is thrown and verify its message ServiceException thrown = @@ -1170,7 +1207,7 @@ public void testCreateNonVersionedNameConstraint() throws IOException { .thenReturn("0__null"); when(tokenHandler.getSDMCredentials()).thenReturn(mockSdmCredentials); sdmUtilsMockedStatic - .when(() -> SDMUtils.isRestrictedCharactersInName(anyString())) + .when(() -> SDMUtils.hasRestrictedCharactersInName(anyString())) .thenReturn(true); // Use assertThrows to expect a ServiceException and validate the message @@ -1183,7 +1220,7 @@ public void testCreateNonVersionedNameConstraint() throws IOException { // Verify the exception message assertEquals( - SDMConstants.nameConstraintMessage(Collections.singletonList("sample@.pdf"), "Upload"), + SDMConstants.nameConstraintMessage(Collections.singletonList("sample@.pdf")), thrown.getMessage()); } } @@ -1250,14 +1287,14 @@ public void testFolderDeletion() throws IOException { void testDuplicateCheck_NoDuplicates() { Result result = mock(Result.class); - // Mocking a raw list of maps + // Mocking a raw list of maps to match Result.listOf(Map.class) expectation + @SuppressWarnings("rawtypes") List mockedResultList = new ArrayList<>(); Map map1 = new HashMap<>(); map1.put("key1", "value1"); mockedResultList.add(map1); - // Casting to raw types to avoid type mismatch - when(result.listOf(Map.class)).thenReturn((List) mockedResultList); + when(result.listOf(Map.class)).thenReturn(mockedResultList); String filename = "sample.pdf"; String fileid = "123"; @@ -1265,8 +1302,9 @@ void testDuplicateCheck_NoDuplicates() { attachment.put("fileName", filename); attachment.put("ID", fileid); + @SuppressWarnings("rawtypes") List resultList = Arrays.asList((Map) attachment); - when(result.listOf(Map.class)).thenReturn((List) resultList); + when(result.listOf(Map.class)).thenReturn(resultList); boolean isDuplicate = handlerSpy.duplicateCheck(filename, fileid, result); assertFalse(isDuplicate, "Expected no duplicates"); @@ -1279,8 +1317,9 @@ void testDuplicateCheck_WithDuplicate() { sdmUtilsMockedStatic .when(() -> SDMUtils.getAttachmentCountAndMessage(anyList(), any())) .thenReturn("0__null"); - // Mocking a raw list of maps - List mockedResultList = new ArrayList<>(); + + // Initialize list with proper generic type + List> mockedResultList = new ArrayList<>(); // Creating a map with duplicate filename but different file ID Map attachment1 = new HashMap<>(); @@ -1291,11 +1330,13 @@ void testDuplicateCheck_WithDuplicate() { attachment2.put("fileName", "sample.pdf"); attachment2.put("ID", "456"); // Same filename but different ID (this is the duplicate) attachment2.put("repositoryId", SDMConstants.REPOSITORY_ID); - mockedResultList.add((Map) attachment1); - mockedResultList.add((Map) attachment2); + mockedResultList.add(attachment1); + mockedResultList.add(attachment2); - // Mocking the result to return the list containing the attachments - when(result.listOf(Map.class)).thenReturn((List) mockedResultList); + // Mock with proper type casting + @SuppressWarnings("unchecked") + List typedList = (List) (List) mockedResultList; + when(result.listOf(Map.class)).thenReturn(typedList); String filename = "sample.pdf"; String fileid = "123"; // The fileid to check, same as attachment1, different from attachment2 @@ -1610,7 +1651,6 @@ public void testMaxCountError() throws IOException { @Test public void throwAttachmetDraftEntityException() throws IOException { - when(eventContext.getUserInfo()).thenReturn(userInfo); when(userInfo.getTenant()).thenReturn("t123"); RepoValue repoValue = new RepoValue(); @@ -1625,12 +1665,14 @@ public void throwAttachmetDraftEntityException() throws IOException { when(parameterInfo.getHeaders()).thenReturn(headers); when(cdsModel.findEntity(anyString())) .thenThrow(new ServiceException(SDMConstants.DRAFT_NOT_FOUND)); + ServiceException thrown = assertThrows( ServiceException.class, () -> { handlerSpy.createAttachment(mockContext); }); + assertEquals(SDMConstants.DRAFT_NOT_FOUND, thrown.getMessage()); } @Test diff --git a/sdm/src/test/java/unit/com/sap/cds/sdm/service/handler/SDMServiceGenericHandlerTest.java b/sdm/src/test/java/unit/com/sap/cds/sdm/service/handler/SDMServiceGenericHandlerTest.java index 29a2be32..ebf82565 100644 --- a/sdm/src/test/java/unit/com/sap/cds/sdm/service/handler/SDMServiceGenericHandlerTest.java +++ b/sdm/src/test/java/unit/com/sap/cds/sdm/service/handler/SDMServiceGenericHandlerTest.java @@ -190,7 +190,7 @@ void testCreate_shouldCreateLink() throws IOException { sdmUtilsMock .when(() -> SDMUtils.getAttachmentCountAndMessage(anyList(), any())) .thenReturn("10__null"); - sdmUtilsMock.when(() -> SDMUtils.isRestrictedCharactersInName(anyString())).thenReturn(false); + sdmUtilsMock.when(() -> SDMUtils.hasRestrictedCharactersInName(anyString())).thenReturn(false); RepoValue repoValue = new RepoValue(); repoValue.setVirusScanEnabled(false); repoValue.setVersionEnabled(false); @@ -296,7 +296,7 @@ void testCreate_ShouldThrowSpecifiedExceptionWhenMaxCountReached() throws IOExce sdmUtilsMock .when(() -> SDMUtils.getAttachmentCountAndMessage(anyList(), any())) .thenReturn("2__Maximum two links allowed"); - sdmUtilsMock.when(() -> SDMUtils.isRestrictedCharactersInName(anyString())).thenReturn(false); + sdmUtilsMock.when(() -> SDMUtils.hasRestrictedCharactersInName(anyString())).thenReturn(false); RepoValue repoValue = new RepoValue(); repoValue.setVirusScanEnabled(false); repoValue.setVersionEnabled(false); @@ -357,7 +357,7 @@ void testCreate_ShouldThrowDefaultExceptionWhenMaxCountReached() throws IOExcept sdmUtilsMock .when(() -> SDMUtils.getAttachmentCountAndMessage(anyList(), any())) .thenReturn("2__"); - sdmUtilsMock.when(() -> SDMUtils.isRestrictedCharactersInName(anyString())).thenReturn(false); + sdmUtilsMock.when(() -> SDMUtils.hasRestrictedCharactersInName(anyString())).thenReturn(false); RepoValue repoValue = new RepoValue(); repoValue.setVirusScanEnabled(false); repoValue.setVersionEnabled(false); @@ -418,7 +418,7 @@ void testCreate_ShouldThrowExceptionWhenRestrictedCharacterInLinkName() throws I sdmUtilsMock .when(() -> SDMUtils.getAttachmentCountAndMessage(anyList(), any())) .thenReturn("10__null"); - sdmUtilsMock.when(() -> SDMUtils.isRestrictedCharactersInName(anyString())).thenReturn(true); + sdmUtilsMock.when(() -> SDMUtils.hasRestrictedCharactersInName(anyString())).thenReturn(true); RepoValue repoValue = new RepoValue(); repoValue.setVirusScanEnabled(false); repoValue.setVersionEnabled(false); @@ -427,8 +427,7 @@ void testCreate_ShouldThrowExceptionWhenRestrictedCharacterInLinkName() throws I ServiceException ex = assertThrows(ServiceException.class, () -> sdmServiceGenericHandler.create(mockContext)); assertEquals( - SDMConstants.linkNameConstraintMessage(Collections.singletonList("test/URL"), "created"), - ex.getMessage()); + SDMConstants.nameConstraintMessage(Collections.singletonList("test/URL")), ex.getMessage()); } @Test @@ -483,7 +482,7 @@ void testCreate_ThrowsServiceExceptionOnDuplicateFile() throws IOException { sdmUtilsMock .when(() -> SDMUtils.getAttachmentCountAndMessage(anyList(), any())) .thenReturn("10__null"); - sdmUtilsMock.when(() -> SDMUtils.isRestrictedCharactersInName(anyString())).thenReturn(false); + sdmUtilsMock.when(() -> SDMUtils.hasRestrictedCharactersInName(anyString())).thenReturn(false); RepoValue repoValue = new RepoValue(); repoValue.setVirusScanEnabled(false); repoValue.setVersionEnabled(false); @@ -543,7 +542,7 @@ void testCreate_ThrowsServiceException_WhenCreateDocumentThrowsException() throw sdmUtilsMock .when(() -> SDMUtils.getAttachmentCountAndMessage(anyList(), any())) .thenReturn("10__null"); - sdmUtilsMock.when(() -> SDMUtils.isRestrictedCharactersInName(anyString())).thenReturn(false); + sdmUtilsMock.when(() -> SDMUtils.hasRestrictedCharactersInName(anyString())).thenReturn(false); RepoValue repoValue = new RepoValue(); repoValue.setVirusScanEnabled(false); repoValue.setVersionEnabled(false); @@ -614,7 +613,7 @@ void testCreate_ThrowsServiceExceptionOnDuplicateStatus() throws IOException { sdmUtilsMock .when(() -> SDMUtils.getAttachmentCountAndMessage(anyList(), any())) .thenReturn("10__null"); - sdmUtilsMock.when(() -> SDMUtils.isRestrictedCharactersInName(anyString())).thenReturn(false); + sdmUtilsMock.when(() -> SDMUtils.hasRestrictedCharactersInName(anyString())).thenReturn(false); RepoValue repoValue = new RepoValue(); repoValue.setVirusScanEnabled(false); repoValue.setVersionEnabled(false); @@ -686,7 +685,7 @@ void testCreate_ThrowsServiceExceptionOnFailStatus() throws IOException { sdmUtilsMock .when(() -> SDMUtils.getAttachmentCountAndMessage(anyList(), any())) .thenReturn("10__null"); - sdmUtilsMock.when(() -> SDMUtils.isRestrictedCharactersInName(anyString())).thenReturn(false); + sdmUtilsMock.when(() -> SDMUtils.hasRestrictedCharactersInName(anyString())).thenReturn(false); RepoValue repoValue = new RepoValue(); repoValue.setVirusScanEnabled(false); repoValue.setVersionEnabled(false); @@ -757,7 +756,7 @@ void testCreate_ThrowsServiceExceptionOnUnauthorizedStatus() throws IOException sdmUtilsMock .when(() -> SDMUtils.getAttachmentCountAndMessage(anyList(), any())) .thenReturn("10__null"); - sdmUtilsMock.when(() -> SDMUtils.isRestrictedCharactersInName(anyString())).thenReturn(false); + sdmUtilsMock.when(() -> SDMUtils.hasRestrictedCharactersInName(anyString())).thenReturn(false); RepoValue repoValue = new RepoValue(); repoValue.setVirusScanEnabled(false); repoValue.setVersionEnabled(false); @@ -1175,7 +1174,7 @@ void testCreateLink_AttachmentCountConstraintExceeded() throws IOException { sdmUtilsMock .when(() -> SDMUtils.getAttachmentCountAndMessage(anyList(), any())) .thenReturn("3__Maximum attachments exceeded"); // Max 3, current 5 - sdmUtilsMock.when(() -> SDMUtils.isRestrictedCharactersInName(anyString())).thenReturn(false); + sdmUtilsMock.when(() -> SDMUtils.hasRestrictedCharactersInName(anyString())).thenReturn(false); RepoValue repoValue = new RepoValue(); repoValue.setVirusScanEnabled(false); @@ -1229,7 +1228,7 @@ void testCreateLink_RestrictedCharactersInName() throws IOException { sdmUtilsMock .when(() -> SDMUtils.getAttachmentCountAndMessage(anyList(), any())) .thenReturn("10__null"); - sdmUtilsMock.when(() -> SDMUtils.isRestrictedCharactersInName(anyString())).thenReturn(true); + sdmUtilsMock.when(() -> SDMUtils.hasRestrictedCharactersInName(anyString())).thenReturn(true); RepoValue repoValue = new RepoValue(); repoValue.setVirusScanEnabled(false); @@ -1287,7 +1286,7 @@ void testCreateLink_UnauthorizedError() throws IOException { sdmUtilsMock .when(() -> SDMUtils.getAttachmentCountAndMessage(anyList(), any())) .thenReturn("10__null"); - sdmUtilsMock.when(() -> SDMUtils.isRestrictedCharactersInName(anyString())).thenReturn(false); + sdmUtilsMock.when(() -> SDMUtils.hasRestrictedCharactersInName(anyString())).thenReturn(false); RepoValue repoValue = new RepoValue(); repoValue.setVirusScanEnabled(false); diff --git a/sdm/src/test/java/unit/com/sap/cds/sdm/utilities/SDMUtilsTest.java b/sdm/src/test/java/unit/com/sap/cds/sdm/utilities/SDMUtilsTest.java index dedb2f5e..600c55ba 100644 --- a/sdm/src/test/java/unit/com/sap/cds/sdm/utilities/SDMUtilsTest.java +++ b/sdm/src/test/java/unit/com/sap/cds/sdm/utilities/SDMUtilsTest.java @@ -19,6 +19,7 @@ import com.sap.cds.reflect.*; import com.sap.cds.sdm.caching.CacheConfig; import com.sap.cds.sdm.constants.SDMConstants; +import com.sap.cds.sdm.handler.applicationservice.helper.AttachmentsHandlerUtils; import com.sap.cds.sdm.persistence.DBQuery; import com.sap.cds.sdm.utilities.SDMUtils; import com.sap.cds.services.persistence.PersistenceService; @@ -97,49 +98,55 @@ public void testIsFileNameDuplicateInDrafts() { @Test public void testIsFileNameContainsRestrictedCharaters() { List data = new ArrayList<>(); - CdsData mockCdsData = mock(CdsData.class); - - when(mockCdsData.get("attachments")).thenReturn(null); // Correctly mock get method - data.add(mockCdsData); + Map entity = new HashMap<>(); + List> attachments = new ArrayList<>(); + Map attachment = new HashMap<>(); + attachment.put("fileName", "file/1.txt"); // restricted char + attachments.add(attachment); + entity.put("composition", attachments); + data.add(CdsData.create(entity)); - List restrictedFilenames = SDMUtils.isFileNameContainsRestrictedCharaters(data); + try (MockedStatic mocked = mockStatic(AttachmentsHandlerUtils.class)) { + mocked + .when( + () -> + AttachmentsHandlerUtils.fetchAttachments("TestEntity", entity, "compositionName")) + .thenReturn(attachments); - assertEquals(0, restrictedFilenames.size()); + List result = + SDMUtils.isFileNameContainsRestrictedCharaters(data, "compositionName", "TestEntity"); + assertTrue(result.contains("file/1.txt")); + } } @Test public void testIsFileNameContainsRestrictedCharatersNoData() { List data = new ArrayList<>(); - CdsData mockCdsData = mock(CdsData.class); Map entity = new HashMap<>(); - List> attachments = new ArrayList<>(); - - Map attachment1 = new HashMap<>(); - attachment1.put("fileName", "file1.txt"); - Map attachment2 = new HashMap<>(); - attachment2.put("fileName", "file2/abc.txt"); - Map attachment3 = new HashMap<>(); - attachment3.put("fileName", "file3\\abc.txt"); - attachments.add(attachment1); - attachments.add(attachment2); - attachments.add(attachment3); - entity.put("attachments", attachments); - when(mockCdsData.get("attachments")).thenReturn(attachments); // Correctly mock get method - data.add(mockCdsData); + entity.put("composition", new ArrayList<>()); + data.add(CdsData.create(entity)); - List restrictedFilenames = SDMUtils.isFileNameContainsRestrictedCharaters(data); + try (MockedStatic mocked = mockStatic(AttachmentsHandlerUtils.class)) { + mocked + .when( + () -> + AttachmentsHandlerUtils.fetchAttachments("TestEntity", entity, "compositionName")) + .thenReturn(Collections.emptyList()); - assertEquals(2, restrictedFilenames.size()); - assertTrue(restrictedFilenames.contains("file2/abc.txt")); - assertTrue(restrictedFilenames.contains("file3\\abc.txt")); + List result = + SDMUtils.isFileNameContainsRestrictedCharaters(data, "compositionName", "TestEntity"); + assertTrue(result.isEmpty()); + } } @Test public void testIsRestrictedCharactersInName() { - assertTrue(SDMUtils.isRestrictedCharactersInName("file/abc.txt")); - assertTrue(SDMUtils.isRestrictedCharactersInName("file\\abc.txt")); - assertFalse(SDMUtils.isRestrictedCharactersInName("file-abc.txt")); - assertFalse(SDMUtils.isRestrictedCharactersInName("file_abc.txt")); + assertTrue(SDMUtils.hasRestrictedCharactersInName("file/abc.txt")); + assertTrue(SDMUtils.hasRestrictedCharactersInName("file\\abc.txt")); + assertFalse(SDMUtils.hasRestrictedCharactersInName("file-abc.txt")); + assertFalse(SDMUtils.hasRestrictedCharactersInName("file_abc.txt")); + assertFalse(SDMUtils.hasRestrictedCharactersInName("")); + assertFalse(SDMUtils.hasRestrictedCharactersInName(null)); } @Test