function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Ido Greenbaum 10Ido Greenbaum 10 

Help with test coverage for implementation of QuickAction.QuickActionDefaultsHandler

I have an Apex Class 'EmailPublisherLoader', which implements QuickAction.QuickActionDefaultsHandler, to set dynamic Email Templates, Recipients and From address in the Case Feed Email Publisher.

I am struggling with pushing the code to production, as the test class yields 74% coverage. I wonder which additional tests can be added to raise the test code coverage.

Below is the Apex Class:
 
global class EmailPublisherLoader implements QuickAction.QuickActionDefaultsHandler {
// Empty constructor
    global EmailPublisherLoader() { }

// The main interface method
    global void onInitDefaults(QuickAction.QuickActionDefaults[] defaults) {
        QuickAction.SendEmailQuickActionDefaults sendEmailDefaults = null;

        // Check if the quick action is the standard Case Feed send email action
        for (Integer j = 0; j < defaults.size(); j++) {
            if (defaults.get(j) instanceof QuickAction.SendEmailQuickActionDefaults && 
               defaults.get(j).getTargetSObject().getSObjectType() == 
                   EmailMessage.sObjectType && 
               defaults.get(j).getActionName().equals('Case.Email') && 
               defaults.get(j).getActionType().equals('Email')) {
                   sendEmailDefaults = 
                       (QuickAction.SendEmailQuickActionDefaults)defaults.get(j);
                   break;
            }
        }

         if (sendEmailDefaults != null) {
            Case c = [SELECT Status, contact.Email, Additional_To__c, Additional_CC__c, Additional_BCC__c, RecordType.name FROM Case WHERE Id=:sendEmailDefaults.getContextId()];
            EmailMessage emailMessage = (EmailMessage)sendEmailDefaults.getTargetSObject();  

    //set TO address
         String contactEmail = c.contact.Email; 
         if (c.contact.Email == c.Additional_To__c){
            emailMessage.toAddress = (c.contact.Email);
            }
            else{
                if (c.Additional_To__c != null){
                    //contactEmail is included in Additional TO
                    if (c.Additional_To__c.indexOf(contactEmail) != -1){
                        emailMessage.toAddress = (c.Additional_To__c);
                        }
                else{
                    emailMessage.toAddress = (c.contact.Email+' '+c.Additional_To__c);
                    }
                }
            }
    //set CC address
            emailMessage.ccAddress = (c.Additional_CC__c);
    //set BCC address        
            emailMessage.bccAddress = (c.Additional_BCC__c);
    //set From 'security@test.com' for 'Security' RecordType
            if (c.recordtype.name  == 'Security'){
            emailMessage.fromAddress = ('security@test.com');
            }

    //if In Reply To Id field is null we know the interface is called on page load
        if (sendEmailDefaults.getInReplyToId() == null) {

                    if (c.recordtype.name  == 'Consumer'){
                        sendEmailDefaults.setTemplateId(getTemplateIdHelper('Custom_Default_Consumer_Email'));                       
                        }
                        else if (c.recordtype.name  == 'Security') {
                            sendEmailDefaults.setTemplateId(getTemplateIdHelper('Custom_Default_Security_Email'));
                            } 
                            else {
                            sendEmailDefaults.setTemplateId(getTemplateIdHelper('Custom_Default_Enterprise_Email'));
                            }                

           }
          // Now, we know that the 'Reply' or 'Reply All' button has been clicked, so we load the default response template 
          else
          {
               if (c.recordtype.name  == 'Consumer'){
                            sendEmailDefaults.setTemplateId(getTemplateIdHelper('Custom_Default_Consumer_Email_No_Body'));
                            sendEmailDefaults.setInsertTemplateBody(true);
               }
               else if (c.recordtype.name  == 'Security') {
                            sendEmailDefaults.setTemplateId(getTemplateIdHelper('Custom_Default_Security_Email'));
                            sendEmailDefaults.setInsertTemplateBody(true);
               }
                   else {
                            sendEmailDefaults.setTemplateId(getTemplateIdHelper('Custom_Default_Enterprise_Email_No_Body'));
                            sendEmailDefaults.setInsertTemplateBody(true);
                   }      
          }
         }
       }

    private Id getTemplateIdHelper(String templateApiName) {
        Id templateId = null;
        try {
            templateId = [select id, name from EmailTemplate 
                          where developername = : templateApiName].id;   
        } catch (Exception e) {
            system.debug('Unble to locate EmailTemplate using name: ' + 
                templateApiName + ' refer to Setup | Communications Templates ' 
                    + templateApiName);
        }
        return templateId;
    }
}
And the Test Class:
@isTest
private class EmailPublisherLoaderTest {
    static Case myCase {get;set;}
    static EmailMessage myMsg {get;set;}

    static testmethod void EmailPublisherLoader_NoReplyToId() {
        Exception failureDuringExecution = null;
        init();
        init2();
        init3();
        init4();

        //create QuickActionDefaults
        List<Map<String, Object>> defaultSettingAsObject = new List<Map<String, Object>>
        {
          new Map<String, Object>
          {
                'targetSObject' => new EmailMessage(),
                'contextId' => myCase.Id,
                'actionType' => 'Email',
                'actionName' => 'Case.Email',
                'fromAddressList' => new List<String> { 'salesforce@test.com' }
          }
        };

        List<QuickAction.SendEmailQuickActionDefaults> defaultsSettings = 
            (List<QuickAction.SendEmailQuickActionDefaults>)JSON.deserialize(JSON.serialize(defaultSettingAsObject), List<QuickAction.SendEmailQuickActionDefaults>.class);
        Test.startTest();
        try {
            (new EmailPublisherLoader()).onInitDefaults(defaultsSettings);
        }
        catch(Exception e) {
            failureDuringExecution = e; 
        }

        Test.stopTest();
        System.assertEquals(null, failureDuringExecution, 'There was an exception thrown during the test!');
    }
    static testmethod void EmailPublisherLoader_WithReplyToId() {
        Exception failureDuringExecution = null;
        init();
        init2();
        init3();
        init4();

        //create QuickActionDefaults
        List<Map<String, Object>> defaultSettingAsObject = new List<Map<String, Object>>
        {
          new Map<String, Object>
          {
                'targetSObject' => new EmailMessage(),
                'replyToId' => myMsg.Id,
                'contextId' => myCase.Id,
                'actionType' => 'Email',
                'actionName' => 'Case.Email',
                'fromAddressList' => new List<String> { 'salesforce@test.com' }
          }
        };

        List<QuickAction.SendEmailQuickActionDefaults> defaultsSettings = 
            (List<QuickAction.SendEmailQuickActionDefaults>)JSON.deserialize(JSON.serialize(defaultSettingAsObject), List<QuickAction.SendEmailQuickActionDefaults>.class);
        Test.startTest();
        try {
            (new EmailPublisherLoader()).onInitDefaults(defaultsSettings);
        }
        catch(Exception e) {
            failureDuringExecution = e; 
        }

        Test.stopTest();
        System.assertEquals(null, failureDuringExecution, 'There was an exception thrown during the test!');
    }

    static void init(){
        myCase = 
            new Case(
                Status='Status'
                , Origin='Email'
                , Reason = 'Reason'
                , RecordTypeId = '01261000000XfOl'
            );
        insert myCase;

        myMsg = 
            new EmailMessage(
                ParentId = myCase.Id
            );
        insert myMsg;
    }
     static void init2(){
        myCase = 
            new Case(
                Status='Status'
                , Origin='Email'
                , Reason = 'Reason'
                , RecordTypeId = '01261000000XfOq'
            );
        insert myCase;

        myMsg = 
            new EmailMessage(
                ParentId = myCase.Id
            );
        insert myMsg;
    }
    static void init3(){
        myCase = 
            new Case(
                Status='Status'
                , Origin='Email'
                , Reason = 'Reason'
                , RecordTypeId = '01261000000iuJL'
            );
        insert myCase;

        myMsg = 
            new EmailMessage(
                ParentId = myCase.Id
            );
        insert myMsg;
    }
    static void init4(){
        myCase = 
            new Case(
                Status='Status'
                , Origin='Email'
                , Reason = 'Reason'
                , RecordTypeId = '01261000000XfP0'
            );
        insert myCase;

        myMsg = 
            new EmailMessage(
                ParentId = myCase.Id
            );
        insert myMsg;
    }
    @isTest
static void test_mockIfAtAllPossible(){
}
}



 
NightFoxNightFox
Even Im doing the same, My preference is to populate the FROM Address.
global class EmailPublisherLoader implements QuickAction.QuickActionDefaultsHandler {
    // Empty constructor
    global EmailPublisherLoader(){}

    // The main interface method
    global void onInitDefaults(QuickAction.QuickActionDefaults[] defaults){
        QuickAction.SendEmailQuickActionDefaults sendEmailDefaults = null;

        // Check if the quick action is the standard Case Feed send email action
        for (Integer j = 0; j < defaults.size(); j++) {
            if (defaults.get(j) instanceof QuickAction.SendEmailQuickActionDefaults && defaults.get(j).getTargetSObject().getSObjectType() == 
                   EmailMessage.sObjectType && defaults.get(j).getActionName().equals('Case.Email') &&  defaults.get(j).getActionType().equals('Email')){
                   sendEmailDefaults = (QuickAction.SendEmailQuickActionDefaults)defaults.get(j);
                   break;
            }
        }

        if(sendEmailDefaults != null){
            system.debug(' sendEmailDefaults # ' + sendEmailDefaults  );
            system.debug(' sendEmailDefaults ID # ' + sendEmailDefaults.getcontextId()); 
            Case c = [SELECT Status, Casenumber,Reason FROM Case WHERE Id=:sendEmailDefaults.getContextId()];
            system.debug(' Case '+ c.CaseNumber);
            system.debug(' sendEmailDefaults.getTargetSObject() '+ sendEmailDefaults.getTargetSObject());

            EmailMessage emailMessage = (EmailMessage)sendEmailDefaults.getTargetSObject();    
            // Set bcc address to make sure each email goes for audit
            system.debug(' getBccAddress(c.Reason) # ' + getBccAddress(c.Reason) );
            system.debug(' getFromAddress(c.Reason) # ' + getFromAddress(c.Reason));
            emailMessage.BccAddress = getBccAddress(c.Reason);
            emailMessage.FromAddress = getFromAddress(c.Reason);
            emailMessage.BccAddress = 'ff@gmail.com';
            emailMessage.FromAddress = 'tt@gmail.com';

            system.debug(' emailMessage '+ emailMessage );

            /* 
            Set Template related fields 
            When the In Reply To Id field is null we know the interface 
            is called on page load. Here we check if 
            there are any previous emails attached to the case and load 
            the 'New_Case_Created' or 'Automatic_Response' template.
            When the In Reply To Id field is not null we know that 
            the interface is called on click of reply/reply all 
            of an email and we load the 'Default_reply_template' template
            */

            system.debug(' sendEmailDefaults get Reply To '+ sendEmailDefaults.getInReplyToId());
            system.debug(' sendEmailDefaults getFrom Address '+ sendEmailDefaults.getFromAddressList());

            Integer emailCount = [SELECT count() FROM EmailMessage WHERE ParentId=:sendEmailDefaults.getContextId()];

            system.debug(' emailCount ' + emailcount );

            if(emailCount!= null && emailCount > 0){
                sendEmailDefaults.setTemplateId(
                getTemplateIdHelper('Send_Personal_Loan_Details'));
            }else{
                sendEmailDefaults.setTemplateId(
                getTemplateIdHelper('New_Case_Created'));
            }

            sendEmailDefaults.setInsertTemplateBody(false);
            sendEmailDefaults.setIgnoreTemplateSubject(false);

            system.debug(' sendEmailDefaults ### ' + sendEmailDefaults);

            /*
            if(sendEmailDefaults.getInReplyToId() == null){

            }else{
                sendEmailDefaults.setTemplateId(
                getTemplateIdHelper('Default_reply_template'));
                sendEmailDefaults.setInsertTemplateBody(false);
                sendEmailDefaults.setIgnoreTemplateSubject(true);
            }*/
        }
    }

    private Id getTemplateIdHelper(String templateApiName){
        Id templateId = null;
        try{
            templateId = [select id, name from EmailTemplate where developername = : templateApiName].id;
            system.debug(' Temp id # '+ templateId );   
        }catch(Exception e){
            system.debug('Unble to locate EmailTemplate using name: ' + templateApiName + ' refer to Setup | Communications Templates ' + templateApiName);
        }
        return templateId;
    }

    private String getBccAddress(String reason){
        return 'support_technical@mycompany.com, tt@gmail.com'; 
    }

    private String getFromAddress(String reason){
        return 'loan@mycompany.com, personalloan@gmail.com'; 
    }
}

Here is my code sample. Apart from From Address all other fields are getting populated. If I debug the same in my console, From address is holding is the value what passing in my apex class. but in UI, its only considering the Org Wide Addresses..

Please help me to get rid of this. Do I have to change any settings?

Hopefully, For you, the FROM address value is populating as you defined in your Apex. 
emailMessage.BccAddress = getBccAddress(c.Reason); // populating
emailMessage.FromAddress = getFromAddress(c.Reason); // Not populating
emailMessage.ValidatedFromAddress = ('ValidatedFrom@address.com'); // Not populating
emailMessage.BccAddress = 'ff@gmail.com'; // populating