Hi All,
I've been struggling with achieving the 75%+ coverage required for a trigger to prevent users from deleting files linked to Account.
The trigger works as intended; allowing System Administrators OR users with a "File_Deletion" permission set to delete files
Any advice is much appreciated!
Trigger
trigger PreventFileDeletion on ContentDocument (before delete) { Boolean isAdmin = false; Boolean hasPermissionSet = false; // Check if running user has the SysAdmin profile Profile adminProfile = [SELECT Id, Name FROM Profile WHERE Name = 'System Administrator' LIMIT 1]; if (UserInfo.getProfileId() == adminProfile.Id) { isAdmin = true; } // Check if running user has "File Deletion" permission set if user is not SysAdmin if(isAdmin == false){ PermissionSet ps = [SELECT Id, Name FROM PermissionSet WHERE Name = 'File_Deletion' LIMIT 1]; // Get current user's Id Id userId = UserInfo.getUserId(); // Check for PermSet allowing deletion PermissionSetAssignment psa = [SELECT id FROM PermissionSetAssignment WHERE AssigneeId = :userId AND PermissionSetId = :ps.id LIMIT 1]; if (psa != null) { hasPermissionSet = true; } } // If running user not SysAdmin and does not have "File Deletion" permission set run the logic if (!isAdmin && !hasPermissionSet) { // Check if any related ContentDocumentLink records exist with related AccountIds Set<Id> accountIds = new Set<Id>(); // Gather ContentDocumentIds being deleted for (ContentDocument cd : Trigger.old) { accountIds.add(cd.Id); } // Query related ContentDocumentLink records List<ContentDocumentLink> relatedLinks = [SELECT Id, LinkedEntityId FROM ContentDocumentLink WHERE ContentDocumentId IN :accountIds]; // Check if any related ContentDocumentLink records exist with AccountIds for (ContentDocumentLink link : relatedLinks) { if (link.LinkedEntityId.getSObjectType() == Account.SObjectType) { // Prevent deletion and throw an error message Trigger.oldMap.get(link.ContentDocumentId).addError('Files related to Accounts cannot be deleted.'); } } }}Test Class (36% coverage)
@isTestprivate class TestPreventFileDeletion { private static PermissionSet ps; private static User SystemAdminUser; private static User StandardUser; private static User PermSetUser; @TestSetup static void setup() { // Create test Acc Account testAccount = new Account(name = 'Acme'); insert testAccount; // Create test ContentDocument ContentVersion cv = new ContentVersion(); cv.Title = 'Test Document'; cv.PathOnClient = 'test_document.txt'; cv.VersionData = Blob.valueOf('Test Content'); insert cv; // Create a ContentDocumentLink between Acc & ContentDocument ContentDocumentLink testLink = new ContentDocumentLink(); testLink.ContentDocumentId = [SELECT ContentDocumentId FROM ContentVersion WHERE Id = :cv.Id].ContentDocumentId; testLink.LinkedEntityId = testAccount.Id; testLink.ShareType = 'V'; insert testLink; } @isTest static void AllowSystemAdminUser() { // Retrieve profile for test Profile adminProfile = [SELECT Id FROM Profile WHERE Name = 'System Administrator' LIMIT 1]; // Create SysAdmin user SystemAdminUser = new User( Alias = 'SysAdUsr', Email = 'SystemAdminUser@test.com', EmailEncodingKey = 'UTF-8', LastName = 'Testing', LanguageLocaleKey = 'en_US', LocaleSidKey = 'en_US', ProfileId = adminProfile.Id, TimeZoneSidKey = 'America/Los_Angeles', UserName = 'SystemAdminUser@test.com.hdyfjtutkg' ); insert SystemAdminUser; // Get Acc Account testAccount = [SELECT id FROM Account LIMIT 1]; // Query ContentDocumentLink records related to the test Account List<Id> relatedContentDocumentIds = new List<Id>(); for (ContentDocumentLink link : [SELECT ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId = :testAccount.Id]) { relatedContentDocumentIds.add(link.ContentDocumentId); } Test.startTest(); System.RunAs(SystemAdminUser){ // Attempt to delete the test ContentDocument as SystemAdmin try { delete [SELECT Id FROM ContentDocument WHERE Id IN :relatedContentDocumentIds]; //System.assert(false, 'Expected error not thrown'); } catch (DmlException e) { //System.assert(e.getDmlMessage(0).contains('Files related to Accounts cannot be deleted.'), 'Unexpected error message'); System.debug('e.getDmlMessage(0) = ' + e.getDmlMessage(0)); } } Test.stopTest(); } @isTest static void PreventStandardUser() { // Get Id the Standard User Profile Profile StandardProfile = [SELECT Id FROM Profile WHERE Name = 'Standard User' LIMIT 1]; // Create Standard Profile user StandardUser = new User( Alias = 'StandUsr', Email = 'StandardUser@test.com', EmailEncodingKey = 'UTF-8', LastName = 'Testing', LanguageLocaleKey = 'en_US', LocaleSidKey = 'en_US', ProfileId = StandardProfile.Id, TimeZoneSidKey = 'America/Los_Angeles', UserName = 'StandardUser@test.com.hdyfjtutkg' ); insert StandardUser; // Get Acc Account testAccount = [SELECT id FROM Account LIMIT 1]; // Query ContentDocumentLink records related to the test Account List<Id> relatedContentDocumentIds = new List<Id>(); for (ContentDocumentLink link : [SELECT ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId = :testAccount.Id]) { relatedContentDocumentIds.add(link.ContentDocumentId); } Test.startTest(); // Attempt to delete the test ContentDocument as Standard User System.runAs(StandardUser){ try { delete [SELECT Id FROM ContentDocument WHERE Id IN :relatedContentDocumentIds]; //System.assert(false, 'Expected error not thrown'); } catch (DmlException e) { System.assert(e.getDmlMessage(0).contains('insufficient access rights on object id'), 'Unexpected error message'); } } Test.stopTest(); } @isTest static void AllowPermSetUser() { // Get Id for Standard User Profile Profile StandardUser = [SELECT Id FROM Profile WHERE Name = 'Standard User' LIMIT 1]; // Retrieve Account for testing Account testAccount = [SELECT id FROM Account LIMIT 1]; // Create a Standard Profile test user with PermSet PermSetUser = new User( Alias = 'PermSUsr', Email = 'PermSetUser@test.com', EmailEncodingKey = 'UTF-8', LastName = 'Testing', LanguageLocaleKey = 'en_US', LocaleSidKey = 'en_US', ProfileId = StandardUser.Id, TimeZoneSidKey = 'America/Los_Angeles', UserName = 'PermSetUser@test.com.hdyfjtutkg' ); insert PermSetUser; // Get the 'File_Deletion' permission set ps = [SELECT id FROM PermissionSet WHERE Name='File_Deletion']; // Assign Permission Set to the Standard User PermissionSetAssignment psa = new PermissionSetAssignment(AssigneeId=PermSetUser.Id, PermissionSetId=ps.Id); insert psa; // Query ContentDocumentLink records related to the test Account List<Id> relatedContentDocumentIds = new List<Id>(); for (ContentDocumentLink link : [SELECT ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId = :testAccount.Id]) { relatedContentDocumentIds.add(link.ContentDocumentId); } Test.startTest(); System.RunAs(PermSetUser){ // Attempt to delete the test ContentDocument as Standard User try { delete [SELECT Id FROM ContentDocument WHERE Id IN :relatedContentDocumentIds]; //System.assert(false, 'Expected error not thrown'); } catch (DmlException e) { //System.assert(e.getDmlMessage(0).contains('Files related to Accounts cannot be deleted.'), 'Unexpected error message'); } } Test.stopTest(); }}
#Apex #Test Classes #Salesforce Developer #Salesforce Developers #Apex Class #Triggers #Developer Forums
2 件の回答
Sometimes in your if statements - like on line #11 - I'll do an "|| test.isRunningTest()" - and that way the loop will run during test - to get more test coverage.
It's probably not the "correct" way to do it, but I works.