I’m using SONARQUBE locally v. 8.8 and on our Jenkins Server v.7.9
I’ve created QUnit tests because we’re using AEM (Adobe Experience Manager) and they’ve tasked me with writing code coverage for “TWO” JavaScript functions to test this.
I have and it runs both in the terminal and browser with 100% success.
The code will be shown below.
BUT, when I run it online in Jenkins or locally with Sonar, the dashboard shows the following:
And the code issues are shown as below

What I am trying to achieve is getting COVERAGE to be greater than ZERO while there are 373 lines of code that show need coverage. I’m only doing two functions currently.
Here’s my set up…

This {test} folder resides in the same line as src/apps/
Here’s my code for QUNIT in a file called: header.js
"use strict";
// Zipcode Module
QUnit.module("Send to VPP");
var zipcodevalue = '98237'; // Change this value for testing
QUnit.test("Should validate that the zip code going in is valid", function (assert) {
zipToVppTestCase.call(this, {
assert: assert,
zipcodevalue: '98237',
expected: "Success"
});
// QUnit.assert.equal(zipcodevalue, '98237', 'string value and hard code value are equal', (callback) => {
// callback(zipcodevalue);
// });
});
function zipToVppTestCase() {
// Act
// Assert
// QUnit.equal(zipcodevalue, '98237', "Testing the Zip Code", function (assert) {
if (isNaN(zipcodevalue === false)) {
QUnit.assert.equal(zipcodevalue, '98237', 'string value and hard code value are NOT equal', (callback) => {
callback(zipcodevalue);
});
} else {
QUnit.assert.equal(zipcodevalue, '98237', 'string value and hard code value are equal', (callback) => {
callback(zipcodevalue);
});
// ok(true);
}
// });
}
// Email validation
QUnit.module('Validate Email');
var emailvalue = 'peter_borreggine@optum.com'; // Change this value for testing
var returnMsg = '';
QUnit.test("Should validate that the email going in is valid", function (assert) {
validateEmail.call(this, {
assert: assert,
emailvalue: 'peter_borreggine@optum.com',
expected: "Success"
});
});
function validateEmail() {
// Act
// Assert
// QUnit.equal(emailvalue, 'peter_borreggine@optum.com', "Testing the Email address", function (assert) {
const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if (re.test(String(emailvalue).toLowerCase())) {
QUnit.assert.equal(emailvalue, 'peter_borreggine@optum.com', 'string value and hard code value are equal', (callback) => {
callback(emailvalue);
});
// ok(true);
returnMsg = 'valid email';
} else {
QUnit.assert.equal(emailvalue, 'peterborreggine@optum.com', 'string value and hard code value are NOT equal', (callback) => {
callback(emailvalue);
});
// ok(false);
returnMsg = 'invalid email';
}
return returnMsg;
// });
}
Now here’s my index.html file for QUnit
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>QUnit Main Test Suite</title>
<link data-require="qunit@*" data-semver="1.17.1" rel="stylesheet"
href="http://code.jquery.com/qunit/qunit-1.17.1.css" />
<script data-require="qunit@*" data-semver="1.17.1" src="http://code.jquery.com/qunit/qunit-1.17.1.js"></script>
<script src="../require.js"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="navigationClientLibs/js/header.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"></script>
</body>
</html>
Here’s the result in the browser:
Finally, here’s the code I’m covering in a folder up in the main code block section. QUnit suggests we MOCK the folder and name of the .js file in the test folder, which I did.
Here’s sendToVPP and then vaildateEmail.
function sendZipToVPP() {
var zipcodevalue = $('#nav-zipcode').val();
if (!($.isNumeric(zipcodevalue)) || zipcodevalue.length < 5) {
$('#nav-zipcode').addClass('invalid').attr('aria-describedby', 'shop-fp-err').focus();
$('#shop-fp-err').css({ "display": "block" });
if (typeof _satellite !== 'undefined') {
_satellite.track("globalheader_finderror");
}
return;
} else if (countyResponse === null || typeof countyResponse === 'undefined') {
$('#nav-zipcode').addClass('invalid').attr('aria-describedby', 'shop-fp-err').focus();
$('#shop-fp-err').css({ "display": "block" });
if (typeof _satellite !== 'undefined') {
_satellite.track("globalheader_finderror");
}
return;
} else {
if (typeof _satellite !== 'undefined') {
_satellite.track("globalheader");
}
$('#nav-zipcode').removeClass('invalid').removeAttr('aria-describedby');
$('#shop-fp-err').css({ "display": "none" });
var state = globalCommonUtilityService.getValueFromStorage(globalCommonUtilityService.storageTypes.SESSIONSTORAGE, "geotrackingState");
var zip = globalCommonUtilityService.getValueFromStorage(globalCommonUtilityService.storageTypes.SESSIONSTORAGE, "geotrackingZip");
var profileChatData = globalCommonUtilityService.getValueFromStorage(globalCommonUtilityService.storageTypes.SESSIONSTORAGE, "profileUserChatData");
var campaignCodeFromSession = globalCommonUtilityService.getValueFromStorage(globalCommonUtilityService.storageTypes.SESSIONSTORAGE, "campaignCode");
globalCommonUtilityService.clearEntireStorage(globalCommonUtilityService.storageTypes.SESSIONSTORAGE);
globalCommonUtilityService.setValueInStorage(globalCommonUtilityService.storageTypes.SESSIONSTORAGE, "geotrackingState", state);
globalCommonUtilityService.setValueInStorage(globalCommonUtilityService.storageTypes.SESSIONSTORAGE, "geotrackingZip", zip);
globalCommonUtilityService.setValueInStorage(globalCommonUtilityService.storageTypes.SESSIONSTORAGE, "profileUserChatData", profileChatData);
campaignCodeFromSession != null ? globalCommonUtilityService.setValueInStorage(globalCommonUtilityService.storageTypes.SESSIONSTORAGE, "campaignCode", campaignCodeFromSession) : null;
trackVPPData(zip);
if (location.href.indexOf('/confirmation') > -1) {
globalCommonUtilityService.setValueInStorage(globalCommonUtilityService.storageTypes.SESSIONSTORAGE, "vppZipcode", $('#nav-zipcode').val());
location.href = "/plns.html#/summary";
}
if ($.cookie) {
$.removeCookie("locationSessionCookie");
} else {
$j.removeCookie("locationSessionCookie");
}
globalCommonUtilityService.setValueInStorage(globalCommonUtilityService.storageTypes.SESSIONSTORAGE, "vppZipcode", $('#nav-zipcode').val());
location.href = "/plan.html";
}
}
and
function validateEmail(subnavType) {
var subnavClass = $('.' + subnavType);
var email = $(subnavClass).find('.menu-email-address').val();
var emailErrorID = $(subnavClass).find('.email-error').attr('id');
var errormsg = $(subnavClass).find('.email-error');
var emailregex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
var validemail = emailregex.test(String(email).toLowerCase());
if (validemail) {
$(subnavClass).find('.menu-email-address').removeAttr('aria-describedby');
submitEmail(email, subnavClass);
return;
} else {
$(subnavClass).find('.menu-email-address').attr('aria-describedby', emailErrorID);
$(subnavClass).find('.menu-email-address').addClass('invalid').focus();
$('.email-subscribe-form').addClass('errormsg-mobile-alignment');
errormsg.show();
if (typeof _satellite !== 'undefined') {
_satellite.track("globalheader_emailsubmiterror");
}
return false;
}
}
That’s pretty much it.
Here’s my sonar-project.properties file
sonar.host.url=http://localhost:9000
sonar.login=admin
sonar.language=js
sonar.password=************************
sonar.projectKey=apps
sonar.projectName=apps
sonar.projectVersion=1.0
sonar.sourceEncoding=UTF-8
sonar.sources=src/main/content/root
sonar.inclusions=src/main/content/root/**/*.js
sonar.exclusions=**/node_modules/**, src/main/content/jcr_root/*.jsp, src/main/content/jcr_root/*.java, src/main/content/jcr_root/*.html
sonar.tests=test/navigationClientLibs
sonar.test.inclusions=test
sonar.javascript.jstests.reportPaths=test
sonar.typescript.lcov.reportPaths=test/coverage/lcov.info
sonar.testExecutionReportPaths=${project.projectDir}/reports/ut_report.xml
Hope all this detail helps.
Thank you


. If you look into them carefully, you can see that the scanner failed to retrieve your coverage report file: