Showing posts with label Code Coverage. Show all posts
Showing posts with label Code Coverage. Show all posts

Thursday, December 19, 2019

How to cover the Approval Process in test class in Salesforce

# Approach 1

Ex: you have an approval process on an opportunity when the amount is greater than 500 the opportunity requires an approval.
Create the opportunity test data as per the approval process criteria and query the process instance object data and use the assert methods to verify the values.

Sample Code
Opportunity objOpp = new Opportunity(Name = 'Test Opp', amount = 800);
insert objOpp;

ProcessInstance objProcessInstance = [SELECT Id,TargetObjectId, CreatedDate FROM ProcessInstance WHERE TargetObjectId = :objOpp.Id];
System.assertEquals(objOpp.CreatedDate,objProcessInstance.CreatedDate);

# Approach 2

Create the Opportunity test data and submit the Opportunity for the approval process using the ProcessSubmitRequest method.

Sample Code
Opportunity objOpp = new Opportunity(Name = 'Test Opp', amount = 500);
insert objOpp;

Approval.ProcessSubmitRequest app = new Approval.ProcessSubmitRequest();
app.setObjectId(objOpp.id);
Approval.ProcessResult result = Approval.process(app);

Sunday, October 13, 2019

Code Coverage Export Using Lightning Web Components(lwc)

This post explains how to export code coverage using the lightning web component

This component explores
1.  It will show the total Apex lines org.
2.  Shows how many line covered and uncovered lines 
3.  how much percentage covered in org
4.  shows the different color based on the percentage covered of apex class in the data table



CodeCoverageExportLWC.html
<template>
    <lightning-card title="Code Coverage Analysis Using Lightning Web Component" icon-name="standard:apex"><br/>
        <div class="slds-grid slds-gutters" style="margin-left: 3%;">
            <div class="slds-col">
                <span class="slds-badge"><b>Total Apex Lines In Org: <b style="color: steelblue">{orgTotalApexLines}</b></b></span>
            </div>
            <div class="slds-col">
                <span class="slds-badge"><b>Total Apex Lines Covered In Org: <b style="color: steelblue">{OrgTotalCoveredLines}</b></b></span>
            </div>
            <div class="slds-col">
                <span class="slds-badge"><b>Total Code Coverage In Org: <b style="color: steelblue">{OrgTotalCodeCoverage}%</b></b></span>
            </div>
        </div><br/>

        <template if:true={data}>
            <lightning-datatable columns={columns} 
                                 data={data} 
                                 key-field="id"
                                 hide-checkbox-column="true"
                                 show-row-number-column="true"></lightning-datatable>
        </template>

    </lightning-card>
</template>

CodeCoverageExportLWC.js
import { LightningElement, track } from 'lwc';

// Importing Aapex class
import codeCoverageAnalysis from '@salesforce/apex/CodeCoverageExportController.exportClassCoverage';

const columns = [
    {
        label: 'Name',
        fieldName: 'ApexClassOrTrigger',
        cellAttributes: { class: { fieldName: 'covrageLowCSSClass' }}
    },{
        label: 'Total Lines',
        fieldName: 'TotalLines'
    }, {
        label: 'NumLinesCovered',
        fieldName: 'CoveredLinesCount'
    }, {
        label: 'NumLinesUncovered',
        fieldName: 'UncoveredLinesCount'
    }, {
        label: 'Percentage Covered',
        fieldName: 'PercentageCovered',
        cellAttributes: { class: { fieldName: 'covrageLowCSSClass' }}
    }
];

export default class CodeCoverageExportLWC extends LightningElement {
    // reactive variables
    @track columns = columns;
    @track data = [];
    @track orgTotalApexLines;
    @track OrgTotalCodeCoverage;
    @track OrgTotalCoveredLines;

    connectedCallback() {
        this.codeAnalysis();
    }

    codeAnalysis() {
        codeCoverageAnalysis()
        .then(result => {
            let rows = result.records;
            let orgTotalLines = 0;
            let totalCoveredLines = 0;
            let totalCountLines = 0;

            rows.forEach((key) => {
                let row = key;
                
                // Total apex lines in org
                orgTotalLines = orgTotalLines + totalCountLines;
                
                // Total lines of current apex class
                totalCountLines = Number(row.NumLinesCovered) + Number(row.NumLinesUncovered);

                // Covered lines of Apex class
                totalCoveredLines = totalCoveredLines + Number(row.NumLinesCovered);

                // Percentage covered for current apex class
                row.PercentageCovered = Math.round(Number(row.NumLinesCovered) / totalCountLines * 100).toString() + '%';

                // Showing different color in column based on percentage covered
                if(Math.round(Number(row.NumLinesCovered) / totalCountLines * 100) < 75) {
                    row.covrageLowCSSClass = 'slds-text-color_error';
                }
                else {
                    row.covrageLowCSSClass = 'slds-text-color_success';
                }


                row.TotalLines = totalCountLines.toString();

                if(row.ApexClassOrTrigger) {
                    row.ApexClassOrTrigger = row.ApexClassOrTrigger.Name;
                }

                if(row) {
                    row.CoveredLinesCount = row.NumLinesCovered.toString();
                    row.UncoveredLinesCount = row.NumLinesUncovered.toString();
                }
            }); 

            this.OrgTotalCodeCoverage = Math.round(totalCoveredLines/orgTotalLines * 100);
            this.orgTotalApexLines = orgTotalLines;
            this.OrgTotalCoveredLines = totalCoveredLines;
            
            // assging data to datatable
            this.data = rows;
        })
        .catch(error => {
            this.error = error;
        });
    }


}

Apex Class
public inherited sharing class CodeCoverageExportController {

    @AuraEnabled
    public static CoverageWrap exportClassCoverage() {
        String strResourceQuery = null;
        String strResponse = null;
        CoverageWrap cw;

        strResourceQuery = 'tooling/query/?q=Select+id,ApexClassorTrigger.Name,NumLinesCovered,NumLinesUncovered+from+ApexCodeCoverageAggregate';

        if(strResourceQuery != null) {
            // OrgREST Custom Class returns the response as string
            strResponse = OrgREST.retriveResult(strResourceQuery, 'GET', null);
        }

        if(strResponse != null) {
            cw = new CoverageWrap();
            cw  = (CoverageWrap)JSON.deserialize(strResponse, CoverageWrap.class);
        }

        return cw;
 
    }


    public class Attributes {
       @AuraEnabled public String type;
       @AuraEnabled public String url;
    }

    public class Records {
       @AuraEnabled public Attributes attributes;
       @AuraEnabled public String Id;
       @AuraEnabled public ApexClassOrTrigger ApexClassOrTrigger;
       @AuraEnabled public Integer NumLinesCovered;
       @AuraEnabled public Integer NumLinesUncovered;
    }

    public class ApexClassOrTrigger {
       @AuraEnabled public Attributes attributes;
       @AuraEnabled public String Name;
    }
    
    public class CoverageWrap{
      @AuraEnabled public Integer size;
      @AuraEnabled public Integer totalSize;
      @AuraEnabled public Boolean done;
      @AuraEnabled public Object queryLocator;
      @AuraEnabled public String entityTypeName;
      @AuraEnabled  public List<Records> records;
    }
}

OrgRest Apex Class
/*
purpose: This Class gives response based on resource name you entered.
Author: Shaik Nagajani
Date: 15/June/2019
*/

public inherited sharing class OrgREST {
    
    public static String retriveResult(String strResourceName, String strMethod, String strBody) {
        String response;
         String strEndPonitURL = URL.getSalesforceBaseUrl().toExternalForm() + '/services/data/v46.0/' + strResourceName;
        if(String.isNotBlank(strResourceName)) {
            HttpRequest httpRequest = new HttpRequest();  
            httpRequest.setEndpoint(strEndPonitURL);

            httpRequest.setMethod(strMethod);   
            httpRequest.setHeader('Authorization', 'OAuth ' + getSessionId());        
            httpRequest.setHeader('Authorization', 'Bearer ' + getSessionId()); 
            
            if(String.isNotBlank(strBody)) {
                httpRequest.setBody(strBody);
                httpRequest.setHeader('Content-Type', 'application/json');
             httpRequest.setHeader('Accept', 'application/json');
            }
            
            try {  
                Http http = new Http();   
                HttpResponse httpResponse = http.send(httpRequest);  

                while(httpResponse.getStatusCode() == 302) {
                    httpRequest.setEndpoint(httpResponse.getHeader('Location'));
                    httpResponse = new Http().send(httpRequest);
                }

                if (httpResponse.getStatusCode() == 200 ) {  
                    response = httpResponse.getBody();  
                } 
                else {  
                    throw new CalloutException(httpResponse.getBody());  
                }   
            } 
            catch(Exception ex) {  
                throw ex;  
            }  
        } 
        return response;
    }

    public static String getSessionId() {
        return Page.GenerateSessionIdForLWC.getContent().toString();
    }
}

You can also find the code on Github
GitHub Link


Output