/** * @description Test class for DocusignCompositeEnvelopeBuilder (dfsle Apex Toolkit) * @author Paul Huliganga * @date 2026-02-25 */ @isTest(SeeAllData=true) private class DocusignCompositeEnvelopeBuilderTest { @isTest static void testSuccessfulCompositeEnvelope() { // Arrange dfsle.TestUtils.setMock(new dfsle.ESignatureAPIMock()); DocusignEnvelopeRequest req = new DocusignEnvelopeRequest(); req.templateIds = new List{ '01234567-abcd-ef01-2345-6789abcdef01', '01234567-abcd-ef01-2345-6789abcdef02', '01234567-abcd-ef01-2345-6789abcdef03' }; req.recordId = getTestCaseId(); req.language = 'en'; req.emailSubject = 'Please sign these forms'; // Act Test.startTest(); List results = DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope( new List{req} ); Test.stopTest(); // Assert System.assertEquals(1, results.size(), 'Should return 1 result'); System.assertEquals(true, results[0].success, 'Should be successful'); System.assertNotEquals(null, results[0].envelopeId, 'Should have envelope ID'); System.assertEquals(null, results[0].errorMessage, 'Should have no error'); } @isTest static void testSingleTemplate() { // Arrange dfsle.TestUtils.setMock(new dfsle.ESignatureAPIMock()); DocusignEnvelopeRequest req = new DocusignEnvelopeRequest(); req.templateIds = new List{'01234567-abcd-ef01-2345-6789abcdef01'}; req.recordId = getTestCaseId(); // Act Test.startTest(); List results = DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope( new List{req} ); Test.stopTest(); // Assert System.assertEquals(true, results[0].success, 'Should succeed with 1 template'); } @isTest static void testMaximumTemplates() { // Arrange dfsle.TestUtils.setMock(new dfsle.ESignatureAPIMock()); List templateIds = new List(); for (Integer i = 1; i <= 14; i++) { templateIds.add('01234567-abcd-ef01-2345-6789abcdef' + String.valueOf(i).leftPad(2, '0')); } DocusignEnvelopeRequest req = new DocusignEnvelopeRequest(); req.templateIds = templateIds; req.recordId = getTestCaseId(); // Act Test.startTest(); List results = DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope( new List{req} ); Test.stopTest(); // Assert System.assertEquals(true, results[0].success, 'Should succeed with 14 templates'); } @isTest static void testDuplicateTemplatesDeduped() { // Arrange dfsle.TestUtils.setMock(new dfsle.ESignatureAPIMock()); DocusignEnvelopeRequest req = new DocusignEnvelopeRequest(); req.templateIds = new List{ '01234567-abcd-ef01-2345-6789abcdef01', '01234567-abcd-ef01-2345-6789abcdef02', '01234567-abcd-ef01-2345-6789abcdef01' // duplicate }; req.recordId = getTestCaseId(); // Act Test.startTest(); List results = DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope( new List{req} ); Test.stopTest(); // Assert System.assertEquals(true, results[0].success, 'Should handle duplicates'); } @isTest static void testNullRequest() { // Act Test.startTest(); List results = DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(null); Test.stopTest(); // Assert System.assertEquals(false, results[0].success, 'Should fail with null request'); System.assertEquals('No request provided', results[0].errorMessage, 'Should have error message'); } @isTest static void testEmptyRequest() { // Act Test.startTest(); List results = DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope( new List() ); Test.stopTest(); // Assert System.assertEquals(false, results[0].success, 'Should fail with empty request'); } @isTest static void testValidationNoTemplates() { // Arrange DocusignEnvelopeRequest req = new DocusignEnvelopeRequest(); req.templateIds = new List(); req.recordId = '001000000ABC123'; // Act Test.startTest(); List results = DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope( new List{req} ); Test.stopTest(); // Assert System.assertEquals(false, results[0].success, 'Should fail validation'); System.assert(results[0].errorMessage.containsIgnoreCase('template'), 'Should mention templates'); } @isTest static void testValidationTooManyTemplates() { // Arrange List templateIds = new List(); for (Integer i = 1; i <= 15; i++) { templateIds.add('01234567-abcd-ef01-2345-6789abcdef' + String.valueOf(i).leftPad(2, '0')); } DocusignEnvelopeRequest req = new DocusignEnvelopeRequest(); req.templateIds = templateIds; req.recordId = '001000000ABC123'; // Act Test.startTest(); List results = DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope( new List{req} ); Test.stopTest(); // Assert System.assertEquals(false, results[0].success, 'Should fail validation'); System.assert(results[0].errorMessage.contains('Maximum 14'), 'Should mention limit'); } @isTest static void testValidationNoRecordId() { // Arrange DocusignEnvelopeRequest req = new DocusignEnvelopeRequest(); req.templateIds = new List{'01234567-abcd-ef01-2345-6789abcdef01'}; req.recordId = ''; // Act Test.startTest(); List results = DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope( new List{req} ); Test.stopTest(); // Assert System.assertEquals(false, results[0].success, 'Should fail validation'); System.assert(results[0].errorMessage.contains('record ID'), 'Should mention record ID'); } @isTest static void testValidationBlankTemplateId() { // Arrange DocusignEnvelopeRequest req = new DocusignEnvelopeRequest(); req.templateIds = new List{'01234567-abcd-ef01-2345-6789abcdef01', ''}; req.recordId = '001000000ABC123'; // Act Test.startTest(); List results = DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope( new List{req} ); Test.stopTest(); // Assert System.assertEquals(false, results[0].success, 'Should fail validation'); System.assert(results[0].errorMessage.contains('blank'), 'Should mention blank'); } @isTest static void testWithEmailSubject() { // Arrange dfsle.TestUtils.setMock(new dfsle.ESignatureAPIMock()); DocusignEnvelopeRequest req = new DocusignEnvelopeRequest(); req.templateIds = new List{'01234567-abcd-ef01-2345-6789abcdef01'}; req.recordId = getTestCaseId(); req.emailSubject = 'Custom: Please review and sign'; // Act Test.startTest(); List results = DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope( new List{req} ); Test.stopTest(); // Assert System.assertEquals(true, results[0].success, 'Should succeed with custom subject'); } @isTest static void testWithoutEmailSubject() { // Arrange dfsle.TestUtils.setMock(new dfsle.ESignatureAPIMock()); DocusignEnvelopeRequest req = new DocusignEnvelopeRequest(); req.templateIds = new List{'01234567-abcd-ef01-2345-6789abcdef01'}; req.recordId = getTestCaseId(); req.emailSubject = null; // Act Test.startTest(); List results = DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope( new List{req} ); Test.stopTest(); // Assert System.assertEquals(true, results[0].success, 'Should succeed without subject'); } @isTest static void testEmailSubjectTruncation() { // Arrange dfsle.TestUtils.setMock(new dfsle.ESignatureAPIMock()); DocusignEnvelopeRequest req = new DocusignEnvelopeRequest(); // Create multiple templates to make combined name > 100 chars req.templateIds = new List{ '01234567-abcd-ef01-2345-6789abcdef01', '01234567-abcd-ef01-2345-6789abcdef02', '01234567-abcd-ef01-2345-6789abcdef03', '01234567-abcd-ef01-2345-6789abcdef04', '01234567-abcd-ef01-2345-6789abcdef05' }; req.recordId = getTestCaseId(); // Act Test.startTest(); List results = DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope( new List{req} ); Test.stopTest(); // Assert System.assertEquals(true, results[0].success, 'Should succeed with truncated subject'); } @isTest static void testSmsDeliveryPath() { // Arrange - use existing sandbox case; SMS delivery path exercises withSmsDelivery() dfsle.TestUtils.setMock(new dfsle.ESignatureAPIMock()); DocusignEnvelopeRequest req = new DocusignEnvelopeRequest(); req.templateIds = new List{'01234567-abcd-ef01-2345-6789abcdef01'}; req.recordId = getTestCaseId(); req.recipientSmsPhone = '+15551234567'; // Act Test.startTest(); List results = DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List{req}); Test.stopTest(); // Assert - should succeed and produce an envelope id System.assertEquals(true, results[0].success, 'SMS path should succeed'); System.assertNotEquals(null, results[0].envelopeId, 'Should have envelope ID for SMS envelope'); } @isTest static void testSpanishGreetingPath() { // Arrange - basic happy path but with language set to Spanish dfsle.TestUtils.setMock(new dfsle.ESignatureAPIMock()); DocusignEnvelopeRequest req = new DocusignEnvelopeRequest(); req.templateIds = new List{'01234567-abcd-ef01-2345-6789abcdef01'}; req.recordId = getTestCaseId(); req.language = 'es'; // Act Test.startTest(); List results = DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List{req}); Test.stopTest(); // Assert - succeeded; language handling exercised (no exception) System.assertEquals(true, results[0].success, 'Spanish language path should succeed'); } @isTest static void testMultiCopyExpansion() { // Arrange - insert a dfsle configuration that matches the MULTI_COPY_TEMPLATE_NAME // so the multi-copy expansion logic will detect and duplicate template IDs. dfsle__EnvelopeConfiguration__c cfg = new dfsle__EnvelopeConfiguration__c( Name = 'Authorization to Release Information - English', dfsle__DocuSignId__c = '01234567-abcd-ef01-2345-6789abcdef99', dfsle__EmailMessage__c = 'Please sign this release.' ); insert cfg; dfsle.TestUtils.setMock(new dfsle.ESignatureAPIMock()); DocusignEnvelopeRequest req = new DocusignEnvelopeRequest(); req.templateIds = new List{'01234567-abcd-ef01-2345-6789abcdef99'}; req.recordId = getTestCaseId(); req.authReleaseFormCopies = 3; // Act Test.startTest(); List results = DocusignCompositeEnvelopeBuilder.sendCompositeEnvelope(new List{req}); Test.stopTest(); // Assert - ensure envelope creation succeeded when multi-copy expansion is requested System.assertEquals(true, results[0].success, 'Multi-copy expansion should succeed. Error: ' + results[0].errorMessage); } private static Id getTestCaseId() { // Sandbox: a0tPo000010ZsTFIA0 (case 00520074) // Production fallback: case number 00496136 List cases = [ SELECT Id FROM Client_Case__c WHERE Id = 'a0tPo000010ZsTFIA0' OR Name = '00496136' LIMIT 1 ]; if (!cases.isEmpty()) { return cases[0].Id; } throw new TestSetupException( 'No test Client_Case__c record found. ' + 'Expected sandbox case 00520074 (id a0tPo000010ZsTFIA0) or production case 00496136.' ); } class TestSetupException extends Exception {} }