+ Start a Discussion
STar14STar14 

Trailhead - Apex Automation logic Challenge failing for Apex Specialist Superbadge !

Hi, I have completed the test class for the Test Automation logic  challenge. Both my trigger and helper class are getting 100% covered. But the challenge is not complted due to the following error:

Challenge Not yet complete... here's what's wrong: 
The 'MaintenanceRequestHelper' class did not achieve 100% code coverage via your test methods. Make sure that you chose 'Run All' tests in the Developer Console at least once before attempting to verify this challenge.


Can some one point me in the right direction to move forward with the badge completion. TIA !!!
Raj VakatiRaj Vakati
Go to salesforce Developer Console --> Test --> Run ALL test class and reverify the challange 
lakshmi prasanna 84lakshmi prasanna 84
Total solution  for  Apex Specialist Superbadge: challenge 4 : Test automation logic
create a test class : MaintenanceRequestTest.apex
paste the following code in it ...
MaintenanceRequestTest.apex:
------------------------------------------------------------------------------------------
@isTest
private class MaintenanceRequestTest{
    @testSetup
    static void setup(){
        //Equipment SETUP
        List<Product2> lstOfEqpmnts = new List<Product2>();
        
        Product2 eqip = new Product2(Name = 'Test Equipment', 
                                     Maintenance_Cycle__c = 10,
                                     Cost__c = 100,
                                     Current_Inventory__c = 10,
                                     Lifespan_Months__c = 10,
                                     Replacement_Part__c = true,
                                     Warehouse_SKU__c = 'abc');
        lstOfEqpmnts.add(eqip);
        INSERT lstOfEqpmnts;
    }
    
    @isTest
    static void testMaintenanceRequest(){
        List<Case> lstOfInsertMRs = new List<Case>();
        
        List<Case> lstOfUpdtMRs = new List<Case>();
        
        Id equipId = [SELECT Id FROM Product2 LIMIT 1].get(0).Id;
        
        Case newCase = new Case(Type = 'Routine Maintenance',Status = 'New', Origin = 'Phone');
        newCase.Equipment__c = equipId;
        lstOfInsertMRs.add(newCase);
      
       Case mrInsert = new Case(Type = 'Routine Maintenance2', Status = 'New', Origin = 'Phone');
       mrInsert.Equipment__c = equipId;
       lstOfInsertMRs.add(mrInsert);
        
        
        Test.startTest();
            INSERT lstOfInsertMRs;
            
            System.assertEquals(2, lstOfInsertMRs.size());
            
            for(Case mrUpdt : lstOfInsertMRs){
                mrUpdt.Status = 'Closed';
                lstOfUpdtMRs.add(mrUpdt);    
            }
            
            UPDATE lstOfUpdtMRs;
            
          System.assertEquals(2, lstOfUpdtMRs.size());
        Test.stopTest();
    }
}
------------------------------------------------------------------------------------------------------
then in the MaintenanceRequest.trigger 
paste the following code .
 MaintenanceRequest.trigger :
------------------------------------------------------------------------------------------------------
trigger MaintenanceRequest on Case (before update, after update) {
    // call MaintenanceRequestHelper.updateWorkOrders  
    Map<Id,Case> caseLst = new Map<Id,Case>();
    
    if(Trigger.isUpdate  && Trigger.isAfter){
        for(Case oCase: Trigger.new){
            if (oCase.IsClosed && (oCase.Type.equals('Repair') || oCase.Type.equals('Routine Maintenance'))){
                caseLst.put(oCase.Id, oCase);
            }
        }
        if(caseLst.size() > 0){
            System.debug('*******Calling updateWorkOrders from MaintenanceRequestHelper Class*******');
            MaintenanceRequestHelper.updateWorkOrders(caseLst);    
        }        
    } 
}
 ------------------------------------------------------------------------------------------------------
then run the above test class ...
it works fine .challenge will be completed

thanks
 
Saket Ranjan 3Saket Ranjan 3
@lakshmi prasanna 84  is correct.
in case you still face any problem because of using list in helper class and map here being used by "lakshmi prasanna 84"
you can replace:
" MaintenanceRequestHelper.updateWorkOrders(caseLst);  " by :" MaintenanceRequestHelper.updateWorkOrders(Trigger.New);  ".
Pavan Raj NPavan Raj N
Hello can someone post MaintenanceRequestHelper.cls I have executed the code but I get 86% on the MaintenanceRequestHelper.cls which should be 100%
Challenge Not yet complete... here's what's wrong:
The 'MaintenanceRequestHelper' class did not achieve 100% code coverage via your test methods. Make sure to 'Run All' tests in the Developer Console at least once before attempting to verify this challenge.


MaintenanceRequest.apxt
trigger MaintenanceRequest on Case (before update, after update) {
    // call MaintenanceRequestHelper.updateWorkOrders  
    Map<Id,Case> caseLst = new Map<Id,Case>();
    
    if(Trigger.isUpdate  && Trigger.isAfter){
        for(Case oCase: Trigger.new){
            if (oCase.IsClosed && (oCase.Type.equals('Repair') || oCase.Type.equals('Routine Maintenance'))){
                caseLst.put(oCase.Id, oCase);
            }
        }
        if(caseLst.size() > 0){
            System.debug('*******Calling updateWorkOrders from MaintenanceRequestHelper Class*******');
            MaintenanceRequestHelper.updateWorkOrders(Trigger.New, Trigger.oldMap);    
        }        
    } 
}

MaintenanceRequestHelper.cls
public class MaintenanceRequestHelper {
    
    public static void updateWorkOrders(List<Case> updatedCases, Map<Id,Case> oldCaseMap){
    
        // updatedCases <= Trigger.New
        // oldCaseMap <= Trigger.oldMap

        // we only need to create new Routine Maintenance cases if 
        // 1. the case has been updated to 'Closed'
        // 2. the case Type is either 'Repair' or 'Routine Maintenance'
        
        Set<Id> validCaseIds = new Set<Id>(); // holds all Case Ids that need to be touched
        for (Case c: updatedCases) {
            // continue only if the Case status has just been updated to 'Closed'
            if (oldCaseMap.get(c.Id).Status != 'Closed' && c.Status == 'Closed') {
                // continue only if the Type is 'Repair' or 'Routine Maintenance'
                if (c.Type == 'Repair' || c.Type == 'Routine Maintenance') {
                    // add the Case to the map of valid cases that need to be touched
                    validCaseIds.add(c.Id);
                }
            }
        } 

        // continue only if there's something to do
        if (!validCaseIds.isEmpty()) {
            // create a list to hold all the new Cases
            List<Case> newCases = new List<Case>();
            
            // create a map to hold all the old Case info including the associated Work Parts
            // we need the map because we're going to assign the old Case Id to be the parent of the new Case
            // we're going to use that ParentId to look up related Work Parts so that we can CLONE them to the new Case
            // NOTE: after the challenge, I looked online at some other solutions; the three that I found all said 
            //       to RE-PARENT the Work Parts to the new Case. Not only is there nothing in the scenario to suggest that this 
            //       is correct, but common sense suggests that you don't want to remove data (like these related records) from the 
            //       old, closed Cases. Seems like that would be an audit problem if anyone ever wanted to go back and see what
            //       was done for that old case.
            // NOTE: to clone (or re-parent) the Work Parts, we need to know from which closed Case the new Routine Maintenance Case
            //       was created. I used the standard 'Parent' field to hold that history. All the other solutions I saw created 
            //       a new custom field. In retrospect, the custom field might have been a better choice. The scenario is not 
            //       very detailed. A requirements discussion with the customer should elicit how the Parent field is or might be used. 
            Map<Id,Case> closedCaseMap = new Map<Id,Case>([SELECT Id, Vehicle__c, Equipment__c, Equipment__r.Maintenance_Cycle__c, 
                                                                  (SELECT Id, Equipment__c, Quantity__c FROM Work_Parts__r) 
                                                           FROM Case 
                                                           WHERE Id IN :validCaseIds]);
            
            // create a map to hold the minimum cycle time for each of the valid cases
            Map<Id, Decimal> maintCycleMap = new Map<Id, Decimal>();
            
            // use the MIN aggregate to get the minimum value of Maintenance_Cycle__c for each Case and map it to the Case ID
            AggregateResult[] results = [SELECT Maintenance_Request__c, MIN(Equipment__r.Maintenance_Cycle__c)cycle
                                            FROM Work_Part__c 
                                         WHERE Maintenance_Request__c IN :validCaseIds 
                                         GROUP BY Maintenance_Request__c];
        
            // build the map; remember, the Case Id is for the old, closed case  
            for (AggregateResult ar : results) {
                maintCycleMap.put((Id) ar.get('Maintenance_Request__c'), (Decimal) ar.get('cycle') );
            }

            for (Case cc: closedCaseMap.values()){
                // create a new child Case; keep the Vehicle and Equipment fields from the parent case; the other fields are defaulted
                // all the other field assignments are per requirements
                Case nc = new Case (ParentId = cc.Id,
                                    Status = 'New',
                                    Subject = 'Routine Maintenance',
                                    Type = 'Routine Maintenance',
                                    Vehicle__c = cc.Vehicle__c,
                                    Equipment__c = cc.Equipment__c,
                                    Origin = 'Web',  // NOTE: Origin is required, but the valued was not specified; I used a standard value; a better solution would have been to create a new custom value
                                    Date_Reported__c = Date.today());

                // if there are no Work Parts, there won't be a minimum value to assign to the new Case
                // the req'ts don't specify what to do in this case; it seems reasonable to use the cycle from Equipment__c
                if (maintCycleMap.containsKey(cc.Id) ) {
                    nc.Date_Due__c = Date.today().addDays((Integer) maintCycleMap.get(cc.Id));
                } else {
                    nc.Date_Due__c = Date.today().addDays((Integer) cc.Equipment__r.Maintenance_Cycle__c);
                } 
                
                newCases.add(nc);
            }
            
            // insert the new Cases
            insert newCases;
            
            // clone the Work Parts and assign them to the new Case
            List<Work_Part__c> clonedWorkParts = new List<Work_Part__c>();
            for (Case nc: newCases) {
                // for each new Case, clone all the Work Parts from the parent case, and assign them to the new Case
                for (Work_Part__c wp: closedCaseMap.get(nc.ParentId).Work_Parts__r) {
                    Work_Part__c wpClone = wp.clone();
                    wpClone.Maintenance_Request__c = nc.Id;
                    clonedWorkParts.add(wpClone);
                }
            }
            
            // insert the cloned work parts
            insert clonedWorkParts;
        }
    }        
}

MaintenanceRequestTest.apxc

@isTest
private class MaintenanceRequestTest{
    @testSetup
    static void setup(){
        //Equipment SETUP
        List<Product2> lstOfEqpmnts = new List<Product2>();
        
        Product2 eqip = new Product2(Name = 'Test Equipment', 
                                     Maintenance_Cycle__c = 10,
                                     Cost__c = 100,
                                     Current_Inventory__c = 10,
                                     Lifespan_Months__c = 10,
                                     Replacement_Part__c = true,
                                     Warehouse_SKU__c = 'abc');
        lstOfEqpmnts.add(eqip);
        INSERT lstOfEqpmnts;
    }
    
    @isTest
    static void testMaintenanceRequest(){
        List<Case> lstOfInsertMRs = new List<Case>();
        
        List<Case> lstOfUpdtMRs = new List<Case>();
        
        Id equipId = [SELECT Id FROM Product2 LIMIT 1].get(0).Id;
        
        Case newCase = new Case(Type = 'Routine Maintenance',Status = 'New', Origin = 'Phone');
        newCase.Equipment__c = equipId;
        lstOfInsertMRs.add(newCase);
      
       Case mrInsert = new Case(Type = 'Routine Maintenance2', Status = 'New', Origin = 'Phone');
       mrInsert.Equipment__c = equipId;
       lstOfInsertMRs.add(mrInsert);
        
        
        Test.startTest();
            INSERT lstOfInsertMRs;
            
            System.assertEquals(2, lstOfInsertMRs.size());
            
            for(Case mrUpdt : lstOfInsertMRs){
                mrUpdt.Status = 'Closed';
                lstOfUpdtMRs.add(mrUpdt);    
            }
            
            UPDATE lstOfUpdtMRs;
            
          System.assertEquals(2, lstOfUpdtMRs.size());
        Test.stopTest();
    }
}
Ashrafali NagatiAshrafali Nagati
Any Update On This @
Pavan Raj N , i am also stuck at same point
 
Akshita KanungoAkshita Kanungo
@lakshmi prasanna 84 could you please share maintainencerequestHelper class code, my total coverage is 70 for the class and I am not able to clear the challenge. Please help.
Yadavalli RaghavendraYadavalli Raghavendra
@Akshita Kanungo Are you able to close this? I 'm struck. Can anyone help me, please