diff --git a/sdm/pom.xml b/sdm/pom.xml index 1d9fce31b..f75d53660 100644 --- a/sdm/pom.xml +++ b/sdm/pom.xml @@ -29,7 +29,7 @@ sdm - 7.6.0 + 8.9.8 com.sap.cds.sdm.generated src/test/gen 17 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 a0ca8b8b6..507658c4d 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,9 @@ package com.sap.cds.sdm.constants; +import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; public class SDMConstants { private SDMConstants() { @@ -81,25 +83,32 @@ private SDMConstants() { public static final String FAILED_TO_FETCH_UP_ID = "Failed to fetch up_id"; public static final String FAILED_TO_FETCH_FACET = "Invalid facet format, unable to extract required information."; + public static final String FILENAME_WHITESPACE_WARNING_MESSAGE = + "The file name cannot be empty or consist entirely of space characters. Enter a value."; - 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"; + // Helper Methods to create error/warning messages + public static String buildErrorMessage( + Collection filenames, String operation, String prefixTemplate) { + String closingRemark = "Rename the files and try again."; + StringBuilder message = new StringBuilder(String.format(prefixTemplate, operation)); - // Create the formatted prefix message - String formattedPrefixMessage = String.format(prefixMessage, operation); + for (String file : filenames) { + message.append(String.format("\t• %s%n", file)); + } + message.append("\n ").append(closingRemark); + return message.toString(); + } - // Initialize the StringBuilder with the formatted message prefix - StringBuilder bulletPoints = new StringBuilder(formattedPrefixMessage); + public static String nameConstraintMessage(List invalidFileNames, String operation) { + String prefix = + "%s unsuccessful. The following filename(s) contain unsupported characters (/, \\). \n\n"; + return buildErrorMessage(invalidFileNames, operation, prefix); + } - // Append each unsupported file name to the StringBuilder - for (String file : fileNameWithRestrictedCharacters) { - bulletPoints.append(String.format("\t• %s%n", file)); - } - bulletPoints.append("\nRename the files and try again."); - return bulletPoints.toString(); + public static String duplicateFilenameFormat(Set duplicateFileNames, String operation) { + String prefix = + "%s unsuccessful. The following filename(s) have been added multiple times. \n\n"; + return buildErrorMessage(duplicateFileNames, operation, prefix); } public static String linkNameConstraintMessage( 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 4543250f4..988d687d4 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 @@ -62,15 +62,15 @@ public void updateName(CdsCreateEventContext context, List data, String throws IOException { Map propertyTitles = new HashMap<>(); Map secondaryPropertiesWithInvalidDefinitions = new HashMap<>(); - Set duplicateFilenames = SDMUtils.isFileNameDuplicateInDrafts(data, composition); - if (!duplicateFilenames.isEmpty()) { - handleDuplicateFilenames(context, duplicateFilenames); - } else { + Boolean isError = false; + isError = SDMUtils.validateFileName(context, data, composition, "Create"); + if (!isError) { List fileNameWithRestrictedCharacters = new ArrayList<>(); List duplicateFileNameList = new ArrayList<>(); List filesNotFound = new ArrayList<>(); List filesWithUnsupportedProperties = new ArrayList<>(); Map badRequest = new HashMap<>(); + List fileWithWhiteSpace = new ArrayList<>(); List noSDMRoles = new ArrayList<>(); for (Map entity : data) { List> attachments = (List>) entity.get(composition); @@ -95,7 +95,8 @@ public void updateName(CdsCreateEventContext context, List data, String composition, attachmentEntity, secondaryPropertiesWithInvalidDefinitions, - noSDMRoles); + noSDMRoles, + fileWithWhiteSpace); handleWarnings( context, fileNameWithRestrictedCharacters, @@ -104,7 +105,8 @@ public void updateName(CdsCreateEventContext context, List data, String filesWithUnsupportedProperties, badRequest, propertyTitles, - noSDMRoles); + noSDMRoles, + fileWithWhiteSpace); } } } @@ -130,7 +132,8 @@ private void processEntity( String composition, Optional attachmentEntity, Map secondaryPropertiesWithInvalidDefinitions, - List noSDMRoles) + List noSDMRoles, + List fileWithWhiteSpace) throws IOException { List> attachments = (List>) entity.get(composition); if (attachments != null) { @@ -146,7 +149,8 @@ private void processEntity( composition, attachmentEntity, secondaryPropertiesWithInvalidDefinitions, - noSDMRoles); + noSDMRoles, + fileWithWhiteSpace); } SecondaryPropertiesKey secondaryPropertiesKey = new SecondaryPropertiesKey(); // Emptying cache after attachments are updated in loop @@ -166,7 +170,8 @@ private void processAttachment( String composition, Optional attachmentEntity, Map secondaryPropertiesWithInvalidDefinitions, - List noSDMRoles) + List noSDMRoles, + List fileWithWhiteSpace) throws IOException { String id = (String) attachment.get("ID"); String fileNameInDB; @@ -224,14 +229,17 @@ private void processAttachment( 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) { + if (filenameInRequest != null && !filenameInRequest.isBlank()) { updatedSecondaryProperties.put("filename", filenameInRequest); } else { throw new ServiceException("Filename cannot be empty"); } } else { - if (filenameInRequest == null) { - throw new ServiceException("Filename cannot be empty"); + if (filenameInRequest == null || filenameInRequest.trim().length() == 0) { + fileWithWhiteSpace.add(fileNameInDB); + replacePropertiesInAttachment( + attachment, fileNameInDB, propertiesInDB, secondaryTypeProperties); + } 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 @@ -322,7 +330,8 @@ private void handleWarnings( List filesWithUnsupportedProperties, Map badRequest, Map propertyTitles, - List noSDMRoles) { + List noSDMRoles, + List fileWithWhiteSpace) { if (!fileNameWithRestrictedCharacters.isEmpty()) { context .getMessages() @@ -363,6 +372,14 @@ private void handleWarnings( if (!noSDMRoles.isEmpty()) { context.getMessages().warn(SDMConstants.noSDMRolesMessage(noSDMRoles, "create")); } + if (!fileWithWhiteSpace.isEmpty()) { + context + .getMessages() + .warn( + String.format( + SDMConstants.FILENAME_WHITESPACE_WARNING_MESSAGE, + String.join(", ", fileWithWhiteSpace))); + } } private List getEntityCompositions(CdsCreateEventContext context) { 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 c40d6968d..f4a51017a 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 @@ -54,15 +54,9 @@ public void processBefore(CdsUpdateEventContext context, List data) thr public void updateName(CdsUpdateEventContext context, List data, String composition) throws IOException { - Set duplicateFilenames = SDMUtils.isFileNameDuplicateInDrafts(data, composition); - if (!duplicateFilenames.isEmpty()) { - context - .getMessages() - .error( - String.format( - SDMConstants.DUPLICATE_FILE_IN_DRAFT_ERROR_MESSAGE, - String.join(", ", duplicateFilenames))); - } else { + Boolean isError = false; + isError = SDMUtils.validateFileName(context, data, composition, "Update"); + if (!isError) { Optional attachmentEntity = context.getModel().findEntity(context.getTarget().getQualifiedName() + "." + composition); renameDocument(attachmentEntity, context, data, composition); @@ -83,6 +77,7 @@ private void renameDocument( Map badRequest = new HashMap<>(); Map propertyTitles = new HashMap<>(); List noSDMRoles = new ArrayList<>(); + List fileWithWhiteSpace = new ArrayList<>(); for (Map entity : data) { List> attachments = (List>) entity.get(composition); if (attachments != null && !attachments.isEmpty()) { @@ -109,7 +104,8 @@ private void renameDocument( filesWithUnsupportedProperties, badRequest, secondaryPropertiesWithInvalidDefinitions, - noSDMRoles); + noSDMRoles, + fileWithWhiteSpace); } } handleWarnings( @@ -120,7 +116,8 @@ private void renameDocument( filesWithUnsupportedProperties, badRequest, propertyTitles, - noSDMRoles); + noSDMRoles, + fileWithWhiteSpace); } private void processAttachments( @@ -133,7 +130,8 @@ private void processAttachments( List filesWithUnsupportedProperties, Map badRequest, Map secondaryPropertiesWithInvalidDefinitions, - List noSDMRoles) + List noSDMRoles, + List fileWithWhiteSpace) throws IOException { Iterator> iterator = attachments.iterator(); while (iterator.hasNext()) { @@ -148,7 +146,8 @@ private void processAttachments( filesWithUnsupportedProperties, badRequest, secondaryPropertiesWithInvalidDefinitions, - noSDMRoles); + noSDMRoles, + fileWithWhiteSpace); } SecondaryPropertiesKey secondaryPropertiesKey = new SecondaryPropertiesKey(); secondaryPropertiesKey.setRepositoryId(SDMConstants.REPOSITORY_ID); @@ -168,7 +167,8 @@ public void processAttachment( List filesWithUnsupportedProperties, Map badRequest, Map secondaryPropertiesWithInvalidDefinitions, - List noSDMRoles) + List noSDMRoles, + List fileWithWhiteSpace) throws IOException { String id = (String) attachment.get("ID"); Map secondaryTypeProperties = @@ -222,8 +222,10 @@ public void processAttachment( throw new ServiceException("Filename cannot be empty"); } } else { - if (filenameInRequest == null) { - throw new ServiceException("Filename cannot be empty"); + if (filenameInRequest == null || filenameInRequest.trim().length() == 0) { + fileWithWhiteSpace.add(fileNameInDB); + replacePropertiesInAttachment( + attachment, fileNameInDB, propertiesInDB, secondaryTypeProperties); } else if (!fileNameInDB.equals(filenameInRequest)) { updatedSecondaryProperties.put("filename", filenameInRequest); } @@ -313,7 +315,8 @@ private void handleWarnings( List filesWithUnsupportedProperties, Map badRequest, Map propertyTitles, - List noSDMRoles) { + List noSDMRoles, + List fileWithWhiteSpace) { if (!fileNameWithRestrictedCharacters.isEmpty()) { context .getMessages() @@ -353,6 +356,14 @@ private void handleWarnings( if (!noSDMRoles.isEmpty()) { context.getMessages().warn(SDMConstants.noSDMRolesMessage(noSDMRoles, "update")); } + if (!fileWithWhiteSpace.isEmpty()) { + context + .getMessages() + .warn( + String.format( + SDMConstants.FILENAME_WHITESPACE_WARNING_MESSAGE, + String.join(", ", fileWithWhiteSpace))); + } } private List getEntityCompositions(CdsUpdateEventContext context) { 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 bf073caba..806a2405f 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 @@ -7,6 +7,7 @@ import com.sap.cds.sdm.caching.CacheConfig; import com.sap.cds.sdm.constants.SDMConstants; 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; @@ -32,6 +33,53 @@ private SDMUtils() { // Doesn't do anything } + public static Boolean validateFileName( + EventContext context, List data, String composition, String operation) { + Boolean isError = false; + + // Validation for file names + Set whitespaceFilenames = isFileNameContainsWhitespace(data, composition); + List restrictedFileNames = isFileNameContainsRestrictedCharaters(data); + Set duplicateFilenames = isFileNameDuplicateInDrafts(data, composition); + + // Collecting all the errors + if (whitespaceFilenames != null && !whitespaceFilenames.isEmpty()) { + context.getMessages().error(SDMConstants.FILENAME_WHITESPACE_WARNING_MESSAGE); + isError = true; + } + if (restrictedFileNames != null && !restrictedFileNames.isEmpty()) { + context + .getMessages() + .error(SDMConstants.nameConstraintMessage(restrictedFileNames, operation)); + isError = true; + } + if (duplicateFilenames != null && !duplicateFilenames.isEmpty()) { + String formattedMessage = + String.format(SDMConstants.duplicateFilenameFormat(duplicateFilenames, operation)); + context.getMessages().error(formattedMessage); + } + // returning the error message + return isError; + } + + public static Set isFileNameContainsWhitespace(List data, String composition) { + Set filenamesWithWhitespace = new HashSet<>(); + for (Map entity : data) { + List> attachments = (List>) entity.get(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) { Set uniqueFilenames = new HashSet<>(); Set duplicateFilenames = new HashSet<>(); @@ -42,10 +90,12 @@ public static Set isFileNameDuplicateInDrafts(List data, String 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); + } } } } @@ -72,6 +122,9 @@ public static List isFileNameContainsRestrictedCharaters(List d } public static boolean isRestrictedCharactersInName(String cmisName) { + if (cmisName == null || cmisName.isBlank()) { + 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 afee9092a..f1f616a92 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 @@ -524,8 +524,41 @@ void testRenameEntities() { @Test @Order(9) + void testRenameWhitespaceInAttachment() throws IOException { + System.out.println("Test (9) : Rename attachment, reference, and footnote with whitespace"); + Boolean testStatus = false; + String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID); + if (response.equals("Entity in draft mode")) { + String name = " "; + for (int i = 0; i < facet.length; i++) { + response = api.renameAttachment(appUrl, entityName, facet[i], entityID, ID[i], name); + if (response.equals("Renamed")) { + counter++; + } + } + if (counter >= 2) { + response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID); + String expected = + "[{\"code\":\"\",\"message\":\"The file name cannot be empty or consist entirely of space characters. Enter a value.\",\"numericSeverity\":3}," + + "{\"code\":\"\",\"message\":\"The file name cannot be empty or consist entirely of space characters. Enter a value.\",\"numericSeverity\":3}," + + "{\"code\":\"\",\"message\":\"The file name cannot be empty or consist entirely of space characters. Enter a value.\",\"numericSeverity\":3}]"; + if (response.equals(expected)) { + testStatus = true; + counter = -1; // Reset counter for the next check + } + } else { + api.saveEntityDraft(appUrl, entityName, srvpath, entityID); + } + } + if (!testStatus) { + fail("Attachment was renamed with whitespace"); + } + } + + @Test + @Order(10) void testCreateEntitiesWithUnsupportedCharacter() throws IOException { - System.out.println("Test (9): Create attachments with unsupported characters"); + System.out.println("Test (10): Create attachments with unsupported characters"); boolean testStatus = false; ClassLoader classLoader = getClass().getClassLoader(); @@ -582,9 +615,9 @@ void testCreateEntitiesWithUnsupportedCharacter() throws IOException { } @Test - @Order(10) + @Order(11) void testRenameEntitiesWithUnsupportedCharacter() { - System.out.println("Test (10) : Rename attachments with unsupported characters"); + System.out.println("Test (11) : Rename attachments with unsupported characters"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID); @@ -614,9 +647,9 @@ void testRenameEntitiesWithUnsupportedCharacter() { } @Test - @Order(11) + @Order(12) void testRenameMultipleEntityComponents() { - System.out.println("Test (11) : Rename multiple attachments, references, and footnotes"); + System.out.println("Test (12) : Rename multiple attachments, references, and footnotes"); boolean testStatus = true; String draftResponse = api.editEntityDraft(appUrl, entityName, srvpath, entityID); if (!"Entity in draft mode".equals(draftResponse)) { @@ -644,9 +677,9 @@ void testRenameMultipleEntityComponents() { } @Test - @Order(12) + @Order(13) void testRenameSingleDuplicate() { - System.out.println("Test (12) : Rename duplicates for attachment, reference, and footnote"); + System.out.println("Test (13) : Rename duplicates for attachment, reference, and footnote"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID); @@ -693,10 +726,10 @@ void testRenameSingleDuplicate() { } @Test - @Order(13) + @Order(14) void testRenameMultipleEntitiesWithOneUnsupportedCharacter() { System.out.println( - "Test (13) : Rename multiple files out of which one file name contains unsupported characters"); + "Test (14) : Rename multiple files out of which one file name contains unsupported characters"); boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID); @@ -729,57 +762,55 @@ void testRenameMultipleEntitiesWithOneUnsupportedCharacter() { } @Test - @Order(14) + @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); - if ("Entity in draft mode".equals(apiResponse)) { - String[] name = {"sample456", "reference456", "footnote456"}; - for (int i = 0; i < facet.length; i++) { - apiResponse = - apiNoRoles.renameAttachment(appUrl, entityName, facet[i], entityID, ID[i], name[i]); - if (!"Renamed".equals(apiResponse)) { - testStatus = false; - } + String apiResponse = apiNoRoles.editEntityDraft(appUrl, entityName, srvpath, entityID); + if ("Entity in draft mode".equals(apiResponse)) { + String[] name = {"sample456", "reference456", "footnote456"}; + for (int i = 0; i < facet.length; i++) { + apiResponse = + apiNoRoles.renameAttachment(appUrl, entityName, facet[i], entityID, ID[i], name[i]); + if (!"Renamed".equals(apiResponse)) { + testStatus = false; } - if (testStatus) { - apiResponse = apiNoRoles.saveEntityDraft(appUrl, entityName, srvpath, entityID); - String expected = - "[{\"code\":\"\",\"message\":\"Could not update the following files. \\n" - + // - "\\n" - + // - "\\t\\u2022 sample123\\n" - + // - "\\n" - + // - "You do not have the required permissions to update attachments. Kindly contact the admin\",\"numericSeverity\":3},{\"code\":\"\",\"message\":\"Could not update the following files. \\n" - + // - "\\n" - + // - "\\t\\u2022 reference123\\n" - + // - "\\n" - + // - "You do not have the required permissions to update attachments. Kindly contact the admin\",\"numericSeverity\":3},{\"code\":\"\",\"message\":\"Could not update the following files. \\n" - + // - "\\n" - + // - "\\t\\u2022 footnote123\\n" - + // - "\\n" - + // - "You do not have the required permissions to update attachments. Kindly contact the admin\",\"numericSeverity\":3}]"; - if (!apiResponse.equals(expected)) { - testStatus = false; - } - } else { - apiNoRoles.saveEntityDraft(appUrl, entityName, srvpath, entityID); + } + if (testStatus) { + apiResponse = apiNoRoles.saveEntityDraft(appUrl, entityName, srvpath, entityID); + String expected = + "[{\"code\":\"\",\"message\":\"Could not update the following files. \\n" + + // + "\\n" + + // + "\\t\\u2022 sample123\\n" + + // + "\\n" + + // + "You do not have the required permissions to update attachments. Kindly contact the admin\",\"numericSeverity\":3},{\"code\":\"\",\"message\":\"Could not update the following files. \\n" + + // + "\\n" + + // + "\\t\\u2022 reference123\\n" + + // + "\\n" + + // + "You do not have the required permissions to update attachments. Kindly contact the admin\",\"numericSeverity\":3},{\"code\":\"\",\"message\":\"Could not update the following files. \\n" + + // + "\\n" + + // + "\\t\\u2022 footnote123\\n" + + // + "\\n" + + // + "You do not have the required permissions to update attachments. Kindly contact the admin\",\"numericSeverity\":3}]"; + if (!apiResponse.equals(expected)) { + testStatus = false; } + } else { + apiNoRoles.saveEntityDraft(appUrl, entityName, srvpath, entityID); } - } catch (Exception e) { + } else { testStatus = false; } if (!testStatus) { @@ -788,9 +819,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; @@ -816,9 +847,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")) { @@ -844,9 +875,9 @@ void testDeleteMultipleAttachmentsReferencesFootnotes() throws IOException { } @Test - @Order(17) + @Order(18) void testDeleteEntity() { - System.out.println("Test (17) : Delete entity"); + System.out.println("Test (18) : Delete entity"); Boolean testStatus = false; String response = api.deleteEntity(appUrl, entityName, entityID); String response2 = api.deleteEntity(appUrl, entityName, entityID2); @@ -855,9 +886,9 @@ void testDeleteEntity() { } @Test - @Order(18) + @Order(19) void testUpdateValidSecondaryProperty_beforeEntityIsSaved_single() throws IOException { - System.out.println("Test (18) : Rename & Update secondary property before entity is saved"); + System.out.println("Test (19) : Rename & Update secondary property before entity is saved"); System.out.println("Creating entity"); Boolean testStatus = false; @@ -954,9 +985,9 @@ void testUpdateValidSecondaryProperty_beforeEntityIsSaved_single() throws IOExce } @Test - @Order(19) + @Order(20) void testUpdateValidSecondaryProperty_afterEntityIsSaved_single() { - System.out.println("Test (19): Rename & Update secondary property after entity is saved"); + System.out.println("Test (20): Rename & Update secondary property after entity is saved"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID3); System.out.println("Editing entity"); @@ -1022,10 +1053,10 @@ void testUpdateValidSecondaryProperty_afterEntityIsSaved_single() { } @Test - @Order(20) + @Order(21) void testUpdateInvalidSecondaryProperty_beforeEntityIsSaved_single() throws IOException { System.out.println( - "Test (20): Rename & Update invalid secondary property before entity is saved"); + "Test (21): 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); @@ -1141,10 +1172,10 @@ void testUpdateInvalidSecondaryProperty_beforeEntityIsSaved_single() throws IOEx } @Test - @Order(21) + @Order(22) void testUpdateInvalidSecondaryProperty_afterEntityIsSaved_single() throws IOException { System.out.println( - "Test (21): Rename & Update invalid secondary property after entity is saved"); + "Test (22): Rename & Update invalid secondary property after entity is saved"); System.out.println("Editing entity"); Boolean testStatus = false; @@ -1249,11 +1280,11 @@ void testUpdateInvalidSecondaryProperty_afterEntityIsSaved_single() throws IOExc } @Test - @Order(22) + @Order(23) void testUpdateValidSecondaryProperty_beforeEntityIsSaved_multipleAttachments() throws IOException { System.out.println( - "Test (22): Rename & Update valid secondary properties for multiple facets before entity is saved"); + "Test (23): 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); @@ -1422,10 +1453,10 @@ void testUpdateValidSecondaryProperty_beforeEntityIsSaved_multipleAttachments() } @Test - @Order(23) + @Order(24) void testUpdateValidSecondaryProperty_afterEntityIsSaved_multipleAttachments() { System.out.println( - "Test (23): Rename & Update valid secondary properties for multiple facets after entity is saved"); + "Test (24): 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); @@ -1562,11 +1593,11 @@ void testUpdateValidSecondaryProperty_afterEntityIsSaved_multipleAttachments() { } @Test - @Order(24) + @Order(25) void testUpdateInvalidSecondaryProperty_beforeEntityIsSaved_multipleAttachments() throws IOException { System.out.println( - "Test (24): Rename & Update invalid and valid secondary properties for multiple facets before entity is saved"); + "Test (25): Rename & Update invalid and valid secondary properties for multiple facets before entity is saved"); System.out.println("Creating entity"); Boolean testStatus = false; @@ -1792,11 +1823,11 @@ void testUpdateInvalidSecondaryProperty_beforeEntityIsSaved_multipleAttachments( } @Test - @Order(25) + @Order(26) void testUpdateInvalidSecondaryProperty_afterEntityIsSaved_multipleAttachments() throws IOException { System.out.println( - "Test (25): Rename & Update invalid and valid secondary properties for multiple attachments after entity is saved"); + "Test (26): 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); @@ -1996,10 +2027,10 @@ void testUpdateInvalidSecondaryProperty_afterEntityIsSaved_multipleAttachments() } @Test - @Order(26) + @Order(27) void testNAttachments_NewEntity() throws IOException { System.out.println( - "Test (26): Creating new entity and checking only max 4 attachments are allowed to be uploaded"); + "Test (27): 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); @@ -2113,9 +2144,9 @@ void testNAttachments_NewEntity() throws IOException { } @Test - @Order(27) + @Order(28) void testUploadNAttachments() throws IOException { - System.out.println("Test (27): Upload maximum 4 attachments in an exsisting entity"); + System.out.println("Test (28): Upload maximum 4 attachments in an exsisting entity"); ClassLoader classLoader = getClass().getClassLoader(); File originalFile = new File(classLoader.getResource("sample.exe").getFile()); @@ -2172,9 +2203,9 @@ void testUploadNAttachments() throws IOException { } @Test - @Order(28) + @Order(29) void testDiscardDraftWithoutAttachments() { - System.out.println("Test (28) : Discard draft without adding attachments"); + System.out.println("Test (29) : Discard draft without adding attachments"); Boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -2191,9 +2222,9 @@ void testDiscardDraftWithoutAttachments() { } @Test - @Order(29) + @Order(30) void testDiscardDraftWithAttachments() throws IOException { - System.out.println("Test (29): Discard draft with attachments, references, and footnotes"); + System.out.println("Test (30): Discard draft with attachments, references, and footnotes"); boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -2228,9 +2259,9 @@ void testDiscardDraftWithAttachments() throws IOException { } @Test - @Order(30) + @Order(31) void testDraftUpdateUploadTwoDeleteOneAndCreate() throws IOException { - System.out.println("Test (30): Upload to all facets, delete one, and create entity"); + System.out.println("Test (31): Upload to all facets, delete one, and create entity"); boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -2298,9 +2329,9 @@ void testDraftUpdateUploadTwoDeleteOneAndCreate() throws IOException { } @Test - @Order(31) + @Order(32) void testUpdateEntityDraft() throws IOException { - System.out.println("Test (31): Update entity draft with new facet content"); + System.out.println("Test (32): Update entity draft with new facet content"); boolean testStatus = false; ClassLoader classLoader = getClass().getClassLoader(); @@ -2343,9 +2374,9 @@ void testUpdateEntityDraft() throws IOException { } @Test - @Order(32) + @Order(33) void testUploadAttachmentWithoutSDMRole() throws IOException { - System.out.println("Test (32): Upload attachment across facets without SDM role"); + System.out.println("Test (33): Upload attachment across facets without SDM role"); boolean testStatus = true; String response = apiNoRoles.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -2383,9 +2414,9 @@ void testUploadAttachmentWithoutSDMRole() throws IOException { } @Test - @Order(33) + @Order(34) void testCopyAttachmentsSuccessNewEntity() throws IOException { - System.out.println("Test (33): Copy attachments from one entity to another new entity"); + System.out.println("Test (34): Copy attachments from one entity to another new entity"); List> attachments = new ArrayList<>(); for (int i = 0; i < 3; i++) { attachments.add(new ArrayList<>()); @@ -2507,10 +2538,10 @@ void testCopyAttachmentsSuccessNewEntity() throws IOException { } @Test - @Order(34) + @Order(35) void testCopyAttachmentsUnsuccessfulNewEntity() throws IOException { System.out.println( - "Test (34): Copy incorrect attachments from one entity to another new entity"); + "Test (35): Copy incorrect attachments from one entity to another new entity"); String editResponse1 = api.editEntityDraft(appUrl, entityName, srvpath, copyAttachmentSourceEntity); copyAttachmentTargetEntityEmpty = @@ -2554,9 +2585,9 @@ void testCopyAttachmentsUnsuccessfulNewEntity() throws IOException { } @Test - @Order(35) + @Order(36) void testCopyAttachmentsSuccessExistingEntity() throws IOException { - System.out.println("Test (35): Copy attachments from one entity to another existing entity"); + System.out.println("Test (36): Copy attachments from one entity to another existing entity"); List> attachments = new ArrayList<>(); for (int i = 0; i < 3; i++) { attachments.add(new ArrayList<>()); @@ -2690,9 +2721,9 @@ void testCopyAttachmentsSuccessExistingEntity() throws IOException { } @Test - @Order(36) + @Order(37) void testCopyAttachmentsUnsuccessfulExistingEntity() throws IOException { - System.out.println("Test (36): Copy attachments from one entity to another new entity"); + System.out.println("Test (37): Copy attachments from one entity to another new entity"); String editResponse1 = api.editEntityDraft(appUrl, entityName, srvpath, copyAttachmentSourceEntity); String editResponse2 = 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 9b41d708e..83b91eb26 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 @@ -610,8 +610,34 @@ void testUpdateEntityDraft() throws IOException { @Test @Order(12) + void testRenameWhitespaceInAttachment() throws IOException { + System.out.println("Test (13) : Rename attachment with whitespace"); + Boolean testStatus = false; + String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID); + if (response.equals("Entity in draft mode")) { + String name = " "; + response = api.renameAttachment(appUrl, entityName, facetName, entityID, attachmentID1, name); + if (response.equals("Renamed")) { + response = api.saveEntityDraft(appUrl, entityName, srvpath, entityID); + String expected = + "[{\"code\":\"\",\"message\":\"The file name cannot be empty or consist entirely of space characters. Enter a value.\"," + + "\"numericSeverity\":3}]"; + if (response.equals(expected)) { + testStatus = true; + } + } else { + api.saveEntityDraft(appUrl, entityName, srvpath, entityID); + } + } + if (!testStatus) { + fail("Attachment was renamed with whitespace"); + } + } + + @Test + @Order(13) void testRenameSingleAttachment() { - System.out.println("Test (12) : Rename single attachment"); + System.out.println("Test (13) : Rename single attachment"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID); String name = "sample123"; @@ -632,9 +658,9 @@ void testRenameSingleAttachment() { } @Test - @Order(13) + @Order(14) void testRenameAttachmentWithUnsupportedCharacter() { - System.out.println("Test (13) : Rename single attachment with unsupported characters"); + System.out.println("Test (14) : Rename single attachment with unsupported characters"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID); String name = "invalid/name"; @@ -658,9 +684,9 @@ void testRenameAttachmentWithUnsupportedCharacter() { } @Test - @Order(14) + @Order(15) void testRenameMultipleAttachments() { - System.out.println("Test (14) : Rename multiple attachments"); + System.out.println("Test (15) : Rename multiple attachments"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID); String name1 = "sample1234"; @@ -685,9 +711,9 @@ void testRenameMultipleAttachments() { } @Test - @Order(15) + @Order(16) void testRenameSingleAttachmentDuplicate() { - System.out.println("Test (15) : Rename single attachment duplicate"); + System.out.println("Test (16) : Rename single attachment duplicate"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID); String name = "sample123"; @@ -719,10 +745,10 @@ void testRenameSingleAttachmentDuplicate() { } @Test - @Order(16) + @Order(17) void testRenameMultipleAttachmentsWithOneUnsupportedCharacter() { System.out.println( - "Test (16) : Rename multiple attachments where one name has unsupported characters"); + "Test (17) : Rename multiple attachments where one name has unsupported characters"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID); @@ -756,9 +782,9 @@ void testRenameMultipleAttachmentsWithOneUnsupportedCharacter() { } @Test - @Order(17) + @Order(18) void testRenameSingleAttachmentWithoutSDMRole() throws IOException { - System.out.println("Test (17) : Rename attachments where user don't have SDM-Roles"); + System.out.println("Test (18) : Rename attachments where user don't have SDM-Roles"); boolean testStatus = false; String apiResponse = apiNoRoles.editEntityDraft(appUrl, entityName, srvpath, entityID); String name = "sample123"; @@ -790,9 +816,9 @@ void testRenameSingleAttachmentWithoutSDMRole() throws IOException { } @Test - @Order(18) + @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") { @@ -813,9 +839,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") { @@ -841,9 +867,9 @@ void testDeleteMultipleAttachments() throws IOException { } @Test - @Order(20) + @Order(21) void testDeleteEntity() { - System.out.println("Test (20) : Delete entity"); + System.out.println("Test (21) : Delete entity"); Boolean testStatus = false; String response = api.deleteEntity(appUrl, entityName, entityID); String response2 = api.deleteEntity(appUrl, entityName, entityID2); @@ -856,9 +882,9 @@ void testDeleteEntity() { } @Test - @Order(21) + @Order(22) void testUpdateValidSecondaryProperty_beforeEntityIsSaved_singleAttachment() throws IOException { - System.out.println("Test (21): Rename & Update secondary property before entity is saved"); + System.out.println("Test (22): Rename & Update secondary property before entity is saved"); System.out.println("Creating entity"); Boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -943,9 +969,9 @@ void testUpdateValidSecondaryProperty_beforeEntityIsSaved_singleAttachment() thr } @Test - @Order(22) + @Order(23) void testUpdateValidSecondaryProperty_afterEntityIsSaved_singleAttachment() { - System.out.println("Test (22): Rename & Update secondary property after entity is saved"); + System.out.println("Test (23): Rename & Update secondary property after entity is saved"); System.out.println("Editing entity"); Boolean testStatus = false; String response = api.editEntityDraft(appUrl, entityName, srvpath, entityID3); @@ -1014,11 +1040,11 @@ void testUpdateValidSecondaryProperty_afterEntityIsSaved_singleAttachment() { } @Test - @Order(23) + @Order(24) void testUpdateInvalidSecondaryProperty_beforeEntityIsSaved_singleAttachment() throws IOException { System.out.println( - "Test (23): Rename & Update invalid secondary property before entity is saved"); + "Test (24): 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); @@ -1143,10 +1169,10 @@ void testUpdateInvalidSecondaryProperty_beforeEntityIsSaved_singleAttachment() } @Test - @Order(24) + @Order(25) void testUpdateInvalidSecondaryProperty_afterEntityIsSaved_singleAttachment() throws IOException { System.out.println( - "Test (24): Rename & Update invalid secondary property after entity is saved"); + "Test (25): 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); @@ -1241,11 +1267,11 @@ void testUpdateInvalidSecondaryProperty_afterEntityIsSaved_singleAttachment() th } @Test - @Order(25) + @Order(26) void testUpdateValidSecondaryProperty_beforeEntityIsSaved_multipleAttachments() throws IOException { System.out.println( - "Test (25): Rename & Update valid secondary properties for multiple attachments before entity is saved"); + "Test (26): 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); @@ -1429,10 +1455,10 @@ void testUpdateValidSecondaryProperty_beforeEntityIsSaved_multipleAttachments() } @Test - @Order(26) + @Order(27) void testUpdateValidSecondaryProperty_afterEntityIsSaved_multipleAttachments() { System.out.println( - "Test (26): Rename & Update valid secondary properties for multiple attachments after entity is saved"); + "Test (27): 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); @@ -1561,11 +1587,11 @@ void testUpdateValidSecondaryProperty_afterEntityIsSaved_multipleAttachments() { } @Test - @Order(27) + @Order(28) void testUpdateInvalidSecondaryProperty_beforeEntityIsSaved_multipleAttachments() throws IOException { System.out.println( - "Test (27): Rename & Update invalid and valid secondary properties for multiple attachments before entity is saved"); + "Test (28): 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); @@ -1782,11 +1808,11 @@ void testUpdateInvalidSecondaryProperty_beforeEntityIsSaved_multipleAttachments( } @Test - @Order(28) + @Order(29) void testUpdateInvalidSecondaryProperty_afterEntityIsSaved_multipleAttachments() throws IOException { System.out.println( - "Test (28): Rename & Update invalid and valid secondary properties for multiple attachments after entity is saved"); + "Test (29): 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); @@ -1946,10 +1972,10 @@ void testUpdateInvalidSecondaryProperty_afterEntityIsSaved_multipleAttachments() } @Test - @Order(29) + @Order(30) void testNAttachments_NewEntity() throws IOException { System.out.println( - "Test (29): Creating new entity and checking only max 4 attachments are allowed to be uploaded"); + "Test (30): 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); @@ -2063,9 +2089,9 @@ void testNAttachments_NewEntity() throws IOException { } @Test - @Order(30) + @Order(31) void testUploadNAttachments() throws IOException { - System.out.println("Test (30): Upload maximum 4 attachments in an exsisting entity"); + System.out.println("Test (31): Upload maximum 4 attachments in an exsisting entity"); ClassLoader classLoader = getClass().getClassLoader(); File originalFile = new File(classLoader.getResource("sample.exe").getFile()); @@ -2122,9 +2148,9 @@ void testUploadNAttachments() throws IOException { } @Test - @Order(31) + @Order(32) void testDiscardDraftWithoutAttachments() { - System.out.println("Test (31) : Discard draft without adding attachments"); + System.out.println("Test (32) : Discard draft without adding attachments"); boolean testStatus = false; String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath); @@ -2143,9 +2169,9 @@ void testDiscardDraftWithoutAttachments() { } @Test - @Order(32) + @Order(33) void testDiscardDraftWithAttachments() throws IOException { - System.out.println("Test (32) : 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")) { @@ -2179,9 +2205,9 @@ void testDiscardDraftWithAttachments() throws IOException { } @Test - @Order(33) + @Order(34) void testCopyAttachmentsSuccessNewEntity() throws IOException { - System.out.println("Test (33): Copy attachments from one entity to another new entity"); + System.out.println("Test (34): 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); @@ -2274,9 +2300,9 @@ void testCopyAttachmentsSuccessNewEntity() throws IOException { } @Test - @Order(34) + @Order(35) void testCopyAttachmentsUnsuccessfulNewEntity() 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"); String editResponse1 = api.editEntityDraft(appUrl, entityName, srvpath, copyAttachmentSourceEntity); copyAttachmentTargetEntityEmpty = @@ -2311,9 +2337,9 @@ void testCopyAttachmentsUnsuccessfulNewEntity() throws IOException { } @Test - @Order(35) + @Order(36) void testCopyAttachmentsSuccessExistingEntity() throws IOException { - System.out.println("Test (35): Copy attachments from one entity to another existing entity"); + System.out.println("Test (36): Copy attachments from one entity to another existing entity"); List attachments = new ArrayList<>(); ClassLoader classLoader = getClass().getClassLoader(); List files = new ArrayList<>(); @@ -2419,9 +2445,9 @@ void testCopyAttachmentsSuccessExistingEntity() throws IOException { } @Test - @Order(36) + @Order(37) void testCopyAttachmentsUnsuccessfulExistingEntity() throws IOException { - System.out.println("Test (36): Copy attachments from one entity to another new entity"); + System.out.println("Test (37): Copy attachments from one entity to another new entity"); String editResponse1 = api.editEntityDraft(appUrl, entityName, srvpath, copyAttachmentSourceEntity); String editResponse2 = 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 03db40a13..c1f8b99b6 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 @@ -5,10 +5,12 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; import com.sap.cds.CdsData; import com.sap.cds.reflect.*; +import com.sap.cds.sdm.caching.CacheConfig; import com.sap.cds.sdm.handler.TokenHandler; import com.sap.cds.sdm.handler.applicationservice.SDMCreateAttachmentsHandler; import com.sap.cds.sdm.model.SDMCredentials; @@ -25,6 +27,7 @@ import java.io.IOException; import java.util.*; import java.util.stream.Stream; +import org.ehcache.Cache; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -43,6 +46,8 @@ public class SDMCreateAttachmentsHandlerTest { @Mock private SDMCredentials mockCredentials; @Mock private Messages messages; @Mock private CdsModel model; + private MockedStatic cacheConfigMockedStatic; + private Cache mockCache; private SDMCreateAttachmentsHandler handler; private MockedStatic sdmUtilsMockedStatic; @Mock private CdsElement cdsElement; @@ -55,6 +60,9 @@ public class SDMCreateAttachmentsHandlerTest { public void setUp() { MockitoAnnotations.openMocks(this); sdmUtilsMockedStatic = mockStatic(SDMUtils.class); + cacheConfigMockedStatic = mockStatic(CacheConfig.class); + mockCache = mock(Cache.class); + cacheConfigMockedStatic.when(CacheConfig::getSecondaryPropertiesCache).thenReturn(mockCache); handler = spy(new SDMCreateAttachmentsHandler(persistenceService, sdmService, tokenHandler, dbQuery)); @@ -77,6 +85,9 @@ public void tearDown() { if (sdmUtilsMockedStatic != null) { sdmUtilsMockedStatic.close(); } + if (cacheConfigMockedStatic != null) { + cacheConfigMockedStatic.close(); + } } @Test @@ -169,6 +180,110 @@ public void testUpdateNameWithNoAttachments() throws IOException { verify(messages, never()).warn(anyString()); } + @Test + public void testRenameWithWhitespaceFilename() throws IOException { + // Arrange + List data = new ArrayList<>(); + + // Create entity with attachment that has whitespace-only filename + Map entity = new HashMap<>(); + + // Create attachments list with whitespace-only filename + List> attachments = new ArrayList<>(); + + // Attachment with whitespace-only filename + Map attachment = new HashMap<>(); + attachment.put("ID", "id1"); + attachment.put("fileName", " "); // Only whitespace + attachment.put("objectId", "objId1"); + attachments.add(attachment); + + // Add attachments to entity + entity.put("attachments", attachments); + + // Wrap entity in CdsData and add to data list + CdsData cdsDataEntity = CdsData.create(entity); + data.add(cdsDataEntity); + + // Mock the attachment entity + CdsEntity attachmentEntity = mock(CdsEntity.class); + when(model.findEntity("some.qualified.Name.attachments")) + .thenReturn(Optional.of(attachmentEntity)); + + // Mock utility methods + sdmUtilsMockedStatic + .when(() -> SDMUtils.isFileNameDuplicateInDrafts(data, "attachments")) + .thenReturn(Collections.emptySet()); + + sdmUtilsMockedStatic + .when(() -> SDMUtils.getPropertyTitles(any(Optional.class), any(Map.class))) + .thenReturn(new HashMap<>()); + + sdmUtilsMockedStatic + .when( + () -> + SDMUtils.getSecondaryPropertiesWithInvalidDefinition( + any(Optional.class), any(Map.class))) + .thenReturn(new HashMap<>()); + + sdmUtilsMockedStatic + .when(() -> SDMUtils.getSecondaryTypeProperties(any(Optional.class), any(Map.class))) + .thenReturn(new HashMap<>()); + + sdmUtilsMockedStatic + .when( + () -> + SDMUtils.getUpdatedSecondaryProperties( + any(Optional.class), any(Map.class), any(), any(Map.class), any(Map.class))) + .thenReturn(new HashMap<>()); + + // Mock that the whitespace filename does NOT have restricted characters + sdmUtilsMockedStatic.when(() -> SDMUtils.isRestrictedCharactersInName(" ")).thenReturn(false); + + // Mock database queries + when(dbQuery.getAttachmentForID(any(CdsEntity.class), any(PersistenceService.class), eq("id1"))) + .thenReturn("existingFile.txt"); // Existing filename in DB + + // Mock properties query to return empty map + Map emptyProperties = new HashMap<>(); + when(dbQuery.getPropertiesForID( + any(CdsEntity.class), any(PersistenceService.class), eq("id1"), any(Map.class))) + .thenReturn(emptyProperties); + + // Mock SDM service calls - CRITICAL: Prevent any exceptions + when(tokenHandler.getSDMCredentials()).thenReturn(mockCredentials); + when(sdmService.getObject("objId1", mockCredentials, false)).thenReturn("originalFile.txt"); + + // IMPORTANT: Mock the updateAttachments to return success to avoid permission + // errors + when(sdmService.updateAttachments(any(), any(), any(), any(), anyBoolean())) + .thenReturn(200); // Return HTTP 200 success + + // Mock UserInfo + UserInfo userInfo = mock(UserInfo.class); + when(context.getUserInfo()).thenReturn(userInfo); + when(userInfo.isSystemUser()).thenReturn(false); + + // Act + handler.updateName(context, data, "attachments"); + + // Assert + // Verify that the warning message for whitespace filename was called + // Check if the exact warning message matches what's in SDMConstants + verify(messages, times(1)).warn(anyString()); + + // Verify that the attachment filename was reverted to the DB value + assertEquals("existingFile.txt", attachment.get("fileName")); + + // Verify no error messages were called (only warnings) + verify(messages, never()).error(anyString()); + + // Verify that SDM service updateAttachments was called (since whitespace + // doesn't prevent the call) + // The key is that it should succeed (return 200) instead of throwing exceptions + verify(sdmService, times(1)).updateAttachments(any(), any(), any(), any(), anyBoolean()); + } + // @Test // public void testUpdateNameWithRestrictedCharacters() 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 2c9cf5259..08f68e49c 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 @@ -122,6 +122,82 @@ public void testRenameWithDuplicateFilenames() throws IOException { "The file(s) file1.txt, file2.txt have been added multiple times. Please rename and try again."); } + @Test + public void testRenameWithWhitespaceFilename() throws IOException { + // Mock the data structure to simulate the attachments + List data = new ArrayList<>(); + Map entity = new HashMap<>(); + List> attachments = new ArrayList<>(); + Map attachment = spy(new HashMap<>()); + + attachment.put("fileName", " "); // Whitespace filename + attachment.put("objectId", "test-object-id"); + attachment.put("ID", "test-id"); + attachments.add(attachment); + + entity.put("composition", attachments); + CdsData mockCdsData = mock(CdsData.class); + when(mockCdsData.get("composition")).thenReturn(attachments); + data.add(mockCdsData); + + CdsEntity attachmentDraftEntity = mock(CdsEntity.class); + when(context.getTarget()).thenReturn(attachmentDraftEntity); + when(context.getModel()).thenReturn(model); + when(attachmentDraftEntity.getQualifiedName()).thenReturn("some.qualified.Name"); + when(model.findEntity("some.qualified.Name.composition")) + .thenReturn(Optional.of(attachmentDraftEntity)); + when(context.getMessages()).thenReturn(messages); + + // Mock database query to return the original filename from DB + when(dbQuery.getAttachmentForID( + any(CdsEntity.class), any(PersistenceService.class), anyString())) + .thenReturn("original-file.pdf"); + + // Mock secondary type properties + Map secondaryTypeProperties = new HashMap<>(); + secondaryTypeProperties.put("prop1", "secondary1"); + + // Mock properties from DB + Map propertiesInDB = new HashMap<>(); + propertiesInDB.put("prop1", "value1"); + when(dbQuery.getPropertiesForID( + eq(attachmentDraftEntity), + eq(persistenceService), + eq("test-id"), + eq(secondaryTypeProperties))) + .thenReturn(propertiesInDB); + + // Mock static SDMUtils methods + sdmUtilsMockedStatic = mockStatic(SDMUtils.class); + sdmUtilsMockedStatic + .when(() -> isFileNameDuplicateInDrafts(data, "composition")) + .thenReturn(new HashSet<>()); + + sdmUtilsMockedStatic + .when(() -> SDMUtils.getSecondaryTypeProperties(any(Optional.class), any())) + .thenReturn(secondaryTypeProperties); + + sdmUtilsMockedStatic + .when(() -> SDMUtils.getPropertyTitles(any(), any())) + .thenReturn(new HashMap<>()); + + // Call the method + handler.updateName(context, data, "composition"); + + // Verify that the attachment's fileName was replaced with the original filename + // from DB + verify(attachment).replace("fileName", "original-file.pdf"); + + // Capture and assert the warning message for whitespace filename + ArgumentCaptor warningCaptor = ArgumentCaptor.forClass(String.class); + verify(messages).warn(warningCaptor.capture()); + String warningMessage = warningCaptor.getValue(); + + String expectedMessage = + String.format(SDMConstants.FILENAME_WHITESPACE_WARNING_MESSAGE, "original-file.pdf"); + assertEquals(expectedMessage, warningMessage); + } + // @Test // public void testRenameWithUniqueFilenames() throws IOException { // List data = prepareMockAttachmentData("file1.txt");