This post explains how to export code coverage using the lightning web component
CodeCoverageExportLWC.js
Apex Class
OrgRest Apex Class
You can also find the code on Github
GitHub Link
Output
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
can you please share how we can create VF for this
ReplyDelete